ReviewOS

zig-utils/zig-js

Conformance: publish installed globals in fresh agent realms

#1075
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Parent: #502 Discovered while validating the follow-up to #1028.

Executed reproductions

On current main cce66bb724fa25945efbd11322155c86b1e632f9 with the real collector:

zig build test -Dtest-filter='real agents: broadcast rendezvous' -j1

The selected test never completes. A process sample shows the main thread repeatedly executing $262.agent.sleep(1) in the Atomics.notify(...) === 0 loop and no live agent thread.

The related focused case:

zig build test -Dtest-filter='Atomics.waitAsync: not-equal sync' -j1

fails after the cross-agent waiter remains unsettled. Exact parent 3c139f9f reproduces the same failure, so this is not caused by #1028's follow-up.

Disposable-snapshot instrumentation of the production path establishes:

agent.start before active=0 limit=9 waiters=0
agent.start after active=0 limit=9 waiters=0
agentMain entered
agentThreadRun globals installed
agentThreadRun parsed
agentThreadRun vm Throw
agentThreadRun exception ReferenceError: Can't find variable: $262

The typed agent is admitted and enters normally. agentThreadRun calls installGlobals, then creates a fresh global_obj, but unlike normal Context realm construction it never publishes the installed environment bindings as own properties of that global object. Bytecode global lookup therefore cannot resolve $262 (and would likewise miss the other installed globals). Agent execution swallows the throw by design, so the parent observes only a missing rendezvous/report.

Required change

  • Publish every installed agent-realm global binding onto the fresh global object with the same attributes as ordinary Context realm creation.
  • Wire $262.global to that exact object after publication.
  • Preserve agent group ownership: an agent realm must not reset the parent group's broadcast/report state.
  • Do not special-case $262, force tree-walker execution, add polling, or weaken the rendezvous assertions.

Definition of done

  • Focused real-agent rendezvous passes normally and under unsuppressed TSan.
  • Cross-agent Atomics.waitAsync notification settles normally and under unsuppressed TSan.
  • A focused regression proves representative installed globals are own properties of the agent global object before VM execution.
  • Full unit suite completes with zero failures and leaks, or any unrelated exact-parent blocker is documented precisely.
9 days ago

Fixed in 27d58465. Fresh agent realms now publish every installed binding on their actual global object before bytecode execution, with the ordinary Context descriptors. $262.global references that object; agent-group ownership and execution policy are unchanged.

Validation:

  • The pre-change cross-agent notification test fails with an unsettled waiter. The existing rendezvous and notification tests, the new pre-VM own-property regression, and the new real-GC required-bytecode rendezvous all pass in Debug, ReleaseSafe, and unsuppressed TSan. The module-root runs report no allocator leaks.
  • Against the saved before binary (b64cc348), true-for-timeout-agent.js and no-spurious-wakeup-on-store.js exceed the same 20-second external guard; both pass after. The non-agent timeout-promise control passes on both sides.
  • The complete pinned test/built-ins/Atomics/waitAsync subtree passes 101/101 files after the fix. This is scoped evidence, not a full test262 pass-rate update.

The full local unit suite remains blocked by the pre-existing source-link memory limit documented in #933: the cold combined unit link peaks near 3.1 GB, above HOME_RUN_MAX_MB=3072. This affects the unchanged parent as well and is unrelated to agent initialization. Per-module test roots were used as prescribed; the cap was not raised. Full CI integration results are still pending.

9 days ago

Follow-up landed on main in e9400ed6.

The fresh agent global was publishing the right own bindings after 27d58465, but its [[Prototype]] still remained null. Ordinary Context and child-realm construction both inherit their realm's Object.prototype; agents now do the same, and the direct realm-publication regression pins exact prototype identity.

Executed evidence with the real collector:

  • disposable exact-main prototype probe: 0/1 before (expected Object.prototype, found null) -> 1/1 after;
  • direct agent-realm publication regression: pass normally and under unsuppressed TSan, 0 leaks;
  • real-GC required-bytecode agent rendezvous: pass normally and under unsuppressed TSan, 0 leaks;
  • exact pushed HEAD e9400ed6: direct regression passes normally and under unsuppressed TSan, 0 leaks.

Sign in to comment on this issue.