-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Make number serialization compatible with V8 (and new IETF spec draft) #149
Comments
Node.js uses V8 by default so I'm not surprised the behavior is the same. I wonder if the behavior still matches V8 when using Node with ChakraCore? |
@cyberphone Is it possible to add javascript snippet which fails with console binary such as ch.exe for this? |
I believe this is a bug in precision in parseFloat on edge cases. |
@abchatra I think the sequence below shows that it is the output formatting of the very last (unprecise) digit that is the problem:
Chrome, Firefox, Safari: 33333333.333333336 IE11: 33333333.333333335 @dilijev I would assume that node.js with Chakra would exhibit the same behavior. I solved this issue in my Java implementation by simply taking the V8 number serializer "as is": |
Related issues in .NET: |
Removing "Bug" and adding "Suggestion." This is a suggestion to use a number formatting algorithm consistent with other engines. |
Confirmed compat issue still exists:
|
It might be interesting knowing that a new JSON signature standards proposal based on ES6 normalization is in progress with Microsoft as a co-editor. Unofficial document: |
Since this behavior breaks the now published https://tools.ietf.org/id/draft-erdtman-jose-cleartext-jws-00.html I would consider re-branding this as a bug. |
I'll see if I can contribute a fix for this.
|
That would be great! There is now a 100 million test value file: |
So I've taken a look and identified that in the following case within FDblToRgbFast: With this change - i.e. dropping to the slow path from this case - ChakraCore passes the provided 100,000,000 test cases - though there is a small performance impact as the slow path is now being used significantly more than it was before. Questions before submitting a PR:
|
I believe that @irinayat-MS looked into some of these issues recently |
Yes, please see nodejs/node-chakracore#498 and #2512 |
The fix only requires dropping to the slow path in the case Edit: using the 100 million cases in the provided test file the execution time with/without the fix is measurably different the .toString calls on average are taking twice as long
Edit2: comparing to other engines v8 and Jsc actually appear to be faster than CCs fast path at the moment - though producing the same results as CCs precise/slow path - so this should be "fixable" without a performance cost just may be a bit more involved. |
Correction to my comment above to match the other engines the slow path is only required when: So the change would be to change this: else if (bHL - bLH > 1)
{
Assert(ib < kcbMaxRgb);
if(!(ib < kcbMaxRgb))
goto LFail;
// HL and LH differ by at least two in this digit, so split
// the difference if there's an exact mid-point
// if not fall back on the slow path
if ((bHL + bLH) %2 !=0)
{
prgb[ib++] = (bHL + bLH + 1) / 2;
}
else
{
goto LFail;
}
} I can't make a more narrow condition than this I've tried looking at the values of bHL and BLH at this and comparing against the output number that v8 gets and there is no 1-1 mapping that will work. Testing over a large number of samples introducing the slow path for these items only seems to cause around a 5-10% slow down on toString(someDouble). I note that v8 and Jsc are around 5 times faster than CC for toString(someDouble) they seemingly achieve this speed through using various fast maths helpers - including a "Do it yourself floating point" comprised of an int64 base and an int32 exponent - whilst largely doing the same basic calculations. If this path needs to fast could you just use v8's code for it? (Jsc does) It's available here as a separate BSD3 licensed library: https://github.com/google/double-conversion |
@rhuanjl re: large test case -- we could archive this test case as a Slow test we run in our Nightly test suite, rather than every check in, but it's probably not necessary. A sampling of some of the cases that were previously incorrect is probably sufficient to track regressions. Changes to this area could manually verify with the large test, and any other issues will be opened as new bugs. |
The code in my previous comment is the fix for this. But I'm going to hold off on submitting anything for now as it seems that some of the code here needs optimising before this fix (which will incur a performance cost) is added. I will see if I can do something on optimising it but that's going to take more thought and be significantly more involved than the logical fix. |
As a possible solution to this, recent versions of ICU incorporate double to string code cut from v8 (https://github.com/unicode-org/icu/tree/master/vendor/double-conversion) - if we update to use a recent version of ICU then builds of CC with ICU could pipe their double to string conversions through that which would fix this issue. |
The latest ARM Macs seem to output a different answer with CC's algorithm to other architectures. Would be good to follow up and fix this, perhaps by bringing in the ICU idea mentioned above. |
In order to create signed JavaScript objects, you need to normalize data.
The JCS specification https://cyberphone.github.io/openkeystore/resources/docs/jcs.html#ECMAScript_Compatibility_Mode accomplish this "automatically" by relying on ES6 for property order (which Chakra implements), but also depends on the extended number formatting algorithm used in the Google V8 engine which after testing with 100 million of random and selected values appears to be used by Chrome, Firefox, and Safari as well as "node.js".
Browser test program:
http://webpki.org/ietf/es6numberbrowsertest.html
10 million value test file:
http://webpki.org/ietf/es6testfile.txt
Although JCS does not (a this stage) represent a standard, the core concept will most likely become a de-facto standard due to its simplicity.
The text was updated successfully, but these errors were encountered: