Zotero 11 for Developers#
Zotero 11 includes an internal upgrade of the Mozilla platform on which Zotero is based, incorporating changes from Firefox 140 through Firefox 153.
For previous changes, see Zotero 10 for Developers.
Feedback#
If you have questions about anything on this page or encounter other problems while updating your plugin, let us know on the dev list. Please don’t post to the Zotero Forums about Zotero 11 at this time.
Dev Builds#
WARNING: These are test builds based on Firefox 153 intended solely for use by Zotero plugin developers and should not be used in production. We strongly recommend using a separate profile and data directory for development.
These dev channel builds will stop updating once a beta is available with these changes.
- Mac
- Linux x86_64
- Linux ARM64
- Windows 64-bit ZIP
- Windows 64-bit Installer
- Windows ARM64 ZIP
- Windows ARM64 Installer
- Windows 32-bit ZIP
- Windows 32-bit Installer
Updating plugin compatibility#
Do not update your plugin to declare compatibility with Zotero 11 at this time. We’ll make an announcement on the dev list when Zotero 11 is feature-frozen and it’s time to test for compatibility.
Note that beta, dev, and source builds no longer enforce strict_max_version, either at install time or for updates, so you can test a plugin with a lower max version on one of thoes builds without modifying it. Stable builds still enforce it.
Platform Changes#
Mozilla Platform#
The following list includes nearly all Mozilla changes that affected Zotero code. You may encounter other breaking changes if you use APIs not used in Zotero. Searchfox is the best resource for identifying current correct usage in Mozilla code and changes between Firefox 140 and Firefox 153.
Many of these changes fail silently rather than throwing, so a plugin that appears to load fine may still have dead handlers or elements stuck in the wrong state.
You can use Zotero.platformMajorVersion in your code to test what Firefox version the current Zotero build is based on.
hidden,collapsed,selected,disabled, andcheckedbecame boolean XUL attributes matched on presence alone (bug 1979014, bug 2008041) — the UA sheet’s[hidden="true"]is now[hidden], and any value,"false"included, means true (example, example, example)setAttribute()stringifies its value, sosetAttribute('hidden', false)setshidden="false"and hides the element — usetoggleAttribute()or the booleanhidden/disabled/checkedproperties- Reflected boolean properties such as
hiddenwrite an empty value, soelem.hidden = truegiveshidden=""rather thanhidden="true". Anything set that way reads back empty:getAttribute('hidden') == 'true'→hasAttribute('hidden'), and[hidden="true"]→[hidden]in CSS andquerySelector()alike
<browser remote="false">now creates a remote browser, sinceisRemoteBrowserishasAttribute("remote"). Omit the attribute for a non-remote browser.ownerGlobal→documentGlobal(bug 2033243) — the attribute was renamed and moved fromEventTargettoNode, soelement.ownerGlobalis nowundefinedrather than throwing (example)XPCOMUtils.defineLazyServiceGetter()anddefineLazyServiceGetters()require annsIIDrather than an interface name:"nsIIOService"→Ci.nsIIOService(example)- The XUL checkbox
CheckboxStateChangeevent was removed (bug 2009806) — listen forcommandinstead (example).commandfires only on user interaction, so assigning to.checkedin code no longer notifies your handler. - The icon element inside
<menuitem>and<menu>changed from a XUL<image>to an<html:img>. A XUL<image>paintedlist-style-image; the<html:img>renders theimageattribute orcontent: var(--menuitem-icon)instead.- Set
--menuitem-iconon the<menuitem>or<menu>. Keeplist-style-imagetoo for native macOS menus, which still read it (example) - Plugins that add menus through
Zotero.MenuManagerdon’t need to change anything
- Set
Cu.Sandboxfreezes built-ins by default for system-principal sandboxes (bug 2017957). Since a plugin’s bootstrap scope is such a sandbox, built-ins are frozen there: assignments toPromise,Array.prototype,JSON.parse, and the like now fail silently, or throw in strict mode. Your plugin’s own globals and objects are unaffected. If your plugin creates its own sandbox and needs to modify built-ins in it, passfreezeBuiltins: false(example).- Login-manager access to stored login records is now asynchronous. findLogins() now throws and searchLogins() was removed; use await searchLoginsAsync({…}) instead. Other synchronous methods, such as addLogin(), modifyLogin(), and removeLogin(), were all also removed; use their Async-suffixed equivalents (example). Code that cannot await must use cached state rather than reading login records synchronously.
<wizard>no longer hasextra1andextra2buttons — create them yourself if you need them (example)oncommandwas added toGlobalEventHandlersfor the Invoker Commands API (bug 1974578), soelem.oncommand = "someFunction()"— previously an inert expando write — now sets the WebIDL event handler, and a string becomesnull, wiping any handler compiled from the attribute (example)<input type="search">now gets a native clear button in chrome documents regardless oflayout.forms.input-type-search.enabled(bug 1655503), which will double up with one you draw yourself (example)
Some other Firefox 153 changes that would have affected plugins are handled in Zotero, either by restoring the previous behavior or by providing a replacement, and need no changes in plugins: the removal of <search-textbox> and of wantdropmarker support on <toolbarbutton>, restrictions on loading chrome: DTDs, and new restrictions on eval() in the parent process.
One of these is temporary. Firefox now applies a baseline script-src chrome: resource: moz-src: CSP to every chrome: document (bug 2038660), which blocks inline <script>s and inline event handlers. Zotero currently disables it with security.chrome_baseline_csp.enabled, but we intend to move our own inline scripts and event handlers into separate files and drop the pref, so plugins should do the same.