The action column's width was given as "32px", which VirtualizedTable
now turns into an invalid CSS width, collapsing the column and hiding
the buttons needed to resolve unmapped and ambiguous citations. Also
restore the accept-match icon on ambiguous-citation candidates.
https://forums.zotero.org/discussion/133740/
A condition that matched a child item in the trash rolled up to its
parent when the search had a top-level (or other ancestor) result level,
or when "Include parent and child items of matching items" was checked.
https://forums.zotero.org/discussion/133836/
A standalone PDF recognized by ISBN wasn't moved under the new parent
item, because the move was attempted before the item had been saved
and had an ID.
https://forums.zotero.org/discussion/133957/
A userdata upgrade that took more than 5 minutes (e.g., dropping a large
legacy word index) was rolled back by Sqlite.sys.mjs, while its remaining
statements autocommitted and marked the database as upgraded, leaving
steps 126 and 127 missing.
Disable the transaction timeout and replace steps 122-129 (added in
Zotero 7, 9, and 10) with step 130, which checks for each change before
making it. To speed up the upgrade, drop the legacy word index without
overwriting the freed pages, since the full text already exists on disk
and we're just rewriting it in fulltext.sqlite.
https://forums.zotero.org/discussion/133859/zotero-connector-in-chrome-not-workinghttps://forums.zotero.org/discussion/133965/citation-saving-does-not-work-with-zotero-connector-firefox
Firefox has AppKit draw the menulist's capsule and chevron, but it sizes
the box and positions the label itself, using a fixed dropdown border
and the label's CSS margins. On macOS 27 (and probably 26), that left the
label closer to the edges and the chevron than in a native NSPopUpButton.
It also made the box 26.5px tall. Firefox assumes regular pop-up buttons
are 22px tall and only draws them unscaled in boxes up to 2px taller, so
it drew the control at 22px and scaled the image up, enlarging the
capsule and chevron.
Add padding to match native label insets, and trim the label's vertical
margins to keep the box at 24px, so Firefox draws the control unscaled.
The result measures the same as a native NSPopUpButton.
Build the launcher with the macOS 26.5 SDK. AppKit chooses control metrics
based on the main executable's SDK, so with the old 15.5 launcher, native
buttons and menulists used pre-Tahoe metrics with built-in margins while
Mozilla's XUL (built with 26.5) stopped compensating for them on macOS 26+
(bug 1992898), leaving labels cramped and controls indented.
Also add custom libmozglue.dylib (#6056) and set source info in mozconfig,
which official builds require and which Mozilla only detects automatically
from Mercurial checkouts.
Mozilla's helper apps (GPU, content, etc.) use the hardened runtime and
Mozilla's Team ID, so in unsigned builds they couldn't load our custom
libmozglue.dylib and failed to launch. Re-sign them ad hoc.
Firefox stopped inflating native controls on Tahoe (bug 1992898), but
still uses the old widget border sizes, so labels nearly touch the edges
of the new capsule-shaped buttons and run into menulist arrows.
curl is already required, so drop wget as a build requirement.
build_autoupdate.sh now checks the HTTP status code for its ETag cache
instead of relying on wget not creating the file on a 304.
If NOTARIZATION_PROFILE is set, notarize_mac_app and notarization_info
authenticate with that stored notarytool profile (e.g., an App Store
Connect API key) instead of an Apple ID and app-specific password,
unlocking the keychain first if needed.
153.3.0esr updated the Chromium sandbox, changing the TargetConfig
interface that xul.dll calls into the launcher's sandbox broker
through. The stubs were still built from 153.0esr, so the 153.3.0esr
xul.dll called the wrong methods and crashed on startup with
"config->SetProcessMitigations(initialMitigations) failed".
The release script never set SAFARI_APP_EXTENSION, so 10.0 through
10.0.3 shipped with only the web extension, which doesn't run on Big Sur
or Monterey. Only beta builds have been including both.
https://forums.zotero.org/discussion/133871/
This showed up as devtools failing to start in a -d build on some machines, but any Subprocess.call() could fail because of it.
---------
Co-authored-by: Dan Stillman <dstillman@zotero.org>
The login manager can fail to store a value even when the OS keystore
works -- e.g., if key4.db is read-only, which Firefox 153 triggers
because NSS now creates a new AES key on the first write. Show the
existing corrupted-logins instructions instead of the keystore alert or
the unencrypted-storage offer, neither of which can help.
Also update the corrupted-logins dialog to add an "Open Profile
Directory" button
Allowing only 'copy' for file attachment drags kept File Explorer from
moving files out of 'storage' but locked the cursor at '+' even for
moves within Zotero. Instead, provide the file via a flavor data
provider that copies it to the temp directory when a target asks for it,
so the drag can allow 'copyMove' again and Explorer's move only touches
the copy. A copy's directory is removed once Explorer has moved the file
out of it, at the next drag, or with the temp directory at shutdown.
Since 56eb77b704, drags of file attachments allow only 'copy' so that
File Explorer doesn't move the file out of storage, but the trees set
dropEffect to 'move' in onDragOver() for drops within Zotero, and OLE
refuses a drop whose dropEffect isn't among the drag's allowed effects.
Have setDropEffect() fall back to an allowed effect and have onDrop()
act on the effect the tree chose, kept in
Zotero.DragDrop.currentDropEffect, rather than on the drop event's
dropEffect.
https://forums.zotero.org/discussion/133765/
The drop indicator span was inserted before the cells, so the first
cell stopped matching :first-child and picked up inline-start padding.
Insert it after the cells instead.
Regression from 5ca1fbb167, which replaced the .first-column class with
:first-child.
fd812070b6 made _parseURI() decode the URL credentials so that
download() could build its own Basic Auth header from the decoded
values, but request() passed the decoded credentials to xmlhttp.open(),
which percent-decodes them again, so a password like "example%41pass"
was sent as "exampleApass". Re-encode the credentials before passing
them to open().
Fixes#6048
Gecko 140.15 made nsIExternalProtocolService.loadURI()'s triggering
principal mandatory, so Zotero.launchURL() threw NS_ERROR_ILLEGAL_VALUE
for any scheme handled by an external app.
https://forums.zotero.org/discussion/133709/
relinkAttachment() calls getClosestDirectory() before showing the file
picker, and a too-long filename caused the OS.File.stat() in
getClosestDirectory() to throw, which prevented the file picker from
appearing after clicking Locate.
https://forums.zotero.org/discussion/133685/
Firefox ESR 140.15 rejects loads from a content process for URLs that
process couldn't load on its own, including blob: URLs created by chrome
code. Full-text indexing loads HTML attachments through such a URL, so
indexing crashed Zotero with "Illegal load attempt of blob: URL from
web". Loads started by the parent are exempt, so start the load there
and use the child actor only to disable content retargeting.
https://forums.zotero.org/discussion/133661/
SpiderMonkey stacks contain only frames, so the startup error messages
that showed just the stack didn't say what had failed. 9b3d7a32e3 added
the message to one of the three, where a ternary-precedence bug then
dropped the surrounding text instead. Format all three the same way.
We only ever checked for corruption errors from transactions in
queryAsync(), so a corruption error raised by the COMMIT that mozStorage
runs itself bypassed the check. A 10.0 schema upgrade -- which heavily
exercises the database -- that failed due to corruption showed "Database
upgrade error" and a single Sqlite.sys.mjs frame instead of the prompt
offering to restore from a backup.
Two users reported this, but it's not clear what triggered it --
corruption usually occurs during a statement, which we did catch. There
may have been some statement transaction whose corruption error was
caught and ignored rather than being left to abort the transaction,
causing SQLite to then block the commit. That's what the test does, and
it fails without the fix.
https://forums.zotero.org/discussion/133611/
If the keystore's secret is replaced -- say, after a keyring reset --
the stored value won't be able to be decrypted again, so tell them to
try logging in again instead of trying to fix their keyring.
https://forums.zotero.org/discussion/133603/
unload() closes and re-adds the tab, and the close recorded an undo-close
history entry, so Undo Close Tab could open a duplicate of a tab that was
still open.
_addEntry() wrote the row with REPLACE INTO, listing only itemID and
data, so flag reverted to its default of 0. It's called for every match
on every update, not just new ones, so a retraction the user had hidden
came back as soon as the list changed and Zotero restarted.
A window is marked as closed before its unload handlers run, so the tab
events fired from ZoteroPane.destroy() warned about every observer that
the closing window hadn't torn down yet. The leak check now also requires
the window to be detached from its docShell, and it covers functions. It
caught an observer that outlived its window -- the sync-reminder API key
observer, which is now unregistered on teardown.
Listeners added to the item and collection trees' event bindings
survived unregister() and held ZoteroPane and the views for as long
as the tree objects did. makeClassEventDispatcher() now provides
clearEventListeners(), which the trees call on unregister, so callers
don't need to remove their own listeners. The collection tree focus
listener, a plain DOM listener, is removed in destroy().
Hiding the tag selector destroyed the TagSelectorContainer but left
its media-query listener registered, keeping the destroyed instance
alive for the lifetime of the window and firing setState() on the
unmounted component when the display density changed. The fontSize
pref observer id was also overwritten by the uiDensity registration,
so it was never unregistered.
Selecting a collection doesn't wait for the tag selector to re-render,
so waitForTagSelector() could be resolved by the initial render instead
of the awaited change, and the assertions could run against a stale tag
list.
The cached retractions list is saved with the current data version from
the code, which we can bump to make clients discard their cached data
and refetch it. We've never actually done that, but if we did, it
would've hit a bug: init() would've started the refetch but still sent
the cached ETag, so if the list itself hadn't changed, the server
would've returned 304 and nothing would have been updated. The stale
version then would have survived, so the refetch would have been retried
on every startup.
Retraction Watch has renamed, merged, and added reason terms since these
were added, leaving only 65 of the 102 entries matching a term still in
use. 90% of retracted items had at least one reason that didn't show a
description, and 21% showed none at all. Rebuilt from the current
Appendix B list, which covers every reason in the data.