Last Comment Bug 722087 - Incorrect/inconsistent use of NaN in Reflect.parse()
: Incorrect/inconsistent use of NaN in Reflect.parse()
Status: RESOLVED DUPLICATE of bug 571617
:
Product: Core
Classification: Components
Component: JavaScript Engine (show other bugs)
: 1.8 Branch
: x86 Linux
-- normal (vote)
: ---
Assigned To: general
:
: Jason Orendorff [:jorendorff]
Mentors:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2012-01-28 14:10 PST by Joe Gibbs Politz
Modified: 2012-08-19 20:52 PDT (History)
3 users (show)
See Also:
Crash Signature:
(edit)
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---


Attachments

Description User image Joe Gibbs Politz 2012-01-28 14:10:17 PST
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.
Comment 1 User image Jeff Walden [:Waldo] (remove +bmo to email) 2012-01-28 14:34:40 PST
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.
Comment 2 User image Jeff Walden [:Waldo] (remove +bmo to email) 2012-01-28 15:01:31 PST
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.
Comment 3 User image Chris Leary [:cdleary] (not checking bugmail) 2012-01-30 16:47:02 PST
I think there may have been a bug open to decouple Reflect.parse from constant folding. CC'ing dherman.
Comment 4 User image Dave Herman [:dherman] 2012-02-01 20:14:51 PST
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
Comment 5 User image Dave Herman [:dherman] 2012-02-01 20:27:08 PST
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
Comment 6 User image Dave Herman [:dherman] 2012-08-19 20:52:58 PDT
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

*** This bug has been marked as a duplicate of bug 571617 ***

Note You need to log in before you can comment on or make changes to this bug.