-
Notifications
You must be signed in to change notification settings - Fork 478
Description
The current algorithm within ToWebAssemblyValue
to convert from JS values to floats looks like this:
If type is f64,
It's very unclear how NaNs should be handled here. ToNumber
returns a JS number, which isn't quite the same as a regular f64
; 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:
;; float-bits.wasm
(module
(func $f64toi64 (param $float f64) (result i64)
local.get $float
i64.reinterpret_f64
)
(func $i64tof64 (param $bits i64) (result f64)
local.get $bits
f64.reinterpret_i64
)
(export "f64toi64" (func $f64toi64))
(export "i64tof64" (func $i64tof64))
)
const wasm = fetch("./float-bits.wasm");
const { instance } = await WebAssembly.instantiateStreaming(wasm);
const { f64toi64, i64tof64 } = instance.exports;
document.body.textContent = f64toi64(i64tof64(0x7ff8000000001234n)).toString(16);
Chromium preserves the bits and shows 7ff8000000001234
, whereas Firefox and Safari pick a single NaN bit pattern of 7ff8000000000000
.
In the opposite direction, ToJSValue
also doesn't specify how NaNs should be handled:
- If w is of the form f64.const f64, return the Number value for f64.
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.