Skip to content

Fix initializedPromise never resolve in Zotero Reader - #171

Open
duanxianpi wants to merge 1 commit into
zotero:masterfrom
duanxianpi:hotfix-reader-init-promis
Open

Fix initializedPromise never resolve in Zotero Reader#171
duanxianpi wants to merge 1 commit into
zotero:masterfrom
duanxianpi:hotfix-reader-init-promis

Conversation

@duanxianpi

Copy link
Copy Markdown

Hello,

While working on a tool with the Zotero Reader, I noticed that the initializedPromise was never resolving. This caused any await calls on it to hang indefinitely.

To address this, I added a call to _resolveInitializedPromise after the primary view is initialized. I believe this is an appropriate place for it, but please let me know if there’s a better location or if you have any questions or concerns.

Thanks!

@duanxianpi duanxianpi changed the title Fix initializedPromise never resolving in Zotero Reader Fix initializedPromise never resolve in Zotero Reader Jul 17, 2025
jamesbraza added a commit to jamesbraza/zotero-context that referenced this pull request Jul 24, 2026
Grab mode's sentence snap booted slowly because whole-document Read Aloud
segmentation only started at activation. Now (pref `warmOnOpen`, default on)
each reader warms in the background at open: await `reader._initPromise` then
the primary view's `initializedPromise` (the chain Zotero core itself relies
on; after it the page count is guaranteed known, so no polling or retries),
then fill the shared segment cache and precompute snap targets for the
visible page ±1. Activation coalesces onto the same cached fetch.

NEVER await `_internalReader.initializedPromise`: it is created but never
resolved (zotero/reader#171) — see zotero-reader-initializedpromise-report.md.

Also: per-page segment index replaces the O(all-segments) scan on every page
hover, and `Intl.Segmenter` is now a lazy singleton instead of being rebuilt
per paragraph.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jamesbraza added a commit to jamesbraza/zotero-context that referenced this pull request Jul 24, 2026
Grab mode's sentence snap booted slowly because whole-document Read Aloud
segmentation only started at activation. Now (pref `warmOnOpen`, default on)
each reader warms in the background at open: await `reader._initPromise` then
the primary view's `initializedPromise` (the chain Zotero core itself relies
on; after it the page count is guaranteed known, so no polling or retries),
then fill the shared segment cache and precompute snap targets for the
visible page ±1. Activation coalesces onto the same cached fetch.

NEVER await `_internalReader.initializedPromise`: it is created but never
resolved (zotero/reader#171) — see zotero-reader-initializedpromise-report.md.

Also: per-page segment index replaces the O(all-segments) scan on every page
hover, and `Intl.Segmenter` is now a lazy singleton instead of being rebuilt
per paragraph.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jamesbraza added a commit to jamesbraza/zotero-context that referenced this pull request Jul 24, 2026
Grab mode's sentence snap booted slowly because whole-document Read Aloud
segmentation only started at activation. Now (pref `warmOnOpen`, default on)
each reader warms in the background at open: await `reader._initPromise` then
the primary view's `initializedPromise` (the chain Zotero core itself relies
on; after it the page count is guaranteed known, so no polling or retries),
then fill the shared segment cache and precompute snap targets for the
visible page ±1. Activation coalesces onto the same cached fetch.

NEVER await `_internalReader.initializedPromise`: it is created but never
resolved (zotero/reader#171) — see zotero-reader-initializedpromise-report.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jamesbraza added a commit to jamesbraza/zotero-context that referenced this pull request Jul 24, 2026
* Grab-mode perf: shared Intl.Segmenter, per-page segment index

Hover-time costs shrink: computing a page's sentence targets no longer
scans ALL document segments (a per-page index, built once per segments
array, replaces the O(total-segments) filter on every hovered page), and
Intl.Segmenter is a lazy module singleton instead of being rebuilt for
every paragraph segment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Sentence snap warm-up: promise-driven segment prefetch at reader open

Grab mode's sentence snap booted slowly because whole-document Read Aloud
segmentation only started at activation. Now (pref `warmOnOpen`, default on)
each reader warms in the background at open: await `reader._initPromise` then
the primary view's `initializedPromise` (the chain Zotero core itself relies
on; after it the page count is guaranteed known, so no polling or retries),
then fill the shared segment cache and precompute snap targets for the
visible page ±1. Activation coalesces onto the same cached fetch.

NEVER await `_internalReader.initializedPromise`: it is created but never
resolved (zotero/reader#171) — see zotero-reader-initializedpromise-report.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* MCP perf: lazy-load the SDK handler bundle

zod + the MCP SDK were ~72% of the plugin bundle, parsed at every Zotero
startup even with MCP disabled (the default). The SDK-bearing request core
(handleRequest, dispatch, single-exchange transport, tools) now lives in a
second esbuild entry (src/mcp-handler.ts) that the eager control layer
loadSubScripts on first server start, publishing `addon.data.mcpHandler`
into the plugin sandbox. Eager bundle: 1.6 MB → 91 KB.

The load scope borrows web globals (console, AbortController, ...) from the
app-lifetime hidden window: Zotero's plugin sandbox realm lacks them and the
SDK needs them (its embedded Ajv reads `console` at construction). Session
state (trail, paper infos) is injected into the tool server
(`createMcpServer(deps)`): the lazy bundle carries its own copies of every
module it imports, so a static grab-session import would have served a
second, always-empty trail.

Also: NetUtil resolves once instead of per request in the HTTP adapter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Build: minify release bundles

NODE_ENV=production builds minify both esbuild entries (~3-4x fewer bytes
for end users to parse); dev builds stay readable for debugging.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant