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

JSON.parse broken #206

Closed
lastmjs opened this issue Dec 13, 2023 · 2 comments
Closed

JSON.parse broken #206

lastmjs opened this issue Dec 13, 2023 · 2 comments

Comments

@lastmjs
Copy link

lastmjs commented Dec 13, 2023

In Chrome, Node, and Firefox this works just fine:

JSON.parse('19686109595169230000')
// 19686109595169230000

In QuickJS in wasm32-wasi (using Javy) and on my Ubuntu laptop x86 this is broken:

JSON.parse('19686109595169230000')
// 19686109595169227000
ulan added a commit to ulan/javy that referenced this issue Dec 15, 2023
The upstream issue: bellard/quickjs#206

This changes `js_strtod` to use the standard `strtod` in cases
when the input number is not an integer that is guaranteed to be
representable as a double without any precision errors.

As a result, parsing of integers that exceed 2^53 as floats becomes
slower than before, but it also becomes spec-compliant and matches
literal parsing:

```
> let x = 19686109595169230000;
> let y = parseFloat("19686109595169230000");
> x == y

< false (before this patch)
< true (after this patch)
```
@ulan
Copy link

ulan commented Dec 15, 2023

JSON.parse() uses parseFloat() under the hood, so all integers in JSON are treated as floating point numbers and precision errors are expected.

That said, the spec requires that parseFloat() is consistent with parsing of literals in the program:

> let x = 19686109595169230000;
> let y = parseFloat("19686109595169230000");
> x == y

This should return true, but currently it returns false and it appears to be a bug indeed.

I debugged the issue to this part of js_strtod: https://github.com/bellard/quickjs/blob/4bb8c35da7c83b5eb67541772b857e822da855da/quickjs.c#L9976
Precision errors are introduced when a large n is assigned to double d.

One way to fix this issue would be to restrict the fast-path parsing only to integers up to 2^53 and fall back to the slower strtod for larger integers:
ulan/javy@149ff4c

@bellard
Copy link
Owner

bellard commented Dec 22, 2023

fixed

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

No branches or pull requests

3 participants