Skip to content

Commit b422528

Browse files
committed
feat(binary-object): round-trip QuickJS module images
1 parent 079e499 commit b422528

9 files changed

Lines changed: 2637 additions & 87 deletions

File tree

docs/status.md

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -151,27 +151,33 @@ QuickJS's `u32`-to-`u16` truncation, while signed negative-size and
151151
decrement-overflow spellings remain hard safety rejections.
152152

153153
The whole-image reader uses one heterogeneous frame stack, one `DataMachine`,
154-
one `ObjectArena`, and one preorder function table across the root and every
155-
constant pool. FunctionBytecode records never consume object-reference IDs.
156-
Function frames retain linear, source-bound data completions until a consuming
157-
whole-image finalizer unwraps the root and every constant by move. Function IDs
158-
carry the same non-wrapping machine-source token, are checked against reserved
159-
function slots before publication, and cannot be used to index a different
160-
image. Aggregate limits independently bound function count, mixed traversal
161-
depth, constant-pool entries, locals, closures, code bytes, instruction spans,
162-
atom relocations, and debug bytes in addition to the existing per-function,
163-
wire, and graph limits. Each function prefix receives the intersection of its
164-
per-function cap and the remaining whole-image budget before table allocation
165-
or code copying/scanning. The completed `BytecodeImage` is deliberately
154+
one `ObjectArena`, and preorder function and module tables across the root,
155+
every constant pool, every request-attributes value, and every module function
156+
object. FunctionBytecode and Module records never consume object-reference IDs.
157+
Their frames retain linear, source-bound data completions until a consuming
158+
whole-image finalizer unwraps every nested value by move. Function and Module
159+
IDs carry the same non-wrapping machine-source token, are checked against
160+
reserved slots before publication, and cannot index a different image.
161+
Aggregate limits independently bound function and module counts, mixed
162+
traversal depth, constant-pool entries, locals, closures, code bytes,
163+
instruction spans, atom relocations, debug bytes, and all four module metadata
164+
tables in addition to the per-record, wire, and graph limits. Each function
165+
prefix and each staged module table receives the intersection of its
166+
per-record cap and the remaining whole-image budget before table allocation or
167+
payload copying/scanning. The completed `BytecodeImage` is deliberately
166168
non-executable: it has no heap materializer, verifier bypass, or evaluation
167169
entry point.
168170
The matching canonical writer consumes that immutable image through a
169171
source-bound authentication plan before exposing any bytes. Decode and encode
170172
share the same whole-image totals, remaining-budget intersection, and
171173
per-function-versus-aggregate error attribution. The plan rebuilds dynamic
172-
atoms in QuickJS first-use order, regenerates opcode atom operands from typed
173-
relocations, assigns object-reference IDs in one preorder spanning every
174-
constant pool, and never assigns those IDs to FunctionBytecode records.
174+
atoms in QuickJS first-use order, including the request-name/attributes
175+
continuation, regenerates opcode atom operands from typed relocations, assigns
176+
object-reference IDs in one preorder spanning every nested value, and never
177+
assigns those IDs to FunctionBytecode or Module records. Module writes preserve
178+
unknown non-zero export types, normalize boolean bytes, and retain arbitrary
179+
request attributes and function-object values without imposing linker-only
180+
relationships on the archival codec.
175181
Ordinary-object writes match `JS_WriteObjectTag` by omitting enumerable symbol
176182
and private-name properties before their values can affect atoms, traversal,
177183
references, or resource accounting. A complete encoded-size proof precedes
@@ -209,24 +215,26 @@ through fresh-runtime read, byte-exact reserialization, resolve, evaluation,
209215
and a global `42` receipt. Its `JS_WRITE_OBJ_BSWAP` bytes are identical. A
210216
second 283-byte vector records the complete request/attribute, local and
211217
indirect export, star export, default/named/namespace import, top-level-await,
212-
and FunctionBytecode-body topology without pretending that the Rust archival
213-
reader can link or execute it yet.
218+
and FunctionBytecode-body topology. The Rust whole-image reader and canonical
219+
writer now preserve both vectors byte exactly without pretending that the
220+
archival image can link or execute them yet.
214221
The data decoder separates preorder identity registration from value
215222
completion: every parent/root attachment now uses one completed-subtree
216-
delivery path owned by the decode state. Its reference state is now an
217-
independent generic `ObjectArena`, ready for a whole-image decoder to carry one
218-
instance through every recursive constant pool without registering
219-
FunctionBytecode records themselves. The data-value and container state machine
223+
delivery path owned by the decode state. Its reference state is an independent
224+
generic `ObjectArena`; the whole-image decoder carries one instance through
225+
constant pools and module children without registering FunctionBytecode or
226+
Module records themselves. The data-value and container state machine
220227
is now independently generic over value and property-key carriers as
221228
`DataMachine`/`DataFrame`. The data-only facade still owns its own header
222229
interning, key timing, frame stack, root delivery, and unconditional cursor
223-
finalization, and still rejects FunctionBytecode without consuming its payload.
224-
The separate whole-image driver carries authenticated function identities
225-
through ordinary properties, Arrays, and TemplateObjects while reusing the
226-
same budgets and arena; TypedArray, ObjectValue, and Date expose typed failures
227-
when such an identity is invalid in their child position. The arena represents
228-
incomplete identities with kind-checked pending/ready slots. Source-bound linear node
229-
reservations, opaque data frames, and linear completed values prevent stale or
230+
finalization, and still rejects FunctionBytecode and Module without consuming
231+
their payloads. The separate whole-image driver carries authenticated function
232+
and module identities through ordinary properties, Arrays, and TemplateObjects
233+
while reusing the same budgets and arena; TypedArray, ObjectValue, and Date
234+
expose typed failures when such an identity is invalid in their child position.
235+
The arena represents incomplete identities with kind-checked pending/ready
236+
slots. Source-bound linear node reservations, opaque data frames, and linear
237+
completed values prevent stale or
230238
cross-machine commits; machine identities never wrap, and raw node values
231239
cannot be rebranded as caller-produced opaque values. The value adapter is
232240
sealed inside the graph reader, so sibling modules cannot substitute a
@@ -237,12 +245,11 @@ another node.
237245
Malicious TypedArray placeholder paths are rejected deterministically instead
238246
of reproducing pinned QuickJS's native crashes.
239247
The data-only graph still rejects SharedArrayBuffer, FunctionBytecode, and
240-
Module. The BytecodeImage reader admits FunctionBytecode but still rejects
241-
Module and SharedArrayBuffer, and neither reader is a public binary-object API
242-
yet. A module-image model, heap materializer, native-code semantic
243-
verifier/translator, public read/write flags, and a public authenticated
244-
whole-image facade remain future
245-
milestones. In addition,
248+
Module. The BytecodeImage reader admits FunctionBytecode and Module but still
249+
rejects SharedArrayBuffer, and neither reader is a public binary-object API yet.
250+
A heap materializer, native-code semantic verifier/translator, public read/write
251+
flags, and a public authenticated whole-image facade remain future milestones.
252+
In addition,
246253
`num-bigint` lacks fallible construction, so heap materialization, decoder OOM
247254
mapping, and allocator fault-injection remain hardening gates before untrusted
248255
input admission.

0 commit comments

Comments
 (0)