17:55 | <Aapo Alasuutari> | Regarding this, I think I figured out another place where %TypedArray%.prototype.sort implicitly relies on canonicalisation: if I'm not badly mistaken, the CompareTypedArrayElements AO is designed to invoke the "usual" total ordering for floats (convert to uint64, compare by value), but with the assumption that all NaNs are the usual canonical positive NaNs. If the sentence about canonicalisation is dropped, then the sorting algorithm is no longer the usual total ordering but instead something more custom with presumably a branch for NaNs needed. |
17:59 | <littledan> | there's "one" NaN value at the JS level, but then when you write it to a TypedArray, it gets the chance to choose a new value. so the de-canonicalization is happening after the code you're talking about. |
17:59 | <littledan> | the spec is pretty editorially confusing, and we should make that point more clear |
18:00 | <Aapo Alasuutari> |
|
18:01 | <shu> | https://tc39.es/ecma262/#sec-comparetypedarrayelements has special casing for NaN, doesn't compare by bit pattern |
18:02 | <shu> | would more NOTEs help here? i agree the raw bits <> number machinery for TAs can be confusing but i'm not sure how to improve on it atm |
18:02 | <Aapo Alasuutari> | If you create a Float64Array containing NaNs without ever assigning NaNs into it, you can get to a path where the sort() call would be the first place where the NaNs would actually be "observed", and it seems like the CompareTypedArrayElements is designed for engines to be able to use bit pattern comparison as an optimisation there. But that then falls apart if NaN canonicalisation isn't actually done/allowed by the spec. |
18:03 | <Aapo Alasuutari> | Yeah, it only reads like it was written to be compare-by-bit-pattern-but-we-know-all-nans-are-positive. |
18:03 | <shu> | "it seems like the CompareTypedArrayElements is designed for engines to be able to use bit pattern comparison as an optimisation there" where do you get that sense from? |
18:05 | <Aapo Alasuutari> | From the fact that it is entirely equivalent (from my understanding and somewhat limited testing) to a comparison by bit pattern if one makes the assumption that all NaNs are canonicalised or at least positive. |
18:05 | <shu> | that last bit is pretty important though. you can't make that assumption |
18:05 | <littledan> | the spec was deliberately written to enable multiple implementation styles. So if you read it and think, "it permits this", you're not wrong, but that's different from requiring it |
18:09 | <Aapo Alasuutari> | Mm, roger. I keep falling into the mistake of thinking that NaN canonicalisation exists somewhere in the spec :) |
18:16 | <Aapo Alasuutari> | Except of course for the NumericToRawBytes bit where implementations are (currently) required to always use the same pattern for NaN, and sort() using that AO later when it assigns stuff into the buffer... And since the order of these operations isn't observable, I guess an implementation could freely reorder them, first canonicalise to their chosen positive NaN bit pattern and then run a normal total order comparison. |
18:17 | <littledan> | yeah the thing about "it must keep using the same pattern when serializing multiple times" is spec fiction; we should remove it. |
18:22 | <shu> | could one of you file an editorial issue? :) |
18:26 | <Aapo Alasuutari> | I at least commented on https://github.com/tc39/ecma262/issues/635 but if you want to, I can also open a new issue or a PR for the change, assuming there's no particular problem with non-delegates doing so. |
18:28 | <shu> | i meant specifically about "yeah the thing about "it must keep using the same pattern when serializing multiple times" is spec fiction; we should remove it." |
18:33 | <Aapo Alasuutari> | https://github.com/tc39/ecma262/issues/3567 |