Repository navigation
Compile any crossings: destructuring, namespace patterns, any parameters and async callbacks - #1503
Merged
Merged
Conversation
…ameters and async callbacks - Destructuring an `any` value in TypeScript (a function typed `any`, an awaited `any`, `JSON.parse`, an `any` table read) now goes through the checked-dynamic value, as JavaScript sources and #1407's JS-declared results already did. Object sources get V8's RequireObjectCoercible TypeError for the spellings the assignment form reproduces. - A method call or member read on a checker-`any` receiver whose value is a fresh typed call result (`out.split("\n").map(...)`, `.pop()`, `.length`) boxes that temporary and dispatches on the runtime kind, only after every other lowering declined. - `const { a, b: c } = ns` and `= await import("./m")` over a program module bind each export the way `ns.a` reads it. - A defaulted parameter of a program-source function, arrow or function expression that the checker types `any` (a default under an `(...args: any[]) => any` wrapper slot, where the contextual `any` wins) is a dyn ABI slot in the callable's type. - An async lambda whose signature answered a bare dyn result (a library slot `A | Promise<A>` with A = any) produces Promise<unknown>. - `761-any-objects` compiles and moves back to the corpus; the retired-engine 2083/2104 snapshots shrink to their remaining fences. - JavaScript `Promise.resolve(value)` (in a JavaScript file) over a dyn value holding a promise answers that promise instead of wrapping it, so a TypeScript async callback's result is adopted by JavaScript retry helpers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…any)` bindings dynamically
- `new Promise(run)` where `run` is a JavaScript function value whose
parameters are untyped (the retry-helper shape `function run(resolve,
reject) {...}; return new Promise(run)`) gets an adapter executor: it
receives the native resolve/reject pair and calls the original with
both boxed as checked-dynamic function values. This was a deferred
runtime refusal inside such packages.
- A catch binding annotated `any` reads the caught value through its
checked-dynamic face, as an unannotated `unknown` one does: member
reads, expando writes, `delete` and `in` act on the thrown object, and
a rethrow keeps its identity. It was refused (SC1063).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…any)` bindings dynamically (#1508)
euphemism
pushed a commit
to euphemism/scriptc
that referenced
this pull request
Oct 20, 2026
The fixture's launch() helper calls run().then, which used to be the first statement these programs fenced at (SC1090). It compiles since vercel-labs#1503, so node24-web-stream-pipe-abort and node24-web-stream-readable-lifecycle now stop at 'new ReadableStream' and node24-web-stream-tee at 'ReadableStream.tee', which have no lowering (SC2020).
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.
TypeScript code that receives
anyfrom untyped dependencies (a command runner, a JavaScript retry helper,JSON.parse) hit a group of refusals. Each item below was a compile error on main; everything that compiled before still compiles to the same IR, LLVM and binaries.Destructuring
anyconst { stdout, stderr } = run(cmd),const { body } = await fetchAny(),const [a, , b = 1, ...rest] = JSON.parse(text)andconst { mode, path } = table[key](withtabletypedany) now go through the checked-dynamic value. This covers renames, defaults, nesting, rest and holes.Cannot destructure property 'a' of 'f(...)' as it is null.<any>0), unit sources and computed keys keep their diagnostics, now reported by their own fences (see the updated retired-engine snapshots).Chains over
anystringsstdout.split("\n").map(...),.pop()ands.split(" ").lengthfailed becausesplitanswers a nativestring[]that has no typed home under itsanyspelling. Only after every other lowering has declined, a method call or member read on a checker-anyreceiver whose value is a fresh call result now boxes that temporary and dispatches on its runtime kind. The box copies; a call result has no other holder that could observe the copy.761-any-objectscompiles because of this and moves back from the diagnostics fixtures to the corpus.Module namespaces
const { add, label: name = "x" } = nsand= await import("./lib.ts")over a program module bind each export the wayns.addreads it: once, at the pattern's position. Rest elements keep a fence, because they would need the namespace object itself.Defaulted
anyparameters in callable typesA defaulted parameter that the checker types
anyis now a dyn slot in the callable's ABI. This covers functions, arrows and function expressions in program source, in the typical form of a default under an(...args: any[]) => anywrapper,wrap((limit = 5) => ...), where the contextualanywins over the default's type. Inside the body the binding was already dyn. Otheranyparameters keep their existing paths: object literals holding such callbacks stay checked-dynamic objects, sochecked-callback-optionsandcjs-open-options-npmcompile exactly as before.Async callbacks into JavaScript libraries
retry(async () => loose(), opts)failed when the library types the slot(...) => A | Promise<A>withA = any: the union collapses toany, and an async lambda with a bare dyn result was refused. That value now has the typePromise<unknown>.Promise.resolve(value)over a dyn value that holds a promise now answers that same promise instead of wrapping it. On main, a TypeScript async callback handed to a JavaScript helper that doesPromise.resolve(fn()).then(resolve)silently lost its payload. Corpus 6475 pins this.Evidence
corpus/4642-acyclic-contract.tsfails on both sides, as it already does on main. Bench geomean -0.22% and self-hosted compile time -0.28%, both within tolerance.unknown-collections.ts:Promise.resolve<unknown>(3)in TypeScript had taken the new adoption path. The path is now limited to JavaScript files, andunknown-collections.tsplus all 99 TypeScript corpus programs that callPromise.resolveare identical again.5197-object-entries-dynamic-objects,checked-callback-optionsandcjs-open-options-npm: object literals and callbacks withanyparameters had changed representation. Theany-parameter rule is now limited to defaulted parameters of functions, so all three are identical.pnpm lintandpnpm format:checkare clean.pnpm test:ts7 --baselines-onlypasses, with the new baselines recorded and 761's baseline moved.tests/harness/diagnostics.test.ts: the retired-engine 2083 and 2104 snapshots shrink to their remaining fences.contract-acyclic.tsfails identically on main.tests/harness/self-hosting-native-driver.test.tspasses.🤖 Generated with Claude Code