Summary
Nine Array.prototype methods that do not exist on %TypedArray%.prototype
answer with a value on a typed-array receiver instead of throwing. Node throws
TypeError: … is not a function; perry returns [], undefined, or garbage.
function opaque(x: any): any { return x; }
opaque(new Int32Array([1, 2, 3])).flatMap((x: any) => [x])
// node: TypeError: opaque(...).flatMap is not a function
// perry: [5.08e-321, 2.1219957924e-314, 1e-323]
Measured against node v26.5.1 on main @ 0a1e78e5f.
Full list
The methods absent from %TypedArray%.prototype are exactly:
concat, flat, flatMap, pop, push, shift, splice, toSpliced,
unshift.
| expression |
perry |
node |
i32.concat([9]) |
[9] |
TypeError |
i32.flat() |
[] |
TypeError |
i32.flatMap(f) |
[5.08e-321,2.12e-314,1e-323] — garbage |
TypeError |
i32.push(9) |
[] |
TypeError |
i32.pop() |
undefined |
TypeError |
i32.shift() |
undefined |
TypeError |
i32.unshift(9) |
[] |
TypeError |
i32.splice(1,1) |
{obj}, receiver untouched |
TypeError |
i32.toSpliced(1,1) |
[] |
TypeError |
u8.flat() |
[] |
TypeError |
u8.toSpliced(1,1) |
[] |
TypeError |
u8.push(9) |
[] |
TypeError |
u8.splice, u8.concat and u8.flatMap DO throw — but with
TypeError: (Buffer).splice is not a function, i.e. right answer, wrong
message and wrong reason (dispatch_buffer_method's name list simply has no
entry, rather than the property genuinely being absent).
Why this is NOT the #8041 receiver-reroute family
These helpers are dead below clean_arr_ptr in the same textual sense as the
ones #8090/#8109/#8119/#8120/#8130 fixed, and it is tempting to file them
together. They are a different bug, and "fixing the reroute" would make them
worse:
js_array_concat is the worked example, already noted in #8130's caveats. Node
gives [{}] for a typed-array argument; perry gives [] today; and the
pre-#8041 live reroute gave [1,2,3]. It was wrong before #8041 and wrong
after, in different ways. Waking the reroute back up would restore an answer
node never produces.
The actual defect is one level up: the property should not resolve at all.
Perry's method dispatch answers flatMap on a typed array because the fused
Expr::ArrayFlatMap fold and is_array_expr both treat Int32Array as an
array, and nothing consults %TypedArray%.prototype's membership. So the fix
is a receiver-kind check at method resolution, producing the spec
TypeError, not a reroute inside the helper.
js_array_concat specifically is being handled by #8124
(concat-spreadable); this issue covers the other eight.
Suggested shape
A single table of the nine names, consulted where the typed-array/Buffer
dispatch decision is already made — dispatch_typed_array_method
(object/native_call_method/typed_array.rs) and dispatch_buffer_method
(object/buffer_dispatch.rs) already return None / "is not a function" for
unrecognised names, so the missing piece is preventing the static HIR folds
from claiming these nine for a receiver whose type is a typed array. That is
the same gate is_array_expr already applies to exclude Uint8Array from
copyWithin's fold (local_array_methods.rs:800-839), generalised.
Low urgency: every row here is a program that is already broken and would
throw under node, so no working code depends on the current answers. The
flatMap row is the one worth prioritising, because it returns garbage
values rather than an empty result, which a caller can propagate silently.
Context
Found by the exhaustive Array.prototype receiver sweep that produced #8135.
The full 33-row table, with the funnel verdict and measured node diff for every
Array.prototype-reachable runtime entry point, is in the #8135 PR description.
Summary
Nine
Array.prototypemethods that do not exist on%TypedArray%.prototypeanswer with a value on a typed-array receiver instead of throwing. Node throws
TypeError: … is not a function; perry returns[],undefined, or garbage.Measured against node
v26.5.1onmain@0a1e78e5f.Full list
The methods absent from
%TypedArray%.prototypeare exactly:concat,flat,flatMap,pop,push,shift,splice,toSpliced,unshift.i32.concat([9])[9]TypeErrori32.flat()[]TypeErrori32.flatMap(f)[5.08e-321,2.12e-314,1e-323]— garbageTypeErrori32.push(9)[]TypeErrori32.pop()undefinedTypeErrori32.shift()undefinedTypeErrori32.unshift(9)[]TypeErrori32.splice(1,1){obj}, receiver untouchedTypeErrori32.toSpliced(1,1)[]TypeErroru8.flat()[]TypeErroru8.toSpliced(1,1)[]TypeErroru8.push(9)[]TypeErroru8.splice,u8.concatandu8.flatMapDO throw — but withTypeError: (Buffer).splice is not a function, i.e. right answer, wrongmessage and wrong reason (
dispatch_buffer_method's name list simply has noentry, rather than the property genuinely being absent).
Why this is NOT the #8041 receiver-reroute family
These helpers are dead below
clean_arr_ptrin the same textual sense as theones #8090/#8109/#8119/#8120/#8130 fixed, and it is tempting to file them
together. They are a different bug, and "fixing the reroute" would make them
worse:
js_array_concatis the worked example, already noted in #8130's caveats. Nodegives
[{}]for a typed-array argument; perry gives[]today; and thepre-#8041 live reroute gave
[1,2,3]. It was wrong before #8041 and wrongafter, in different ways. Waking the reroute back up would restore an answer
node never produces.
The actual defect is one level up: the property should not resolve at all.
Perry's method dispatch answers
flatMapon a typed array because the fusedExpr::ArrayFlatMapfold andis_array_exprboth treatInt32Arrayas anarray, and nothing consults
%TypedArray%.prototype's membership. So the fixis a receiver-kind check at method resolution, producing the spec
TypeError, not a reroute inside the helper.js_array_concatspecifically is being handled by #8124(concat-spreadable); this issue covers the other eight.
Suggested shape
A single table of the nine names, consulted where the typed-array/Buffer
dispatch decision is already made —
dispatch_typed_array_method(
object/native_call_method/typed_array.rs) anddispatch_buffer_method(
object/buffer_dispatch.rs) already returnNone/ "is not a function" forunrecognised names, so the missing piece is preventing the static HIR folds
from claiming these nine for a receiver whose type is a typed array. That is
the same gate
is_array_expralready applies to excludeUint8ArrayfromcopyWithin's fold (local_array_methods.rs:800-839), generalised.Low urgency: every row here is a program that is already broken and would
throw under node, so no working code depends on the current answers. The
flatMaprow is the one worth prioritising, because it returns garbagevalues rather than an empty result, which a caller can propagate silently.
Context
Found by the exhaustive
Array.prototypereceiver sweep that produced #8135.The full 33-row table, with the funnel verdict and measured node diff for every
Array.prototype-reachable runtime entry point, is in the #8135 PR description.