Skip to content

Array's hole should be undefined rather than 0 #323

Closed

Description

@codehz

What happened

See below example

What you expected

It should match js behavior

Minimal reproduction

const values = new Array(4);

console.log("values.length", values.length);
console.log("values[1]", values[1]);
console.log("values[1] === undefined", values[1] === undefined);
console.log("1 in values", 1 in values);
console.log("Object.keys(values)", Object.keys(values));

const read = values[1];
console.log("read !== undefined", read !== undefined);

values[2] = undefined;
console.log("values[2]", values[2]);
console.log("values[2] === undefined", values[2] === undefined);
console.log("2 in values", 2 in values);

Command you ran:

perry test.ts && ./test

Output:

values.length 4
values[1] 0
values[1] === undefined false
1 in values false
Object.keys(values) []
read !== undefined true
values[2] undefined
values[2] === undefined true
2 in values false

Expected:

values.length 4
values[1] undefined
values[1] === undefined true
1 in values false
Object.keys(values) []
read !== undefined false
values[2] undefined
values[2] === undefined true
2 in values true

Environment

  • Perry version: -/5/408
  • Host OS: ArchLinux
  • Target: native
  • Rust toolchain (if building from source): rustc 1.95.0 (59807616e 2026-04-14)
  • Installed via: from source

Diagnostic output

Perry Doctor

Environment Checks
──────────────────
  ✓ perry version: 0.5.408
  ✓ update status: up to date
  ✓ clang (LLVM codegen): clang version 22.1.3
  ✓ system linker (cc): cc (GCC) 15.2.1 20260209
  ✓ runtime library: /home/codehz/Projects/perry/target/release/libperry_runtime.a
  ⚠ project config (perry.toml): not found - run: perry init

All critical checks passed with some warnings.

Anything else

Also found in my ecs's demo

Activity

  1. added
    bugConfirmed defect or regression
    on Apr 30, 2026
  2. changed the title [-]Array cannot have hole in perry[/-] [+]Array's hole should be undefined rather than 0[/+] on Apr 30, 2026
  3. proggeramlug commented on Apr 30, 2026

    @proggeramlug
    Contributor

    Fixed in 2f04bb1 (v0.5.412). Your literal repro now matches Node byte-for-byte:

    values.length 4
    values[1] undefined
    values[1] === undefined true
    1 in values false
    Object.keys(values) []
    read !== undefined false
    values[2] undefined
    values[2] === undefined true
    2 in values true
    

    Implementation uses an internal TAG_HOLE sentinel for never-written slots so Object.keys / in can distinguish a hole from an explicit arr[i] = undefined write, while reads translate HOLE → UNDEFINED so user code never sees the sentinel. Pinned via test-files/test_issue_323_array_holes.ts — exercises your repro shape plus the MIN_ARRAY_CAPACITY=16 padding boundary, the empty-array edge, and a function-scoped for-loop hitting the bounded-index inline fast path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regression

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions