Skip to content

console.log on prototype-less object throws TypeError #536

@frostney

Description

@frostney

Bug: console.log(Object.create(null)) throws TypeError: Cannot convert object to primitive value

Goccia's console.log formats values via ToStringLiteral, which now correctly performs ES2026 §7.1.17 ToString on objects (per #527). For an object without a working prototype chain (no toString reachable), ToStringLiteral throws TypeError per spec — which matches String(Object.create(null)) semantics. But that throw propagates out of console.log instead of being caught for display.

V8/Node never invoke user toString() from console.log at all — they use util.inspect, which renders structured output ([Object: null prototype] {} for the prototype-less case). Goccia has no equivalent.

Reproduce

./build.pas loader
cat > /tmp/probe.js <<'EOJS'
const obj = Object.create(null);
console.log(obj);
EOJS
./build/GocciaScriptLoader /tmp/probe.js

Output (both interpreter and bytecode modes):

TypeError: Cannot convert object to primitive value

V8/Node print: [Object: null prototype] {}

Surfaced by

#527 — the ToStringLiteral ES2026 refactor. Before that PR, TGocciaObjectValue.ToStringLiteral returned a hardcoded [object <Tag>] and could not throw, so this code path was implicitly safe.

Likely fix area

source/units/Goccia.Builtins.Console.pas — the value-formatter callsites. The natural fix mirrors what the test-runner already does (FormatForMessage in Goccia.Builtins.TestingLibrary.pas after #527): dispatch by type and use the existing TGocciaObjectValue.ToDebugString for objects so console output is structured and side-effect-free, matching V8/Node util.inspect behavior more closely. That also means console.log({...}) would no longer invoke a user-defined toString() (it would render structurally) — a small UX shift but matching mainstream engine behavior.

Scope notes

  • Tests in tests/built-ins/Console/ may need updates for the rendering shift if any rely on user toString() being invoked from console.log.
  • Out of scope of Make ToStringLiteral ES2026-compliant; add ToPropertyKey #527 — that PR was about the spec-correct ToStringLiteral semantics and ToPropertyKey wiring; console output is a separate UX surface.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    engineTGocciaEngine: language semantics, ECMAScript built-ins, parser, interpreter, bytecode VM

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions