Skip to content

fix(runtime): serialize BigInt attribute values instead of throwing#3471

Open
chatman-media wants to merge 1 commit into
pugjs:masterfrom
chatman-media:fix/bigint-attribute-values
Open

fix(runtime): serialize BigInt attribute values instead of throwing#3471
chatman-media wants to merge 1 commit into
pugjs:masterfrom
chatman-media:fix/bigint-attribute-values

Conversation

@chatman-media

Copy link
Copy Markdown

Problem

Fixes #3437.

Passing a BigInt as an attribute value throws instead of rendering it. For example:

pug.render("input(type='hidden' value=whatIsIt)", { whatIsIt: BigInt(10) });

On the current master this throws:

TypeError: Do not know how to serialize a BigInt

(On 3.0.2, as reported in #3437, it produced value=""10"".) The expected output is value="10", exactly as it already works for a Number.

Cause

In pug_attr (packages/pug-runtime/index.js), every non-string value is serialized with JSON.stringify:

if (typeof val !== 'string') {
  val = JSON.stringify(val);
  ...
}

typeof someBigInt === 'bigint', so a BigInt reaches JSON.stringify, which throws for BigInt values. Number works only because JSON.stringify(10) === "10".

This affects both:

  • runtime values (value=local where the local is a BigInt), and
  • compile-time constant attributes, since pug-attrs folds constants through runtime.attr(...) too.

Fix

Coerce bigint to its decimal string before the JSON.stringify branch, mirroring how a Number is rendered and preserving precision beyond Number.MAX_SAFE_INTEGER:

if (typeof val === 'bigint') {
  val = val.toString();
}

Tests

Added BigInt cases to the existing attr test in packages/pug-runtime/test/index.test.js (all escaped/terse combinations, plus a value above Number.MAX_SAFE_INTEGER to confirm precision is preserved). The test fails without the fix (TypeError: Do not know how to serialize a BigInt) and passes with it.

The two failing tests in packages/pug/test/error.reporting.test.js are pre-existing on master (outdated V8 error-message wording, see #3466) and are unrelated to this change.

`pug_attr` serialized any non-string attribute value with
`JSON.stringify`, which throws `TypeError: Do not know how to serialize a
BigInt` for `bigint` values. As a result an attribute whose value is a
BigInt (e.g. `input(value=count)` with `count` a BigInt local) crashed
rendering instead of producing `value="10"` as it does for a Number.

Coerce `bigint` values to their decimal string before the
`JSON.stringify` branch, mirroring how Numbers are handled and preserving
precision beyond `Number.MAX_SAFE_INTEGER`.

Fixes pugjs#3437
@rollingversions

Copy link
Copy Markdown

There is no change log for this pull request yet.

Create a changelog

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.

Bigints are parsed incorrectly resulting in escaped double quotes

1 participant