From 5e00c96368fdad8dc8d5fd62598098515bb3669a Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Tue, 22 May 2018 14:37:06 -0700 Subject: [PATCH] Handle Infinity, -Infinity, NaN, and -0 in t.valueToNode(). (#8005) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit | Q                       | A | ------------------------ | --- | Fixed Issues? | Fixes #8001 | Patch: Bug Fix? | Y | Major: Breaking Change? | Not unless things were relying on a very specific AST structure as output | Minor: New Feature? | | Tests Added + Pass? | Yes | Documentation PR | | Any Dependency Changes? | | License | MIT The filed bug was for `-0`, but I also realize that `numericLiteral` also shouldn't be getting `-Infinity`/`Infinity` or `NaN` since those just get stringified with the JS-standard stringification logic which means we get a reference to `NaN` or `Infinity` identifiers, which could have been shadowed in a local scope and thus not be the right value. I've avoided that by generating `NaN` as `0/0` and the infinity values as `1/0` and `-1/0`. --- .../babel-types/src/converters/valueToNode.js | 24 +++++++++++++++++- packages/babel-types/test/converters.js | 25 +++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/babel-types/src/converters/valueToNode.js b/packages/babel-types/src/converters/valueToNode.js index 85aca82e0a..a4f195765c 100644 --- a/packages/babel-types/src/converters/valueToNode.js +++ b/packages/babel-types/src/converters/valueToNode.js @@ -12,6 +12,8 @@ import { arrayExpression, objectProperty, objectExpression, + unaryExpression, + binaryExpression, } from "../builders/generated"; export default function valueToNode(value: any): Object { @@ -37,7 +39,27 @@ export default function valueToNode(value: any): Object { // numbers if (typeof value === "number") { - return numericLiteral(value); + let result; + if (Number.isFinite(value)) { + result = numericLiteral(Math.abs(value)); + } else { + let numerator; + if (Number.isNaN(value)) { + // NaN + numerator = numericLiteral(0); + } else { + // Infinity / -Infinity + numerator = numericLiteral(1); + } + + result = binaryExpression("/", numerator, numericLiteral(0)); + } + + if (value < 0 || Object.is(value, -0)) { + result = unaryExpression("-", result); + } + + return result; } // regexes diff --git a/packages/babel-types/test/converters.js b/packages/babel-types/test/converters.js index f3966c7f3a..29c9abb378 100644 --- a/packages/babel-types/test/converters.js +++ b/packages/babel-types/test/converters.js @@ -19,8 +19,29 @@ describe("converters", function() { describe("valueToNode", function() { it("number", function() { expect(t.valueToNode(Math.PI)).toEqual(t.numericLiteral(Math.PI)); - expect(t.valueToNode(-Infinity)).toEqual(t.numericLiteral(-Infinity)); - expect(t.valueToNode(NaN)).toEqual(t.numericLiteral(NaN)); + expect(t.valueToNode(-Math.PI)).toEqual( + t.unaryExpression("-", t.numericLiteral(Math.PI)), + ); + expect(t.valueToNode(0)).toEqual(t.numericLiteral(0)); + expect(t.valueToNode(-0)).toEqual( + t.unaryExpression("-", t.numericLiteral(0)), + ); + expect(t.valueToNode(NaN)).toEqual( + t.binaryExpression("/", t.numericLiteral(0), t.numericLiteral(0)), + ); + expect(t.valueToNode(-NaN)).toEqual( + t.binaryExpression("/", t.numericLiteral(0), t.numericLiteral(0)), + ); + + expect(t.valueToNode(Infinity)).toEqual( + t.binaryExpression("/", t.numericLiteral(1), t.numericLiteral(0)), + ); + expect(t.valueToNode(-Infinity)).toEqual( + t.unaryExpression( + "-", + t.binaryExpression("/", t.numericLiteral(1), t.numericLiteral(0)), + ), + ); }); it("string", function() { expect(t.valueToNode('This is a "string"')).toEqual(