05:58
<ljharb>
* this was the precise suggestion you made for global, if you recall.
07:00
<littledan>
global was in a known web-incompatible state with no changes publicly proposed over the course of a year, so I think that's different. We don't have particular known issues for Temporal, and definitely not with respect to web compatibility.
07:02
<littledan>
(or did I say something about what should happen after the new name was proposed? I don't remember making that suggestion at that time.)
07:02
<ljharb>
very true that there's no web compat concern; it's not exactly the same
07:02
<ljharb>
but what i remember is that you argued (a position i disagreed with at the time, but have come around on and now agree with) that it should have dropped to stage 2 since the name was going to change
07:03
<littledan>
right, so that's a case of a change that needs to happen for something to be shippable, whereas we're not aware of changes that need to happen for Temporal for it to be shippable
07:03
<ljharb>
wasn't that the entire agenda item? it was too big to be shippable.
07:04
<littledan>
and we addressed it, we hope (modulo implementer feedback, which makes sense to seek during Stage 3)
07:05
<ljharb>
right. it's the "we hope" part that's been proven false in nearly every plenary for the last 4 years, and i'd think that (likely well) over 10 times bitten should at least produce once shy
07:06
<littledan>
"once shy"?
07:07
<ljharb>
lol i was trying to paraphrase "once bitten twice shy", i've been up for nearly 20 hours so it might not make sense
07:07
<Chris de Almeida>
once bitten, twice shy idiom —used to mean that a person who has failed or been hurt when trying to do something is careful or fearful about doing it again
07:08
<Chris de Almeida>
if the corrective action suggested here is to more liberally request consensus to regress proposals when it seems they should be regressed, that seems reasonable to me
07:09
<ljharb>
exactly that. which is something we've discussed multiple times in recent years, like with import attributes for example
07:09
<ljharb>
(to pretty consistently positive response, iirc)
07:10
<littledan>
so, for import attributes, it was retracted because a change was in progress, which is more similar to the globalThis case.
07:10
<ljharb>
the concept of a "scoped demotion" helped make that palatable, i think
07:10
<nicolo-ribaudo>
I wonder if the proposed action would have been "lets split the proposal in two and bring this part back to stage 2", rather than "lets remove this part", the stability impression would have been different
07:11
<littledan>
it was unfortunate that we didn't permit ourselves a scoped demotion. I think the committee agreed to the demotion partly because the strongly opinionated people agreed to scoping, even if the committee as a whole wasn't going to commit to scoping.
07:11
<ljharb>
or alternatively, at this point we could move it back to ~2 with a scope of "no design changes, only implementation-driven ones" - which sounds like stage 3, but, because of the scale of Temporal might be worthy of some flexibility
07:11
<littledan>
but there's no design changes proposed here, so I'm not sure what the criteria would be later for re-promotion
07:11
<ljharb>
dropping calendar and timezone were pretty massive design changes
07:11
<littledan>
right, but we don't have any further changes proposed
07:11
<ljharb>
oh sure. that's been the case after every plenary tho, until the next one
07:12
<littledan>
when import attributes were re-promoted, there was the idea raised, "even though we agree on these changes, should we wait longer to let things settle?" we decided no wait was needed, and that turned out just fine.
07:12
<ljharb>
since we won't have time to discuss temporal's stage this meeting, i guess we'll see either way :-)
07:13
<ljharb>
but if more changes come back in july, i think we should seriously consider demoting it until changes stop coming
07:13
<littledan>
since we won't have time to discuss temporal's stage this meeting, i guess we'll see either way :-)
we could have time--I agreed to the chair's request to cut down the signals topic to 30 minutes to permit an overflow topic on this subject.
07:13
<ljharb>
perhaps yall can indeed discuss it; i'm going to bed in an hour or so and won't be present after that. i sleepy.
07:13
<littledan>
ah OK good to know
07:14
<ljharb>
(presumably) my opinion is clear tho so i don't necessarily need to be there
07:16
<littledan>
I think we've made the points back and forth here; I'm not sure what more we should discuss
07:17
<ljharb>
it'd only be worth discussing imo if there's a decent chance of a demotion, otherwise it's probably more efficient to just wait til july and revisit if there's more changes
07:36
<Michael Ficarra>
maybe I wasn't clear?
07:37
<Michael Ficarra>
the question is NOT about whether there are only editorial changes remaining, it is about whether the remaining changes are considered "major", which is subjective
07:37
<rbuckton>
I understood "High level APIs and Syntax" to mean the rough design we want to proceed with. We've never been so strict for stage 2.
07:38
<rbuckton>
"Placeholders and TODOs are acceptable"
07:38
<rbuckton>
The description in the Purpose column describes the kinds of things Waldemar is discussing
07:39
<ptomato>
there have been proposals entering stage 2 with entire methods stubbed out
07:39
<littledan>
re Shane's topic: I think we do approve slideshows: we advance things based on conceptual agreements, which I think we have here. Stage 2.7 is where we look for the spec to be basically perfect.
07:40
<Michael Ficarra>
@littledan even stage 4 is advanced on conceptual agreements
07:41
<Chris de Almeida>
the question is NOT about whether there are only editorial changes remaining, it is about whether the remaining changes are considered "major", which is subjective
agree, and I disagree with the characterization that we are having a meta discussion on process. we are talking about this proposal and what appear to be blocking possibly based on stage 2.7 or 3 entrance criteria rather than stage 2
07:41
<Michael Ficarra>
the editor group often finds things in the 262 spec document that don't align to what we conceptually agreed to and we just fix them and notify committee at the next plenary
07:42
<Michael Ficarra>
part of the editor's job responsibilities is going back through consensus (written and in our memory) to confirm that the document aligns with it
07:43
<Rob Palmer>

Purpose of Stage 2:

  • Refining the solution.
  • Work out minor details such as ordering of observable effects, handling of invalid inputs, API names, etc.
  • Receive and address spec text reviews from the assigned reviewers and the appropriate editor group
  • Produce experimental implementations such as loosely-correct (not for production use) polyfills to aid in validating the design and exploring the details
  • Investigate integration with relevant host APIs, if necessary
07:45
<rbuckton>
If we agree this is the right direction to go for Decimal, then Stage 2 seems perfectly reasonable. It means we've committed to that direction and now we want to flesh out the details.
07:49
<Chris de Almeida>

more greatest hits from the process doc, re: stage 2 status

The committee has chosen a preferred solution or solution space, but the design is a draft and may still change significantly.

07:50
<littledan>
If Decimals overflow, please feel free to take time away from Signals (even if it means we don't get to it at all this meeting)
07:50
<Ben>
The DurationForrmat update is not going to even come close to filling its timebox, so that clears up time this afternoon
07:51
<Ben>
(I've reached out to Ujjwal about this)
07:51
<nicolo-ribaudo>
Duncan MacGregor When comparing floats there is the same beahvior: 1 < NaN is false, 1 > NaN is false, and 1 == NaN is false, so compare cannot return neither -1, nor 0, nor 1.
07:53
<mgaudet>
I'd like us to not over-rotate on API design based on the temporal experience
07:54
<nicolo-ribaudo>
Chrome is working on shipping the web neural network API, that has all the comparisons :)
07:55
<nicolo-ribaudo>
(just to put feedback on Chrome's code size into perspective)
07:55
<waldemar>
If we don't provide an equals method, users will test for = and ≠ via compare(…) == 0 and compare(…) != 0 respectively. This produces incorrect results.
07:56
<rbuckton>
Stage 1 is scouting the terrain and coming up with a battle plan. Stage 2 is starting the long march to battle and preparing fortifications. Stage 2.7 is checking your gear before the battle starts. Stage 3 is when you see how much of your plan survives contact with the enemy. Stage 4 is the parade.
07:56
<Duncan MacGregor>
Duncan MacGregor When comparing floats there is the same beahvior: 1 < NaN is false, 1 > NaN is false, and 1 == NaN is false, so compare cannot return neither -1, nor 0, nor 1.
Ah right. Too used to comparison methods which return an int and so cannot return NaN. It is also worth noting that things like Array.prototype..sort() turn a Nan value as +0.
07:56
<nicolo-ribaudo>
Ah right. Too used to comparison methods which return an int and so cannot return NaN. It is also worth noting that things like Array.prototype..sort() turn a Nan value as +0.
The .sort behavior seems good with the .compare behavior: "I don't know how to compare these two things, so I don't shuffle them around"
07:58
<Chris de Almeida>
Eemeli's comment makes it sound like it's a foregone conclusion that a new primitive is not possible
07:59
<Chris de Almeida>
facts?
07:59
<ljharb>
that is browsers' position as i understand it, yes
07:59
<ljharb>
(which impacts both R&T and Decimal)
08:00
<nicolo-ribaudo>
I understand browsers position as "a primitive only makes sense if we see proof that it's actually going to be widely used", and I hope that decimal objects getting adoption will fulfill that
08:00
<Duncan MacGregor>
The .sort behavior seems good with the .compare behavior: "I don't know how to compare these two things, so I don't shuffle them around"
Yeah seems consistent, and maps reasonably to IEEE spec.
08:01
<Rob Palmer>
I do not see any route to convincing browsers that the juice is worth the squeeze on Decimal, other than the incremental route of proving it out first in API form.
08:01
<ljharb>
it can be proved out, though, without being in the spec - that's what npm is for
08:01
<Michael Ficarra>
The .sort behavior seems good with the .compare behavior: "I don't know how to compare these two things, so I don't shuffle them around"
this would be an inconsistent comparator though: https://tc39.es/ecma262/#consistent-comparator
08:01
<Chris de Almeida>
I do not see any route to convincing browsers that the juice is worth the squeeze on Decimal, other than the incremental route of proving it out first in API form.
precedent?
08:02
<ljharb>
this constraint on primitives is pretty new so i'm not sure there is any precedent
08:03
<nicolo-ribaudo>
Ugh, that's annoying. In wonder wether we could extend the definition of consistent comparators to include "some values can consistently not be compared with any other value"
08:03
<Chris de Almeida>
it would be nice to hear from vendors if that sort of signal would might be sufficient to convince
08:03
<nicolo-ribaudo>
Because, NaN returned from .compare happens if and only if one of the arguments is a NaN
08:04
<nicolo-ribaudo>
I would have to check if implementations in practice are already doing it
08:04
<Richard Gibson>

very much related: https://matrix.to/#/!wbACpffbfxANskIFZq:matrix.org/$oOM8aZZATkGRuYJ1QzLp2veLMwV3yXlD1275Z1d6nBs?via=matrix.org&via=mozilla.org&via=igalia.com

you can get consistent sorting like newPages.sort( ( a, b ) => (isNaN(a.index) ? Infinity : a.index) - (isNaN(b.index) ? Infinity : b.index) ), but I don't think there's any way to avoid some kind of surrogate value

08:04
<nicolo-ribaudo>
Infinity - Infinity is NaN, right?
08:04
<Richard Gibson>
right
08:05
<Duncan MacGregor>
Yes
08:05
<Richard Gibson>
which is treated as zero, i.e. same-sign infinities are not differentiated by that kind of sorting
08:06
<waldemar>
agree, and I disagree with the characterization that we are having a meta discussion on process. we are talking about this proposal and what appear to be blocking possibly based on stage 2.7 or 3 entrance criteria rather than stage 2
That's an unfair characterization. A lot of folks making this claim are making assumptions about what's currently working and what isn't working in the spec.
08:06
<eemeli>
Eemeli's comment makes it sound like it's a foregone conclusion that a new primitive is not possible
I meant that only in the current specific context of Decimal as a class being proposed to Stage 2.
08:07
<Duncan MacGregor>

So the JVM's position on this is

Compares two Double objects numerically. This method imposes a total order on Double objects with two differences compared to the incomplete order defined by the Java language numerical comparison operators (<, <=, ==, >=, >) on double values.
A NaN is unordered with respect to other values and unequal to itself under the comparison operators. This method chooses to define Double.NaN to be equal to itself and greater than all other double values (including Double.POSITIVE_INFINITY).
Positive zero and negative zero compare equal numerically, but are distinct and distinguishable values. This method chooses to define positive zero (+0.0d), to be greater than negative zero (-0.0d).
This ensures that the natural ordering of Double objects imposed by this method is consistent with equals; see this discussion for details of floating-point comparison and ordering.

08:09
<Duncan MacGregor>
It ends up putting all the doubles at the end of a sorted array, which also seems to be what I see in Array.prototype.sort() implementations.
08:09
<Chris de Almeida>
That's an unfair characterization. A lot of folks making this claim are making assumptions about what's currently working and what isn't working in the spec.
you're right -- and the purpose of the discussion was to clarify
08:10
<waldemar>
The spec is not even in a good enough state for Shane to be able to read and understand it.
08:10
<rbuckton>
Could we add Decimal as a class and later add a primitive version for it if we block off relevant functionality to allow for it in the future? i.e., you have to write new Decimal() for now while Decimal() and Decimal.prototype.valueOf() throw, and later we add decimal primitives treating new Decimal as the boxed primitive version? That would give us the opportunity to ship it and prove out its utility in the ecosystem. IIRC, shu's concern was that BigInt added too much complexity for something whose only significant use ended up being for unscrupulous cryptocurrency mining.
08:11
<littledan>
waldemar: What do you think about "conditional Stage 2" on fixing those spec issues?
08:11
<waldemar>
waldemar: What do you think about "conditional Stage 2" on fixing those spec issues?
That's fine by me.
08:12
<waldemar>
I want this to go to stage 2. It's just not ready at the moment, but it's getting there quickly.
08:12
<littledan>
That's fine by me.
sffc: ?
08:13
<Duncan MacGregor>
I'm not convinced by the argument that Decimal is a good answer to solving rounding issues seen by inexperienced developers, but I do understand that Decimal is a good answer to a particular set of problems.
08:14
<littledan>
I think the existing libraries have tons of downloads, but maybe that is partly because of people depending on them when they don't really need them
08:15
<hax (HE Shi-Jun)>
About the diff with Decimal128 and Temporal, I think it's how people expect. For Decimal128 in non-primitive form, people will say: WTF! For Temporal, people will say: ok, it at least much much better than Date!
08:15
<Chris de Almeida>
13,603,794 weekly downloads is tons or no?
08:15
<ljharb>
looking around on npm, i do see https://www.npmjs.com/package/bignumber.js which has 11m downloads, which is a pretty decent number
08:15
<jkup>
https://www.npmjs.com/package/decimal.js, https://www.npmjs.com/package/big.js, https://www.npmjs.com/package/bignumber.js
08:15
<sffc>
The spec intelligibility issues are not egregious enough to get in the way of Stage 2 for me; I think the committee sending a positive signal by promoting to Stage 2 is more important at this point in time
08:15
<jkup>
50mil
08:16
<ljharb>
and indeed decimal.js has 17 million
08:16
<ljharb>
so that's a great indicator, thank you. (i'd still want the proposal readme to have a list ofc)
08:16
<littledan>
the polyfill is not being developed in a way where it intends to compete with other decimal libraries
08:17
<ljharb>
oh sure, i don't care that a specific package has low usage, to be clear, i just was not aware that any were significantly used; those 3 high-usage examples certainly addresses the "demand" point for me (but still not the "carries its weight" part)
08:17
<Luca Casonato>
the polyfill is not being developed in a way where it intends to compete with other decimal libraries
can you elaborate this? this seems like a statement that needs more explanation
08:17
<Chris de Almeida>
might need to invite MikeMcl to the chat at some point
08:17
<nicolo-ribaudo>
The goal of the polyfill is to have spec-compliant semantics, not to be an optimized production-ready implementation Luca Casonato
08:18
<nicolo-ribaudo>
Same for temporal for example
08:18
<rbuckton>
Lets just add a single new primitive type that covers flexible user-defined data types and operator overloading and just base all other new primitives on that.
08:18
<nicolo-ribaudo>
Let's call this primitive "object" :)
08:18
<Luca Casonato>
oh i misread polyfill as spec 🤦‍♂️
08:19
<Luca Casonato>
i read "this spec is not being developed in a way where it intends to compete with other decimal libraries"
08:19
<rbuckton>
Honestly, this was one of the things I wanted to do with my version of the struct proposal prior to Shu's version.
08:19
<Duncan MacGregor>
So I can say that operator overloading is a significant implementation overhead in Ruby, and we try very hard to boil it away as much as we can. It's tempting, but it has real downsides.
08:19
<rbuckton>
I would have just called the primitive "value"
08:20
<ljharb>
"tempting but has real downsides" is an understatement in my experience on both parts in any language i've used with the feature
08:20
<Duncan MacGregor>
🤣
08:20
<nicolo-ribaudo>
So I can say that operator overloading is a significant implementation overhead in Ruby, and we try very hard to boil it away as much as we can. It's tempting, but it has real downsides.
It would probably have to be lexically scoped to restrict the overhead to where you need it
08:20
<ljharb>
i suspect that would remove a lot of the downsides
08:22
<Duncan MacGregor>
It would probably have to be lexically scoped to restrict the overhead to where you need it
But then you can end up with weird corner cases because you're code does one thing while a library does another.
08:23
<rbuckton>
Question to implementers, when bigint was added along with its necessary operator overloads, how much of an impact on performance did that have for other javascript code that didn't make use of bigint?
08:23
<keith_miller>
Scoped overloads seems like a footgun how does a library support overloading in that case?
08:24
<ljharb>
i suppose it'd provide exports that can be "activated" inside a scope with syntax
08:24
<keith_miller>
Question to implementers, when bigint was added along with its necessary operator overloads, how much of an impact on performance did that have for other javascript code that didn't make use of bigint?
AFAIK, none
08:24
<ljharb>
like a special decorator or something
08:24
<keith_miller>
Or it wouldn't have shipped
08:25
<keith_miller>
On the === front you could say that if object identity is equal then it doesn't call your overload. I don't think that's a crazy rule.
08:25
<keith_miller>
littledan: CC^
08:25
<Duncan MacGregor>
AFAIK, none
Generally none, but some sites could end up having more types flowing through them than previously. Rarely significant though.
08:25
<littledan>
I think browsers want to be able to return "false" fast
08:26
<nicolo-ribaudo>
When we talk about performance, do we also include "time from when the user clicks on a link to when the page is available"? (i.e. loading time)
08:26
<nicolo-ribaudo>
Or just runtime performance?
08:26
<keith_miller>
You already have to look into your object to figure out if it's a string or BigInt though
08:26
<Duncan MacGregor>
I think we mean both.
08:26
<keith_miller>
At that point you can check for overloading, without too much cost in an IC
08:27
<rbuckton>
If we did provide a user-defined primitive capability with operator overloading in a similar vein, would it then be reasonable to assume that all performance overhead would be in interactions with those primitives, and not all other JS?
08:28
<keith_miller>
I don't understand what you mean by "user-defined primitive capability"?
08:28
<hax (HE Shi-Jun)>
something close to Tuple/Record
08:29
<Ashley Claymore>
Record & Tuple was also blocked from being a primitive
08:29
<keith_miller>
It would still be an object though so it's not really a primitive. It just looks kinda like a primitive unless you squint
08:29
<rbuckton>
I don't understand what you mean by "user-defined primitive capability"?
For the purpose of this discussion, I mean some bespoke syntax to declare a user-defined "primitive" type, much like a class, except it isn't Object.
08:29
<Duncan MacGregor>
Oh, the area where we would likely see a performance degradation is if people can define new cases involving the existing primitives.
08:30
<mgaudet>
(Personal Hat on): User defined primitives are a fascinating design space that I think would provide a lot of value, and potentially could be done -- a path I would propose would be abstracting BigInt such that you could re-host BigInt atop the abstraction, then provide user access to the abstraction. But there's many, many dragons here
08:30
<rbuckton>
It would still be an object though so it's not really a primitive. It just looks kinda like a primitive unless you squint
Sure, that's fine to me. I'm talking about "looks like a primitive".
08:30
<mgaudet>
(c.f. Project Valhalla etc)
08:31
<hax (HE Shi-Jun)>
For the purpose of this discussion, I mean some bespoke syntax to declare a user-defined "primitive" type, much like a class, except it isn't Object.
like Java primitive class ...
08:31
<Duncan MacGregor>
(c.f. Project Valhalla etc)
Trigger warning, please. 😀
08:31
<rbuckton>
With the caveat that operator overloads on a user-defined "primitive" will likely be far slower than native primitives.
08:31
<Michael Ficarra>
I see where Jordan's coming from. I believe this proposal is much less motivated without the primitive. But I still think it is motivated enough by its other merits, and there is a path to a primitive in the future, so I support it.
08:31
<mgaudet>
Trigger warning, please. 😀
Apologies
08:33
<keith_miller>
Oh, the area where we would likely see a performance degradation is if people can define new cases involving the existing primitives.
Yeah, I DEFINITELY don't think we can let users change e.g. number + number
08:33
<keith_miller>
For both performance and sanity reasons
08:33
<rbuckton>
You don't pay the cost of operator overloading for all Objects, only this different thing. If you want to define a "primitive"-like type with operator overloading, you use this and not Object. Implementations only have to plumb this through once and it is a catch-all for any "primitive"-like type we might want to include in the standard library as well.
08:34
<Duncan MacGregor>
Yeah, I DEFINITELY don't think we can let users change e.g. number + number
But if I have a matrix type I'd definitely want to be able to define number * matrix… This is where the dragons are.
08:34
<rbuckton>
Yeah, I DEFINITELY don't think we can let users change e.g. number + number
Agreed. You'd only get custom overloading when one of the operands is the user-defined primitive.
08:34
<ljharb>
what if both operands have a different overload?
08:34
<Duncan MacGregor>
That's another dragon.
08:35
<keith_miller>
You could say both have to have the same function?
08:35
<Duncan MacGregor>
Ruby does it by operators really being methods
08:35
<keith_miller>
Or an exception
08:35
<keith_miller>
idk
08:35
<Duncan MacGregor>
Other langauges do multi-argument dispatch
08:35
<rbuckton>
But if I have a matrix type I'd definitely want to be able to define number * matrix… This is where the dragons are.
Yes, but the expectation is that using a user-defined "primitive" as an operand is about convenience and not performance.
08:36
<rbuckton>
We've investigated various mechanisms for operator overloading in the past.
08:39
<keith_miller>
But if I have a matrix type I'd definitely want to be able to define number * matrix… This is where the dragons are.
Yeah, I could see object <op> primitive calling some overload too
08:39
<keith_miller>
But maybe there's dragons there I haven't thought through
08:39
<Luca Casonato>
Can someone advance the queue?
08:40
<littledan>
You don't pay the cost of operator overloading for all Objects, only this different thing. If you want to define a "primitive"-like type with operator overloading, you use this and not Object. Implementations only have to plumb this through once and it is a catch-all for any "primitive"-like type we might want to include in the standard library as well.
yes, this corresponds to my previous operator overloading proposal, where you had to make it clear when allocating the object that it had overloading
08:40
<rbuckton>

I had a very early draft for operator overloading syntax in my original struct proposal, something like:

struct Decimal {
  ...
  static (Decimal + Decimal) (a, b) { return ...; }
  static (Decimal - Decimal) (a, b) { return ...; }
  static (Decimal * Decimal) (a, b) { return ...; }
  ...
}

NOTE that this is not being considered for the current struct proposal.

08:41
<littledan>
sure if there's an easy to check tag on the object that says whether it has overloading
08:42
<mgaudet>
(There's another dimension here to operators, which is also identity; primitives bring both operators and a lack of identity, and there's no ability as a user to create a user-defined-thing that has no identity too -- c.f. earlier R&T)
08:43
<rbuckton>
Though I did spend some time fleshing out what a user-defined "primitive" might look like in my old struct proposal: https://github.com/rbuckton/proposal-struct
08:43
<keith_miller>
You don't pay the cost of operator overloading for all Objects, only this different thing. If you want to define a "primitive"-like type with operator overloading, you use this and not Object. Implementations only have to plumb this through once and it is a catch-all for any "primitive"-like type we might want to include in the standard library as well.
I don't think from the engine side there's a difference
08:43
<mgaudet>
(a lack of identity also ties in immutability too)
08:43
<keith_miller>
But maybe that's different for other engines
08:44
<Duncan MacGregor>
Lack of guaranteed identity seems like a relatively small problem.
08:44
<mgaudet>
Lack of guaranteed identity seems like a relatively small problem.
was arguably the core of R&T
08:44
<Richard Gibson>
Yeah, I could see object <op> primitive calling some overload too
obligatory suggestion for infix function calls
08:44
<rbuckton>
But maybe that's different for other engines
My understand was that the with operators from ... syntax that littledan had proposed was primarily to address performance concerns raised by some implementations
08:45
<littledan>
My understand was that the with operators from ... syntax that littledan had proposed was primarily to address performance concerns raised by some implementations
sure but it creates other ones
08:45
<littledan>
it's also to address the behavior injection concerns from a design/correctness perspective
08:45
<Duncan MacGregor>
Right, records, tuples, value decorators (hard for JS as there aren't good immutability guarantees without R&T…) lots of ways to do it in VM implementations.
08:48
<keith_miller>
My understand was that the with operators from ... syntax that littledan had proposed was primarily to address performance concerns raised by some implementations
That sounds... just worse than even a Symbol.add but I'd have to hear the exact performance objections. I would imagine Symbol.add would behave the same as a getter in the IC. Most engines already have the infrastructure for getters so I'm a bit surprised such code couldn't be generalized for operators.
08:49
<rbuckton>
When I put together my old struct proposal I was looking for a way to unify the mechanics for R&T, a Decimal primitive, maybe Temporal as a "primitive", and other user-defined "primitive" types.
08:49
<littledan>
with operators from means a lot of requirements for bookkeeping. But it's easy to see when you're not inside of those things and you can use the ICs which don't have support for the new operator overloaded things
08:51
<rbuckton>
If we did have operator overloading, I'd much rather restrict it to a specific domain of values than support with operators from. with operators from would be a mess for TypeScript.
08:52
<keith_miller>
with operators from means a lot of requirements for bookkeeping. But it's easy to see when you're not inside of those things and you can use the ICs which don't have support for the new operator overloaded things
The whole point of ICs is that you only generate the cases you've seen though. So, I'm a bit surprised that would help anything.
08:52
<rbuckton>
And that's just type checking, we wouldn't downlevel operator overloading it would be to expensive based on our "no type-based emit" policy.
08:52
<keith_miller>
But, that said, I'm only intimately familiar with JSC's ICs
08:53
<littledan>
The whole point of ICs is that you only generate the cases you've seen though. So, I'm a bit surprised that would help anything.
oh sorry I don't mean ICs, I guess I mean paths in the interpreter or something
08:53
<Duncan MacGregor>
I think the thing I wouldn't like about trying to add operator overloading to JS as currently defined is that we do various coercions on the two arguments and then perform the operation. Ruby and Python both tree all this stuff as a simple method call, so it is simply up to the left operand what is done to the right operand.
08:54
<keith_miller>
oh sorry I don't mean ICs, I guess I mean paths in the interpreter or something
Ah ok. Assuming we don't allow primitive operator overloading I don't think that would be an issue. At least for JSC.
08:55
<keith_miller>
Once you're in the non-primitive not-equal pointer case you're already doing slow stuff
08:56
<keith_miller>
Again, that's just JSC not necessarily other engines
08:56
<rbuckton>
Oh, also, my old struct proposal required "typed" field definitions to handle cases like size, alignment, packing, etc. You could, in theory, support === using the memory contents of the value.
08:57
<keith_miller>
I think the thing I wouldn't like about trying to add operator overloading to JS as currently defined is that we do various coercions on the two arguments and then perform the operation. Ruby and Python both tree all this stuff as a simple method call, so it is simply up to the left operand what is done to the right operand.
Why is it necessary to do coercions?
08:58
<Duncan MacGregor>
Why is it necessary to do coercions?
So at the moment we do GetValue and then ToPrimitive (which of course we don't actually need to do most of the time).
08:59
<nicolo-ribaudo>

Michael Ficarra

I was going to answer that this is more of a question for the existing stage 3 proposal, that adds the concept of "sources" and wasm is already using it. This new proposal is only for defining what a JS source is.

However, Guy can probably still answer that (I know well how this proposal works for JS, but my Wasm knowledge is more limited 😛)

09:00
<Michael Ficarra>
yeah but this is the first to introduce an import syntax, right?
09:00
<Duncan MacGregor>
So at the moment we do GetValue and then ToPrimitive (which of course we don't actually need to do most of the time).
The fact those are just used in operator coercion means we'd need to come up with a new way to spec that, and work out whether we look for overloads before or after doing those conversion.
09:00
<nicolo-ribaudo>
yeah but this is the first to introduce an import syntax, right?
No, that's already in stage 3 and being implemented
09:00
<nicolo-ribaudo>
This only defines what using that syntax for importing JS files does
09:00
<Michael Ficarra>
oh maybe I'm confused
09:00
<Michael Ficarra>
can you send me a link?
09:00
<keith_miller>
The fact those are just used in operator coercion means we'd need to come up with a new way to spec that, and work out whether we look for overloads before or after doing those conversion.
Ah, yeah, I see. I would expect we would do the coercion after but maybe that causes problems?
09:00
<Michael Ficarra>
there's so many of these module proposals
09:01
<nicolo-ribaudo>
Stage 3: https://github.com/tc39/proposal-source-phase-imports this: https://github.com/tc39/proposal-esm-phase-imports/
09:01
<nicolo-ribaudo>
there's so many of these module proposals
Sorry about that, the space is huge and we ended up trying to split it in "independently motivated incremental changes", but maybe it ended up not being the best way 😅
09:04
<Michael Ficarra>
Sorry about that, the space is huge and we ended up trying to split it in "independently motivated incremental changes", but maybe it ended up not being the best way 😅
I'm legitimately still confused 😭
09:05
<nicolo-ribaudo>
I'm legitimately still confused 😭
Let's talk about that during lunch? :)
09:05
<Michael Ficarra>
Let's talk about that during lunch? :)
yes, please help me
09:08
<jkup>
yes, please help me
would love to join this session!
10:01
<Christian Ulbrich>
Could someone from Zoom plz. post the slide deck link, here?
10:08
<Ashley Claymore>
cc Ben
10:09
<Ben>
https://notes.igalia.com/p/pj5uX_5nC#/
10:17
<Duncan MacGregor>
Going back through meeting notes I have found the first reference to operator overloading and decimal here in section 9.iv.b "Decimal for stage 0". keith_miller .
10:26
<nicolo-ribaudo>
Going back through meeting notes I have found the first reference to operator overloading and decimal here in section 9.iv.b "Decimal for stage 0". keith_miller .
It's much older (2002-04): https://web.archive.org/web/20161227042517/http://www.mozilla.org/js/language/js20-2002-04/core/operators.html
10:27
<nicolo-ribaudo>
And then https://web.archive.org/web/20161227042517/http://wiki.ecmascript.org/doku.php?id=proposals:operators some years later
10:33
<Michael Ficarra>
the problem with underscore is that you can't avoid shadowing an outer underscore variable
10:33
<Michael Ficarra>
void doesn't have this problem
10:34
<Michael Ficarra>
like I get the people who want underscore for aesthetics, but it's technically strictly worse
10:34
<shu>
get a custom ligature font that converts void to _
10:35
<Duncan MacGregor>
It's much older (2002-04): https://web.archive.org/web/20161227042517/http://www.mozilla.org/js/language/js20-2002-04/core/operators.html

Oh yeah, that was just the first ref I could find to operator overloading with reference to the decimal proposal, with a very FLT like comment

I was going to propose operator overloading this meeting but didnt have time to finish it.

10:39
<shu>
Michael Ficarra: i really do not think void operator is a thing JS developers know about?
10:40
<shu>
like the extent to which people will know about it is using (void 0) as an incantation for undefined
10:40
<nicolo-ribaudo>
Sometimes we get questions in Babel about what's that void 0 thing that we generate so much in our output
10:40
<jkup>
feeling a lot less imposter syndrome having just googled "mdn void operator"
10:41
<Richard Gibson>
https://github.com/search?q=%2F%5Cbvoid+%5Ba-z_%5D%2F+language%3AJavaScript+&type=code
10:42
<Richard Gibson>
looks like mostly minified code, but there is definitely intentional use
10:42
<Michael Ficarra>
other than void 0, void is often used in front of IIFEs or in arrow concise bodies
10:43
<nicolo-ribaudo>
Those results are mind blowing
10:43
<nicolo-ribaudo>
There are so many usages of void e in the catch block in a statement position
10:43
<nicolo-ribaudo>
I assume it's to workaround bad linters before that the catch binding was optional
10:43
<nicolo-ribaudo>
Than, many of the results "for JS" are actually C code 😛
10:44
<Michael Ficarra>
this is a really good example from those search results
10:44
<shu>
yeah those results are quite surprising to me as well, fascinating
10:46
<Richard Gibson>
void undefined at https://github.com/inspect-js/is-equal/blob/1b8f8f4ffe6e652b0bce57b4563237c90898b150/why.js#L244 🙃
10:46
<Michael Ficarra>
okay lol not all of them are good
10:47
<Michael Ficarra>
who knows, maybe there's a var undefined in there somewhere
10:47
<nicolo-ribaudo>
sent an image.
If you look at this file it's clearly code that has been minified and then re-formatted
10:47
<nicolo-ribaudo>
https://github.com/everthis/tpp_script/blob/1e4b0f02adea066ccdb21df4a857ec9e2fe2fcd0/um.js#L1219
10:48
<shu>
lol um.js is a great name
10:48
<jkup>
I like that the two most interesting examples are a why.js file and an um.js file
10:51
<sffc>
I searched over some large JS codebases I've worked on and I didn't find any references to void, except where it is used in TypeScript to mean "this function does not return a value"
10:51
<Ashley Claymore>
To explicitly not want to handle a promise https://typescript-eslint.io/rules/no-floating-promises/ void somePromiseChain
10:56
<Richard Gibson>
void undefined at https://github.com/inspect-js/is-equal/blob/1b8f8f4ffe6e652b0bce57b4563237c90898b150/why.js#L244 🙃
10:56
<Ashley Claymore>

You already have to look into your object to figure out if it's a string or BigInt though

I don't think that is true for SpiderMonkey, their tagging includes that info AFAIK

10:57
<Ashley Claymore>
belt and braces
10:58
<Duncan MacGregor>
I think I've seen Java code with annotations to suppress unnecessary type casts, which feels similar.
11:10
<Ashley Claymore>
note: we'll need to merge https://github.com/tc39/notes/pull/326/files for the meeting notes to pass CI when that time comes
11:11
<Michael Ficarra>
is that who was just speaking?
11:11
<nicolo-ribaudo>
Yes
11:11
<ryzokuken (TC39 🇫🇮)>
is there any reason not to just merge it right away?
11:12
<nicolo-ribaudo>
is there any reason not to just merge it right away?
https://github.com/tc39/Admin-and-Business/issues/442 is still pending
11:12
<ryzokuken (TC39 🇫🇮)>
this issue means they were accepted as IE
11:12
<ryzokuken (TC39 🇫🇮)>
and are being onboarded
11:13
<ryzokuken (TC39 🇫🇮)>
done
11:24
<Ashley Claymore>
resume at hh:40
11:46
<Michael Ficarra>
@ryzokuken (TC39 🇫🇮) please advance the queue so I can reply
11:46
<ryzokuken (TC39 🇫🇮)>
Michael Ficarra to waldemar's?
11:46
<ryzokuken (TC39 🇫🇮)>
ah yes nvm
11:46
<Michael Ficarra>
yes that's the topic we're on
11:56
<Chris de Almeida>
sounds like a good rule for the nascent guide to writing good spec text 🧐
11:59
<nicolo-ribaudo>
I think the spec should not change meaning if you remove all green notes -- they should just clarify what you can otherwise infer
12:07
<Michael Ficarra>
@littledan please try not to jump queue topics like that
12:07
<littledan>
what? I was on the queue
12:07
<Michael Ficarra>
I really don't like when people read a TCQ topic and try to pre-reply to it, assuming what the person was going to say
12:07
<littledan>
sorry
12:08
<Michael Ficarra>
it's also speaking out of turn IMO
12:08
<littledan>
you mean how I used replies?
12:09
<littledan>
OK I'll be more careful about that, thanks
12:09
<Michael Ficarra>
if we have two topics, A and B, in TCQ in that order, a reply to A (or the submitter of topic A if different from B) shouldn't try to also address B before B has been introduced
12:09
<littledan>
oh, about testing? right, sorry I didn't want to presume what you were going to say, but yes my comment was off-topic for what I had put on the queue
12:10
<Michael Ficarra>
yes, thank you
12:10
<littledan>
(I had wanted to make that point independently from whether I was responding to you, just with respect to what Shu and Keith seemed to be assuming about the implications of normative text)
12:11
<keith_miller>
I guess I don't understand the point of having normative text that has no requirement?
12:11
<Michael Ficarra>
I have no hard feelings, it's just every time it happens, it makes me feel more pressure to fully express myself in the topic so nobody pre-replies to me with a misinterpretation of what I want to say
12:12
<littledan>
I guess I don't understand the point of having normative text that has no requirement?
The notes should be for context; reading the normative text should be enough to build an implementation, even if we can't have tests for it
12:13
<nicolo-ribaudo>
And Atomics.pause does have behavior, you just cannot test it within JS. Otherwise we wouldn't have this proposal at all
12:13
<keith_miller>
The notes should be for context; reading the normative text should be enough to build an implementation, even if we can't have tests for it
I guess but how do you ever say if something meets the specification or not if it's subjective?
12:14
<littledan>
specs are allowed to say "should", it's not must or nothing. There's more that the spec can say than "does this conform, yes or no"
12:14
<littledan>
these are just communication devices for humans
12:15
<nicolo-ribaudo>
Example: step 7 of https://tc39.es/ecma262/#sec-suspendthisagent
12:16
<nicolo-ribaudo>
It waits for some time
12:16
<nicolo-ribaudo>
Example: step 7 of https://tc39.es/ecma262/#sec-suspendthisagent
Doing something like this would address what I asked for, and it would do it exactly in the form that Richard Gibson proposed
12:17
<nicolo-ribaudo>
And the time in that case is implementation-defined (see step 24 of https://tc39.es/ecma262/#sec-dowait)
12:18
<keith_miller>
Example: step 7 of https://tc39.es/ecma262/#sec-suspendthisagent
That's definitively observable though. So it has actual requirements and is testable.
12:18
<hax (HE Shi-Jun)>
what is p1/p2 in the slide?
12:18
<littledan>
what is p1/p2 in the slide?
probably thinking of this and p
12:18
<keith_miller>
I think it's a typo
12:18
<rbuckton>
what is p1/p2 in the slide?
copy paste typo. p1 is this and p2 is p
12:23
<justingrant>
Yeah, this change was made by the IANA TZDB maintainers in 2015. Of all the intra-country merges, I do wish we could find some principled excuse to make this exception for my Quebcois friends (my current startup is based in Montreal) while not opening the door for 100+ other intra-country merges that are justified.
12:23
<keith_miller>
That's definitively observable though. So it has actual requirements and is testable.
The text in Atomics.pause is outside the engine's or even OS's control in the third box. So would be impossible to do. Unless you want it to say is "For integral numbers N, Atomics.pause(N) should attempt to wait at most as long as Atomics.pause(N+1)."? Then I would agree that has some meaning.
12:23
<littledan>
yes, I agree that this "should" needs to be super non-binding. "should attempt to" SGTM.
12:25
<nicolo-ribaudo>
Yes I would be ok with that text
12:25
<keith_miller>
The first box would have to be something like: "Implementations are expected to implement a pause or yield instruction if some version of the best practices of the underlying architecture recommends such instructions in spin loops."
12:25
<justingrant>
The context is that adding Zones in TZDB was originally done pretty much arbitrarily. And the volunteer maintainer (Paul Eggert) who has maintained for the last 15 years has been trying to prune it ever since, using a basic rule that if rules have been the same since 1/1/1970 then they get merged.
12:26
<nicolo-ribaudo>
The question is: if you were to delete the green notes, would your implementation still behave the same as if you are implementing it by also taking the green notes into account?
12:26
<nicolo-ribaudo>
The answer should be "yes"
12:26
<keith_miller>
Since the best practices can change over time and the engine may not know the best practices for the particular CPU it's targeting
12:26
<hax (HE Shi-Jun)>
If we have such auto correlation incantation, could it also apply to normal class?? 😃
12:27
<rbuckton>
If we have such auto correlation incantation, could it also apply to normal class?? 😃
No, how could it? Classes aren't shareable.
12:28
<keith_miller>
The question is: if you were to delete the green notes, would your implementation still behave the same as if you are implementing it by also taking the green notes into account?
What if some implementation finds people get better performance if they differ from those notes?
12:28
<keith_miller>
Should they be considered non-spec compliant?
12:29
<nicolo-ribaudo>
Assume that the person doing the implementation is infinitely smart and they can find all the possible optimizations
12:29
<nicolo-ribaudo>
The current spec text does not have enough info to hint what N is for
12:30
<nicolo-ribaudo>
Oh I misread
12:30
<nicolo-ribaudo>
Should they be considered non-spec compliant?
No, violating a should is not non-compliant
12:30
<nicolo-ribaudo>
But that doesn't mean that the spec text shouldn't clearly communicate the intention / recommended behavior
12:32
<Luca Casonato>
rbuckton: is the manual correlation token the same as Mechanism 1? or was Mechanism 1 "manually add the prototype to all incoming shared structs"? I couldn't quite tell
12:32
<rbuckton>
Not quite the same, no
12:33
<Luca Casonato>
ok, so then i don't understand Mechanism 1 I think
12:33
<littledan>
The first box would have to be something like: "Implementations are expected to implement a pause or yield instruction if some version of the best practices of the underlying architecture recommends such instructions in spin loops."
sure this sounds fine. Honestly I think the current text has enough caveats but no harm adding more.
12:34
<keith_miller>
If that's the consensus then I don't have a problem with normative should. Although, I would prefer a recommends but maybe should is well defined enough in TC39?
12:34
<littledan>
ok, so then i don't understand Mechanism 1 I think
no, it's like, at startup, thread A sends a message to thread B containing some magical reference to the Point class, and thread B hooks up that reference to its Point class
12:34
<hax (HE Shi-Jun)>
No, how could it? Classes aren't shareable.
I mean, u postMessage a normal class instance, and u got structured clone object which lose methods, so maybe it could be used to also auto correlation methods of them? 😃
12:34
<littledan>
If that's the consensus then I don't have a problem with normative should. Although, I would prefer a recommends but maybe should is well defined enough in TC39?
either seems fine to me, I don't know what the difference is tbh
12:34
<Luca Casonato>
no, it's like, at startup, thread A sends a message to thread B containing some magical reference to the Point class, and thread B hooks up that reference to its Point class
ok, i don't understand how this "magical reference" could work
12:34
<Luca Casonato>
we'd still need some "key" for each shared struct?
12:34
<Ashley Claymore>
Something something module declarations
12:35
<littledan>
we'd still need some "key" for each shared struct?
yes, this actually physically has to exist as the thing that's in memory as the prototype
12:35
<littledan>
but yes this is breaking new ground for postMessage
12:35
<mgaudet>
To clarify for myself.. if you don't have auto correlation, but you have imported the module on main and worker... it's just that points which are post-messaged will have no prototype; right?
12:35
<Luca Casonato>
ok - i still don't quite see how this isn't exactly the same as the auto correlation key
12:36
<littledan>
ok - i still don't quite see how this isn't exactly the same as the auto correlation key
autocorrelation means, you don't have to send that reference explicitly; the system just already is using the same key
12:36
<Luca Casonato>
oh i guess that each realm does not need to automatically resolve to the same key
12:36
<keith_miller>
either seems fine to me, I don't know what the difference is tbh
To me, should implies not doing it could be seen as non-compliance. Recommends is well a recommendation lol
12:36
<Luca Casonato>
the shared structs on either side do not have to have the same "identity" - you manually have to tie the identities together?
12:36
<mgaudet>
(and, I have forgotten a bit) and if you don't import on a worker, and you recieve a shared struct... you can read them like they're just POJOs with a null proto?
12:37
<littledan>
ok - i still don't quite see how this isn't exactly the same as the auto correlation key
so we skip adding a weird API that's "Correlate this magic key to this prototype", and reifying that magic key
12:37
<littledan>
(and, I have forgotten a bit) and if you don't import on a worker, and you recieve a shared struct... you can read them like they're just POJOs with a null proto?
yes
12:37
<littledan>
or maybe a "[[Prototype]] which throws"
12:37
<rbuckton>
To clarify for myself.. if you don't have auto correlation, but you have imported the module on main and worker... it's just that points which are post-messaged will have no prototype; right?
Not just postmessage. You can just set a shared struct value into a field on an existing shared struct
12:37
<littledan>
Not just postmessage. You can just set a shared struct value into a field on an existing shared struct
right, this is why the only thing needed with postMessage is this one-time setup
12:38
<mgaudet>
rbuckton: Ah that's a helpful reminder too
12:39
<rbuckton>
right, this is why the only thing needed with postMessage is this one-time setup
My biggest concern with manual correlation is that it weakens privacy, so we could probably never have private state in a shared struct. Auto correlation means you're loading the same code with the same privacy guarantees.
12:40
<Mathieu Hofman>
manual correlation does not have to weaken privacy
12:41
<rbuckton>
And I think having private state is an important capability for encapsulation, such as ensuring a field is only read/written atomically or under a lock via a method on the struct.
12:41
<Duncan MacGregor>
manual correlation does not have to weaken privacy
Yeah, do we know how it was thought it would?
12:42
<littledan>
yeah I can see how autocorrelation could help us with private field sharing, but I don't see how we'd do it with manual sharing
12:42
<Mathieu Hofman>
You have to reify a sharable object for the type that describes the capability to attach behavior and access private data (that is not reachable simply from having an instance, or even the constructor)
12:42
<nicolo-ribaudo>
I would consider the identity of a ModuleSource to be specifier+(id of the realm where it was originally created), and not just the specifier
12:42
<nicolo-ribaudo>
Which means that what I and Dan said is not the same behavior
12:43
<littledan>
right so in particular it's much more convenient if you don't have to pass along the handle, and can just independently import the same specifier and have it autocorrelate
12:43
<nicolo-ribaudo>
Yes I agree it's more convenient
12:43
<nicolo-ribaudo>
It's also more magical
12:43
<littledan>
yes, so, the mechanism you're describing is a way to do a handshake without exposing "too powerful" APIs
12:44
<nicolo-ribaudo>
Yes right
12:44
<littledan>
somehow in between the two mechanisms
12:44
<littledan>
(and corresponds to what I proposed a while ago)
12:44
<Mathieu Hofman>
right, I would like "a type admin capability" to the basis of the implementation, and then we can consider sugar on top
12:45
<littledan>
what nicolo-ribaudo is proposing would give us plenty of rope to implement sharing private field names
12:45
<littledan>
but a more imperative mechanism would not
12:46
<Mathieu Hofman>
Not really if you start to consider wasm, and how some wasm code would correlate the type
12:46
<Mathieu Hofman>
a more imperative mechanism can conceptually give you access to private data (maybe not fields per se)
12:47
<littledan>
well, currently Wasm doesn't need to correlate types because it's all structural. But if it gets some nominal capacity, why not transmit it by postMessaging WebAssembly.Module instances? I guess the thing is, they don't contain any reference to their Realm/Agent right now.
12:48
<littledan>
(I really want Wasm to get this nominal capacity)
12:48
<rbuckton>
Yeah, do we know how it was thought it would?
I can explain my concerns after plenary. Feel free to ask in #shared-structs:matrix.org and I'll follow up. Unfortunately I'm still fighting off COVID so it would be easier to explain my position once I've had time to recover and have a clear head.
12:48
<Mathieu Hofman>
well, currently Wasm doesn't need to correlate types because it's all structural. But if it gets some nominal capacity, why not transmit it by postMessaging WebAssembly.Module instances? I guess the thing is, they don't contain any reference to their Realm/Agent right now.
What restricts a module to contain only a single shared struct definition?
12:49
<littledan>
What restricts a module to contain only a single shared struct definition?
nothing, but in Wasm it'd also correlate by index (a sufficient replacement for source position)
12:49
<littledan>
similar to us correlating by Parse Node
12:50
<littledan>
so it would be by specifier + allocating agent/realm + index
12:52
<Mathieu Hofman>
That really seems like forcing JS specific concepts onto wasm. Does that mean wasm needs a JS module if it wants to correlate types between its own threads ?
12:53
<littledan>
Wasm as agents and specifiers; not sure what you mean
12:54
<littledan>
Wasm on the web (theoretically, with ESM integration) has a module map per Realm, so it'd be natural to use that rather than agent
12:55
<Duncan MacGregor>
I'm glad it's not just me who didn't understand that thread safety argument.
13:03
<rbuckton>
littledan: I think auto-correlation could handle privacy just fine.
13:03
<littledan>
littledan: I think auto-correlation could handle privacy just fine.
yep agreed
13:04
<littledan>
I think nicolo-ribaudo 's handshake mechanism would also handle it fine. It's "even more lexical".
13:04
<nicolo-ribaudo>
I think nicolo-ribaudo 's handshake mechanism would also handle it fine. It's "even more lexical".
Yes I think so too
13:05
<Mathieu Hofman>
How would auto correlation work across languages in a way that doesn't require either language to hold objects specific to the other language (as each language may run without the other existing)
13:06
<rbuckton>
My concern with manual correlation (i.e., based on postMessage/exemplars) is that realm B could wire up a struct from realm A into a struct definition that exposes private state, so you have to guard against malicious code being able to spawn a Worker (CSP helps on the web, but not in NodeJS) that can be used to hijack a struct.
13:06
<Mathieu Hofman>
Aka how would 2 wasm threads correlate shared structs (to get access private data) without requiring it to know what a JS module is
13:07
<littledan>
My concern with manual correlation (i.e., based on postMessage/exemplars) is that realm B could wire up a struct from realm A into a struct definition that exposes private state, so you have to guard against malicious code being able to spawn a Worker (CSP helps on the web, but not in NodeJS) that can be used to hijack a struct.
Yes, I share these kinds of soundness concerns with a very expressive imperative API, but I think nicolo-ribaudo 's suggestion is not subject to this risk.
13:07
<rbuckton>
How would auto correlation work across languages in a way that doesn't require either language to hold objects specific to the other language (as each language may run without the other existing)
Does it need to work across languages? If JS private state is a uniquely JS mechanism, then WASM could interact with the struct via FFI calls into JS.
13:08
<shu>
Does it need to work across languages? If JS private state is a uniquely JS mechanism, then WASM could interact with the struct via FFI calls into JS.
yeah exactly
13:08
<littledan>
Does it need to work across languages? If JS private state is a uniquely JS mechanism, then WASM could interact with the struct via FFI calls into JS.
some form of nominal correlation would be useful for Wasm, especially if Wasm wants to interact with JS in various threads and give prototypes to its objects
13:08
<shu>
you do some tearoffs that can exfiltrate private data and import them from the wasm side
13:08
<Mathieu Hofman>
My concern with manual correlation (i.e., based on postMessage/exemplars) is that realm B could wire up a struct from realm A into a struct definition that exposes private state, so you have to guard against malicious code being able to spawn a Worker (CSP helps on the web, but not in NodeJS) that can be used to hijack a struct.
if you use forgeable type description, of course. Manual correlation has to be based on non forgeable type descriptors that need to be explicitly shared with the realm in the first place
13:09
<shu>
Mathieu Hofman: you're engaged in the nuts & bolts of how correlation could work. great! but i'm more interested in working through the very high level, "i feel this is unsafe" objection
13:10
<Mathieu Hofman>
Does it need to work across languages? If JS private state is a uniquely JS mechanism, then WASM could interact with the struct via FFI calls into JS.
Does wasm really have no notion of private data for objects?
13:10
<rbuckton>
some form of nominal correlation would be useful for Wasm, especially if Wasm wants to interact with JS in various threads and give prototypes to its objects
Is there any concern that malicious code could craft a WASM assembly on the fly to unpack private state from a class?
13:10
<shu>
Does wasm really have no notion of private data for objects?
why would it?
13:10
<shu>
it's a target for compilers of higher level languages
13:10
<littledan>
Does wasm really have no notion of private data for objects?
wasm structs are simply typed tuples
13:10
<shu>
it doesn't have methods because you're supposed to just compile a vtable yourself
13:10
<shu>
not that it literally doesn't have methods
13:12
<Christian Ulbrich>
How is soon is now, I deployed dockerized TCQ reloaded to https://tcq.staging.tcq-reloaded.tcq.ninja/ , now with persistent storage, actual PR is at: https://github.com/zalari/tcq/pull/7 ; I will explain individual decisions. So I think, we can use TCQ reloaded next plenary!
13:12
<shu>
i feel like there's a lot of wishful thinking from opponents of the proposal
13:12
<shu>
yes, this is a difficult-to-program-correctly space
13:12
<rbuckton>
some form of nominal correlation would be useful for Wasm, especially if Wasm wants to interact with JS in various threads and give prototypes to its objects
Ignoring private state JS could expose an API to acquire a "correlation token" it could pass to WASM to set up prototypes?
13:13
<shu>
but adding on little guardrails doesn't really advance the goal of writing correct programs
13:13
<shu>
well, not even guardrails, just pointless friction imo
13:13
<rbuckton>
if you use forgeable type description, of course. Manual correlation has to be based on non forgeable type descriptors that need to be explicitly shared with the realm in the first place
What do you consider to be a "non forgeable type descriptor"?
13:14
<Mathieu Hofman>
Mathieu Hofman: you're engaged in the nuts & bolts of how correlation could work. great! but i'm more interested in working through the very high level, "i feel this is unsafe" objection
That is mostly a question for Mark. My personal opinion right now is that shared fields should be private by default, and that correlated behavior would be providing the necessary encapsulation to access that shared data in a thread safe way
13:14
<shu>
mark literally just said that didn't work for java
13:14
<shu>
why do you think that'll move the safety needle here?
13:15
<shu>
i'd also request you ask yourself the question, what happens if you get thread unsafe code in JS/Wasm
13:15
<Mathieu Hofman>
you do some tearoffs that can exfiltrate private data and import them from the wasm side
jumping to JS land for this seems inefficient. I am really surprised that wasm wouldn't want a private field concept on its own wasm gc objects (shared or non shared)
13:15
<shu>
it's the wrong abstraction level
13:18
<Aki>
so who wants to volunteer to take a look at the print PDFs? they're in a state approaching publishable
13:18
<Mathieu Hofman>
What do you consider to be a "non forgeable type descriptor"?
An object you get when defining the struct that is itself shareable. Not something you can obtain simply by having a reference to the constructor or any instance.
13:20
<rbuckton>
Do we, as a committee, think JS privacy is a security feature? Would it be unforgivable if private state isn't really private at the realm boundary? If we could have struct S { #x; ... } in realm A mapped to struct S { x; ... } in realm B, would we consider that a security vulnerability?
13:21
<shu>
good question
13:21
<shu>
this is all echoes of hard constraints held by SES folks that are not clearly communicated as such, and so they feel like stop energy
13:22
<shu>
also like look, i'm fine with removing methods
13:23
<shu>
but i think that's actually worse for correctness! and i really don't get the arguments that it's better for correctness
13:23
<shu>
and it sounded like others share my confusion
13:23
<rbuckton>
In a shared struct, struct S { #x; ... } means that in the realm where it is defined, the private name #x refers to the first fixed storage field in the struct. in another realm you could have struct S { x; ... } that just says the field "x" refers to the first fixed storage field in the struct. If you manually correlate S in each realm, does the privacy need to be preserved?
13:23
<shu>
the only thing i can make sense of is, "if we don't have methods, i can mentally compartmentalize everything over in wasm land, so i can not think about it"
13:24
<shu>
but end-to-end that argument doesn't make sense
13:24
<Mathieu Hofman>
The equivalence of private fields has always been WeakMap, and the guiding principle is "how do you give access to the WeakMap instance to access private data". In JS, the WeakMap instance is an object capability like everything else. No-one should be able to get object references without explicitely receiving them.
13:24
<shu>
you can use shared structs as a WeakMap key in a per-thread WeakMap
13:25
<shu>
that's fine
13:26
<rbuckton>
Methods are just functions with lexical access to private state. The correlation mechanism is to make sure you're using the right functions (methods) in a given realm. Free functions provide no benefits.
13:26
<shu>
yeah exactly!
13:26
<Mathieu Hofman>
IMO the only interest to private data is to have it shared, so that it can be used for encapsulation
13:27
<shu>
i am going to become le joker
13:27
<rbuckton>
And if you want to guard your shared memory multithreading data structures and logic with a wrapper facade, as Mark suggested, you can do the same thing with methods. Methods vs functions has no impact on that.
13:29
<rbuckton>
IMO the only interest to private data is to have it shared, so that it can be used for encapsulation
That's precisely why I want private state to be an option for shared structs in the future.
13:31
<shu>
i want to be very clear on my thinking on footguns
13:33
<shu>
where something is already expressible, we should be thinking hard about not introducing alternative forms that are easy to get wrong, or easy to be slow, etc. because the incentive for a developer to do a thing is because it has the semantics the developer wants to do. so if choosing between form A and B that have more or less the same core behavior but differ in performance or some aspect of correctness, we shouldn't add forms that have higher likelihood of being slow or incorrect
13:34
<shu>
but if one's claim is that the likelihood of incorrectness comes from expressing the thing at all (like shared memory), banning alternate forms adds friction for zero gain!
13:41
<rbuckton>
In terms of TypeScript's "incremental adoption" story, most of our AST nodes are essentially "immutable" after they are created (though that's only enforced through type checking). Being able to produce AST nodes in parallel parsers and collect them in the main thread for checking, and then spin them out to parallel emitters would be essential for incremental adoption in TS. Public fields aren't really a concern since we could annotate them with a design-time only readonly modifier, though it would be interesting to add an actual concept of an init-only field, e.g., shared struct S { const x; ... }
13:42
<shu>
ah right, that reminds me i didn't respond to the narrow point that mark made about the Point example being not thread safe
13:43
<shu>
i also didn't show any code mutating .x and .y :)
13:44
<rbuckton>
But for incremental adoption to work those nodes would need to have methods, otherwise we would need to rewrite the entire compiler to even get started.
13:58
<Chris de Almeida>
Do we, as a committee, think JS privacy is a security feature? Would it be unforgivable if private state isn't really private at the realm boundary? If we could have struct S { #x; ... } in realm A mapped to struct S { x; ... } in realm B, would we consider that a security vulnerability?
yes, yes, and yes. if I understand your example correctly, the private field on A being accessible from B, I would consider that a security vulnerability
14:00
<rbuckton>
yes, yes, and yes. if I understand your example correctly, the private field on A being accessible from B, I would consider that a security vulnerability
Then I would expect that WASM can't read JS private state directly as it constitutes a vulnerability.
14:01
<rbuckton>
But I also do not hold that private state is a security feature.
14:07
<Chris de Almeida>
But I also do not hold that private state is a security feature.
would you agree that encapsulation is a security feature?
14:08
<Chris de Almeida>
to be clear I don't suggest that privacy (or encapsulation in general) is exclusively a security feature
14:09
<rbuckton>
I see it as a developer experience/convenience mechanism. It's not that I think it should be less "secure", per se, but that I don't consider private state to be trustworthy as there are limitations to its "security" in some situations.
14:10
<Chris de Almeida>
I agree with not relying on it completely as a protection mechanism
14:10
<shu>
would you agree that encapsulation is a security feature?
that risks devolving into arguing what "security" means so i think of it in terms of SLAs and who's responsible for hitting those SLAs
14:11
<Chris de Almeida>
that risks devolving into arguing what "security" means so i think of it in terms of SLAs and who's responsible for hitting those SLAs
I'm just trying to understand his perspective and where the line is drawn
14:11
<Chris de Almeida>
forgetting about security for the moment, the private field on A being accessible from B, is it not problematic that this is violating privacy/encapsulation in general?
14:11
<shu>
practically to me, as a SWE, "security" means the highest priority bug that we'll pull out all the stops for to fix
14:12
<shu>
forgetting about security for the moment, the private field on A being accessible from B, is it not problematic that this is violating privacy/encapsulation in general?
all bugs are problematic, i'm explaining the real world consequences of how problematic it's considered
14:13
<shu>
if there were a bug with private fields, browser VMs aren't going consider it a "security bug" in that we're not going to be trying to get a fix ASAP, respin binaries for stable branch, etc
14:13
<shu>
but an application that depends on that private field might
14:14
<Chris de Almeida>
all bugs are problematic, i'm explaining the real world consequences of how problematic it's considered
I may not be connecting the dots between what you're saying and what Ron is saying
14:15
<shu>
okay then ignore me, i don't think it's particularly important for this concrete topic
14:20
<justingrant>
IANA's rule for zone merges is that the largest-population city (at the time of the merge) wins.
14:25
<rbuckton>
If privacy is an important security concern, then you must have an unforgeable correlation mechanism. Auto-correlation by source location is unforgeable. I'll admit I still don't quite understand Mathieu Hofman's suggestion about an unforgeable type descriptor as it still seems unsound to me.
14:26
<justingrant>

They also do merges across country boundaries, which is the thing that CLDR (correctly, IMO and now according to the 402 PR we approved on Tuesday) backs out.

But backing out intra-country merges too would make time zone picker UIs hugely confusing for end users, and backing out some but not others would generate political fuss that TC39 (and CLDR) wants to stay far away from.

What's nice about the "don't merge across country codes" rule is that ISO 3166-1 decides what the country codes are, not CLDR or TC39. And IANA maps every country code to a Zone. So JS can just draft behind others.

14:31
<justingrant>
One more important detail: today, merges are really visible in JS because Intl.DateTimeFormat canonicalizes zone IDs. This behavior will change once Temporal is Stage 4. So if you create a Temporal.ZonedDateTime with America/Montreal, then it will stay America/Montreal. After Temporal Stage 4, the only place that merges will matter up in JS will be when the IDs come from ECMAScript built-ins: when reading the system's current time zone and when calling Intl.supportedValuesOf('timeZone'). Any time users provide IDs, JS won't touch them anymore. Vive La Quebec!
14:31
<justingrant>
Le Quebec?
14:34
<justingrant>
yeah that's an interesting typo that only an English speaker could make

Yep, guilty as charged! I was in a hurry and made a typo. Thanks hax (HE Shi-Jun) for calling it out. I just corrected the slide.

Sorry it's taken so long to respond, I'm just now catching up on matrix.

14:37
<Chris de Almeida>

If privacy is an important security concern, then you must have an unforgeable correlation mechanism. Auto-correlation by source location is unforgeable.
👍️

20:02
<justingrant>
Yes, ICU and JS implementations tend to implement this historical part

My understanding was that JS implementations don't actually use the data in backzone. I think (not 100% sure) that the actual timezone data used is Asia/Shanghai. Here's Chrome:

new Intl.DateTimeFormat("en", {timeZone: 'Asia/Chongqing', timeStyle: 'long'}).format(new Date('1940-01-01T00:00Z'))
// => '8:00:00 AM GMT+8'
new Intl.DateTimeFormat("en", {timeZone: 'Asia/Shanghai', timeStyle: 'long'}).format(new Date('1940-01-01T00:00Z'))
//=> '8:00:00 AM GMT+8' 
20:35
<justingrant>
Could somebody re-explain to me this comment? 😅 Do databases use timezones that are not the timezones we are using in temporal?
nicolo-ribaudo: - did you get an answer to this? I don't remember this comment but it was a long presentation so it might have slipped by me.
20:50
<justingrant>
leftmostcat (UTC-7): I would like to start a proposal for declarative custom time zones. Would you be interested in co-championing this with me? I don't have the domain expertise in iCalendar/jCal/JSCalendar to turn their schemas into spec text, but if you (or someone you know) is interested in doing that part, then I'd be eager to help turn that into reality.
20:55
<leftmostcat (UTC-7)>
leftmostcat (UTC-7): I would like to start a proposal for declarative custom time zones. Would you be interested in co-championing this with me? I don't have the domain expertise in iCalednar/jCal/JSCalendar to turn their schemas into spec text, but if you (or someone you know) is interested in doing that part, then I'd be eager to help turn that into reality.
I would be.
21:17
<justingrant>
I would be.
Great! I'll DM you and we can get a proposal started.
21:26
<bakkot>
speaking of timezones, people interested may wish to follow or contribute to the proposal for adding timezones to WASI https://github.com/WebAssembly/wasi-clocks/pull/61
21:50
<ptomato>
I won't have time to look at it in detail for a while. At first glance it looks like they are exposing an "in DST" flag. Unfortunately that's not well defined for many time zones.