Skip to content

fix(node:v8): Serializer/Deserializer classes + lifecycle/diagnostic namespaces - #3763

Merged
proggeramlug merged 6 commits into
mainfrom
fix-v8-2-3680-3679
May 31, 2026
Merged

fix(node:v8): Serializer/Deserializer classes + lifecycle/diagnostic namespaces#3763
proggeramlug merged 6 commits into
mainfrom
fix-v8-2-3680-3679

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Closes #3680
Closes #3679

Implementation

Builds on the existing node:v8 surface (v8.serialize/deserialize/heap-stats/GCProfiler) in crates/perry-runtime/src/node_v8.rs.

#3680v8.Serializer / v8.Deserializer classes

  • new v8.Serializer() / new v8.DefaultSerializer() / new v8.Deserializer(buf) / new v8.DefaultDeserializer(buf) now construct real, stateful instances backed by the structured-clone codec that already powers v8.serialize/deserialize (child_process::v8_serde).
  • Each instance is a NATIVE_MODULE_CLASS_ID namespace object carrying a registry id in field[1] (mirrors the PerformanceObserver instance pattern) — no new HIR/codegen variant. Instance method calls route through dispatch_native_module_method.
  • Methods: writeHeader/writeValue/writeUint32/writeUint64/writeDouble/writeRawBytes/releaseBuffer and readHeader/readValue/readUint32/readUint64/readDouble/readRawBytes.
  • A new OwnedDeserializer keeps the input buffer alive across method calls (the codec's internal Deserializer only borrows). GC suppression wraps each writeValue/readValue walk.
  • typeof v8.Serializer === "function" via the native-callable-export path; construction is statically lowered in expr/new_dynamic.rs.

#3679 — lifecycle / diagnostic-control namespaces

Perry has no V8 engine to drive real snapshots / coverage / promise-lifecycle hooks, so these expose Node's observable shape only:

  • v8.startupSnapshot namespace: isBuildingSnapshot() returns the number 0 (matching Node, not a boolean); addSerializeCallback/addDeserializeCallback/setDeserializeMainFunction throw ERR_NOT_BUILDING_SNAPSHOT like Node.
  • v8.promiseHooks namespace: onInit/onBefore/onAfter/onSettled/createHook return a no-op stop callable.
  • Top-level setFlagsFromString/takeCoverage/stopCoverage/setHeapSnapshotNearHeapLimit are Node-shaped no-op callables returning undefined.
  • Both the chained method-call form (folded to NativeMethodCall { class_name: Some("startupSnapshot") }) and the value-read form (typeof v8.startupSnapshot.isBuildingSnapshot) are handled.

Dropped (correctly): real getHeapSnapshot/writeHeapSnapshot stream/file emission, real coverage capture, real promise-hook lifecycle — these require a V8 engine. They are coordinated with #3140 rather than faked here; only correctly-shaped no-op surface is exposed.

Manifest + generated docs (docs/api/perry.d.ts, docs/src/api/reference.md) updated; regen_api_docs.sh re-run.

Validation

  • Gap test test-files/test_gap_v8_2_3680plus.ts is byte-identical to node --experimental-strip-types under the default auto-optimize compile (Serializer/Deserializer round-trip asserted via deep JSON.stringify equality, not raw bytes).
  • Prior v8 gap test test_gap_node_v8_3137plus.ts remains IDENTICAL (no regression).
  • cargo build --release cold (clean). cargo fmt --all -- --check clean. ./scripts/check_file_size.sh exit 0.
  • cargo test --release passes for perry-runtime, perry-codegen, perry-hir, perry-api-manifest.
  • No new HIR Expr variant added.

@proggeramlug
proggeramlug merged commit df8ccde into main May 31, 2026
1 check passed
@proggeramlug
proggeramlug deleted the fix-v8-2-3680-3679 branch May 31, 2026 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant