Parent: #288. Worker/realm parent: #81.
Problem
Current main has active-listener retention and forced-GC coverage for same-realm and dedicated-Worker MessagePorts, and ordinary transfer coverage for ServiceWorker and iframe realms. It does not forward explicit low-memory collection into ServiceWorker isolates, so the remaining ServiceWorker active-port reachability matrix cannot be exercised deterministically. The iframe bootstrap likewise transfers a live port without forcing collection between listener installation and delivery.
Scope
- Forward the runtime low-memory request into every live ServiceWorker isolate using the existing worker wake/serialized isolate-thread model.
- Run child compaction and V8 low-memory notification before the next ServiceWorker message/fetch dispatch.
- Add a ServiceWorker MessagePort gate covering direct
onmessage Promise resolvers and addEventListener listeners across forced child-isolate GC.
- Add an iframe-realm transfer gate that forces GC after listener installation and before delivery.
- Cover close/listener removal, navigation/termination and retained queue/binding/heap/RSS bounds without adding timing-only JavaScript captures.
Acceptance
- Active transferred ports deliver exactly once after deterministic forced GC in ServiceWorker and iframe realms.
- Removed listeners, closed ports and retired realms release endpoint queues and native bindings.
- Repeated cycles remain bounded and preserve existing queue limits.
- Focused native full-V8 tests pass on the changed runtime.
Implementation
PR #856 implements the gate and runtime repair.
The iframe failure was caused by treating any same-runtime peer as V8-traceable. Parent and iframe wrappers live in different V8 contexts; the native channel connects them, but V8 cannot trace that native edge. Active-listener retention now considers a peer local only when both bindings share the same V8 context.
Low-memory notifications now enter each live ServiceWorker isolate through its serialized runtime thread. The focused ServiceWorker gate exercises 100 alternating onmessage and addEventListener transfers and checks queue, binding, V8 heap, RSS, and elapsed bounds.
Validation evidence
- iframe forced-GC bootstrap/delivery gate: pass
- ServiceWorker forced-GC 100-cycle gate: pass
git diff --check: pass
Parent: #288. Worker/realm parent: #81.
Problem
Current main has active-listener retention and forced-GC coverage for same-realm and dedicated-Worker MessagePorts, and ordinary transfer coverage for ServiceWorker and iframe realms. It does not forward explicit low-memory collection into ServiceWorker isolates, so the remaining ServiceWorker active-port reachability matrix cannot be exercised deterministically. The iframe bootstrap likewise transfers a live port without forcing collection between listener installation and delivery.
Scope
onmessagePromise resolvers andaddEventListenerlisteners across forced child-isolate GC.Acceptance
Implementation
PR #856 implements the gate and runtime repair.
The iframe failure was caused by treating any same-runtime peer as V8-traceable. Parent and iframe wrappers live in different V8 contexts; the native channel connects them, but V8 cannot trace that native edge. Active-listener retention now considers a peer local only when both bindings share the same V8 context.
Low-memory notifications now enter each live ServiceWorker isolate through its serialized runtime thread. The focused ServiceWorker gate exercises 100 alternating
onmessageandaddEventListenertransfers and checks queue, binding, V8 heap, RSS, and elapsed bounds.Validation evidence
git diff --check: pass