Commit 29cbd45
committed
fix(runtime): NaN equality semantics — indexOf(NaN) returns -1 (v0.5.823)
Pre-fix `[1, NaN, 3].indexOf(NaN)` returned 1 (the NaN's index).
Per ECMA-262, strict equality (===) follows IEEE 754 where NaN !== NaN,
but SameValueZero (used by includes/Map/Set keys) considers NaN === NaN.
Perry used one helper for both and got the strict-equality side wrong.
The fast path `if abits == bbits { return 1; }` matched two identical
NaN bit patterns (0x7FF8000000000000). The fast-path comment assumed
"Perry doesn't produce raw IEEE NaN as a user value" but a literal
`NaN` in source lowers to exactly f64::NAN.
Fix:
- js_jsvalue_equals: check top16 == 0x7FF8 BEFORE the bits-match
fast path and return 0 for NaN-vs-NaN.
- New js_jsvalue_same_value_zero that returns 1 for both-NaN.
- js_array_includes_jsvalue routed through SameValueZero so
[NaN].includes(NaN) keeps returning true.
Verified byte-identical to Bun across 15 cases (===, includes, indexOf,
Set-of-NaN, Map-with-NaN-key). 26/28 gap parity tests pass.
Probed while loop-testing real-app patterns.1 parent 0d9e6b9 commit 29cbd45
6 files changed
Lines changed: 103 additions & 74 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
5 | 7 | | |
6 | 8 | | |
7 | 9 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
0 commit comments