Releases: SunboX/circuitjson-toolkit
Release list
CircuitJSON Toolkit 1.4.2
CircuitJSON Toolkit 1.4.2 removes repeated immutable-graph work from
toolkit-owned document rebuilds and cooperative structured-clone adoption.
Changes:
- Reuse already branded, frozen extension roots when rebuilding validated
documents. - Validate each acquired clone container and freeze it atomically rather than
redefining every property. - Preserve defensive handling for arbitrary caller data and cancellation
checkpoints for cooperative work. - Add packaged release notes and ownership/atomicity regression coverage.
Verification:
- Complete multi-phase test suite: 12 + 520 + 18 + 1 + 11 + 5 + 10 tests,
zero failures. npm run check:formatnpm run check:features(1,207 mappings)npm publish --dry-run(circuitjson-toolkit-1.4.2.tgz, 194 entries,
424,001 bytes packed)
circuitjson-toolkit 1.4.1
circuitjson-toolkit 1.4.1
This patch release adds a shared self-adjusting-computation runtime for
persistent toolkit and application state. It implements dynamic dependency
tracing and ordered change propagation without coupling the common package to
DOM, Three.js, or source-format parser state.
Self-adjusting computation
SelfAdjustingComputationis available from the package root and is shared
by identity through the Gerber, Altium, KiCad, and PCB Scene3D packages.- Named synchronous computations record the data and control-flow paths they
observe. Explicit changed roots start propagation from reverse reader lists. - Potentially affected computations compare their previous observations and
reuse successful results when values, presence, key structure, and selected
atomic identities remain unchanged. - Re-execution replaces the previous trace and its abandoned reader edges.
forget()andclear()reclaim trace storage explicitly. - Tracked snapshots reject mutation and asynchronous trace escape. Callers can
choose an atomic boundary for immutable documents and native objects.
Verification
The unit suite covers nested and structural reads, control-flow replacement,
stale reader removal, atomic document identity, failed and asynchronous
computations, write rejection, explicit trace reclamation, and equality with a
fresh runtime after each propagated change.
circuitjson-toolkit 1.4.0
circuitjson-toolkit 1.4.0
This minor release removes redundant ownership work when a source toolkit or
browser worker has already established an exact graph provenance boundary. It
also lets browser hosts return control between validation and extension
sealing without changing the canonical result contract.
Owned document construction
DocumentResult.createValidatedOwned(fields, runtime?)creates the same
validatedecad-toolkit.document.v1envelope ascreateValidated().- A source-toolkit convergence builder may transfer a newly constructed,
standard-built-in graph into the envelope. Ordinary model and extension
nodes retain their identities and are deeply frozen in place instead of
being copied into a second full graph. - The method is intentionally destructive. It is only safe when the toolkit
exclusively owns the complete mutable graph and will not mutate it after the
call. Arbitrary caller values, raw untrusted input, cross-realm objects,
proxies, and altered prototypes must continue throughcreateValidated(). - Binary properties retain their defensive boundary and validation. Ownership
limits, validation proofs, and immutable-envelope guarantees are unchanged.
Cooperative structured-clone preparation
CircuitJsonDocumentContext.prepareStructuredCloneAsync(input, options?)
accepts the same structured-clone input andindexesoption as the
synchronous method, plus the requiredownership: 'exclusive'declaration
and an optionalyieldscheduler.- This is a destructive transfer. Callers must relinquish every alias and
shared-memory writer until settlement. Mutation before a node is acquired is
outside the contract and cannot be detected reliably; rejection can leave a
partially locked graph. - The method validates and deeply freezes the model, then yields between
bounded slices of dense-array traversal, Map/Set normalization, immutable
text accounting, binary copying and installation, and property locking
before sealing the canonical envelope. - Acquired containers are shape-locked and their descriptors are checked while
sealing. Individual plain extension records are capped at 16,384 properties
so one record cannot create an unbounded cooperative inspection step. - Existing immutable contexts are reused without a transfer declaration.
Transferred ordinary records retain identity; dense arrays are normalized
into clean arrays while preserving aliases and cycles, preventing unsupported
hidden properties from leaking mutable state. - An injected
yieldfunction is awaited at each scheduling boundary. Without
one, the toolkit prefersscheduler.yield()and otherwise uses a zero-delay
host task. - The promise resolves to the same immutable
CircuitJsonDocumentContext
shape with the same indexes, caches, limits, and validation authority.
Compatibility
- No parser option, package subpath, class, parameter, or return field is
removed or renamed. DocumentResultremainsecad-toolkit.document.v1; itsmodel,source,
extensions,assets,diagnostics, andstatisticsfields are unchanged.createValidatedOwned()andprepareStructuredCloneAsync()are additive.
The defensive and synchronous APIs retain their previous behavior.
Verification and performance
Synthetic regression coverage verifies ordinary-record identity retention,
alias/cycle-preserving clean arrays, deep freeze, chunked text and binary
processing, dense-array and Map/Set scheduling,
cooperative yield ordering, progressive shape/property locking, the exclusive
ownership contract, and context reuse across document batches. The full
adversarial suite continues to cover hostile accessors, altered and cross-realm
built-ins, defensive binary ownership, worker parity, synchronous mutation
isolation, and bounded extension graphs.
On the same browser and machine, the exact large native-PCB deep link that
previously produced 3.29-second and 2.17-second renderer-main tasks retained
the same 25,729-element PCB SVG and view box after this release. A final fresh
open peaked at 17.7 milliseconds on the renderer main thread. A forced reload
peaked at 404.4 milliseconds, consisting of 196.8 milliseconds of browser
structured-clone deserialization plus 205.3 milliseconds of browser garbage
collection; no application JavaScript task approached the previous stalls.
The largest scheduled parser-worker task in that reload was 5.9 milliseconds.
A separate 150,000-record exclusive-adoption probe yielded 880 times and
completed in 487.35 milliseconds, with a 1.22-millisecond p95 slice and a
6.94-millisecond maximum outlier. A 32 MiB immutable-text probe completed in
8.13 milliseconds across 513 yields; a 32 MiB binary probe completed in 3.40
milliseconds across 514 yields. These figures describe fixed local workloads
and are not runtime guarantees; deterministic shape, validation, and ownership
tests remain the release gates.
circuitjson-toolkit 1.3.0
circuitjson-toolkit 1.3.0
Faster canonical extension ownership
This minor release adds an explicit fast ownership path for large native
extension graphs received through the platform structured-clone algorithm.
Ordinary records, arrays, and standard local data containers are classified
without deliberately invoking incompatible intrinsic getters, while genuine
buffers and views still use captured platform slots as the final authority.
The new CircuitJsonDocumentContext.prepareStructuredClone(document, options?)
method has the same options and return shape as prepare(). It is intended for
the exact result of a completed platform structured clone, or for a graph
created entirely by the toolkit after that boundary. Hosts must continue to use
prepare() for arbitrary caller-owned, cross-realm, proxy-backed, or
prototype-modified input. The optimization is source-format-neutral and
requires no example-specific handling.
Measured on the deterministic standard-built-in metadata workload used during
development, capturing 50,000 populated records fell from about 3.7 seconds to
about 0.16 seconds. Browser timing for the combined library and ECAD Forge
release is documented by the application release because network transfer,
application interaction preparation, and SVG mounting are outside this
library's ownership boundary.
Compatibility and API changes
- No public class, package subpath, parameter, or return field is removed or
renamed. CircuitJsonDocumentContext.prepareStructuredClone(document, options?)is a
new opt-in method for the explicit structured-clone provenance contract.- Parser, project, renderer, worker, and extension result shapes are unchanged.
- The existing
prepare()path remains exact and prototype-independent.
Cross-realm and altered-prototypeArrayBuffer,SharedArrayBuffer, typed
array, andDataViewvalues, resizable buffers, byte ceilings, and
defensive-copy behavior are retained. - Proven standard plain-data graphs no longer generate caught exceptions merely
to prove that each ordinary node is not binary data.
The new regression coverage pauses on every thrown exception in an isolated
runtime, proving that a representative proven-standard metadata graph completes
with zero binary-probe exceptions. Exact-path regressions cover altered and
cross-realm binary objects plus proxy prototype traps. Existing adversarial and
full-suite contracts continue to cover hostile accessors, worker parity,
mutation isolation, and bounded extension ownership.
circuitjson-toolkit 1.2.1
circuitjson-toolkit 1.2.1
Large canonical worker results
This patch release keeps valid high-fidelity documents and multi-document
projects inside explicit, format-neutral worker limits:
- Selected native extensions may contain up to 4,000,000 structured items and
128 MiB of string or binary content. - A canonical standalone document may contain up to 5,000,000 result values
within the existing 250 MB byte ceiling. - An exact canonical project may contain up to 8,000,000 aggregate values and
256 MiB, while every document retains its own 5,000,000-value and 250 MB
limits. - Non-document project metadata retains the generic 2,000,000-value and 250 MB
limits.
Elevated budgets require the complete canonical document or project envelope;
a schema string alone does not change generic result limits. Reused object
graphs are charged independently to document and project-metadata scopes in a
property-order-independent way. Repeated alias-accounting work is also capped
by the project aggregate budget, keeping transport time bounded.
No public class, method, package subpath, parameter, or result field is removed
or renamed. Oversized results continue to fail visibly rather than being
truncated.
circuitjson-toolkit 1.2.0
circuitjson-toolkit 1.2.0
Canonical PCB fidelity
This minor release expands the shared CircuitJSON contract used by the Gerber,
Altium, KiCad, and 3D viewer packages. Existing canonical fields remain
authoritative, while source formats can retain exact rendering information in
validated, source-neutral extension fields.
API additions
pcb_note_text,pcb_fabrication_note_text, andpcb_silkscreen_textmay
retain independentfont_widthandfont_height,stroke_width, the exact
nine-positionsource_anchor_alignment,is_hidden,source_layer,
source_type, andsource_text_kind.- Board-note
ccw_rotationand fabrication-noteis_mirroredare validated
when present, so downstream renderers can consume the original orientation
without source-format adapters. CircuitJsonPcbHolePrimitiveModel.build()now returnscornerRadiusand
computes board-space bounds for rotated rectangles and pills instead of
treating their local width and height as axis-aligned.
Behavior and performance
- Structured metadata snapshots and worker request graphs accept valid nesting
up to 256 levels, matching the deeper native data graphs emitted by ECAD
parsers while retaining the existing item and byte limits. - The new fields pass through the existing immutable document ownership and
validation boundaries; no viewer or host-app workaround is required.
No existing public class, method, package subpath, parameter, or document
envelope is removed in this release. Consumers that exhaustively validate PCB
text or primitive return objects should accept the additive fields above.
v1.1.2
circuitjson-toolkit 1.1.2
Deterministic schematic paint
This patch removes browser-dependent SVG fill behavior from the canonical
schematic renderer.
- Open arcs, polylines, and unfilled shapes now emit
fill="none"explicitly,
so they cannot become black-filled in a browser or host stylesheet. - Filled schematic primitives retain a valid authored
fill_coloror
fillColor. Whenis_filled: truehas no authored paint, rendering uses
var(--schematic-fill-color, #f1d8bd). - Generic
schematic_componentandschematic_symbolbodies now emit the
shared schematic fill and default-ink theme variables explicitly. - Filled paths render as polygons; open paths remain polylines. This preserves
geometry while making fill intent unambiguous. - Unsafe authored paints remain rejected by the existing SVG paint sanitizer.
Public exports, method names, parameters, CircuitJSON document envelopes, and
renderer return shapes are unchanged from 1.1.1.
circuitjson-toolkit 1.1.1
circuitjson-toolkit 1.1.1
Synchronous queued-request ownership
This patch makes the common worker client own every accepted parser and
project request when it enters the queue behind active work.
- Default
transferInput: falserequests clone their exact binary graph into
a private queue snapshot immediately. Later caller mutation cannot change a
queued parser input, project entry, or attached asset. transferInput: truedetaches exact transferable caller buffers immediately
after queue admission. Partial views, resizable buffers, and shared buffers
keep their isolated-copy behavior without detaching unrelated caller bytes.- Shared backing-buffer aliases remain shared in the owned request, and queued
snapshots transfer to the worker without another binary copy when posted. - Disposed, pre-cancelled, over-limit, and initial worker-construction failures
reject before ownership. Automatic direct fallback therefore retains valid
binary input. - Parser and project queues use the same bounded, accessor-safe traversal and
retain existing cancellation, error, and response behavior.
Public names, parameters, package subpaths, document envelopes, and project
envelopes are unchanged from 1.1.0. Gerber, Altium, KiCad, viewers, and ECAD
Forge receive the corrected behavior through the shared ParserWorkerClient.
circuitjson-toolkit 1.1.0
circuitjson-toolkit 1.1.0
Breaking API convergence
This minor release intentionally changes public names, parameters, return
shapes, and package layout so CircuitJSON, Gerber, Altium, and KiCad toolkits
can expose the same API.
The root is an exact 17-class contract: the 14 canonical classes plus temporary
CircuitJsonDocument, CircuitJsonIndexer, and CircuitJsonUnits viewer
compatibility exports. Exactly 37 previous CircuitJSON-specific classes remain
available from circuitjson-toolkit/extensions; they were not removed and are
classified as shared or derived for all four toolkits.
Key changes:
Parser.parse({ fileName, data }, options)replaces filename/text-specific
parser calls and returnsecad-toolkit.document.v1.ProjectLoaderreturnsecad-toolkit.project.v1with canonical document
envelopes. It now captures one bounded stable entry snapshot, enforces
maxEntriesbefore inspecting entries, and gives direct and worker paths the
same known-field behavior.- Parser failures use
ToolkitError;tryParseandtryLoadreturn exact
success/failure discriminants. retainSourceis now the explicit'none' | 'reference'contract.
Reference mode preserves exact caller identity only on direct parser calls,
exposes it non-enumerably, and never serializes or freezes the caller input.- PCB, schematic, BOM, interaction, query, manufacturing, simulation, and 3D
services consume either a document result, a CircuitJSON model, or a reused
CircuitJsonDocumentContext. - Canonical schematic graphics now include asset-backed
schematic_image
rows and hierarchicalschematic_sheet_symbolrows. Images keep payloads
in ToolkitAsset records, and child sheet symbols no longer masquerade as
selectable pages or hide unowned root graphics. PcbScene3dBuilderandPcbScene3dPreparatorreturn data-only,
millimeter-based, right-handed Z-up scenes. The package does not depend on
Three.js and never fetches assets implicitly.ecad-toolkit.worker.v1provides equivalent parse/project results, ordered
progress, cancellation, strict clone-safe errors, opt-in input transfer, and
worker-owned output transfer.ParserWorkerClient.parseAttempt()andloadProjectAttempt()give source
toolkits request-scoped automatic-worker fallback: only local construction
failure setsunavailable: true; parser, protocol, and runtime failures stay
visible.- Canonical subpaths now include
/parser,/project,/renderers,
/interaction,/query,/manufacturing,/simulation,/scene3d,
/capabilities,/extensions, and/testing. - Shared validation proofs, indexes, render preparation, queries, and scene
preparation are request-scoped and reused to avoid repeated parsing,
validation, cloning, and spatial work. - Validated source extensions are captured once as immutable owned data under
a separate 128 MiB payload and 2,000,000-item ceiling. Realistic large native
graphs now survive direct and worker results; over-limit graphs fail visibly
and the worker keeps its 250 MB whole-result ceiling. Binary extension values
stay byte-backed behind defensive-copy access rather than expanding into
plain number arrays. CircuitJsonDocumentContextcan now only be created throughprepare();
direct construction fails before reading input so viewers and applications
can consume the same validation-bound context without adapter workarounds.CircuitJsonDocument.normalizeModel(model, { owned })is the shared
copy-on-write compatibility boundary for legacy table geometry, PCB artwork
paths, pad diagnostics, courtyards, layer aliases, and stroke dash fields.
Toolkits normalize owned projections before one validation pass; viewers no
longer need application-side repair code.- The complete serialized-input validator is compiled from the pinned
development dependencycircuit-json@0.0.446. It preserves upstream
refinement, pipeline, and SI-unit transform rejection behavior while keeping
the published browser runtime dependency-free. - Compiler provenance now also verifies and records the exact lock integrity
and distribution entry SHA-256 forformat-si-unit@0.0.7andzod@3.25.76. - Full compatibility parsing canonicalizes legacy Gerber/KiCad outer-layer
aliases (1/32,F.*/B.*, and descriptorlayer.name), fills via layer
defaults, converts legacy trace vias, and retains silkscreen circle/oval and
courtyard geometry for viewers without app-side adapters. CircuitJsonPcbHolePrimitiveModelnow measures polygonpad_outlinein the
pad's rotation-local coordinate system and retains pill drill width, height,
diameter, and independent board-space rotation. Legalouter_width,
outer_height,rect_ccw_rotation, andhole_ccw_rotationvariants are
preserved. Downstream viewers no longer need format-specific plated-slot
sizing logic.- Legal square
pcb_holerows normalize to equal-width rectangular apertures
rather than circular fallbacks. extensions: 'none'now has the exact common return shape{}for native
documents and projects instead of a source-namespaced placeholder.ZipArchiveInspectornow validates exact local/central filenames, CRC32, and
size metadata and exposesverifyExtractedBytes()so stored and deflated
corruption is rejected after bounded inflation. Compression ratios use
compressed and uncompressed member payload totals, so ZIP comments or other
container padding cannot bypass expansion limits./testingnow exportsToolkitLoopbackWorkeralongside the contract fixtures
and runner so all toolkits share one real structured-clone worker regression
boundary.- Direct async parser/project paths now snapshot exact binary windows and
selected assets before progress callbacks. Worker-received inputs reuse their
structured-clone ownership boundary, and direct companion assets are prepared
once, closing callback mutation races without redundant receiver/result copies. npm run sync:schema -- --checkis a read-only drift gate that recompiles the
live pinned union and checks exact contract, provenance, snapshot, and
generated-module equality.- Validation now freezes each proven model once, the legacy parser hands its
already-built index to the next consumer, multi-side legacy rendering shares
one primitive preparation, and compact identifier indexes avoid cloning
duplicate element graphs. ToolkitAsset.measure(),prepare(), andprepareAll()provide one
descriptor-safe asset boundary. Metadata mode copies no payload; full mode
copies once; project limits include attached assets in direct and worker
execution. Missing media types are inferred consistently for common ECAD
model and image suffixes, includingmodel/vrmlfor WRL/VRML and
model/stepfor STEP/STP, while explicit values remain authoritative.- Canonical schematic rendering preserves explicit multi-value dash patterns,
accepts only safe SVG line-cap values, and honorsshow_label: falsein both
component markup and bounds. Source toolkits can retain native styles and
hidden designators without renderer or application workarounds. - The release benchmark runner enforces the frozen 1.0.17 workloads: both
primary cases must be at least 20% faster, non-primary regressions are
bounded, and the duplicate index graph must be at least 25% smaller. Timing
uses three independent processes. Every process imports toolkit modules from
the freshly extracted npm tarball candidate and records an execution marker
that reconciles its package version and source digest with candidate
provenance. - The retained Node 20 / Apple M3 Max result passes every timing and clone
gate, including at least 20% faster for both primary workloads and 85.32%
fewer duplicate-index clone bytes. See
benchmarks/results-v1.1.0.jsonfor samples and checksums. - Gerber, Altium, and KiCad packages now consume CircuitJSON Toolkit as their
shared runtime; their license terms do not replace this package's AGPL or
separately granted commercial terms.
Before:
import { CircuitJsonParser } from 'circuitjson-toolkit'
const model = CircuitJsonParser.parseText(text, {
fileName: 'board.json'
})After:
import { Parser } from 'circuitjson-toolkit'
const document = Parser.parse({
fileName: 'board.json',
data: text
})
console.log(document.model)See migration.md and its generated
appendix pages for the exhaustive 1.0.17 feature mapping,
and capabilities.md for host-side capability gating.
v1.0.17
Changes
- Added repository fix-quality guidance in AGENTS.md so future fixes must address general behavior instead of sample-specific workarounds.
- Bumped circuitjson-toolkit from 1.0.16 to 1.0.17 in package.json and package-lock.json for publication.
Branch reconciliation
- Fetched all remotes and tags with pruning before release.
- No local or remote branch refs were unmerged into main, so no branch merges were needed.
Validation
- npm test: passed 74 tests.
- npm run check:format: passed.
- npm publish --dry-run --cache /private/tmp/circuitjson-toolkit-npm-cache: produced circuitjson-toolkit-1.0.17.tgz with 64 files, 113.4 kB package size, and 640.0 kB unpacked size.
Git
- Release commit: 8c9d7de.
- Annotated tag: v1.0.17.
- main and tag pushed to origin before publishing.