1 of 7

Revisit NaN again!?! 😠

Daniel Ehrenberg (littledan)

2 of 7

What happened?

  • V8 may violate the ES standard for NaN observable behavior
  • …but I want to argue that it’s OK
  • (and clean up the spec text once we come to a conclusion)
  • Bug thread

3 of 7

Why not write a fixed bit pattern for NaNs?

  • Some implementations fit pointers in NaN payloads, so canonicalize
  • V8 does not do NaN tagging, so pointers are 32-bits on 32-bit archs
  • Extra canonicalize writing into a TypedArray is a big perf regression (25%)
  • IIRC discussed at TC39 and decided not to force one NaN representation (sorry, I can’t find the notes)

4 of 7

What does ES2015 say about NaN?

The Number Type

“to ECMAScript code, all NaN values are indistinguishable from each other.”

SetValueInBuffer ( arrayBuffer, byteIndex, type, value [ , isLittleEndian ] )

“An implementation must always choose the same encoding for each implementation distinguishable NaN value.”

5 of 7

What does ES2015 say about NaN?

  • My understanding: Each NaN value carries around its NaN payload implicitly, and it may not change
  • When are “new NaNs” produced? A bit esoteric, as the spec never says explicitly.
    • GetValueFromBuffer
    • Arithmetic operations (unspecified per 754)
    • Open question: Writing something into a property and reading it back out???

6 of 7

Why would property writes make a new NaN

  • V8’s FAST_HOLEY_DOUBLE_ARRAY ElementsKind
  • Sample code:

let x = new Array(6)

for (let i = 0; i < x.length; i++) x[i] = 0.5

  • Initially “filled with holes” (missing properties), then entries are added
  • V8 canonicalizes NaNs when setting elements into such an array so it can have a distinct “hole” NaN value
  • Is this OK?

7 of 7

NaN and information leaks

  • The SetValueInBuffer stability language was added to prevent information leaks: that a write to a frozen property would reveal a different NaN payload
  • This is now banned through a different mechanism
  • If writing to or reading from a property created a new NaN, this would not add an information leak