Skip to content

fix(toml): emit TOML literals for Infinity/NaN/Date in arrays#7163

Draft
spokodev wants to merge 1 commit into
denoland:mainfrom
spokodev:fix/toml-stringify-primitive-and-datetime-literals
Draft

fix(toml): emit TOML literals for Infinity/NaN/Date in arrays#7163
spokodev wants to merge 1 commit into
denoland:mainfrom
spokodev:fix/toml-stringify-primitive-and-datetime-literals

Conversation

@spokodev
Copy link
Copy Markdown

Primitive and mixed array stringification went through code paths that produced invalid TOML for non-finite numbers and Date values. The issue author flagged six distinct cases in #7162; this PR addresses the four with a deterministic spec-aligned fix and leaves the two null-related ones for maintainer guidance, since they are a design call.

What changed

#arrayDeclaration (primitive arrays) previously routed values through JSON.stringify, which has no representation for Infinity, -Infinity, NaN, or TOML datetime literals. #printAsInlineValue (mixed arrays) returned numbers verbatim (so Infinity printed as the JS identifier) and wrapped Dates in string quotes.

A new private helper #printPrimitive produces TOML-compliant literals for Date, string, RegExp, number (including inf/-inf/nan) and boolean. Both array paths now route primitives through it.

Behaviour for null/undefined inside arrays is unchanged - the code still throws Should never reach. The issue author flagged this as a design call (TOML has no null), so it stays as-is until maintainers decide between a clearer error message, silent skip, or another shape.

Before/after

// primitive array
stringify({x: [Infinity, -Infinity, NaN]})
// before: x = [null,null,null]
// after:  x = [inf,-inf,nan]

stringify({x: [new Date(0)]})
// before: x = [\"1970-01-01T00:00:00.000Z\"]
// after:  x = [1970-01-01T00:00:00.000]

// mixed array
stringify({x: [Infinity, -Infinity, NaN, {}]})
// before: x = [Infinity,-Infinity,NaN,{}]   (invalid TOML)
// after:  x = [inf,-inf,nan,{}]

stringify({x: [new Date(0), {}]})
// before: x = [\"1970-01-01T00:00:00.000\",{}]
// after:  x = [1970-01-01T00:00:00.000,{}]

Tests

Six new cases in toml/stringify_test.ts:

  • positive: Infinity/-Infinity/NaN in primitive arrays render as inf/-inf/nan
  • positive: Date in primitive arrays renders as a bare TOML datetime literal
  • positive: Infinity/-Infinity/NaN in mixed arrays
  • positive: Date in mixed arrays
  • regression-check: finite numbers in primitive arrays keep their JSON-style representation (covers the new #printPrimitive path that replaced JSON.stringify)
  • regression-check: scalar Infinity/NaN/Date declarations (not array elements) are unaffected

One existing test (stringify() handles mixed array) had a date inside a mixed inline-table that was previously emitted with quotes. The expected output is updated to the spec-aligned bare datetime literal.

`deno test --allow-all toml/` -> 689 passed, 0 failed, 111 ignored.
`deno fmt` and `deno lint` clean on the changed files.

Fixes #7162 (partial - null handling left for maintainer guidance).

Primitive and mixed array stringification went through code paths
that produced invalid TOML for non-finite numbers and Date values:

- `[Infinity, -Infinity, NaN]` rendered as `[null,null,null]`
  because `#arrayDeclaration` used `JSON.stringify` which has no
  TOML equivalents for those values.
- `[new Date(0)]` rendered as `["1970-01-01T00:00:00.000Z"]` for
  the same reason - a quoted ISO string instead of a TOML datetime
  literal.
- Mixed arrays like `[Infinity, {}]` and `[new Date(0), {}]` ran
  through `#printAsInlineValue` which returned numbers verbatim
  (so Infinity printed as the JS identifier) and wrapped Dates in
  string quotes.

Introduce `#printPrimitive` that produces TOML-compliant literals
for Date, string, RegExp, number (including inf/-inf/nan) and
boolean. `#arrayDeclaration` and `#printAsInlineValue` now route
primitives through it.

The behaviour for `null`/`undefined` inside arrays is left
unchanged (still throws "Should never reach") since the issue
author flagged it as a design call for the maintainers.

Updates one existing test that encoded the old quoted-Date output
inside a mixed array. The new output matches the TOML 1.0 spec for
datetime literals.

Fixes denoland#7162 (partial - null handling deferred per the issue).
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions github-actions Bot added the toml label May 29, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.57%. Comparing base (cdf74a8) to head (8dd582f).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7163   +/-   ##
=======================================
  Coverage   94.57%   94.57%           
=======================================
  Files         636      636           
  Lines       52142    52147    +5     
  Branches     9401     9406    +5     
=======================================
+ Hits        49315    49320    +5     
  Misses       2249     2249           
  Partials      578      578           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@std/toml: Inline array stringification mishandles edge cases

2 participants