22:31
<shu>
Mathieu Hofman: so i don't see how SABs are normative optional
22:31
<shu>
mark made that claim earlier today in the call
22:31
<shu>
there's the line "Whenever a host does not provide concurrent access to SharedArrayBuffers it may omit the "SharedArrayBuffer" property of the global object."
22:32
<shu>
but that's slightly different by normative optional
22:32
<shu>
i guess mark just meant it's optional in the layman sense?
22:32
<Mathieu Hofman>
How is it different?
22:32
<Mathieu Hofman>
Richard opened https://github.com/tc39/ecma262/issues/3280 today
22:32
<ljharb>
it's normative optional because it doesn't have to be present for the environment to be spec-compliant
22:32
<ljharb>
anything that's omittable is normative optional
22:33
<shu>
so the SAB section is not normative optional
22:33
<Mathieu Hofman>
I believe the normative optional annotation didn't exist back then
22:33
<shu>
the thing that's omittable is the SharedArrayBuffer property on the global
22:33
<ljharb>
right, the constructor is, exactly
22:33
<ljharb>
and it's not accessible to JS code otherwise, right?
22:33
<shu>
even on a host that does not provide concurrent access to SABs, you can get it by making a Wasm linear memory that's shared
22:33
<shu>
and that still has all the right prototypes and methods
22:33
<ljharb>
ahhh right, ok, gotcha
22:33
<ljharb>
ok well that's fair. but non-web hosts don't have to have wasm either.
22:34
<Mathieu Hofman>
Right, only the constructor is normative optional
22:34
<shu>
correct
22:34
<shu>
it's still optional in the layman sense
22:34
<ljharb>
so in browsers, it's just the constructor property. but anywhere else, it's effectively the entire thing as long as wasm is not provided, right?
22:34
<shu>
right, if there's no other host-provided special way to get one of those things
22:35
<Mathieu Hofman>
I suppose the question is, if there was a GetIntrinsic, would %SharedArrayBuffer% appear in there or not
22:36
<shu>
agree, if GetIntrinsic exists then it's a bigger distinction
22:36
<ljharb>
no
22:36
<ljharb>
well, hm
22:36
<shu>
well the point of GetIntrinsic is to give access to non-reachable-via-chain-of-property-accesses intrinsics
22:36
<shu>
so it's not clear to me it's an obvious "no"
22:37
<ljharb>
given that it's a top-level intrinsic, yes. but, i assume we'd alter the wording a bit somewhere to say that the intrinsic must exist if there's any way to access those objects, but must not exist otherwise?
22:37
<shu>
🤷
22:37
<shu>
whatever font element uses for emojis is garbage yo
22:37
<shu>
i can hardly tell that person is shrugging
22:37
<ljharb>
iow, it'd still be deniable in places where the constructor property was omitted, even if by wrapping getIntrinsic, but it'd be required to exist if there's any way to get at a SAB
22:40
<Mathieu Hofman>
to rephrase Shu's observation, would it be spec compliant to omit %SharedArrayBuffer% from getIntrinsic, even if there is no other way to reach it?
22:40
<shu>
...is it?
22:40
<shu>
oh sorry you are asking a question
22:41
<Mathieu Hofman>
If it was normative optional, it would be. But with the current working, I'm actually not sure
22:41
<shu>
my gut says "it's spec compliant to omit iff there is no other way to reach it in the host"
22:41
<shu>
otherwise because it's not the case that the entire constructor and prototype and all the methods are in a Normative Optional block, it seems not compliant to omit it
22:41
<ljharb>
i think that's exactly the semantic GetIntrinsic must have, however it's worded
22:42
<Mathieu Hofman>
Anyway, I suppose the question stand, and should SAB be normative optional, and maybe Atomics too ? Afaik, Atomics.waitAsync is causing some problems in some worklet environments
22:42
<shu>
haha i saw that
22:43
<shu>
i don't think either SAB and Atomics can be truly normative optional
22:43
<shu>
especially not Atomics because they do work on ABs, just doesn't do anything interesting
22:43
<Mathieu Hofman>
why not?
22:43
<shu>
(except wait)
22:44
<shu>
because they work on ABs
22:44
<Mathieu Hofman>
ok but the question is whether a spec compliant implementation must offer them to the program
22:44
<shu>
there was a use case from the wasm side iirc that wanted to not ship different binaries depending on whether SABs are actually available
22:45
<shu>
so, when they are not, they will use ABs, use no multithreading, but still ship the same Atomics calls
22:45
<shu>
"graceful degradation" or whatever
22:45
<ljharb>
then in that case Atomics probably can't be optional, but would be entirely useless in an env without SABs. any reason why they work with ABs in the first place?
22:45
<shu>
that says to me that Atomics ought to always be offered as part of a spec compliant implementation
22:46
<shu>
then in that case Atomics probably can't be optional, but would be entirely useless in an env without SABs. any reason why they work with ABs in the first place?
for the reason i just said above about not wanting to ship different binaries
22:46
<ljharb>
ahhh k
22:46
<ljharb>
i mean it'd basically just be a conditional delete Atomics call before allowing any user code to run, right? not sure why it'd require a new binary
22:47
<shu>
i'm confused
22:47
<ljharb>
so like, i would expect one binary. if it makes SABs available, there's a global property and also Atomics. if it doesn't, there's no global property and also no Atomics. both of which are deleteable with a line or two of JS that can be invoked inside a realm before running user code (like how node has "realm bootstrap" JS that runs) entirely possible i'm missing something
22:48
<shu>
the use case is like, you have a bunch of carefully written lockfree mumbo jumbo that uses SABs and Atomics. you don't want to write a whole different version, and you're also not too bothered about running it single-threaded when SABs are not available, even if Atomics are more expensive. in that case, you can check if SABs are available, you construct a SAB and TAs that view that. if you SABs are not available, you construct an AB and TAs that view that. the library code that does Atomics operations on the TAs is agnostic to whether the underlying buffer is an SAB or AB
22:48
<shu>
the one wrinkle is that wait never works if the underlying buffer is an AB
22:49
<shu>
but other than wait, all the other Atomics operations work
22:49
<Mathieu Hofman>
ok I buy the use case for Atomics being present. I think SAB being normative optional is still an option. And it's solve the waitAsync issue, since that throws on non SAB backed views
22:49
<ljharb>
ok but that's the library - so it could easily have a branch, and not be agnostic
22:49
<shu>
that constitutes writing 2 libraries
22:49
<ljharb>
i count one library that branches based on whether SAB was present initially or not. obv the machinery to handle SABs/Atomics would have to be present regardless
22:50
<shu>
one that uses, like a[i] + 42 and one that uses Atomics.add(a, i, 42)
22:50
<shu>
the use case, the library author says, i don't want to write two different versions
22:51
<ljharb>
ok, i mean i get that, but that's a minor convenience issue for something that only really makes sense to call on a SAB. (no need to debate it, ship's sailed, i was just confused)
22:51
<shu>
it's not a convenience issue, it's a maintenance issue
22:53
<ljharb>
i have to write multiple code paths in libraries all the time, it's just the way it is - i don't see it as a real obstacle to do isSAB(a) ? Atomics.add(a, i, 42) : a[i] + 42, and i'd personally find that better since that way it's much clearer - and thus more maintainable - to a reader when something's shared or not. obv it's subjective.