-
Notifications
You must be signed in to change notification settings - Fork 454
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
[js-api] Conversion from JS values to floats doesn't specify how to handle NaNs #1496
Comments
Thanks for pointing this out, I'll try and take a look soon. I'd assume the ES spec prohibits Chromium's behaviour here, though there's some reference to "implementation distinguishable NaN value[s]"... I don't recall who's worked on this on the JS side. |
Thanks for this observation. Indeed, the spec does not define the bit pattern of a NaN when the NaN gets passed to WebAssembly from JavaScript. I see two options, along the lines of https://webassembly.github.io/spec/core/bikeshed/#nan-propagation%E2%91%A0:
The argument for 1) would be that it is more deterministic. However, even within WebAssembly the NaN behavior is not deterministic when patterns like in the example above are used. Also, there are two canonical bit patterns, and not just one. If you have any concrete example why a canonical NaN would be useful, please tell us. The arguments for 2) would be that I think 2) is better, because it's faster, seems consistent with the core spec, and I don't see a reason why the NaN handling in the JS-API has to be more strict than the handling within WebAssembly itself. |
@syg perhaps this might be of interest to you too |
ecma262 does not prohibit Chromium's behavior. There is no normative requirement of NaN canonicalization. NaN bit patterns are not observable outside of TypedArray writes and reads, so NaNs are indistinguishable when flowing through JS variables. If it flows through a TypedArray write, there's this unhelpful language about "An implementation must always choose the same encoding for each implementation distinguishable NaN value". The normative requirement of that thus hinges entirely on what "implementation distinguishable" means, which, AFAICT, in the limit, means an implementation can choose to distinguish all NaN bit patterns. I'm guessing the intent was something like, don't be too chaotic and start randomizing bit patterns. But still, the TypedArray boundary, and it sounds which is to be expanded to include the WebAssembly boundary now, does permit non-canonicalized NaN bit patterns. When we last relitigated this, my recollection is basically that we do not force canonicalization, and while we'd like to say something stronger like "bit patterns are preserved through variables", we couldn't figure out how to formulate it without prohibiting implementation techniques and optimizations. For example, suppose we did say exactly that. But then consider I'd argue for 2) out of the two choices @gahaas presented above. JS already has no canonical bit pattern, and the lack thereof is already observable via TypedArray boundaries. It conceptually makes makes sense to me to expand that boundary to include WebAssembly, which deals with linear memories that are exposed as TypedArrays. |
The current algorithm within
ToWebAssemblyValue
to convert from JS values to floats looks like this:It's very unclear how NaNs should be handled here.
ToNumber
returns a JS number, which isn't quite the same as a regularf64
; it's only defined to have a single NaN value, with an unknown bit pattern. The spec should say something about how that NaN value gets converted, whether it's defined to result in a particular value or just left as implementation-defined.The actual implementation of this currently differs between browsers. Using this code to test:
Chromium preserves the bits and shows
7ff8000000001234
, whereas Firefox and Safari pick a single NaN bit pattern of7ff8000000000000
.In the opposite direction,
ToJSValue
also doesn't specify how NaNs should be handled:I don't find this as bad, since it's pretty obvious that any NaN should map to the JS NaN, but it wouldn't hurt to add a note about it here too.
The text was updated successfully, but these errors were encountered: