While working on some SpiderMonkey JIT compiler optimisations, I was wondering if it makes sense to change ToInteger(-0) to return +0 instead of -0, because in all but one case, the result of ToInteger(-0) is either explicitly or implicitly changed from -0 to +0 anyway.
Example for implicit conversion from String.prototype.startsWith:
max.
- If endPosition is undefined, let pos be len; else let pos be ? ToInteger(endPosition).
- Let end be min(max(pos, 0), len).
And from String.prototype.charAt:
- Let position be ? ToInteger(pos).
...- Return the String value of length 1, containing one code unit from S, namely the code unit at index position.
And from Array.prototype.includes:
ToString(-0) = ToString(+0) = "0" holds.
- Let n be ? ToInteger(fromIndex).
...- If n ≥ 0, then
a. Let k be n.
...- Repeat, while k < len
a. Let elementK be the result of ? Get(O, ! ToString(k)).
Example for explicit conversion from Array.prototype.indexOf:
- Let n be ? ToInteger(fromIndex).
...- If n ≥ 0, then
a. If n is -0, let k be +0; else let k be n.
Or TimeClip:
- Let clippedTime be ! ToInteger(time).
- If clippedTime is -0, set clippedTime to +0.
The only place where changing ToInteger(-0) to return +0 instead of -0 would make a difference, is Atomics.store:
- Let v be ? ToInteger(value).
...- Return v.
So, changing ToInteger(-0) return +0 would allow to remove some explicit -0 to +0 conversions in various operations, but also result in a noticeable change for Atomics.store, (which we could avoid if necessary, but I'm not actually sure anyone would really notice the difference for that function when +0 instead of -0 would be returned.) Does it sound useful to anyone else to make this change?
Do 402 or HTML use our ToInteger at all?
I didn't find any occurrence of ToInteger at https://tc39.es/ecma402/ and https://html.spec.whatwg.org/.
Don't forget to check https://heycam.github.io/webidl/, but yeah, no ToInteger there either.
(And now the usual note: Hopefully we get one day some automatic tooling to help find downstream users resp. make it so that downstream users are notified on behavioural changes.
For example yesterday some Web App manifest test was failing because I changed the result of CanonicalizeLanguageTag from ECMA-402. :-/)
cc @syg for Atomics.store question
I highly doubt that changing the semantics of Atomics.store to always truncate -0 would be a web compat issue, especially since SharedArrayBuffers are just getting turned back on again across browsers.
Editorially it seems helpful to set the precedent for future spec writers to not have to think about whether they would want to truncate -0 or not when returning integral numbers back to script. Implementation-wise both the truncation and no truncation variants of ToInteger would still be implemented, since there are call sites where the result Number can never be -0 or the sign bit pattern doesn't matter so there's no reason to emit the extra branch to truncate. And I suppose the current no-truncation behavior for Atomics.store saves a branch for Atomics.store as well.
All in all I think I am in favor of trying this change -- I like the mental model of methods that return some kind of integral coercion as always doing truncation. -0 isn't an integer.
I'm also in favor of it. I'll put up a PR.
This seems to also impact the following code snippet:
function f() {}
Object.is(f.length, -0); // true
Object.defineProperty(f, 'length', { value: -0 });
Object.is(f.bind().length, -0); // spec says true
however, every browser/engine i have on eshost prints out true false, so that seems like a web reality change I'll put up in a separate PR.
Actually, looking again, the spec says Let _L_ be the larger of 0 and the result of _targetLen_ minus the number of elements of _args_. - which would mean Math.max(+0, -0 - args.length) which would result in +0 - so never mind on that :-)