@hyperframes/sdk 0.8.196 → 0.8.198

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 (2) hide show
  1. package/dist/session.js +31 -2
  2. package/package.json +3 -3
package/dist/session.js CHANGED
@@ -28,8 +28,18 @@ import { createPersistQueue } from "./persist-queue.js";
28
28
  function escapeRegExp(s) {
29
29
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
30
30
  }
31
+ function isProduction() {
32
+ try {
33
+ return process.env.NODE_ENV === "production";
34
+ }
35
+ catch {
36
+ return false; // no process in a browser without a bundler define
37
+ }
38
+ }
31
39
  class CompositionImpl {
32
- parsed;
40
+ parsedDoc;
41
+ disposed = false;
42
+ warnedDisposedRead = false;
33
43
  persist;
34
44
  preview;
35
45
  /** Accumulated override-set — T3 embedded mode fold contract. */
@@ -63,7 +73,7 @@ class CompositionImpl {
63
73
  /** Override-set state at outermost batch entry — restored if the batch throws. */
64
74
  batchOverridesSnapshot = {};
65
75
  constructor(parsed, opts, baseVariableDefaults = {}) {
66
- this.parsed = parsed;
76
+ this.parsedDoc = parsed;
67
77
  this.persist = opts.persist;
68
78
  this.preview = opts.preview;
69
79
  this.overrides = { ...(opts.overrides ?? {}) };
@@ -692,6 +702,18 @@ class CompositionImpl {
692
702
  this.changeHandlers.forEach((h) => h());
693
703
  }
694
704
  // ── Lifecycle ────────────────────────────────────────────────────────────────
705
+ /** The single read path; a read after dispose means a stale reference is still in use. */
706
+ get parsed() {
707
+ if (this.disposed)
708
+ this.warnDisposedRead();
709
+ return this.parsedDoc;
710
+ }
711
+ warnDisposedRead() {
712
+ if (this.warnedDisposedRead || isProduction())
713
+ return;
714
+ this.warnedDisposedRead = true;
715
+ console.warn(`[hyperframes] a disposed Composition was read and answered from an empty document; something still holds the stale session.\n${new Error().stack}`);
716
+ }
695
717
  async flush() {
696
718
  await this.persistQueueModule?.flush();
697
719
  }
@@ -707,6 +729,13 @@ class CompositionImpl {
707
729
  this.selectionHandlers = [];
708
730
  this.patchHandlers = [];
709
731
  this.errorHandlers = [];
732
+ // A disposed session is still referenced by stale closures; without this each
733
+ // one keeps its whole parsed document alive.
734
+ this.elementsCache = null;
735
+ this.rootsCache = null;
736
+ if (!this.disposed)
737
+ this.parsedDoc = parseMutable("");
738
+ this.disposed = true;
710
739
  }
711
740
  }
712
741
  /** Declared defaults across the composition's carriers, the root winning a shared id as in the runtime. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/sdk",
3
- "version": "0.8.196",
3
+ "version": "0.8.198",
4
4
  "description": "Headless, framework-neutral HyperFrames composition editing engine",
5
5
  "repository": {
6
6
  "type": "git",
@@ -44,8 +44,8 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "linkedom": "^0.18.12",
47
- "@hyperframes/core": "0.8.196",
48
- "@hyperframes/parsers": "0.8.196"
47
+ "@hyperframes/core": "0.8.198",
48
+ "@hyperframes/parsers": "0.8.198"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/node": "^25.0.10",