Skip to content

runtime: String(new Map()) renders "[object Object]", not "[object Map]" — the ToString fallback ignores Symbol.toStringTag #6374

Description

@proggeramlug

Summary

String(x) on a builtin exotic with a Symbol.toStringTag renders "[object Object]" instead of "[object <Tag>]".

Repro

console.log(String(new Map()));            // node: [object Map]      perry: [object Object]
console.log(String(new Set()));            // node: [object Set]      perry: [object Object]
console.log(String(Promise.resolve(1)));   // node: [object Promise]  perry: [object Object]
console.log(`${new Map()}`);               // node: [object Map]      perry: [object Object]

Why

Object.prototype.toString is spec'd to read [[Get]](O, @@toStringTag) and use it when it is a string (ES2024 §20.1.3.6); Map.prototype[@@toStringTag] is "Map", Set's is "Set", Promise's is "Promise". Perry's ToString path (js_jsvalue_to_string in crates/perry-runtime/src/value/to_string.rs) ends in a hardcoded "[object Object]" fallback that never consults the tag. Note the runtime does have a to_string_tag.rs — it just isn't wired into this fallback.

An OWN toString on these instances is already honoured correctly (m.toString = () => "X"; String(m)"X"), so this is purely the default-tag rendering.

Found while fixing #6370 (own toString overrides ignored on the ToString coercion path for RegExp/Date); pre-existing on main.

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