mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-26 06:34:20 +08:00
A closure created above the `let`/`const` it captures holds the binding in a TDZ box whose NULL payload slot marks "not yet initialized". A union of one reference arm with `null` and/or `undefined` (`Set<T> | null`, `string | undefined`, `C | null`) is represented as the bare arm pointer with NULL standing for the unit arm, so storing that unit value made the box indistinguishable from the temporal dead zone: every later read or write threw "Cannot access 'x' before initialization" although the declaration had run. The self-hosted compiler trips on exactly this shape in lowerer.ts (`let dynamicViews: Set<string> | null = null`, read by a callback created earlier), which made scriptc 0.2.8 fail to build tsc-ts's relater with SC3004. Node evaluates the source correctly; the native code was wrong. TDZ boxes of nullable-union bindings now start at the module's immortal NULLABLE_ABSENT sentinel and the TDZ test compares against it. No value of the binding can hold that sentinel, and every RC entry point and the cycle collector already skip it, so box release, trace and the initializing store need no other change. Corpus: 4596-tdz-nullable-forward-capture.