@doenet/doenetml-iframe 0.7.24-dev.496 → 0.7.24-dev.498

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +44 -4
  2. package/index.js +1 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -395,6 +395,33 @@ booted yet) — equally safe to unmount.
395
395
  > safe. Every viewer on the page receives a broadcast request and responds
396
396
  > (correlate by `activity_id`/`doc_id`/`message_id`).
397
397
 
398
+ #### The page going away flushes on its own
399
+
400
+ A host need not send `flushState` for an ordinary departure. The viewer
401
+ flushes whatever the throttle is holding back when the page hides — on
402
+ `pagehide` and on a `visibilitychange` to `hidden` — so closing the tab,
403
+ typing a new URL, following an external link, or backgrounding a tab on a
404
+ phone no longer strands up to a minute of work. The flushed work arrives on
405
+ your window as an ordinary `SPLICE.reportScoreAndState` message, so a host
406
+ that already persists those saves it with no extra code. Nothing is torn
407
+ down on the way, so a page that comes back — a re-foregrounded tab, a
408
+ back/forward-cache restore — carries on with its state already saved.
409
+
410
+ > **Important:** for this to survive a real unload, your listener has to
411
+ > persist **synchronously**. The report is handed over by dispatching the
412
+ > message event directly rather than posting it, because a document being
413
+ > unloaded is destroyed before a posted message is ever delivered — but a
414
+ > listener that defers its own write (a `fetch`, a `setTimeout`, an `await`)
415
+ > is destroyed just the same. Write from the listener itself, with
416
+ > `navigator.sendBeacon` or a synchronous store such as `localStorage`.
417
+ >
418
+ > The `reportScoreAndStateCallback` prop does not get this guarantee here:
419
+ > the viewer runs inside the iframe, so calling your callback crosses the
420
+ > frame boundary as a posted message, which an unloading page will not
421
+ > deliver. Listen for `SPLICE.reportScoreAndState` on your window if
422
+ > surviving an unload matters. (Everything else — routine reports, and
423
+ > flushes you requested yourself — reaches the callback as before.)
424
+
398
425
  ### Loading saved state at boot (`SPLICE.getState`)
399
426
 
400
427
  With `flags: { allowLoadState: true }` and no `initialState` prop, the
@@ -420,14 +447,27 @@ respond:
420
447
  { subject: "SPLICE.getState.response", message_id, state }
421
448
  ```
422
449
 
450
+ Quote the `message_id`: a response carrying state is only read by the viewer
451
+ whose request it names. Replies reach every viewer in the window, and `cid`
452
+ cannot tell two of them apart — it hashes the DoenetML text alone, so a
453
+ second attempt at the same document, or that document opened twice on a
454
+ page, carries the identical `cid`. An unaddressed answer would be restored
455
+ by all of them.
456
+
423
457
  If there is no saved state, no response is needed. To surface a load
424
458
  failure to the student instead, respond with
425
- `{ subject: "SPLICE.getState.response", error: { code, message } }`
426
- (and no `message_id`).
459
+ `{ subject: "SPLICE.getState.response", error: { code, message } }`,
460
+ either quoting the request's `message_id` or leaving it out — an error is
461
+ the one reply the viewer will take unaddressed, since the worst it costs is
462
+ a message the next usable answer clears. Prefer quoting it even so: an
463
+ unaddressed error is taken by whichever request is open when it lands, on
464
+ every viewer on the page, including one a rebuild opened after the error was
465
+ sent. A reply quoting a *different* id is ignored, since that id belongs to
466
+ some other request.
427
467
 
428
468
  A request has a single answer: the **first** response carrying state for
429
- this `cid` is the one the viewer reboots from, and later responses to the
430
- same `message_id` are ignored. A response with no state — or state for a
469
+ this `cid` is the one the viewer reboots from, and every response after
470
+ that errors included — is ignored. A response with no state — or state for a
431
471
  different `cid` — does not count as that answer, so a listener with nothing
432
472
  saved cannot shut out one still in flight. Answer once, out of durable
433
473
  storage: a host that replies from an in-memory cache first and from storage
package/index.js CHANGED
@@ -68534,7 +68534,7 @@ function ExternalVirtualKeyboard({
68534
68534
  }
68535
68535
  );
68536
68536
  }
68537
- const version = "0.7.24-dev.496";
68537
+ const version = "0.7.24-dev.498";
68538
68538
  const latestDoenetmlVersion = version;
68539
68539
  function subscribeToPinnedTheme() {
68540
68540
  return () => {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@doenet/doenetml-iframe",
3
3
  "type": "module",
4
4
  "description": "A renderer for DoenetML contained in an iframe",
5
- "version": "0.7.24-dev.496",
5
+ "version": "0.7.24-dev.498",
6
6
  "license": "AGPL-3.0-or-later",
7
7
  "homepage": "https://github.com/Doenet/DoenetML#readme",
8
8
  "repository": {