Summary
A spread call of a native-module method silently no-ops — no dispatch, no throw, callback never invoked, returns undefined:
const crypto = require("crypto");
const args = ["sha256", ikm, salt, info, 64];
crypto.hkdf("sha256", ikm, salt, info, 64, cb); // ✓ works (direct)
const h = crypto.hkdf; h(...allArgs, cb); // ✓ works (value call)
crypto.hkdf(...args, cb); // ✗ SILENT NO-OP under perry
The spread lowering routes through js_closure_call_apply_with_spread → js_closure_call_array, which treats the callee as a plain closure; a bound-native-callable box has no valid closure func_ptr, so the per-arity dispatch degrades to returning undefined without ever reaching the module dispatcher — and without an error. (Depending on the callee shape, a sibling route through js_closure_unbox_callee_checked throws value is not a function instead.)
Found alongside #6667 while root-causing the Auth.js credentials-login failure (jose's node-HKDF wrapper is exactly Z.hkdf(...args, cb)); with #6667 fixed, this becomes the next blocker on that path.
Suggested direction
js_closure_call_apply_with_spread (and the checked-unbox spread route) should detect a non-plain-closure callee and delegate to js_native_call_value with the flattened args — that dispatcher already owns the bound-native/proxy/class-object arms. Silent undefined on a failed dispatch is the worst outcome; if delegation is out of scope, at minimum throw.
Observed on main @ 5eb2bc4, macOS arm64.
Summary
A spread call of a native-module method silently no-ops — no dispatch, no throw, callback never invoked, returns
undefined:The spread lowering routes through
js_closure_call_apply_with_spread→js_closure_call_array, which treats the callee as a plain closure; a bound-native-callable box has no valid closurefunc_ptr, so the per-arity dispatch degrades to returningundefinedwithout ever reaching the module dispatcher — and without an error. (Depending on the callee shape, a sibling route throughjs_closure_unbox_callee_checkedthrowsvalue is not a functioninstead.)Found alongside #6667 while root-causing the Auth.js credentials-login failure (jose's node-HKDF wrapper is exactly
Z.hkdf(...args, cb)); with #6667 fixed, this becomes the next blocker on that path.Suggested direction
js_closure_call_apply_with_spread(and the checked-unbox spread route) should detect a non-plain-closure callee and delegate tojs_native_call_valuewith the flattened args — that dispatcher already owns the bound-native/proxy/class-object arms. Silentundefinedon a failed dispatch is the worst outcome; if delegation is out of scope, at minimum throw.Observed on main @ 5eb2bc4, macOS arm64.