Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stringify with more than 3 arguments should respect the first 3 argum… #806

Conversation

morfav
Copy link

@morfav morfav commented Dec 17, 2020

…ents

resolves #767

Copy link
Collaborator

@gbrail gbrail left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you're looking at this, do you mind looking carefully at:

https://www.ecma-international.org/ecma-262/11.0/index.html#sec-json.stringify

and seeing if there are other things that we should fix? For instance, I see in here that we initialize value to null, rather than Undefined.instance, which means that we're likely not handling undefined properly -- and we're not, since JSON.stringify(undefined) returns null and not undefined.

@@ -91,11 +91,11 @@ public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope,
case Id_stringify: {
Object value = null, replacer = null, space = null;
switch (args.length) {
default:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit conflicted about this since it's a very clever switch statement, but it's also a bit confusing. Would a series of "if (args.length >= 1)", "if (args.length >= 2)", and such statements be easier to follow for future maintainers? I realize that I'm suggesting three comparisons versus (theoretically) one, but it does seem easier to follow. I don't have a strong opinion, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned in the issue that I opened that before the regression bug was introduced by moving the default case to the bottom, the original switch statement was written with the default case at the top. I think it looked a lot cleaner than the cascading if statements. Perhaps it only needs a comment that the default case is for >= 3?

             switch (args.length) {
                   /* >= 3     */ default: space = args[2];
                   /* fallthru */ case 2: replacer = args[1];
                   /* fallthru */ case 1: value = args[0];
                   /* fallthru */ case 0:
               }  

@morfav
Copy link
Author

morfav commented Dec 28, 2020

I replaced the switch (which admittedly also took me some time to figure out), with some if statements that arguably look a bit like an abomination anyway :)

I did some extra investigation, things like:
JSON.stringify()
JSON.stringify({})
JSON.stringify(null)
JSON.stringify(undefined)
JSON.stringify([,1,undefined])
JSON.stringify(NaN)
JSON.stringify(Number.NaN)
JSON.stringify(Infinity)

work well, apart from the first one (which you pointed out). I added a fix for this case.

I also ran the latest test262 tests, some of the recurring themes are to do with the replacer, and have already been pointed out in this issue
Namely:

  1. rhino doesn't remove duplicates from the replacer array, which should be relatively straightforward to fix:
    For example, JSON.stringify({"key":"value"},["key", "key"]) would output "key" twice
  2. from some debugging, it looks like JSON.stringify({"1":"value"}, ["1"]) treats the "1" in the object as a number, vs the "1" in the array as a string. So the output is actually empty since the indexOrHash values end up different and are not matched.
    I was thinking of looking to address these two in a separate commit, if/when I can figure number 2 out.

@gbrail
Copy link
Collaborator

gbrail commented Dec 31, 2020

Thanks for making those improvements -- I think that it makes sense now.

If you have time to investigate other issues with Stringify then that'd be very helpful of course, but I agree that if you do it should be a separate PR. Thanks!

@gbrail gbrail merged commit 20d71ae into mozilla:master Dec 31, 2020
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.

Issue with JSON.stringify when called with more than 3 arguments
3 participants