Handle Infinity, -Infinity, NaN, and -0 in t.valueToNode(). (#8005)

| Q                        | A <!--(Can use an emoji 👍) -->
| ------------------------ | ---
| 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         | <!-- If so, add `[skip ci]` to your commit message to skip CI -->
| 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`.
This commit is contained in:
Logan Smyth 2018-05-22 14:37:06 -07:00 committed by GitHub
parent b4d18f4764
commit 5e00c96368
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 3 deletions

View File

@ -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

View File

@ -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(