Incorrect/inconsistent use of NaN in Reflect.parse()

RESOLVED DUPLICATE of bug 571617

Status

()

Core
JavaScript Engine
RESOLVED DUPLICATE of bug 571617
5 years ago
5 years ago

People

(Reporter: Joe Gibbs Politz, Unassigned)

Tracking

1.8 Branch
x86
Linux
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

5 years ago
User Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7

Steps to reproduce:

I ran the following in the JavaScript shell:

$ js
> Reflect.parse("NaN");
> Reflect.parse("'a-string' - 1");
> JSON.stringify(Reflect.parse("NaN"));
> JSON.stringify(Reflect.parse("'a-string' - 1"));



Actual results:

I got the following output:

$ js
> Reflect.parse("NaN");
({loc:{start:{line:1, column:0}, end:{line:1, column:3}, source:null}, type:"Program", body:[{loc:{start:{line:1, column:0}, end:{line:1, column:3}, source:null}, type:"ExpressionStatement", expression:{loc:{start:{line:1, column:0}, end:{line:1, column:3}, source:null}, type:"Identifier", name:"NaN"}}]})

> Reflect.parse("\"a-string\" - 1");
({loc:{start:{line:1, column:0}, end:{line:1, column:9}, source:null}, type:"Program", body:[{loc:{start:{line:1, column:0}, end:{line:1, column:9}, source:null}, type:"ExpressionStatement", expression:{loc:{start:{line:1, column:0}, end:{line:1, column:9}, source:null}, type:"Literal", value:NaN}}]})

js> JSON.stringify(Reflect.parse("NaN"));
"{\"loc\":{\"start\":{\"line\":1,\"column\":0},\"end\":{\"line\":1,\"column\":3},\"source\":null},\"type\":\"Program\",\"body\":[{\"loc\":{\"start\":{\"line\":1,\"column\":0},\"end\":{\"line\":1,\"column\":3},\"source\":null},\"type\":\"ExpressionStatement\",\"expression\":{\"loc\":{\"start\":{\"line\":1,\"column\":0},\"end\":{\"line\":1,\"column\":3},\"source\":null},\"type\":\"Identifier\",\"name\":\"NaN\"}}]}"

js> JSON.stringify(Reflect.parse("'a-string' - 1")); 
"{\"loc\":{\"start\":{\"line\":1,\"column\":0},\"end\":{\"line\":1,\"column\":14},\"source\":null},\"type\":\"Program\",\"body\":[{\"loc\":{\"start\":{\"line\":1,\"column\":0},\"end\":{\"line\":1,\"column\":14},\"source\":null},\"type\":\"ExpressionStatement\",\"expression\":{\"loc\":{\"start\":{\"line\":1,\"column\":0},\"end\":{\"line\":1,\"column\":14},\"source\":null},\"type\":\"Literal\",\"value\":null}}]}"




Expected results:

Ideally, the output for both cases should both have an ExpressionStatement containing an Identifier whose name is "NaN".  At the very least, the second case should yield some structure that is sensibly interpreted by JSON.stringify(), so it doesn't appear as null in the output string.

This came up in our project because we use the JSON.stringify(Reflect.parse(...)) pattern to produce JSON input for other tools, and NaN is turned to null by JSON.stringify().  We're left needing to hack some kind of workaround.

As far as I know, there's no such thing as a NaN literal in JavaScript (at least not that I can find here: http://es5.github.com/#x7.8.3).  So, if this constant folding is going to be performed, I suggest that it should give back the identifier NaN so it yields consistent JavaScript surface syntax.
You can't give back the identifier NaN because it might not have the same meaning:

  Reflect.parse("function f() { var NaN = 17; return 1/0 + NaN; }")

You could sometimes avoid that with some sort of shadowing analysis, but then you're left with your original problem.  And in some cases eval and with make such analysis impossible.

You could specify a replacer function when stringifying that converted NaN values into some sort of object tagged as a double, then make sure to use a corresponding reviver on the JSON.parse side.  That seems like the best choice to me.
Well, better would be if Reflect.parse didn't include any constant-folding.  That won't happen in the short term, although it might in the longer run.
I think there may have been a bug open to decouple Reflect.parse from constant folding. CC'ing dherman.
Hm, since bug 571617 was closed I thought there wasn't any constant folding left. Maybe I'm remembering wrong and there's still some simple constant folding that I didn't disable for Reflect.parse? Will look.

Dave
Joe, I think you may have an older build of the SpiderMonkey shell. In my current build, I get:

> Reflect.parse("\"a-string\" - 1");
({loc:{start:{line:1, column:0}, end:{line:1, column:14}, source:null}, type:"Program", body:[{loc:{start:{line:1, column:0}, end:{line:1, column:14}, source:null}, type:"ExpressionStatement", expression:{loc:{start:{line:1, column:0}, end:{line:1, column:14}, source:null}, type:"BinaryExpression", operator:"-", left:{loc:{start:{line:1, column:0}, end:{line:1, column:10}, source:null}, type:"Literal", value:"a-string"}, right:{loc:{start:{line:1, column:13}, end:{line:1, column:14}, source:null}, type:"Literal", value:1}}}]})

Dave
Marking dup since I don't believe there's any constant-folding left. Please reopen if there's some constant-folding left that I've forgotten about/overlooked.

Dave
Status: UNCONFIRMED → RESOLVED
Last Resolved: 5 years ago
Resolution: --- → DUPLICATE
Duplicate of bug: 571617
You need to log in before you can comment on or make changes to this bug.