You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
Bug:
console.log(Object.create(null))throwsTypeError: Cannot convert object to primitive valueGoccia's
console.logformats values viaToStringLiteral, which now correctly performs ES2026 §7.1.17 ToString on objects (per #527). For an object without a working prototype chain (notoStringreachable),ToStringLiteralthrows TypeError per spec — which matchesString(Object.create(null))semantics. But that throw propagates out ofconsole.loginstead of being caught for display.V8/Node never invoke user
toString()fromconsole.logat all — they useutil.inspect, which renders structured output ([Object: null prototype] {}for the prototype-less case). Goccia has no equivalent.Reproduce
Output (both interpreter and bytecode modes):
V8/Node print:
[Object: null prototype] {}Surfaced by
#527 — the
ToStringLiteralES2026 refactor. Before that PR,TGocciaObjectValue.ToStringLiteralreturned 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 (FormatForMessageinGoccia.Builtins.TestingLibrary.pasafter #527): dispatch by type and use the existingTGocciaObjectValue.ToDebugStringfor objects so console output is structured and side-effect-free, matching V8/Nodeutil.inspectbehavior more closely. That also meansconsole.log({...})would no longer invoke a user-definedtoString()(it would render structurally) — a small UX shift but matching mainstream engine behavior.Scope notes
tests/built-ins/Console/may need updates for the rendering shift if any rely on usertoString()being invoked fromconsole.log.ToStringLiteralsemantics andToPropertyKeywiring; console output is a separate UX surface.Related
String(obj)usertoString()invocation and theToStringLiteralES2026 refactor that surfaced this.Symbol.IsPrimitivereturns false (separate ToPrimitive corner case).