Skip to content

Map/Set iterator objects expose synthetic .return/.throw; spec has neither #9086

Description

@proggeramlug

Map/Set/string iterator objects answer a bound method for return and throw, but per spec those prototypes have no such properties — only generator objects do.

const it = new Set([1, 2]).values();
console.log(typeof it.return, typeof it.throw);
node v26.5.1  undefined undefined
perry         function  function

typeof it[Symbol.iterator] === "function" is correct and should stay.

Where

crates/perry-runtime/src/object/field_get_set/accessors.rs, map_set_iterator_property — the synthetic bind arm:

let bind_name: Option<&'static [u8]> = match key_bytes {
    b"return" => Some(b"return"),
    b"throw" => Some(b"throw"),
    b"@@iterator" => Some(b"@@iterator"),
    _ => None,
};

Noticed while auditing #9075, which moved this arm out of get_field_by_name_tail.rs verbatim. It is not introduced there — main answers "function" too, confirmed by A/B — so this is long-standing and predates that extraction.

Why it is not purely cosmetic

return is protocol-visible: an early break out of a for…of calls IteratorClose, which does GetMethod(iterator, "return") and invokes it when present. Synthesizing one means we call into a bound method on paths where the spec performs no call at all, so the observable difference is not limited to typeof. Worth checking what the synthesized return actually does on an abrupt loop exit before deciding whether to delete the arm or make it spec-shaped.

The likely fix is to drop return/throw from the bind list and let the generic scans answer undefined, keeping @@iterator. That needs a check for callers relying on the current behaviour — dispatch_set_iterator_method/dispatch_map_iterator_method may route return through this path for their own close handling.

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