Skip to content

TypedArray.prototype.at() returns undefined instead of element value (Int32Array, Float64Array, Uint8Array) #269

@proggeramlug

Description

@proggeramlug

Summary

Tracked in test-parity/known_failures.json as test_gap_array_methods (status: known_limitation). Categorical typed-array gap, same family as test_gap_typed_arrays: Perry's .at() codegen fast path is wired for regular Array but not for the TypedArray instance shapes (Int32Array, Float64Array, Uint8Array, …).

Perry:  Int32Array.at(0): undefined
Node:   Int32Array.at(0): 1

Was passing 26/28 at v0.5.319 after the SSO-unboxing fix transitively flipped it; regressed somewhere in v0.5.319→v0.5.343 (likely an SSO/typed-array interaction in the bulk extraction series).

Minimal repro

const i32 = new Int32Array([1, 2, 3, 4, 5]);
console.log(i32.at(0));   // expected: 1  — actual: undefined
console.log(i32.at(-1));  // expected: 5  — actual: undefined

const f64 = new Float64Array([1.1, 2.2, 3.3]);
console.log(f64.at(-1));  // expected: 3.3  — actual: undefined

const u8 = new Uint8Array([255, 0, 128]);
console.log(u8.at(1));    // expected: 0  — actual: undefined

// (Regular Array.at still works:)
const arr = [10, 20, 30];
console.log(arr.at(-1));  // 30  ✓

Full test: test-files/test_gap_array_methods.ts (the Int32Array.at(0): / Int32Array.at(-1): / Float64Array.at(-1): / Uint8Array.at(1): lines).

How to reproduce

git clone https://github.com/PerryTS/perry && cd perry
cargo build --release -p perry-runtime -p perry-stdlib -p perry

node --experimental-strip-types test-files/test_gap_array_methods.ts > /tmp/node.out
./target/release/perry test-files/test_gap_array_methods.ts -o /tmp/perry_test
/tmp/perry_test > /tmp/perry.out
diff /tmp/node.out /tmp/perry.out

Likely fix area

crates/perry-codegen/src/lower_array_method.rs — the .at(i) arm dispatches against the receiver's HIR Type. The Array variant works; Int32Array / Float64Array / Uint8Array typed-array shapes fall through to a generic byname-property dispatch that returns undefined.

For each TypedArray flavor, the fast path needs to:

  1. Look up the receiver's element type and stride (Int32 = 4 bytes, Float64 = 8, Uint8 = 1).
  2. Read length from the Uint8Array/Int32Array/Float64Array header.
  3. Normalize the index (negative → length+i).
  4. Bounds check (returns undefined on out-of-range, like the spec).
  5. Direct memory load + NaN-box / int box for the result.

Related

  • Was flipped to passing transiently by the v0.5.319 SSO fix; regressed in the v0.5.319→v0.5.343 extraction series. A bisect from v0.5.319 forward might point at the exact commit that broke it.
  • test_gap_typed_arrays is the other categorical gap (new Uint8Array(buffer.buffer) and friends — different shape but same crate).

Acceptance

test-files/test_gap_array_methods.ts matches Node byte-for-byte; remove from known_failures.json. Update the stale CLAUDE.md TypeScript-Parity-Status header (currently 26/28; actual is 25/28 with this + console_methods + typed_arrays failing).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions