fix(runtime): TypedArray + TypedArrayConstructors test262 parity (species/detached/ctor)#4999
Merged
Merged
Conversation
… parity (species/detached/ctor/internals) built-ins/TypedArray 778->834 and built-ins/TypedArrayConstructors 453->518 (1231->1350 of 1385 judged, 88.9%->97.5%), zero regressions vs the 48d6f8d baseline (set-diff per sweep). Root causes: - CanonicalNumericIndexString classified '1e21'-style keys with Rust format! (full-decimal rendering) instead of JS ToString -> ordinary keys like "1000000000000000000000" / "0.0000001" threw 'Invalid typed array index'. - new TA(buffer, byteOffset, length): ToIndex never ran valueOf and never threw on Symbol/BigInt offsets/lengths; string/bool single-arg lengths built empty arrays. - new TA(plainObject/function): spec iterator-or-array-like resolution (non-callable @@iterator TypeError, ToLength on length incl. abrupt completions, RangeError past 2^32) - function sources were reinterpreted as ArrayHeaders (crash). - %TypedArray%.prototype.toLocaleString: spec per-element Invoke honoring a patched Number.prototype/BigInt.prototype toLocaleString (abrupt completions propagate). - indexOf/lastIndexOf compared boxed BigInt pointers bitwise (never matched); len==0 must precede fromIndex coercion; includes() no-arg passed the NaN sentinel as searchElement. - Default sort scrambled BigInt64/BigUint64 (sorted boxed-pointer bits) and mis-ordered NaN/-0; sort/toSorted/toReversed/copyWithin/with returned raw pointer bits as f64 (String(ta.sort()) -> '2.2e-311'). - SpeciesConstructor: Get(O,'constructor') never consulted the per-kind prototype object, so defineProperty(TA.prototype,'constructor',{get}) getters never fired (also wired into the property-get path). - Integer-Indexed exotic internals: 'in' now walks the prototype chain for ordinary keys; symbol-keyed defineProperty stores value/accessor + attrs in the symbol side tables (string-coercion filed them under 'Symbol(x)'); Reflect.defineProperty TA own-key/extensibility predicates fixed. - Object.preventExtensions(ta) wrote the GC-header flag at addr-8, but small typed arrays are raw-alloc'd with NO GcHeader -> allocator-metadata corruption + random non-extensible reads. Replaced with a side table (typedarray_props), consulted by defineProperty/Reflect/isExtensible. - Reflect.set gained the receiver parameter end-to-end (HIR Expr::ReflectSet, codegen, runtime) and ordinary_set_with_receiver now implements the Integer-Indexed exotic [[Set]]: canonical numeric keys never consult the prototype chain; a receiver distinct from the TA redirects the write (including TA receivers rejecting invalid indices). - %TypedArray%.from: map and per-kind coercion now interleave per element (an abrupt coercion stops later map calls); array-like sources run real ToLength (throwing length getters propagate). - ta.set('567') treats a primitive string as the spec ToObject array-like; TA sources with a patched own valueOf/toString run it for ToNumber/ToBigInt. - join(separator): Symbol separator throws TypeError (both the typed-array and Array.prototype.join_value paths). - arrayBuffer.constructor now answers ArrayBuffer/SharedArrayBuffer instead of Uint8Array. Deferred (diagnosed, out of scope): a codegen-at-scale heisenbug cluster (every/some(NaN) + reduce/forEach crashes that reproduce only under the full 10-ctor x 5-factory harness matrix; deterministic, not GC), invoked-as-func IMPLICIT_THIS staleness, %TypedArray% function-identity asserts, Float16 bit-precision.
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
Closes the two untouched TypedArray test262 clusters: built-ins/TypedArray 778→834 (98%) and built-ins/TypedArrayConstructors 453→518 (96%) — 1231→1350 of 1385 judged (88.9% → 97.5%, +119), verified against the node v26 oracle via
test262_subset.py.Zero regressions, proven two ways:
--shard 0/12 built-ins languagebroad sweep (2645 judged) against a from-scratch merge-base baseline build: 0 new failures, +11 shard-visible fixes (94.3% → 94.7%)Root causes (each confirmed by repro vs node before fixing)
CanonicalNumericIndexStringused Rustformat!, which renders1e21as full decimal — keys like"1000000000000000000000"/"0.0000001"misclassified as numeric indices and threwjs_number_to_string(typedarray_props.rs)ToIndexnever ranvalueOf, never threw on Symbol/BigInt offsets;new TA('1')/new TA(true)built empty arraystypedarray_view.rs,typedarray/mod.rs)new TA(object)reinterpreted functions asArrayHeaders (crash); no@@iteratorvalidation; noToLengthInitializeTypedArrayFromList/ArrayLike(typedarray/mod.rs)toLocaleStringwas a plain join — never invoked a patchedNumber.prototype/BigInt.prototypetoLocaleStringInvokewith user-patch detection (native_call_method.rs)indexOf/lastIndexOfcompared boxed BigInt pointers bitwise;len==0after fromIndex coercion;includes()no-arg passed the NaN sentinelarray/search.rs)sort()scrambled BigInt kinds (sorted boxed-pointer bits) and mis-ordered NaN/−0;sort/toSorted/toReversed/copyWithin/withreturned raw pointer bits as f64 (String(ta.sort())→2.2e-311)total_cmpordering + NaN-boxed returnsSpeciesConstructornever consulted the per-kind prototype object —defineProperty(TA.prototype, 'constructor', {get})getters never firedtypedarray/species.rs, GET path)inchecked own keys only; symboldefinePropertystring-coerced the key into a"Symbol(x)"field;Reflectown-key/extensibility predicates misread theTypedArrayHeaderasObjectHeader[[HasProperty]], symbol value/accessor/attrs side tables, TA-aware predicatesObject.preventExtensions(ta)wrote the GC-header flag ataddr-8, but small TAs are raw-alloc'd with no GcHeader — corrupted allocator metadata and produced random non-extensible readstypedarray_props.rs)Reflect.sethad no receiver parameter end-to-end; nothing implemented the Integer-Indexed exotic[[Set]](proto-chain setters wrongly fired for canonical indices)Expr::ReflectSet.receiver+ exotic-[[Set]]interception inordinary_set_with_receiver%TypedArray%.frommapped all elements before coercing any (wrong observable order); array-likelengthgetters that throw were swallowedta.set('567')no-op'd (spec: ToObject array-like),join(Symbol())rendered instead of throwing,arrayBuffer.constructor === Uint8ArrayDeferred (diagnosed, ~35 tests)
every/some(NaN)+reduce/forEach/setcrashes that reproduce only under the full 10-ctor × 5-factory harness matrix — deterministic (not GC;PERRY_GEN_GC=0identical), passes with any ≤2-ctor or single-factory subset. Same class as the receiver-lowering escape/SSA notes from the built-ins-v2 campaign.var f = TA.from; f([])must TypeError —IMPLICIT_THISis stale on bare calls, and clearing it would break the uncurry-this idiom.@@iteratoron closures (2), misc (4).Validation
cargo fmt --allclean, file-size gate clean, noCargo.toml/CLAUDE.md/CHANGELOG.mdedits (maintainer folds metadata at merge per contributor policy).ReflectSet.receiver); no ABI changes to existing runtime entry points exceptjs_reflect_setgaining the 4th arg (codegen updated in lockstep).