Windowed mounting by default: memory tracks the visible window, not assignment length - #44
Merged
Merged
Conversation
23 tasks
dqnykamp
force-pushed
the
windowed-mounting
branch
from
July 13, 2026 03:55
284bae9 to
0ac2752
Compare
…ssignment length Implements Doenet#35, Doenet#36, and Doenet#37. Every item's viewer component stays mounted, but which items are BOOTED is now governed by @doenet/doenetml-iframe's windowed mounting policy: an item only creates its iframe (a multi-MB standalone-bundle parse plus a core worker) when near the viewport or within the pagination window, simultaneous boots are capped page-wide, and at most `maxLiveViewers` stay live — the rest are parked losslessly (state flushed before the iframe is detached; restored, typed work intact, on return). In paginated mode the current page and its neighbors are marked `keepLive`, so page flips within the window stay instant while hidden pages beyond it never boot at all (Doenet#35). A 20-question assignment paged all the way through now holds ~3 live viewers instead of 20 (Doenet#36); scroll-mode memory tracks the viewport (Doenet#37). The viewer's own render-scheduling machinery (itemsToRender / itemsVisible / checkRender / a per-item IntersectionObserver) is deleted in favor of the wrapper's policy, which also brings the boot-concurrency cap. Parking requires flags.allowSaveState or allowLocalState (no persistence path ⇒ viewers still mount lazily but stay live once booted, so no work can be lost). New ActivityViewer props: `mountPolicy` (overrides for maxLiveViewers / visibleMargin / parkDelayMs / flushTimeoutMs / maxConcurrentBoots), `useSharedCoreWorker` (serve cores from a shared worker pool instead of one dedicated ~100 MB worker per document), and working `standaloneUrl` / `cssUrl` / `doenetmlVersion` passthroughs — `doenetViewerUrl` was silently ignored by the iframe wrapper and is kept as a deprecated alias for `standaloneUrl`. Requires @doenet/doenetml-iframe ≥ 0.7.20-dev.329 (windowed mounting with keepLive and report-callback host support). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The committed package-lock.json recorded the root package's @doenet/doenetml-iframe peerDependency as `file:../DoenetML3/packages/doenetml-iframe` — a leftover from local development against a sibling checkout. package.json declares it as `^0.7.20-dev.329` (and the dependency actually resolves to the published 0.7.20-dev.329 from the registry), so regenerate the lockfile's mirror to match. No dependency graph change; only the recorded range is corrected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dqnykamp
force-pushed
the
windowed-mounting
branch
from
July 13, 2026 04:24
0ac2752 to
70620f8
Compare
`doenetViewerUrl` (the `<ref>` renderer's activity-link base) and `doenetMediaUrl` (the `<image source="doenet:…">` media base, Doenet/DoenetML#1457) are props of the inner DoenetViewer, forwarded across the iframe boundary — not aliases for the standalone-bundle `standaloneUrl`. Thread both through ActivityViewer -> Viewer -> Activity -> SingleDocActivity to each embedded DoenetViewer, replacing the incorrect `standaloneUrl ?? doenetViewerUrl` alias so `<ref>` links and `doenet:` images resolve. Add a cypress spec asserting both URLs are baked into the booted viewer's iframe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump from dev.329 to the current `dev` dist-tag. The iframe's public type surface is unchanged between the two, and lint/build/vitest plus the full cypress component suite (windowed, park/restore, viewer-URL forwarding) pass against the new bundle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`cypress/screenshots/` (and `cypress/videos/`) are generated by cypress runs and should not be tracked. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #35, fixes #36, and fixes #37. Requires
@doenet/doenetml-iframe ≥ 0.7.20-dev.332(windowed mounting withkeepLiveand report-callback host support, Doenet/DoenetML#1479).Every item's viewer component stays mounted, but which items are booted is now governed by the iframe wrapper's windowed mounting policy:
maxLiveViewers(default 3) stay live; the rest are parked losslessly — their state is flushed before the iframe is detached, and they are restored (typed work intact, no interaction) when the student returns. A 20-question assignment paged all the way through holds ~3 live viewers instead of 20 (Paginated mode: bound mounted viewers to a window (current ± 1) and unmount items outside it #36); scroll-mode memory tracks the viewport (Scroll mode: shrink the 1000px IntersectionObserver rootMargin and unmount items that leave the viewport #37).keepLive, so page flips within the window stay instant while hidden pages beyond it never boot.The viewer's own render-scheduling machinery (
itemsToRender/itemsVisible/checkRender/per-itemIntersectionObserver) is deleted in favor of the wrapper's policy. Parking requiresflags.allowSaveStateorallowLocalState; without a persistence path viewers still mount lazily but stay live once booted, so no work can be lost.New
ActivityViewerprops:mountPolicy— overrides formaxLiveViewers/visibleMargin/parkDelayMs/flushTimeoutMs/maxConcurrentBoots;useSharedCoreWorker— serve all documents' cores from a shared worker pool instead of one dedicated ~100 MB worker per document (default off);standaloneUrl/cssUrl/doenetmlVersionpassthroughs — the standalone-bundle URL, its CSS, and a version override for every document's viewer;doenetViewerUrlanddoenetMediaUrlare threaded throughViewer→Activity→SingleDocActivityto each embeddedDoenetViewer. Both are inner-viewer props (forwarded across the iframe boundary), not bundle URLs:doenetViewerUrlis the<ref>renderer's activity-link base (it was not being forwarded correctly), anddoenetMediaUrlis the<image source="doenet:…">media base ([Feature]: ExposedoenetMediaUrlinassignment-viewerpackage DoenetML#1457), newly exposed sodoenet:images resolve.Tests
New cypress spec (against the real published dev-channel bundle) covering both modes end to end:
A separate spec asserts that
doenetViewerUrlanddoenetMediaUrlreach the embedded viewer — both are baked into the bootedDoenetViewer's iframesrcdoc, confirming they thread all the way through.The park/restore round trip also exercises DoenetML#1479's report-callback capture path in a real host. Full suite green (47 vitest + 14 cypress), lint/build clean.
🤖 Generated with Claude Code