Skip to content

spread: [...arr] on a class X extends Array instance throws "value is not iterable" #7541

Description

@proggeramlug

[...arr] on a class X extends Array instance throws TypeError: value is not iterable where node spreads it normally.

class MyArr extends Array {}
const sub = MyArr.from([1, 2, 3]);
console.log([...sub]);                  // node: [ 1, 2, 3 ]   perry: TypeError: value is not iterable
console.log(Array.isArray([...sub]));   // node: true          perry: TypeError

Where

array_from_spread_value (crates/perry-runtime/src/array/iterator.rs) has a branch for exactly this:

if crate::array::is_array_subclass_instance(value())
    && !crate::array::array_subclass_has_iterator_override(value())
{
    let snap = crate::array::array_subclass_dense_snapshot(value());
    return crate::value::js_nanbox_get_pointer(snap) as *mut ArrayHeader;
}

so one of is_array_subclass_instance or array_subclass_has_iterator_override is answering wrong for an instance produced by the inherited Array.from (MyArr.from(...)), and the value then falls all the way through to throw_not_iterable. Worth checking whether a directly-constructed new MyArr(...) behaves differently from an inherited-static-produced one — that split is the known-weak "native base-class subclassing" family (CLAUDE.md).

Provenance

Found while building a 32-case [...arr] semantics matrix for #7533. Pre-existing: reproduces byte-identically at f06270d06 (before the #7495/#7516/#7527 rooting stack) and is unchanged by #7540's dense fast path, which deliberately excludes subclass instances — they are GC_TYPE_OBJECT, not GC_TYPE_ARRAY, so they never reach the copy.

Every other case in that matrix matches node, including holes, sparse arrays, past-capacity indices, frozen arrays, index accessors, own @@iterator, strings, Set, Map, generators, arr.values()/arr.entries(), multi-element and call spreads.

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