Skip to content

fix: keep the sign before the radix prefix for negative numbers - #76

Open
spokodev wants to merge 1 commit into
mathiasbynens:mainfrom
spokodev:fix-negative-radix-numbers
Open

fix: keep the sign before the radix prefix for negative numbers#76
spokodev wants to merge 1 commit into
mathiasbynens:mainfrom
spokodev:fix-negative-radix-numbers

Conversation

@spokodev

Copy link
Copy Markdown

Problem

With numbers set to 'hexadecimal', 'binary', or 'octal', a negative number or bigint is serialized to a syntactically invalid JavaScript literal, because Number#toString(radix) / BigInt#toString(radix) place the minus sign before the digits — which leaves it after the radix prefix:

const jsesc = require('jsesc');

jsesc(-42, { numbers: 'hexadecimal' }); // '0x-2A'
jsesc(-42, { numbers: 'binary' });      // '0b-101010'
jsesc(-42, { numbers: 'octal' });       // '0o-52'

eval('(0x-2A)'); // SyntaxError: Invalid or unexpected token

The output therefore can't be evaluated or parsed, which contradicts jsesc's contract of producing valid JavaScript. The decimal branch already produces a valid signed literal (jsesc(-42)'-42'), so this is an inconsistency in the other radixes. bigints are affected identically (-42n'0x-2An').

Fix

Hoist the sign so it precedes the radix prefix, producing a valid signed literal (-0x2A). Works for both numbers and bigints.

Test

Added assertions that negative hexadecimal / binary / octal output keeps the sign before the prefix. The existing numbers vector that includes a negative bigint had baked in the invalid 0x-… / 0b-… / 0o-… output; those expectations are updated to the corrected -0x… / -0b… / -0o… literals. The full suite is green.

With `numbers` set to 'hexadecimal', 'binary', or 'octal', a negative
number or bigint produced an invalid literal such as `0x-2A`, `0b-101010`
or `0o-52`, because `Number#toString(radix)` / `BigInt#toString(radix)`
place the minus sign before the digits, leaving it after the radix prefix.
The output then threw when evaluated or parsed:

  jsesc(-42, { numbers: 'hexadecimal' }); // '0x-2A' -> SyntaxError

Hoist the sign so the result is a valid signed literal (`-0x2A`). The
decimal branch already produced valid signed output; this brings the other
radixes in line. The existing test vector for the negative bigint is
updated to the corrected literals.
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.

2 participants