Skip to content

correctness: class reference + number treats the INT32-boxed class ref as a number (should be string concat) #9087

Description

@proggeramlug

Repro

class K { static m(): number { return 1; } }
let s: any = K;
for (let i = 0; i < 8; i++) s += i;   // also reproduces without the loop: K + 1
console.log(typeof s, String(s).slice(0, 20));

node 26.5.1: string class K { static m()+ on a class does ToPrimitive → the function source string → concatenation.

perry (main b2f163c5a0, also with PERRY_PACKED_LOOP_NUMERIC_ACCUMULATOR=0, so unrelated to #9060): number 29 — the class reference participates as a NUMBER.

Analysis

A ClassRef is NaN-boxed with INT32_TAG carrying the registered class id (see the #321 note on value_bits_to_number in array/header.rs, which added is_class_id_registered exactly to keep class refs off numeric paths — for array slots). The dynamic + path (or an upstream numeric-operand classifier) apparently lacks that exclusion, so class + number takes the numeric arm instead of ToPrimitive/concat.

Found while adversarially testing #9060's accumulator admission (which is not implicated — its tag test rejects the whole NaN-box band including INT32); reported by the ECS/ops perf campaign, session https://claude.ai/code/session_019WVcWKmYsUBnnFB7nBgbBJ. Repro file preserved at /private/tmp/acc-int32.ts shape above.

The same missing exclusion may affect other INT32-band consumers (-/* coercions, comparisons); worth auditing is_class_id_registered call sites vs the numeric-classifier entry points.

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