Repository navigation
Conversation
An optional chain such as `resolved.members?.get(name)` took three references to its receiver: the owned receiver value, a +1 extraction into the bind slot, and a +1 copy for every chainRecv use, each released out of line (scr_map_release for maps). Now the bind slot borrows the payload whenever another owner outlives the body (the statement frame owns the receiver value), chainRecv reads are borrowable receivers and call arguments, and a receiver projected from a borrowable owner is not retained at all when the body preserves reference edges. Optional chains and chain receivers count as edge-preserving themselves; their children decide. Stack receivers, multi-arm unions and bodies that may remove an edge keep the owned forms. Corpus 4620 covers chains whose body clears or replaces the receiver field, drops the last other reference, nested and missing links, call and element receivers, self-clearing optional calls, and values that outlive later stores; a mutation that ignores the body check is caught by ASan (heap-use-after-free).
…eserving A function is edge-preserving when it cannot remove a reference edge; callers then pass field projections borrowed. tsc-ts lost the property for its whole type-ordering family because compareTypeLists reads a module binding behind an import-cycle TDZ check (module.tdzCheck), and for compareSymbols because getSymbolId bumps a shared id counter with Atomics.add (atomics.op). Fresh array literals without spreads and the array operations that only read, copy into a fresh array or append (push and pushSpread retain the new element; moving the slot storage releases nothing) were rejected too. All of these may allocate or throw, which the summary already allows. Removals (pop, shift, splice), truncation, overwrites and Atomics.wait keep the conservative answer. compareTypes now passes its field arguments borrowed: 42 retains and 118 releases in its body become 4 and 4, and compareSymbols, compareTypeNames and binarySearchTypes need none. Corpus 4621 covers a comparator behind a real import-cycle TDZ error, an atomic id counter, appends that move the storage of the array owning a borrowed argument, loop bindings over appending and draining calls, and callees that shift or truncate the owning array.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Count module TDZ checks, atomic counters and array appends as edge-preserving
cramforce
force-pushed
the
perf/length-to-double-nneg
branch
from
October 11, 2026 03:41
67f9de0 to
8cf6e38
Compare
cramforce
force-pushed
the
perf/borrow-optional-chain-receivers
branch
from
October 11, 2026 03:41
9b46089 to
1135960
Compare
cramforce
force-pushed
the
perf/length-to-double-nneg
branch
from
October 11, 2026 03:45
8cf6e38 to
67f9de0
Compare
cramforce
force-pushed
the
perf/borrow-optional-chain-receivers
branch
from
October 11, 2026 03:45
1135960 to
9b46089
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An optional chain such as
resolved.members?.get(name)took three references to its receiver: the owned receiver value, a +1 extraction into the chain's bind slot, and a +1 copy for every use of the bound receiver, each released out of line. The bind slot now borrows the payload whenever another owner outlives the body (the statement frame owns the receiver value), uses of the bound receiver are borrowable receivers and call arguments, and a receiver projected from a borrowable owner is not retained at all when the body preserves reference edges. Stack receivers, multi-arm unions and bodies that may remove an edge keep the owned forms. Corpus 4620 pins chains whose body clears or replaces the receiver's field, drops the last other reference, nested and missing links, call and element receivers, self-clearing optional calls, and values that outlive later stores; ignoring the body check makes it fail under ASan.Second of three; stacked on the length conversion PR.