circuitjson-toolkit 1.4.1 → 1.4.2

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.
package/README.md CHANGED
@@ -83,6 +83,12 @@ dynamic data/control dependencies, changed-root reader lists, stale-trace
83
83
  replacement, explicit reclamation, and from-scratch consistency coverage. See
84
84
  the [1.4.1 release notes](docs/release-notes-v1.4.1.md).
85
85
 
86
+ Version 1.4.2 accelerates immutable document rebuilding and cooperative
87
+ structured-clone adoption. Toolkit-owned frozen extension roots retain their
88
+ identity, and cooperative finalization freezes each validated container
89
+ atomically instead of redefining every property. See the
90
+ [1.4.2 release notes](docs/release-notes-v1.4.2.md).
91
+
86
92
  Before 1.1.0:
87
93
 
88
94
  ```js
@@ -393,6 +399,7 @@ copy while keeping sync, direct async, and worker results mutation-isolated.
393
399
  - [1.3.0 release notes](docs/release-notes-v1.3.0.md)
394
400
  - [1.4.0 release notes](docs/release-notes-v1.4.0.md)
395
401
  - [1.4.1 release notes](docs/release-notes-v1.4.1.md)
402
+ - [1.4.2 release notes](docs/release-notes-v1.4.2.md)
396
403
  - [Library scope](spec/library-scope.md)
397
404
 
398
405
  ## Package scope
@@ -0,0 +1,32 @@
1
+ # circuitjson-toolkit 1.4.2
2
+
3
+ This patch release removes repeated immutable-graph work from toolkit-owned
4
+ document rebuilds and from cooperative structured-clone adoption. Public
5
+ document shapes, validation rules, cancellation behavior, and extension
6
+ selection semantics remain unchanged.
7
+
8
+ ## Owned extension root reuse
9
+
10
+ - `DocumentResult.createValidated()` retains an extension namespace that was
11
+ already captured, bounded, sealed, and branded by the same toolkit runtime.
12
+ - Rebuilding a canonical document no longer traverses or copies a large frozen
13
+ native extension graph when only other document fields changed.
14
+ - Arbitrary caller objects still use the defensive validation and ownership
15
+ path; frozen state alone never grants trusted ownership.
16
+
17
+ ## Atomic cooperative finalization
18
+
19
+ - Cooperative structured-clone adoption validates a container's descriptors
20
+ before freezing the container in one atomic operation.
21
+ - A yield can no longer expose a container with only some properties locked.
22
+ - Large graphs avoid one `defineProperty()` call per ordinary property while
23
+ retaining the same deeply immutable result and cancellation checkpoints.
24
+
25
+ ## Verification
26
+
27
+ - Ownership tests cover identity reuse for toolkit-built frozen namespaces and
28
+ defensive behavior for untrusted objects.
29
+ - Cooperative snapshot tests prove that no partial property locking is visible
30
+ across yields.
31
+ - The complete package suite, formatting check, packed-entrypoint checks, and
32
+ npm dry-run gate the release.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "circuitjson-toolkit",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "Canonical CircuitJSON parsing, project, rendering, query, manufacturing, simulation, and scene contracts",
5
5
  "keywords": [
6
6
  "circuitjson",
@@ -58,6 +58,7 @@
58
58
  "docs/release-notes-v1.3.0.md",
59
59
  "docs/release-notes-v1.4.0.md",
60
60
  "docs/release-notes-v1.4.1.md",
61
+ "docs/release-notes-v1.4.2.md",
61
62
  "docs/testing.md",
62
63
  "spec",
63
64
  "LICENSE",
@@ -506,10 +506,9 @@ class StructuredCloneAdoptionTraversal {
506
506
  }
507
507
 
508
508
  /**
509
- * Locks one target property-by-property so large dense containers never
510
- * require one monolithic Object.freeze operation.
509
+ * Validates and atomically freezes one acquired target.
511
510
  * @param {object} seal Target sealing snapshot.
512
- * @returns {Generator<void, void, void>} Bounded-work locking pass.
511
+ * @returns {Generator<void, void, void>} Cooperative locking pass.
513
512
  */
514
513
  *#sealTargetCooperatively(seal) {
515
514
  StructuredCloneAdoptionTraversal.#requireTargetShape(seal)
@@ -530,31 +529,16 @@ class StructuredCloneAdoptionTraversal {
530
529
  'Canonical asset source changed during adoption.'
531
530
  )
532
531
  }
533
- if (!property.binary) {
534
- try {
535
- Object.defineProperty(seal.target, property.key, {
536
- ...descriptor,
537
- configurable: false,
538
- writable: false
539
- })
540
- } catch {
541
- throw new TypeError(
542
- 'Canonical document values could not be frozen safely.'
543
- )
544
- }
545
- }
546
- yield* this.#checkpoint()
547
532
  }
548
533
  StructuredCloneAdoptionTraversal.#requireTargetShape(seal)
549
- if (!seal.shapeLocked) {
550
- try {
551
- Object.preventExtensions(seal.target)
552
- } catch {
553
- throw new TypeError(
554
- 'Canonical document values could not be frozen safely.'
555
- )
556
- }
534
+ try {
535
+ Object.freeze(seal.target)
536
+ } catch {
537
+ throw new TypeError(
538
+ 'Canonical document values could not be frozen safely.'
539
+ )
557
540
  }
541
+ yield* this.#checkpoint(seal.properties.length || 1)
558
542
  }
559
543
 
560
544
  /**
@@ -1,4 +1,5 @@
1
1
  import { CircuitJsonValidationProof } from '../context/CircuitJsonValidationProof.mjs'
2
+ import { CircuitJsonExtensionBoundary } from '../context/CircuitJsonExtensionBoundary.mjs'
2
3
  import { CircuitJsonReadOnlyDocument } from '../context/CircuitJsonReadOnlyDocument.mjs'
3
4
  import { CircuitJsonSerializedInputAudit } from '../CircuitJsonSerializedInputAudit.mjs'
4
5
  import { ToolkitAsset } from './ToolkitAsset.mjs'
@@ -147,6 +148,14 @@ export class DocumentResult {
147
148
  const hasCandidate = candidate && typeof candidate === 'object'
148
149
  if (!hasCandidate) return {}
149
150
  if (options.readonly === true && hasCandidate) {
151
+ // This private brand proves the frozen namespace was already
152
+ // captured, bounded, and sealed by this runtime.
153
+ if (
154
+ CircuitJsonExtensionBoundary.owns(extensions) &&
155
+ Object.isFrozen(extensions)
156
+ ) {
157
+ return extensions
158
+ }
150
159
  if (options.standardBuiltins === true) {
151
160
  return CircuitJsonReadOnlyDocument.copyReadonlyExtensionValue(
152
161
  DocumentResult.#normalizedExtension(format, candidate),