Skip to content

fix(runtime): TypedArray + TypedArrayConstructors test262 parity (species/detached/ctor)#4999

Merged
proggeramlug merged 1 commit into
mainfrom
typedarray-finish-parity
Jun 11, 2026
Merged

fix(runtime): TypedArray + TypedArrayConstructors test262 parity (species/detached/ctor)#4999
proggeramlug merged 1 commit into
mainfrom
typedarray-finish-parity

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

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:

  • set-diff of the TypedArray-suite failure lists against the 48d6f8d baseline at every iteration (7 sweeps)
  • a --shard 0/12 built-ins language broad 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)

# Bug Fix
1 CanonicalNumericIndexString used Rust format!, which renders 1e21 as full decimal — keys like "1000000000000000000000"/"0.0000001" misclassified as numeric indices and threw render via js_number_to_string (typedarray_props.rs)
2 view-ctor ToIndex never ran valueOf, never threw on Symbol/BigInt offsets; new TA('1')/new TA(true) built empty arrays real ToNumber + truncate-before-range-check (typedarray_view.rs, typedarray/mod.rs)
3 new TA(object) reinterpreted functions as ArrayHeaders (crash); no @@iterator validation; no ToLength spec InitializeTypedArrayFromList/ArrayLike (typedarray/mod.rs)
4 toLocaleString was a plain join — never invoked a patched Number.prototype/BigInt.prototype toLocaleString spec per-element Invoke with user-patch detection (native_call_method.rs)
5 indexOf/lastIndexOf compared boxed BigInt pointers bitwise; len==0 after fromIndex coercion; includes() no-arg passed the NaN sentinel strict-equality helper + spec order (array/search.rs)
6 default sort() scrambled BigInt kinds (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) raw-lane sort per kind + total_cmp ordering + NaN-boxed returns
7 SpeciesConstructor never consulted the per-kind prototype object — defineProperty(TA.prototype, 'constructor', {get}) getters never fired prototype accessor/data patch lookup (typedarray/species.rs, GET path)
8 Integer-Indexed internals: in checked own keys only; symbol defineProperty string-coerced the key into a "Symbol(x)" field; Reflect own-key/extensibility predicates misread the TypedArrayHeader as ObjectHeader full [[HasProperty]], symbol value/accessor/attrs side tables, TA-aware predicates
9 latent heap corruption: Object.preventExtensions(ta) wrote the GC-header flag at addr-8, but small TAs are raw-alloc'd with no GcHeader — corrupted allocator metadata and produced random non-extensible reads non-extensible side table (typedarray_props.rs)
10 Reflect.set had no receiver parameter end-to-end; nothing implemented the Integer-Indexed exotic [[Set]] (proto-chain setters wrongly fired for canonical indices) HIR Expr::ReflectSet.receiver + exotic-[[Set]] interception in ordinary_set_with_receiver
11 %TypedArray%.from mapped all elements before coercing any (wrong observable order); array-like length getters that throw were swallowed per-element map→coerce→store interleave + real ToLength
12 misc: ta.set('567') no-op'd (spec: ToObject array-like), join(Symbol()) rendered instead of throwing, arrayBuffer.constructor === Uint8Array fixed

Deferred (diagnosed, ~35 tests)

  • Codegen-at-scale heisenbug (~8): every/some(NaN) + reduce/forEach/set crashes that reproduce only under the full 10-ctor × 5-factory harness matrix — deterministic (not GC; PERRY_GEN_GC=0 identical), passes with any ≤2-ctor or single-factory subset. Same class as the receiver-lowering escape/SSA notes from the built-ins-v2 campaign.
  • invoked-as-func (6): bare var f = TA.from; f([]) must TypeError — IMPLICIT_THIS is stale on bare calls, and clearing it would break the uncurry-this idiom.
  • function-identity asserts (3), Float16 bit-precision (3), symbol-accessor @@iterator on closures (2), misc (4).

Validation

  • cargo fmt --all clean, file-size gate clean, no Cargo.toml/CLAUDE.md/CHANGELOG.md edits (maintainer folds metadata at merge per contributor policy).
  • Runtime-only + one additive HIR field (ReflectSet.receiver); no ABI changes to existing runtime entry points except js_reflect_set gaining the 4th arg (codegen updated in lockstep).

… 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.
@proggeramlug proggeramlug merged commit 5cee682 into main Jun 11, 2026
12 of 13 checks passed
@proggeramlug proggeramlug deleted the typedarray-finish-parity branch June 11, 2026 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant