Repository navigation
Promisify untyped functions at run time - #1502
Merged
Merged
Conversation
util.promisify(fn) over a function typed any (an npm package method typed by its JavaScript, a bound method of an untyped value) was refused, because the promisified signature is only known at run time. A native wrapper now calls the function with the call's receiver, its arguments and a callback, and answers a promise: a truthy error rejects, otherwise the first value fulfills, the first settlement wins, and a synchronous throw rejects. util.promisify.custom functions are not consulted. The wrapper lives in its own runtime unit (scr_util_promisify.c), linked by the new utilPromisify feature, so other programs are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Node's promisify copies the original's own property descriptors and prototype onto the wrapper and consults util.promisify.custom. The runtime wrapper now copies name and length and refuses, with SC2020 where util.promisify runs, an original with any other own property, instead of returning a wrapper that lacks them. The node24-util-adapters npm case now gets past its promisify scenarios and stops at an unrelated deferred Object.create refusal; its known state records that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
util.promisify(fn)needs the callback's shape to build a typed wrapper. Whenfnis typedany(a method of an untyped client, oftenobj.close.bind(obj)), there is no shape, and the call was refused.An untyped argument now goes to a runtime wrapper,
scr_util_promisify. It lives in its own runtime unit,scr_util_promisify.c, linked by a newutilPromisifyfeature together with the dyn-async and dyn-invoke units, so programs that don't promisify an untyped function are unchanged. The wrapper is an untyped function. Each call creates a promise, passes the call's receiver and arguments plus an error-first callback tofn, and settles once:This matches Node for plain functions. Node's promisify also copies the original's own property descriptors and prototype onto the wrapper and consults
util.promisify.custom; the wrapper copiesnameandlength, and an original with any other own property (util.promisify.customamong them) refuses with SC2020 whereutil.promisifyruns, rather than returning a wrapper without them. The DEP0174 warning for an original that returns a promise is not reported. Both limits are on the limitations page. Typed functions keep the existing static wrapper, and their programs are unchanged.Evidence
6452-promisify-untyped-functions.ts: untyped methods promisified bound and unbound, an extra callback value dropped, error rejection, a callback called twice, a synchronous throw, and the call's receiver reaching the function. Node and native agree in both lanes.npm.test.ts:node24-util-adaptersnow runs its invalid-argument promisify scenarios as Node does and stops at an unrelated deferredObject.createrefusal; its known state records that instead of the earlier promisify refusal.opt/bc-node-surfaceat 25e40af, which merges main 9d80738): PASS, 3293 programs identical (bench, self-hosted compiler, corpus) and 2 that fail on both sides; bench geomean −0.25% [−0.61%, +0.25%], self +1.16%, both within tolerance.self-hosting-runtime-features.test.tscovers the new feature's detection, and the runtime-pack and executable-cache unit tests pass.test:ts7 --baselines-only, the diagnostics suite and the self-hosting IR build are clean.contract-acyclic.tsfails in the diagnostics suite the same way on main.🤖 Generated with Claude Code