Skip to content

JSON.stringify writes an object literal or a tuple - #95

Merged
ASDAlexander77 merged 2 commits into
mainfrom
json-stringify-object-literal
Nov 12, 2026
Merged

ASDAlexander77 merged 2 commits into
mainfrom
json-stringify-object-literal

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

JSON.stringify({x: 1}) threw TypeError("JSON.stringify cannot read the fields of an object literal or a tuple"). Uncaught, that ended a program with 0xC0000409 and no output. Now it writes {"x":1}.

Needs ASDAlexander77/TypeScriptCompiler#832 merged first. That compiler PR makes for...in over an object literal or a tuple once for each field of its type, with the key as a literal. It also fixes a generic instance making other instances: on main, JSON.stringify([1, 2]) does not compile when it is a program's first stringify. The release workflow clones this repo's main, so merging this PR first would fail json.ts with the current compiler.

Change

  • toValue sends a tuple, or an "object" (an object literal with methods), to a new fieldsToValue.
  • fieldsToValue walks the fields with for (const key in value). value[key] is then that field with its own type.
  • A tuple of unnamed fields ("0" in value) becomes a JSON array, as in JavaScript.
  • An object leaves out function and undefined fields. In an array they become null.
  • A BigInt is still a TypeError.

Tests

  • json.ts gets a new objects(), run first, so the writer's inner instances are made from inside it.
  • It covers:
    • a plain literal
    • every kind of field
    • nested literals
    • an array of literals
    • a function field
    • get_-named value fields
    • a tuple
    • space

Verified locally (Windows x64, built with #832)

  • tests.ps1 passes for gc, rc, none and own, in release and debug, compiled and JIT.
  • Not run: Linux/WSL. The release run is this change's first Linux test.

Known limits

  • { "0": … } is written as an array, and a named tuple as an object. The compiler does not tell the two apart.
  • Under -mm=own, a literal holding a class instance ({ when: new Date(0) }) is rejected by the compiler's existing own rule.

🤖 Generated with Claude Code

ASDAlexander77 and others added 2 commits November 12, 2026 21:03
`JSON.stringify({x: 1})` threw a TypeError ("cannot read the fields of an object literal or a
tuple"), which, uncaught, ended the program with 0xC0000409 and no output. The compiler now
makes `for...in` over an object literal or a tuple for each field of its type, with the key a
literal, so `value[key]` is that field with its own type; toValue walks the fields with it.
A tuple of unnamed fields is an array, as in JavaScript; a function or an undefined field is
left out of an object. A BigInt is still a TypeError.

Needs the compiler change in TypeScriptCompiler (for...in over fields, and a generic's
instance making other instances: `JSON.stringify([[1], [2]])` failed to compile in a program
that had not stringified a number first).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant