| 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? |
| 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. |