mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-09 12:08:07 +08:00
`const env = process.env` compiled the hold to a snapshot record copy of the environment, so `env.X = "1"` wrote the copy and was lost while Node's write reached the real environment table (undefined natively, "1" in Node; `repros/d3-env-write.ts`). Node's held value IS the environment object. A hold whose type is the env record now aliases the live table for every member access: dotted and computed reads lower to process.envGet, writes to process.envSet, `delete` to process.envUnset, and the absence probe (`env[k] ?? fallback`, `||`, `if`) reads getenv instead of reconstructing presence over the snapshot. A BARE use of the hold (spread, Object.keys, argument, return) takes a fresh %env.snapshot at that site, so it observes the environment as it is there rather than as it was when the binding was initialized. Two holds keep copy semantics because they cannot alias safely, and a write through either is refused with SC2014 rather than lost: a hold that escapes into another function, and a hold whose declared type is not the env record. Compound and update writes through a hold (`env.X += v`, `env.X++`) are refused the same way. tests/corpus/held-env-value-writes.ts covers writes, computed writes, deletes, child inheritance, direct writes seen through the hold, a copy staying a copy, and bare-use re-snapshotting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>