03:30
<jschoi>
My sincere apologies for the late notice, but I’ve opened an agenda pull request for a 1.5-hour constraint tomorrow.
04:47
<ljharb>
ES2022 candidate: https://github.com/tc39/Reflector/issues/424
04:53
<waldemar>
Are we having the meeting tomorrow morning? I can't find the logistics anywhere: a schedule or a video link.
05:09
<ljharb>
usually the sign-in form is added an hour or so before the meeting, and that form's thank you page has the jitsi details
05:09
<ljharb>
(the draft schedule indeed doesn't seem to be up yet)
06:06
<Rob Palmer>
We'll be updating the Reflector post details shortly.
08:36
<Rob Palmer>
Draft schedule is nearly ready. I will say this meeting we receive a large volume of constraints, which makes catering to all folks tricky.
09:20
<Rob Palmer>
Ujjwal has now prepared the draft schedule. Please see the Reflector Post
13:15
<Rob Palmer>
Hope everyone is feeling full of energy. Plenary begins in 45mins!
13:36
<Rob Palmer>
I have opened the video call. Whoever makes it through first, please say here so we know the passcode is working.
13:38
<Rob Palmer>
Ok, we are confirmed good on the passcode.
13:55
<Rick Waldron>
Good morning. I'm not going to be available until around noon, so if someone else from the Test262 Maintainer Group would like to give the update, that would be great!
13:58
<Rob Palmer>
*** Plenary starts in 2 mins! *** 🎉
14:20
<ljharb>
Rob Palmer: bterlson there's a few welcome emails waiting to be sent, eg https://github.com/tc39/Admin-and-Business/issues/209
14:25
<bakkot>
is IS talking about the JSON standard
14:26
<Tierney Cyren>
I don't believe so
14:30
<ljharb>
i'm confused, isn't everything TC39 does an ecma thing?
14:30
<shu>
yulia: since we're over timebox i'll ask my question in here: my understanding was that whether to adopt the alternative copyright was a per-TC decision, not a per-spec decision
14:31
<shu>
is it in fact per-spec, and that's why we need to back to the IPR committee?
14:31
<yulia>
it is a per tc request for a spec
14:31
<shu>
right, so we shouldn't need to go back to them for 262 or 404
14:31
<shu>
err, 402
14:31
<shu>
yeah, what waldemar's saying
14:32
<yulia>
hm, ok something to clarify
14:33
<yulia>
this is what happens when you go to meetings sick
14:33
<yulia>
ill check the documents
14:35
<msaboff>
yulia: I'll check the special GA docs as well.
14:36
<yulia>
thanks
14:41
<msaboff>
GA-2022-016 states
After discussing TC39's motivation for using the alternative copyright notice there is this statement:
The IPR Ad hoc Group suggests the GA consult with Ecma Counsel and the IPR Ad Hoc Group when considering applying an Alternative Copyright Notice to any other Ecma Standards.
14:43
<shu>
huh, so it is per standard? that process could be streamlined certainly
14:45
<msaboff>

I should point out that ECMAScript is the specific standard talked about before the "any other Ecma Standards" comment.

Therefore one reading of that statement is the 262 can adopt the ACN, but other standards like 402 would require consultation.

14:48
<yulia>
I just found this as well -- yes this is what I was thinking of (sorry, still super foggy)
14:49
<yulia>
waldemar: ^ it is in GA-2022-016
14:49
<Tierney Cyren>
The problem has gone unaddressed for 5 years?
14:50
<Tierney Cyren>
That feels... unacceptable.
14:50
<yulia>
sorry, which problem?
14:50
<Tierney Cyren>
not being able to get information from the IT people
14:50
<yulia>
ah, yeah this is something we should solve. I am talking to someone about it
14:51
<ljharb>
worth noting the LF IT folks are highly responsive and have an SLA measured in days instead of years :-p
14:52
<msaboff>
shu: Visible with sun glasses on!
14:58
<jschoi>
Does ecmarkup now enforce AOs always having structured headers?
15:00
<Michael Ficarra>
jschoi: yes, though it does not mandate that you describe parameter types or return types
15:00
<Michael Ficarra>
please do so as much as possible (or at least explicitly mark unknown) so ecmarkup catches these kinds of errors
15:01
<bakkot>

Does ecmarkup now enforce AOs always having structured headers?

no it does not

15:02
<bakkot>
because "not having a structured header" is just "writing prose which happens to look like an AO"
15:03
<Rob Palmer>
Good morning. I'm not going to be available until around noon, so if someone else from the Test262 Maintainer Group would like to give the update, that would be great!
Who will give the test262 update?
15:04
<shu>
sarahghp maybe? if rick isn't available
15:04
<sarahghp>
yes I will do it
15:07
<bakkot>
ljharb: can you put the names in the notes
15:07
<bakkot>
I couldn't catch all of them
15:07
<ljharb>
re CoC: https://github.com/tc39/Reflector/issues/382#issuecomment-1029240838
15:07
<ljharb>
ljharb: can you put the names in the notes
yep! doing now
15:07
<Michael Ficarra>
maybe we should have somebody explicitly endorse the CoC committee candidates?
15:09
<ljharb>
Michael Ficarra: oh sorry, i should have mentioned that; by presenting them to plenary the CoC committee has implicitly endorsed them
15:20
<Jack Works>
this is surprising
15:21
<Jack Works>
I though it should work, so what I just said is wrong
15:22
<shu>
bakkot: is that really what we say about the current Realm for %name%s?
15:22
<shu>
bakkot: https://tc39.es/ecma262/#sec-well-known-intrinsic-objects isn't super clear
15:23
<shu>
i think the operative sentence is "before any code is evaluated"
15:30
<Michael Ficarra>
test262 relies on @@species in the runner?
15:31
<yulia>
yes, this came up when we proposed restriction of species generally
15:31
<yulia>
and i was afraid that what kevin found was related to that, to which i think the response would be -- can we do something that is test runner specific
15:32
<yulia>
there are other blockers to general removal/restriction, this isn't the only one
15:32
<yulia>
this is another thing on the ever growing pile that grew ever higher while i was sick
15:33
<Rick Waldron>
Michael Ficarra yulia hold on, that's not quite true. The runner does not rely on @@species. There are tests that test for @@species
15:33
<yulia>
oh, i may have misremembered
15:34
<Rick Waldron>
No problem, just clarifying 👍️
15:34
<Michael Ficarra>
yeah, okay, that's what I would've expected
15:34
<yulia>
Rick Waldron: it was a comment you made in relation to https://github.com/tc39/proposal-rm-builtin-subclassing and i think i just linked it wrong
15:34
<yulia>
maybe it was related to type 2 subclassing which won't happen
15:38
<Rick Waldron>
Rick Waldron: it was a comment you made in relation to https://github.com/tc39/proposal-rm-builtin-subclassing and i think i just linked it wrong
I'm having trouble finding the discussion in the notes
15:39
<yulia>

Rick Waldron:

RW: So you were asking for examples of Type III. In Test262, we use Type III extensively for testing the behavior of built-ins across realms. We are heavily reliant on setting the species with a cross realm copy of the constructor to make sure the lookup chain of the constructor is preserved correctly. To make sure that the lookup chain is preserved correctly. If you look at it, I don’t want to rathole into that, we can look at it together offline. But that’s a pretty substantial example of where it’s being used in the wild. And I don’t know how else we would test cross realm behavior which is important to the language cause we have access to multiple realms in any given runtime. So I just wanted to put that on the board and say let’s chat about it offline.

15:39
<yulia>
is that still true?
15:39
<yulia>
maybe this changed
15:40
<Rick Waldron>
Oh right, that makes sense. I was describing what we do when we test Symbol.species.
15:40
<Rick Waldron>
Let check one other thing
15:40
<yulia>
ok, yeah that was what i was worried kevin found
15:40
<yulia>
but it wasn't fortunately
15:41
<yulia>
I am super foggy today, so sorry if i am being confusing
15:41
<Rick Waldron>
Ok, confirmed: we do not rely on Symbol.species in eshost or test262-harness.
15:41
<shu>
correction: Chrome never shipped and unshipped grouping because we saw this before we could ship
15:41
<Rick Waldron>
Symbol.species is used in test262's harness files and tests themselves, for cross realm testing. That could be changed.
15:42
<yulia>
Ok, confirmed: we do not rely on Symbol.species in eshost or test262-harness.
sweet!
15:43
<yulia>
Symbol.species is used in test262's harness files and tests themselves, for cross realm testing. That could be changed.
ok, cool , this is what i thought and expressed poorly
15:43
<Rick Waldron>
I think I may have expressed it poorly myself
15:44
<Michael Ficarra>
if we don't know what versions the websites use, can't we just do a functional test?
15:44
<Rick Waldron>
My description above explain how its being used in the wild, but wasn't clear at which level
15:45
<devsnek>
groupedByTo doesn't compute in my brain
15:46
<TabAtkins>
yeah it feels bad
15:47
<devsnek>
groupMap
15:48
<legendecas>
groupedXX series sounds like what the array change by copy proposal is doing
15:49
<ljharb>
we could also go with Object.group and Map.group /ducks
15:50
<bakkot>
sadness
15:50
<bakkot>
i liked groupBy
15:51
<ljharb>

as much as i think it makes sense on Array.prototype, that does make the naming simpler, and opens up Set.group and friends in the future.

i also prefer groupBy :-/

15:51
<Michael Ficarra>
I feel like we gave up on groupBy way too easily, personally
15:52
<ljharb>
i mean, someone could still go evangelize
15:53
<Kris Kowal>
As long as we don’t break Roll20 😉
15:57
<bakkot>
I'm more worried about all the .gov.br sites
15:57
<bakkot>
breaking government services seems bad
15:57
<bakkot>
though I didn't actually check what they're hosting
16:00
<Kris Kowal>
Facetious wink. 👆
16:35
<TabAtkins>
I'm gonna verify I can project to the jitsi in one sec
16:35
<TabAtkins>
okay, looks good
16:35
<TabAtkins>
can someone verify?
16:36
<Sergey Rubanov>
it works
16:37
<TabAtkins>
cool, thanks
16:42
<Robert Pamely>
Are we starting again on the hour?
16:44
<Ashley Claymore>
yep!
16:45
<Ashley Claymore>
Really cool topics being discussed this afternoon!
16:46
<Kris Kowal>
What are the reasons Promise.resolve(promise) consults promise.constructor for promises that pass the brand check? It would be useful for us in the hardened JavaScript community if Promise.resolve(promise) could be guaranteed to give control to the provider of the promise only in subsequent events.
16:46
<Ashley Claymore>
does it subclass?
16:48
<Kris Kowal>
I believe Promise was one of the first proposals to account for Symbol.species, so I assume so, but also assume that’s not useful.
16:50
<Ashley Claymore>
class P2 extends Promise {}
let x = P2.resolve(1);
P2.resolve(x) === x;
Promise.resolve(x) !== x;
16:50
<Ashley Claymore>
Maybe because of that?
16:50
<Ashley Claymore>
I should probably check the spec instead of guessing...
16:51
<Kris Kowal>
That story checks out.
16:54
<bakkot>
that is almost certainly the reason, yes
16:54
<bakkot>
subclassing: it's bad
16:55
<Kris Kowal>
In a way this is good news. That means that in a SES proposal, we can change the behavior of Promise.resolve() such that subclassing no longer works, but our delegation invariant is preserved (after the host program opts-in by calling lockdown())
16:56
<Rob Palmer>
We start in 4 mins!
17:03
<bakkot>
why does this proposal allow default, instead of just when(unused)?
17:03
<bakkot>
or even just a bare when {, to go with catch {
17:04
<ljharb>
it allows either, but not both
17:04
<ljharb>
we could use a bare when instead of default, sure, that's just bikeshedding
17:04
<ljharb>
but when (unused) has to be allowed for consistency with the way irrefutable patterns work
17:05
<Tierney Cyren>
TIL 0 can have a sign
17:05
<ryzokuken>
is there anyplace else in JavaScript where these sematics hold?
17:05
<ljharb>
ryzokuken: which?
17:05
<ryzokuken>
0 matching both +0 and -0
17:05
<bakkot>
I have no problem with when (unused), I just don't see a use for default if you already have that
17:05
<ljharb>
yes, 0 === -0
17:05
<bakkot>
===
17:06
<bakkot>
also sets and maps
17:06
<ryzokuken>
ah, okay, thanks
17:06
<ljharb>
bakkot: the use is that it's confusing and gross to have to write a binding when you don't want one, and when { i'd argue doesn't convey that it's the "everything else" category very clearly.
17:06
<legendecas>
does match(expr) { if (bool): expr } mean matching against constant bools?
17:06
<ljharb>
legendecas: against an expression that resolves to a truthy or falsy value, yes
17:06
<ljharb>
like any other if
17:07
<bakkot>
also what's the use case for the bare if one
17:07
<bakkot>
it seems like
17:07
<bakkot>
not so useful
17:07
<bakkot>
I have a hard time seeing a case where you don't also need to name the match-ee
17:07
<legendecas>
like any other if
thank you. well, in the context of slides, i'm confused that why it isn't match(expr) { if(expr): expr }
17:07
<ljharb>
it's cleaner than when (unused) if (condition)
17:07
<Kris Kowal>
yes, 0 === -0
Wrt differences between +0 and -0, 1/-0 === -Infinity vs 1/0 === Infinity.
17:07
<bakkot>
ljharb: does that ever happen
17:07
<ljharb>
thank you. well, in the context of slides, i'm confused that why it isn't match(expr) { if(expr): expr }
yeah fair, it's a confusing example
17:08
<ljharb>
bakkot: yes, there's examples in the readme.
17:08
<legendecas>
yeah fair, it's a confusing example
looks like this part is not in the spec, yet.
17:08
<ryzokuken>
so to match an array with holes I'd need to do [undefined, undefined, "foo"]?
17:09
<ljharb>
legendecas: most things aren't in the spec; it's only going for stage 2, where only an initial spec is required.
17:09
<ljharb>
the readme is what you want
17:09
<bakkot>
ljharb: the example in the readme is match (res) { if (isEmpty(res)) but that's still naming the matchee
17:09
<ljharb>
so to match an array with holes I'd need to do [undefined, undefined, "foo"]?
or [,, 'foo'], yes
17:09
<bakkot>
it's just repeating the expression
17:09
<bakkot>
seems bad
17:09
<ljharb>
why?
17:09
<ljharb>
i see what you mean, that a bare if would still need to reference the matchable
17:09
<ljharb>
but why would it be bad to not be forced to create a new binding just to reference it, via when (res) if (isEmpty(res))?
17:10
<Jack Works>
I have no problem with when (unused), I just don't see a use for default if you already have that
yeah. default just make it easier to read
17:10
<bakkot>
I'd just write when (_) if (whatever)
17:10
<bakkot>
so you don't have to learn a new form
17:10
<bakkot>
or default if (whatever), maybe
17:10
<ljharb>
having to write the underscore is gross
17:10
<ljharb>
and default has to be last - it'd be confusing to have default if be allowed all over the place
17:11
<bakkot>
hm
17:11
<bakkot>
not sure I agree
17:11
<ljharb>
having a bare when would be alright, but then you have when { and when if (x) { and that reads odd to me
17:11
<Jack Works>
also what's the use case for the bare if one
if (isSomethingWeWant(expr)):
an escape path when pattern is not expressive enough and you want to do a complex check
17:11
<bakkot>
maybe actually the thing I want is to be able to bind the name in the match (e) part
17:11
<bakkot>
match (e as x), maybe
17:11
<ljharb>
you can, just like that. specifically so you can name the matchable when it's complex expression
17:12
<Tierney Cyren>
imo default is also nice because it's a structure that feels not dissimilar from other uses of default in the language
17:12
<bakkot>
wait, then there should not be when (identifier)
17:12
<ljharb>
it falls out of the ability to do when ([identifier])
17:12
<bakkot>
that's just match (e as x) default
17:12
<devsnek>
what's the case for when (unused) {}
17:12
<ljharb>
an irrefutable pattern works everywhere, and not being able to use it at the top-level is an inconsistency
17:12
<devsnek>
not in the video call atm
17:12
<ljharb>
what's the case for when (unused) {}
like switch default, or an "else" - it's the last uber-catch-all match clause.
17:13
<bakkot>
not being able to mix irrefutable patterns and a default is also inconsistent
17:13
<bakkot>
but that's fine
17:13
<devsnek>
oh right
17:13
<devsnek>
its when not match
17:13
<bakkot>
I prefer the inconsistency of not allowing both match (e as x) and when(x)
17:13
<devsnek>
i am caught up now
17:13
<ljharb>
you can, with when (foo) as the last clause
17:13
<devsnek>
i think eliding makes sense
17:13
<devsnek>
when {}
17:14
<ljharb>
when { is a reasonable alternative spelling for default {, and that can and should be bikeshedded during stage 2
17:14
<Jack Works>
I'd just write when (_) if (whatever)
yeah when(_) if (expr) give you a temporally binding of the matched expression when it is not a simple identifier. 👀 this is an interesting case
17:15
<bakkot>
oh god are we going to have both Symbol.match and Symbol.matcher
17:15
<bakkot>
Symbol.match was a mistake
17:15
<Michael Ficarra>
are these slides on the protocol new? I didn't see these
17:15
<ljharb>
Symbol.match was a mistake
yes it was
17:15
<Jack Works>
match (e as x), maybe
we have that in previous design. we think it's useful but can also be added in the future match (e) as x {}
17:15
<ljharb>
oh god are we going to have both Symbol.match and Symbol.matcher
happy to bikeshed the symbol name; the overlap sucks
17:16
<ljharb>
we have that in previous design. we think it's useful but can also be added in the future match (e) as x {}
i think we have match (e) as x { in the current proposal (or maybe match (e as x) {, i forget which we agreed on)
17:16
<devsnek>
excited for us to say Symbol.matcher was a mistake in 6 years
17:17
<legendecas>
excited for us to say Symbol.matcher was a mistake in 6 years
Symbol.match
17:17
<bakkot>
Symbol.decons
17:18
<Michael Ficarra>
do any of the built-in prototypes implement the matcher protocol?
17:18
<Jack Works>
oh god are we going to have both Symbol.match and Symbol.matcher
😂 yeah and we cannot bikeshedding on this because people will always try Symbol.match whatever we named Symbol.matcher to
17:18
<bakkot>
I dislike this brand checking part more than any other part of the proposal
17:18
<ljharb>
do any of the built-in prototypes implement the matcher protocol?
imo many of them will, as part of this proposal
17:18
<ljharb>
per this slide
17:18
<bakkot>
these are constructors, not prototypes
17:18
<Michael Ficarra>
ljharb: that's on the constructor, not prototype
17:18
<ljharb>
oh sorry
17:19
<ljharb>
no, i wouldn't expect builtin prototypes to have it
17:19
<ljharb>
do you have something in mind?
17:19
<Michael Ficarra>
yeah, what if I put a regexp in there?
17:19
<bakkot>
I claim and and or have an obvious precedence relationship
17:19
<bakkot>
or at least a very well-precedented one
17:19
<ljharb>
ah right. yes, regexes definitely do implement it (with the same logic the literal patterns apply)
17:19
<Michael Ficarra>
where do I find the information on what does and what doesn't?
17:20
<ljharb>
in theory it's all in the readme
17:20
<ljharb>
during stage 2 it'll all end up in the spec
17:20
<Jack Works>
Symbol.decons

If we take rbuckton 's unapply proposal to replace the custom matcher

const Some(x) = val

match (val) {
    when (Some(x)): x
}

and we first teach people this feature in the deconstructing instead of pattern matching, we can be a little confortable than let people figuring out match vs matcher which is the symbol they need🤔

17:21
<ljharb>
Michael Ficarra: https://github.com/tc39/proposal-pattern-matching#regex-pattern is the literal pattern; https://github.com/tc39/proposal-pattern-matching#bindings-from-regex-patterns-with-named-capture-groups says "Regexes (both literals and references inside interpolation patterns) implement the custom matcher protocol"
17:21
<bakkot>
wait, are these actually stacked bindings
17:21
<bakkot>
like if I leak one with an arrow in a ${} does that refer to the outer one
17:22
<bakkot>
after match ([0, 1, 2]) when ([a, ${(probe = () => a, 1)}, a]) {}: if I call probe, does it see 0or1`
17:22
<Michael Ficarra>
ljharb: okay that answers the question for RegExp.prototype, am I to assume that no other built-in prototypes implement it?
17:22
<ljharb>
yes, if you have others in mind, please file an issue
17:24
<Jack Works>
hmm Isn't tagged template pattern are banned?
17:24
<Jack Works>
when (tag`x`): expr
17:24
<Jack Works>
i remember this is invalid
17:24
<ljharb>
currently yes
17:25
<bakkot>
bindings should be reusable across or alternatives, definitely
17:25
<bakkot>
but that does not mean they need to be reusable not across or alternatives
17:27
<bakkot>
related: https://github.com/bakkot/proposal-duplicate-named-capturing-groups
17:35
<bakkot>
calling this "initial spec text" is somewhat generous
17:35
<Michael Ficarra>
our bar for initial spec text is historically VERY low, and I'm okay with that
17:35
<Michael Ficarra>
as long as the explainer is fleshed out enough, of course
17:35
<bakkot>
I think it is higher than this
17:36
<ljharb>
the process document is very not clear on this
17:36
<ljharb>
if there's a higher bar then it should be codified there.
17:36
<Jack Works>
https://github.com/tc39/proposal-pattern-matching/pull/251 NOTE: Part 1 (adding interpolation pattern back to deconstruction) is NOT a nececssary part of the proposal
17:36
<Michael Ficarra>
we've talked about it in plenary before and opted not to set a minimum
17:38
<ljharb>
waldemar: reviewing spec text isn't necessary for stage 2. it's necessary for stage 3.
17:38
<leobalter>
ljharb shu TabAtkins I think we can have a direction to achieve consensus for the current direction this proposal is leading towards and come back in the next meeting with the spec draft updated.
17:38
<leobalter>
setting the direction is not exactly a stage advancement but we can agree with the current direction, right?
17:39
<ljharb>
sure. and the process issue waldemar is bringing up is only really relevant if that's the only potential "blocker" for stage 2
17:39
<Michael Ficarra>
I oppose asking the champions to write complete spec text for this proposal before it reaches stage 2
17:39
<shu>
i don't think complete spec text is being asked for
17:39
<Michael Ficarra>
the explainer is detailed enough
17:39
<shu>
i think there's value in the exercise of writing out a grammar for a very syntax-heavy proposal
17:40
<shu>
the fact that it hasn't been done is a fair objection imo
17:40
<Michael Ficarra>
I also still have open questions about things, but they will not torpedo the proposal, so they can be figured out during stage 2
17:41
<Michael Ficarra>
if you think the general direction of the proposal is wrong, fair, object to advancement
17:41
<Michael Ficarra>
but details are meant to be figured out and codified during stage 2
17:41
<shu>
i also reject the notion that "initial spec text" means any text document that's published as a spec draft
17:41
<Jack Works>
i think there's value in the exercise of writing out a grammar for a very syntax-heavy proposal
yeah we have a spec syntax PR 😂 i think it's already covered the current shape of proposal
17:41
<shu>
it should've been merged for general review before the plenary, then?
17:42
<ljharb>
i also reject the notion that "initial spec text" means any text document that's published as a spec draft
i agree with that. i think the current text still somewhat applies - it's just the parts inside match (…) { … } that need lots of work
17:42
<Jack Works>

hax is talking about:

he think

when (${String} with s): expr to check if it is a string is wordy

17:42
<ljharb>
maybe it doesn't feel "enough" for some, but applying vague adhoc requirements seems undesirable compared to having more specific wording in the process doc
17:42
<shu>
part of the pushback i'm hearing is that there's no sensible intermediate state to have an initial spec text that's not a complete grammar working out
17:42
<leobalter>
I think it's fair to have minimal matching specs. People can consume the proposal by the explainer, other people do it better from the specs, as waldemar pointed out. I might disagree with the heated parts, but asking for some basic specs seems pretty fair and I'd stick to that committed to present something at the next TC39 meeting.
17:42
<bakkot>
Jack Works: I think if your PR landed that would definitely meet the bar
17:42
<bakkot>
but I didn't know to look for it
17:42
<shu>
i also don't think that's true, but it might be in this particular case?
17:42
<ljharb>

hax is talking about:

he think

when (${String} with s): expr to check if it is a string is wordy

to check if something's a string you'd do if (typeof x === 'string'), no?
17:43
<shu>
leobalter: no, the point is that explainers are precisely not substitutes for specs
17:43
<bakkot>
when (x) if (typeof x === 'string') is the obvious way to write this
17:43
<bakkot>
(this particular thing)
17:43
<Jack Works>
to check if something's a string you'd do if (typeof x === 'string'), no?
oh yeah, it's another case for bare if 😂
17:44
<leobalter>
shu: I agree with that, my opinion is that both explainer and specs should have some minimal content for everyone to understand the direction for Stage 2.
17:44
<bakkot>
it's not a use for bare if because you need to refer to the match-ee
17:44
<leobalter>
One doesn't replace the other
17:44
<bakkot>
which requires you to name the thing being matched
17:44
<Jack Works>
when (x) if (typeof x === 'string') is the obvious way to write this
but it's more wordy than when (${String} with x)
17:44
<ljharb>
it's not a use for bare if because you need to refer to the match-ee
when (blah) as S { lets you refer to it
17:44
<bakkot>
Jack Works: but less clear
17:44
<bakkot>
this is a good reason to not allow the when (${String} with x)
17:44
<bakkot>
which I also want to get rid of for other reasons
17:45
<waldemar>
@ljharb: Process requires "all major semantics, syntax and API are covered, but TODOs, placeholders and editorial issues are expected" for entry to stage 2. Process also states that changes during stage 2 are expected to be incremental.
17:45
<ljharb>
when (${String} and x) is shorter :-p
17:45
<legendecas>
Can when (${String} with x) match String wrapper object?
17:45
<ljharb>
waldemar: that column describes the spec quality WITHIN stage 2, not for entering it. the only cell on the stage 2 row that applies to proposals entering stage 2 is "Entrance Criteria"
17:46
<legendecas>
if (typeof x === 'string') is very clear that it can not match string wrapper object
17:46
<ljharb>
Can when (${String} with x) match String wrapper object?
yes.
17:46
<leobalter>
ljharb: I have to disagree. My understanding is that fundamental spec quality should also match entrance for Stage 2.
17:47
<Jack Works>
Can when (${String} with x) match String wrapper object?
Yes
17:47
<ljharb>
ljharb: I have to disagree. My understanding is that fundamental spec quality should also match entrance for Stage 2.
then the process document should be refined; thats not the bar i've seen previous proposals held to.
17:47
<waldemar>
ljharb: The entrance criteria require a spec text, and the spec quality column describes the quality of that spec text.
17:48
<bakkot>
yeah
17:48
<bakkot>
stage 3 requires complete text
17:48
<leobalter>
ljharb waldemar we may schedule a proper venue to discuss this. I don't think this chat will be super productive. We have to agree there is a diversity in interpretations here.
17:48
<bakkot>
that's not something you do during stage 3
17:49
<leobalter>
bakkot: I believe @waldemar is never saying complete spec text.
17:49
<ljharb>
i can certainly see that interpretation - that "spec quality" is an entrance criteria. but that's not how i read it, or have read it in the past, nor is it clear to me from the table.
17:49
<bakkot>
leobalter: sorry, I was just saying I agree with waldemar's intepretation of the "spec quality" column
17:49
<waldemar>
I think some are just misreading the process document.
17:49
<ljharb>
if that's what we all want, maybe we should add some clarification to the "entrance criteria" cell so it references the "spec quality" cell
17:49
<bakkot>
which is that stage 3 requires "Complete: all semantics, syntax and API are completely described", which means that stage 2 requires "Draft: all major semantics, syntax and API are covered, but TODOs, placeholders and editorial issues are expected"
17:50
<shu>
leo, this isn't about a diversity of interpretations, i think it's just misreading?
17:50
<leobalter>
waldemar: if we interpret the document differently, one has to be wrong.
17:50
<shu>
yes, and what bakkot said has to be correct
17:50
<shu>
unless we have disagreement that stage 3 can be obtained without a complete spec text, which i really hope not
17:50
<leobalter>
shu: I read basic specs as entrance criteria for Stage 2, not only as a expectancy for during Stage 2
17:51
<leobalter>
and I'd be supportive for all proposals to go through the same criteria.
17:51
<Michael Ficarra>
we have accepted thorough explainer docs as "spec text" for stage 2 many times in the past
17:51
<bakkot>
have we?
17:52
<shu>
and for something that is super syntax heavy?
17:52
<shu>
like if it's for one array method, sure
17:52
<shu>
with a pseudocode implementation, even
17:52
<ljharb>
for something this big, probably not. but for multiple things, certainly
17:52
<Michael Ficarra>
few proposals are as big as this one, so I don't know what your bar is
17:53
<shu>
i have said my bar: for syntax-heavy proposals, major syntax should be spelled out in the spec text, which it isn't currently because it's in an unmerged PR
17:54
<Michael Ficarra>
shu: fair, at least that gives the champions clear guidance on expectations
17:54
<bakkot>
array grouping had fairly complete text at stage 2: https://github.com/tc39/proposal-array-grouping/blob/6c1e6880eeb58a2f2cae3a0763c884821f730893/spec.emu
17:54
<bakkot>
I'm trying to think of other examples
17:54
<bakkot>
where there might not have been
17:54
<ljharb>
tbf API proposals are the easiest ones to make complete spec text for
17:54
<shu>
please stop with the "complete" strawperson
17:54
<shu>
nobody is asking for complete for entrance to stage 2
17:54
<ljharb>
oh i don't mean that's what's being asked for
17:55
<ljharb>
i'm saying that API proposals are much easier to hit even the stage 3 requirement, far earlier
17:55
<bakkot>
re: ysv's point, I definitely like having large proposals like this presented multiple times before we agree to the major semantics
17:55
<bakkot>
temporal did that IIRC
17:55
<bakkot>
though, maybe that was during stage 2
17:55
<Michael Ficarra>
yeah, that was at a later stage
17:56
<ptomato>
I think this is a good discussion to have, but I do want to say that to demand that Tab put the stub spec text up on the screen for it to be criticized, is both a waste of committee time, and condescending towards the champions. I think that kind of thing is not befitting of a healthy collaboration in the committee
17:58
<yulia>
i feel like there are benefits to both sides, but we are running into issues with the fear that -- if we don't get everything in then we will have classes again (or, maybe i misunderstood -- do you mean, this should be shown multiple times before advancement to grok all the details? with this i agree)
17:58
<Jack Works>

hax's meaning:

he think if is else if, and is not the necessary part of MVP

17:58
<Jack Works>
and he think when (_) if (expr) can replace the bare if
17:59
<shu>
yulia: the spicy take is that this is a committee, we're not going to get cohesive big ideas through
17:59
<yulia>
as you know, i am a fan of process ;)
17:59
<shu>
we're going to get things that hopefully aren't too far off course from what any individual delegate's cohesive big idea is
17:59
<ljharb>
and he think when (_) if (expr) can replace the bare if
it totally can. it's just that then you're forcing people to type that extra boilerplate when they don't conceptually need it
17:59
<Jack Works>
OK my last concern for short:
18:00
<Jack Works>

I prefer an alternative syntax for the custom matcher.

Current:

when (${Some} with x): expr
when (${None}): expr

rbuckton 's unapply

when (Some(x)): expr
when (None()): expr
// also works in deconstruction
const RGB(r, g, b) = "#001234"
18:00
<yulia>
we're going to get things that hopefully aren't too far off course from what any individual delegate's cohesive big idea is
so, my thinking is -- we could do what class fields did, which is that it had several proposals that eventually were merged
18:00
<bakkot>

or, maybe i misunderstood -- do you mean, this should be shown multiple times before advancement to grok all the details? with this i agree

that is the thing I mean, yes

18:00
<yulia>
but do this more intentionally
18:00
<bakkot>
I don't have a problem with large proposals if they are presented a few times, so we have time to think about the whole thing
18:00
<bakkot>
and talk about all the details
18:01
<shu>
yulia: that might work, sure. the biggest hurdle i think is to get enough of committee continuity, well beyond just the champion group, to have the whole space be paged in
18:01
<yulia>
yeah also, splitting it up is just a mechanism for doing precisely that -- but splitting it up also makes parts of it optional which may not be optional (so, why not introduce a construct for that)
18:01
<sarahghp>
yes, I agree with yulia; or rather, I could live with an epic-type approach
18:01
<Michael Ficarra>
pattern matching and decorators as our first 2 proposal topics? time constraints must've been rough this time around
18:01
<sarahghp>
though I would still rather my own weird simple + wacky breakdown :D
18:01
<Jack Works>
pattern matching and decorators as our first 2 proposal topics? time constraints must've been rough this time around
decorator is for stage 3
18:01
<bakkot>
TabAtkins: just to say, because everyone including me was talking about their concerns (which is reasonable), I think pattern matching as presented is pretty rad
18:01
<Michael Ficarra>
Jack Works: decorators is 9th in order on the agenda though lol
18:02
<bakkot>
I have quibbles with details but do support the proposal
18:02
<Jack Works>
I support the current decorator proposal, but the metadata part is sus and need more discussion
18:03
<shu>
yulia: because at the end of the day, as people have said before, we're mostly volunteering our time here, and the biggest problem is unless we're in the champion group, people are paging in a lot of stuff at possibly multi-month intervals. and unless you're already super sold on the motivation, that kind of working mode is going to prime you against large proposals
18:03
<yulia>
I support the current decorator proposal, but the metadata part is sus and need more discussion
same, also some concerns about the accessor keyword
18:03
<shu>
how would "epics" help this? genuinely asking, no idea what those are
18:03
<TabAtkins>
also what's the use case for the bare if one
I'ts a minor case, but sometimes when figuring out how to produce a given value, you in fact don't need to worry about the structure of the matchable.
18:04
<Jack Works>
same, also some concerns about the accessor keyword
they say the accessor keyword is necessary and not blocking the future extension of the Grouping accessor proposal so I guess it is ok for me
18:04
<bakkot>
TabAtkins: that use case doesn't seem worth its own syntactic form, I guess is my feeling
18:04
<yulia>
how would "epics" help this? genuinely asking, no idea what those are
often, when something like temporal has been presented i found myself checking out because i didn't have focus for the whole proposal. if we had a process that was like. Here is the big proposal and what it is trying to do, and it is composed of these parts. we are talking about part 1, which has it's own design concerns -- i would find this easier to think about
18:04
<TabAtkins>
If it required more than just "don't put the when()" in, I'd agree.
18:04
<shu>
yulia: okay i see. i support that
18:05
<yulia>
they say the accessor keyword is necessary and not blocking the future extension of the Grouping accessor proposal so I guess it is ok for me
yeah we were looking into the requirements there, we will have a discussion with that. I think Iain may have posted an issue (lemme check)
18:05
<TabAtkins>
But requiring when (_) if(something) is awkward when the shorter syntax form is right there and totally unambiguous
18:05
<bakkot>
that's fair
18:05
<ryzokuken>
often, when something like temporal has been presented i found myself checking out because i didn't have focus for the whole proposal. if we had a process that was like. Here is the big proposal and what it is trying to do, and it is composed of these parts. we are talking about part 1, which has it's own design concerns -- i would find this easier to think about
I think such a process change would be really useful, thanks
18:05
<shu>
(so what's the "epic" part referring to?)
18:05
<yulia>
the epic is the overall feature (like pattern matching)
18:06
<bakkot>
"this is useful for dependency injection" produces in me an immediate "kill it with fire" reaction
18:06
<bakkot>
perhaps that is not everyone's reaction to dependency injection
18:06
<yulia>
we can say that, when a proposal is large and consists of many components, but they cannot be broken up without compromising the goal of the proposal, it should be treated as an epic (or maybe we can call it a modular proposal or whatever)
18:06
<ljharb>
it's certainly my reaction too
18:06
<shu>
it usually is, but my first reaction is always "what is dependency injection again"
18:06
<ljharb>
function arguments, but implicit and magic
18:06
<shu>
and when i re-learn it as argument passing, then your reaction is my following one
18:06
<TabAtkins>
i think we have match (e) as x { in the current proposal (or maybe match (e as x) {, i forget which we agreed on)
Nah we dropped the as x stuff entirely, in favor of using x and ... matchers.
18:07
<bakkot>
TabAtkins: ok so my feeling is that it would be very useful to bind the name at the top level of the match, because otherwise there's going to be a bunch of match (expr) when (x) if (f(x)) ...; when (x) if (g(x)) ...; etc
18:08
<bakkot>
maybe do-exprs are the fix for that though
18:08
<TabAtkins>
I claim and and or have an obvious precedence relationship
I know the &&/|| precedence is well-established, I strongly object that it's obvious; I've been programming for 20 years and I still always parenthesize when I'm mixing those, because I never remember what the precedence is.
18:08
<bakkot>
do { let x = expr; match(x) {...} }
18:08
<Jack Works>
so for the decorator, I guess the metadata part will be the hardest push at this meeting, maybe they will seek a conditional advancement (once the metadata problem is resolved, it will automatically advance to stage 3)?
18:09
<bakkot>
TabAtkins: that's fair but I stand by "well precedented"
18:09
<iain>
yulia: Reading through old issues I found this, which convinced me that there are good reasons for accessor to exist as a keyword (instead of making decorated fields into accessors by default): https://github.com/tc39/proposal-decorators/issues/348#issuecomment-736889352
18:09
<bakkot>
people who don't know the relationship are already going to be struggling with the && and || cases
18:09
<bakkot>
people who do are going to be annoyed every single time they use and with or
18:09
<ljharb>
which is why common linter rules/styleguides force parens around mixed && and ||, because it's so frequently confusing
18:09
<yulia>
yulia: Reading through old issues I found this, which convinced me that there are good reasons for accessor to exist as a keyword (instead of making decorated fields into accessors by default): https://github.com/tc39/proposal-decorators/issues/348#issuecomment-736889352
oh, great! thanks -- that comment is retracted then
18:09
<yulia>
i was just going to ask
18:10
<Michael Ficarra>
I know the &&/|| precedence is well-established, I strongly object that it's obvious; I've been programming for 20 years and I still always parenthesize when I'm mixing those, because I never remember what the precedence is.
do you use unnecessary parentheses when mixing +/- with * in arithmetic expressions, too?
18:11
<ljharb>
yes, always. there's a linter rule for that too.
18:11
<sarahghp>
yeah, same
18:11
<sarahghp>
helps human brains if not machine ones and it's free!
18:11
<Michael Ficarra>
ljharb: there's also a linter rule to remove them 😉
18:11
<bakkot>
that rule would be completely intolerable if it weren't auto-fixable
18:11
<bakkot>
I'm not going to write a + (x * y) by hand
18:12
<bakkot>
but making it a syntax error to write x and y or z means that I am forced to
18:12
<bakkot>
because eslint won't parse it
18:12
<bakkot>
seems like this is very a case for linters
18:13
<shu>
that's why i exclusively use number of spaces to signal precedence
18:13
<shu>
a + x*y
18:13
<bakkot>
:D
18:14
<nicolo-ribaudo>
Can we just introduce the Polish notation to JS? https://en.wikipedia.org/wiki/Polish_notation#Explanation
18:14
<bakkot>
like, I agree that it can be a good idea to make these things an error in the absence of a well-precedented thing that many (not all) people will already know - but there is that, in this case
18:14
<TabAtkins>
TabAtkins: ok so my feeling is that it would be very useful to bind the name at the top level of the match, because otherwise there's going to be a bunch of match (expr) when (x) if (f(x)) ...; when (x) if (g(x)) ...; etc
That's possible! Grammar's open to that, it was just killed as part of a general "remove the as x renaming facility now that we have and`. Could be brought back in for the matchable in the head specifically. Feel free to open an issue.
18:14
<shu>
nicolo-ribaudo: perhaps you'd like to propose Math.add, Math.multiply, etc?
18:15
<shu>
oops sorry this isn't TDZ
18:15
<nicolo-ribaudo>
Whops I thought I was in TDZ too
18:15
<bakkot>
we should have those, in seriousness though
18:15
<Tierney Cyren>
ngl agree
18:15
<Tierney Cyren>
TDZ to proposal pipeline
18:16
<TabAtkins>
do you use unnecessary parentheses when mixing +/- with * in arithmetic expressions, too?
No, +- and */ have a precedence relationship matching the precedence rules taught in math class since I was a little kid. (That said, I still often use spacing to make it clear - foo*bar + baz, and still parenthesize if the expr is large enough that spacing clues aren't sufficient.)
18:16
<danielrosenwasser>
What's -x ** 2 again?
18:17
<danielrosenwasser>
sorry, not TDZ
18:17
<Tierney Cyren>
(I can think of a lot of beginners who would feel comfortable with the explicit language of a method, and who having those methods would help make more comfortable with syntax like Array.isArray() or Object.hasOwn())
18:17
<Michael Ficarra>
TabAtkins: I know you know this, but in many ways and is * and or is +, so why is that hard to remember?
18:17
<ljharb>
for those who had opinions on the "spec quality" stuff, please share your thoughts https://github.com/tc39/process-document/pull/35
18:17
<bakkot>
danielrosenwasser: that one is not well-precedented
18:17
<bakkot>
or rather, there are conflicting precedents
18:17
<TabAtkins>
That correspondence is very "college-level abstract math", not "elementar-school arithmetic"; they're entirely different
18:23
<Mathieu Hofman>
Can't there be a placeholder for the class given to decorators, and a way to link the placeholder to the class after definition ?
18:24
<ljharb>
i'm sure it could get a symbol. but then how do you symbolicate (unsymbolicate?) it later?
18:25
<bakkot>
"angular wants this" is so far from being compelling to me
18:25
<Mathieu Hofman>
Unless we have symbols as WeakMap keys, I'd want an empty object
18:26
<ljharb>
having an object placeholder that wasn't frozen would be pretty weird
18:26
<Mathieu Hofman>
And maybe "unsymbolicating" could be done as a class decorator ran last, that does get access to the final class and the placeholder, but without replacing the class
18:27
<Mathieu Hofman>
aka an @metadata class Foo {}
18:28
<ljharb>
either way tho, then you have N + 1 identities to manage
18:28
<bakkot>
sidebar: anyone know what millions-of-downloads dependency injection framework was being referenced?
18:28
<bakkot>
I can't find any offhand
18:28
<leobalter>
shu: I confirm what Chris said about TS and Babel usage. LWC is TS based but uses the Babel impl. of Decorators
18:29
<shu>

"angular wants this" is so far from being compelling to me
opposite of compelling really!

18:29
<shu>
and also angular wouldn't care about standard decorators as i said
18:30
<leobalter>
LWC -> Salesforce's Lightning Web Components.
18:31
<shu>
bakkot: the reply here points to something called Inversify: https://github.com/tc39/proposal-decorators/issues/442#issuecomment-1079544675
18:31
<shu>
why do people love dependency injection though
18:33
<danielrosenwasser>
So I don't use DI, but I have consistently seen code editors rely on DI as their pattern for extensibility and even core functionality
18:33
<Jack Works>
Bonus
18:33
<bakkot>
setting the prototype without calling the constructor is very weird, yeah
18:33
<danielrosenwasser>
Basically "we only need one extension instance to be loaded ever, and it can happen at any time"
18:34
<shu>
Jack Works: good one
18:34
<danielrosenwasser>
VS Code uses it, and VS does (written in a different language), and I think Eclipse might have as well (also different language)
18:36
<Jack Works>
why we're having subclassing ArrayBuffer at the first time anyway, it does not expose any API to access the internal data structure (need to use the view) and extending cannot do anything useful (excepts exploits the browser)
18:37
<bakkot>
Jack Works: we're gonna have a whoooooole long discussion about subclassing builtins later this meeting!
18:39
<shu>
Jack Works: yeah, great question!
18:41
<bakkot>
I too would like to see motivation for metadata other than DI before advancing metadata
18:42
<ptomato>
I have some motivation for metadata in https://github.com/tc39/proposal-decorators/issues/441
18:42
<leobalter>
wait
18:43
<shu>
"bubble"?
18:43
<shu>
or did i mishear
18:43
<leobalter>
I've never seen a proposal that had more venues for developer feedback than decorators
18:43
<bakkot>
babel
18:43
<shu>
ah, sorry
18:43
<shu>
thought it was a new toolchain
18:46
<Jack Works>
I've never seen a proposal that had more venues for developer feedback than decorators
but it's for the old version
18:46
<Jack Works>
🤔
18:46
<leobalter>
we had this specific proposal presented here before this meeting, announcing the intention for Stage 3
18:47
<ljharb>
right, but decorator consumption is largely the same
18:47
<ljharb>
the majority of the changes are for decorator authors
18:48
<yulia>
I think this version of the proposal is over a year old?
18:48
<yulia>
there have been minor changes but i think dan presented this redesign a while ago
18:49
<bakkot>

here is how I would write class-level metadata for decorators without explicit support:

let { decorate, finalize } = makeDecorator();
class A {
  @decorate
  property = whatever;
}
finalize(A);

where makeDecorator is a userland function that has an internal WeakMap or whatever. it's two extra lines. does this do the thing you want metadata to do?

18:49
<devsnek>
seeing "old proposal" in context of decorators is very scary 😅 good to see its still a function
18:49
<Jack Works>
oh
18:49
<Jack Works>
we have 8 minutes extra
18:50
<Jack Works>
should we continue to pattern matching?
18:50
<ljharb>
pzuraq: i can help you make the repo for the metadata part, DM me to coordinate
18:52
<ptomato>
if the decorator doesn't get access to the class, what is the WeakMap key?
18:53
<leobalter>
ljharb shu yulia so we consider Decorators - Metadata a Stage 3?
18:53
<bakkot>
ptomato: finalize(A) passes in the class
18:53
<yulia>
contingent stage 3 on for the split
18:53
<bakkot>
and the decorate and finalize functions are paired
18:53
<Mathieu Hofman>

here is how I would write class-level metadata for decorators without explicit support:

let { decorate, finalize } = makeDecorator();
class A {
  @decorate
  property = whatever;
}
finalize(A);

where makeDecorator is a userland function that has an internal WeakMap or whatever. it's two extra lines. does this do the thing you want metadata to do?

Similar to what I proposed here a long time ago: https://github.com/tc39/proposal-decorators/issues/328#issuecomment-694240970
19:08
<bakkot>

oh, or even

let { decorate, decorated } = makeDecorator();
@decorated
class A {
  @decorate
  property = whatever;
}

since class decorators get access to the class in addInitializer, as this

19:12
<bakkot>

so for the gnome use case linked above it would look like

let { registerClass, property } = GObject();

@registerClass
class MyClass {
  @property({ type: Boolean })
  x = false;
}

where the @property decorator would stash the necessary fieldname->type mapping somewhere where the @registerClass decorator could get at it

19:14
<Ashley Claymore>
for composing decorators, there isn't a built-in util for that right?
19:15
<Ashley Claymore>
if someone already had a class-level decorator, and then a field-level one only worked if combined with it's class-level helper
19:15
<bakkot>
I don't think it has any built-in utils?
19:15
<Ashley Claymore>
true, no new namespace
19:17
<ptomato>

so for the gnome use case linked above it would look like

let { registerClass, property } = GObject();

@registerClass
class MyClass {
  @property({ type: Boolean })
  x = false;
}

where the @property decorator would stash the necessary fieldname->type mapping somewhere where the @registerClass decorator could get at it

I see, thanks. in practice though, I'd probably just not make a makeDecorator() style API if I knew metadata was likely to be coming and would enable a better API. I'd end up having to maintain them both
19:19
<bakkot>
That's reasonable, yes
19:20
<bakkot>
I remain unconvinced by the need for metadata, especially if this pattern actually does work the way I think it should
19:20
<bakkot>
I haven't written the implementation of the makeDecorator thing to confirm it does
19:20
<shu>
yeah, i remain most directionally comfortable with doing metadata all in userland
19:20
<pzuraq>
bakkot: metadata seems particularly necessary for parameter decorators, which are another future extension
19:20
<shu>
i understand the "we need something to key off of" expressivity gap now, which i kept missing for a long time
19:20
<bakkot>
pzuraq: I am dead set against parameter decorators
19:20
<pzuraq>
it's unclear that parameter decorators would do anything besides add metadata
19:20
<shu>
i am... not very supportive of parameter decorators right now
19:21
<pzuraq>
good to know
19:21
<shu>
given i've only seen it used for DI in angular and it looked awful
19:21
<pzuraq>
primary use case does seem to be DI for them, I generally agree I prefer field based DI myself
19:22
<shu>
pzuraq: and great work, lots of sweat and tears!
19:22
<bakkot>
wait, doesn't addInitializer also provide you access to the class as this
19:22
<bakkot>
addInitializer for elements
19:22
<pzuraq>
initializers run for every instance
19:22
<bakkot>
oh, right
19:22
<pzuraq>
so it wouldn't really be a good place for adding/manipulating metadata
19:22
<shu>
you could idempotently re-add metadata each instance creation
19:22
<bakkot>
yeah
19:23
<shu>
that's a pro move called "it's the library's problem, not the engine's"
19:23
<bakkot>
shu: that only works if you don't need the metadata before instance construction though
19:23
<pzuraq>
lol
19:23
<shu>
bakkot: good point
19:23
<pzuraq>
yeah, there's also that
19:23
<Mathieu Hofman>
I have use cases for parameters decorators, that would need to couple with a method decorator
19:24
<Mathieu Hofman>
And it's not a DI use case, but a shape / type validator use case
19:24
<pzuraq>
that is another major use case for metadata
19:24
<pzuraq>
validation libs in general
19:25
<pzuraq>
you can do it with accessor, but then you have overhead for every property access
19:25
<pzuraq>
and usually, you want to do the validation once at specific points in time (e.g. when you go to serialize)
19:25
<pzuraq>
oh, serialization is another use case
19:25
<pzuraq>
I believe a number of Node ORMs use decorators this way
19:26
<pzuraq>
really there are a ton of use cases, I just thought DI was the most motivating one 😅
19:26
<Mathieu Hofman>
I don't see how accessor helps here. I want to validate before the code of the method runs so it can rely on the args being the right thing
19:27
<pzuraq>
accessor helps for other forms of validation, not the one you're discussing
19:27
<pzuraq>
e.g. "this field is a number" type validations
19:28
<pzuraq>
there's two forms of decorator validation libraries out there, one which installs getters/setters to validate, and the other which adds metadata and then asks you to call validate() whenever you want to validate
19:35
<jschoi>
yulia: Would you consider the holistic dataflow discussions we’ve been having lately a TC39 “epic” about a broad feature?
19:36
<jschoi>
Also to everyone: I’ve finished writing my updated material for the holistic dataflow redux discussion, scheduled at the end of this plenary. Please take a look if you are interested in the pipe operator, the bind/call-this operator, Extensions, PFA syntax, ecosystem schism, or the like: https://jschoi.org/22/es-dataflow/
19:36
<bakkot>
bakkot: is that really what we say about the current Realm for %name%s?
it could be more explicit, but I think "it refers to the one from the current realm" is the only thing it could possibly mean?
19:38
<shu>
bakkot: i know it intuitively to be true, it just took me multiple readings of the paragraph i linked to get that reading i think
19:38
<bakkot>

oh wait, it is explicit actually:

Within this specification a reference such as %name% means the intrinsic object, associated with the current realm, corresponding to the name.

19:38
<bakkot>
"associated with the current realm" being the relevant part
19:40
<shu>
bakkot: right, but Mark's question was the meaning of current: current at time of execution, or current for the parse node
19:40
<shu>
and i don't think that is clear from the paragraph
19:40
<bakkot>
those are the same thing
19:41
<shu>
they are? huh, i guess so, we don't have a way to preparse for execution elsewhere
19:41
<bakkot>

see https://tc39.es/ecma262/multipage/ordinary-and-exotic-objects-behaviours.html#sec-prepareforordinarycall step 4/5:

  1. Let calleeRealm be F.[[Realm]].
  2. Set the Realm of calleeContext to calleeRealm.
19:44
<shu>
the pre-parse then execute elsewhere observation is interesting for module blocks
20:45
<rbuckton>
Unfortunately, I'm unable to attend plenary this week. I wish I were able to be present to argue for Metadata's inclusion for Stage 3 decorators. Requiring an entangled decorator pair (one for class, one for member) is over complex and highly unmanageable.
20:53
<rbuckton>
There are many Metadata-only use cases. A compiler may want to emit Metadata and needs a consistent way to do so that works for both modules and scripts (and thus cannot depend on dynamically injecting an import).
20:56
<rbuckton>
And as mentioned, there are many non-DI use cases: RTTI, ORM, controlling serialization (binary/json/etc.)
20:59
<rbuckton>
Built-in support for Metadata is more important now than the earlier Stage 1 version due to the restrictions imposed on the latest proposal (lack of ctor/proto access)
21:12
<yulia>
yulia: Would you consider the holistic dataflow discussions we’ve been having lately a TC39 “epic” about a broad feature?
I would consider it a broader design question, which maybe is more about vision. the different proposals target different problems. I am thinking of epics as proposals composed of interlinked components, where minmaxing will result in a poorer solution to the overall problem, but the components are separate enough that they should be considered independently and designed both independently and together.
21:14
<yulia>
I’m still thinking how we might do that but i need to look again how this has failed in different ways. Split proposals don’t work, and I don’t think mega proposals are working either
21:15
ptomato
listens, while preparing to present a mega proposal tomorrow
21:15
<yulia>
I think focus groups worked well for temporal
21:17
<yulia>
But in many ways, it is simpler, it follows an established pattern for APIs
21:17
<rbuckton>
Mega-proposals like the regex features proposal had significant pushback, but splitting them has caused a huge maintainability issue.
21:17
<yulia>
It was the algorithm that was a question and we all agree that date time was an issue
21:18
<yulia>
For Regex, one issue was that the problem of the overall proposal didn’t tie them together. The proposals are largely independent
21:18
<rbuckton>
My only qualm with Temporal is how hard it is to use for its main purpose (date arithmetic, specifically relational comparison).
21:19
<yulia>
Though, as I say this, all of this has degrees of relatedness
21:20
<rbuckton>
Temporal.Instant.compare(inst, Temporal.Now.instant()) > 0 is not a win, imo
21:20
<yulia>
And it might be some of the regex proposals are more related than others
21:21
<justingrant>
My only qualm with Temporal is how hard it is to use for its main purpose (date arithmetic, specifically relational comparison).
Is this the lack of isEarlier/isLater APIs? Or concerns about how compare can return 0 for values where equals will return false?
21:21
<justingrant>
If the former, there's a clear path to add those APIs in a follow-up proposal.
21:22
<rbuckton>
Quite a few are related in the "Why do we need A when we can have B" in both proposals A and B, leading to neither advancing when they're complementary proposals
21:23
<justingrant>
FYI, here's the "more comparison methods" issue for the Temporal V2 repo: https://github.com/js-temporal/proposal-temporal-v2/issues/6
21:24
<ptomato>
I do think that Temporal's size did make it difficult for most delegates to go any deeper than superficial without investing tons of time
21:24
<rbuckton>
A.isEarlier(B) is a bit harder to conceptualize than A < B, imo. And is very English-focused vs. compareTo.
21:25
<justingrant>
A.isEarlier(B) is a bit harder to conceptualize than A < B, imo. And is very English-focused vs. compareTo.
That's great feedback that you might want to add to https://github.com/js-temporal/proposal-temporal-v2/issues/6. 😄
21:26
<rbuckton>
compareTo you learn once and let math take care of the rest. A non-native-English speaker might need to refer to which is which (earlier/later)
21:26
<rbuckton>
The same way I have to look up the difference between co- and contra-variant frequently and I work on a compiler with generics
21:31
<bakkot>
Unfortunately, I'm unable to attend plenary this week. I wish I were able to be present to argue for Metadata's inclusion for Stage 3 decorators. Requiring an entangled decorator pair (one for class, one for member) is over complex and highly unmanageable.
say more? it does not seem particularly complex or unmanageable to me, so far
21:33
<rbuckton>
It does for a large number of disparate uses, your class becomes cluttered with a number of @register-like decorators for each use case.
21:34
<bakkot>
Is it common to have classes which use lots of different metadata-attaching decorators?
21:34
<bakkot>
from different libraries, that is
21:34
<rbuckton>
Consider if I use an ORM (i.e. MikroORM) and a Json serializer to translate a complex object to a Rest endpoint
21:36
<bakkot>
wouldn't those both already have a class-level register decorator?
21:36
<rbuckton>
That's already two separate "registers", and I could see more if your object interacts with multiple systems
21:39
<rbuckton>
I've worked with systems that need to interact with different services in a similar fashion. This would quickly become untenable.
21:40
<rbuckton>
I'd like to chat more, but really can't until next week.
21:44
<bakkot>
I'll open an issue.
21:54
<bakkot>
https://github.com/tc39/proposal-decorators/issues/455
22:00
<pzuraq>
bakkot: my concerns would be the same as rbuckton, that overlapping metadata would require multiple registers which could get confusing
22:00
<pzuraq>
I am currently updating the proposal README to include an example like this however, specifically to showcase access
22:05
<rbuckton>
bakkot: my concerns would be the same as rbuckton, that overlapping metadata would require multiple registers which could get confusing
And unless a single userland library is the only Metadata library, it could become even more complex to interoperate
22:05
<rbuckton>
So either everyone rolls their own Metadata (which is a lot of wasted effort), or there are userland conflicts. Neither is a win
22:08
<bakkot>
if you want to have an explicit extension point for other people to get at your metadata, you can just add a symbol-named method to the class and then everyone can integrate with that
22:08
<bakkot>
there's no need for a central coordination point
22:09
<Mathieu Hofman>
well they have to agree to use your method
22:09
<Mathieu Hofman>
that's coordination
22:09
<bakkot>
metadata from someone else's decorator is only useful to you if you know its shape anyway
22:09
<bakkot>
which implies coordination
22:09
<bakkot>
you can't not have coordination
22:09
<rbuckton>
Given the ecosystem around TS decorators as precedent, I disagree. And that only works because there really was only one Metadata library
22:10
<bakkot>
Which thing are you disagreeing with?
22:13
<pzuraq>
bakkot: it's not about sharing your metadata, it's two separate systems both using metadata
22:13
<pzuraq>
thus both requiring their own @register decorator
22:13
<pzuraq>
or, some way to coordinate around having only a single @register decorator
22:15
<bakkot>
I agree that, in the particular case where you didn't have a class-level decorator but were just adding metadata to individual fields, my design is more onerous in that it also requires a class-level decorator
22:15
<bakkot>
I don't understand the relevance of there being multiple systems here, though
22:15
<bakkot>
except that now you need two class-level decorators
22:15
<bakkot>
which... does not seem so high a cost to me?
22:16
<bakkot>
also the examples discussed so far (for metadata) all seemed like they'd have class-level decorators anyway
22:16
<pzuraq>
it seems like a high cost when each decorator would generally not require a class level decorator
22:16
<pzuraq>
so far none of them do?
22:16
<bakkot>
the gnome one did?
22:18
<bakkot>
I guess not all possible DI ones do
22:18
<bakkot>
though some designs would
22:18
<bakkot>
anyway, I stand by "requiring an additional class-level decorator does not seem like so high a cost to me"
22:18
<bakkot>
certainly not a high enough cost to justify this entire additional system being built into the language
22:19
<pzuraq>
what if we go a much simpler route?
22:20
<pzuraq>
the proposal as its stands is pretty complex, admittedly
22:21
<pzuraq>
but really all we need is a sidechannel, similar to the one you've demonstrated
22:21
<bakkot>
simpler features are always an easier sell, but the burdern of the design I've discussed - if it really is as simple as it looks to me - does not seem high enough to warrant any additional features in the language, personally
22:21
<pzuraq>
I worry that it'll be a common footgun to forget applying the class decorator
22:22
<pzuraq>
and there's not really an easy way to let users know that they haven't done so
22:22
<pzuraq>
the simpler version of the feature would be to just have addMetadata, which would then add the metadata to an array on Symbol.metadata
22:23
<bakkot>
that I dislike for other reasons
22:23
<pzuraq>
does that seem like too much of a burden compared to the improvement in DX we would get from adding it?
22:23
<bakkot>
I'm not convinced that would be an improvement in DX at all, really
22:23
<Mathieu Hofman>
but really all we need is a sidechannel, similar to the one you've demonstrated
I believe all we need is for the decorators to receive a "context" allowing them to tie the decoration to the class
22:23
<bakkot>
since now all the decorators are fighting over that space
22:23
<pzuraq>
they would not be fighting over it
22:24
<pzuraq>
all metadata would be additive, and it would be trivial to mark your metadata separate from other metadata
22:24
<pzuraq>
using a WeakSet or WeakMap
22:24
<pzuraq>
Mathieu Hofman: that is another option, yes
22:24
<pzuraq>
are Symbols as WeakMap keys a thing yet? It could just be a Symbol
22:24
<bakkot>
also, wait, the class decorator is passed the class, right?
22:25
<pzuraq>
bakkot: yes
22:25
<pzuraq>
but if not, it could be an object
22:25
<Mathieu Hofman>
Yeah if we had symbol as weakmap keys, a symbol would work. Or a frozen object with no prop or proto.
22:27
<Mathieu Hofman>
Actually a frozen object might be more interesting, as then you could use the proto chain to link nested contexts (see my comments on bakkot's issue above). In particular, the proto of this "context" object for a future arguments decorator could be the context object of the class/object on which the method is defined.
22:30
<Mathieu Hofman>
ugh, there may be forward compatibility issues with that
22:31
<pzuraq>
yeah I think if we went the more simple route that would be adding more complexity than necessary
22:43
<bakkot>
when a field decorator returns an initializer function, that initializer is invoked with the instances as this?
22:45
<bakkot>

so can't you just...

function inject(injectionKey) {
  return (_, context) => function(v) {
    if (!Object.hasOwn(this, INJECTIONS)) {
      this[INJECTIONS] = [];
    }
    this[INJECTIONS].push({ injectionKey, set: context.set });
    return v;
  };
}
22:49
<rbuckton>
This would mean you need to inject field Metadata differently than method Metadata. This is becoming arbitrarily complex.
22:49
<bakkot>
you already do need that, because field metadata is associated with instances and method metadata is associated with the class, surely?
22:50
<bakkot>
Also my design here is strictly simpler than the DI example in the readme
22:50
<bakkot>
I wrote out the whole thing: https://github.com/tc39/proposal-decorators/issues/455#issuecomment-1081227211
22:57
<Luca Casonato>

I may be totally ignorant here (have not been following the proposal for very long), but what about a context.metadata property that is initialized to an empty object, and is then subsequently available on the class instance as instance[Symbol.metadata]? Users could add metadata like this:

const symbol = Symbol("my lib symbol");
function decorate(x, ctx) {
  ctx.metadata[symbol] = 'stuff';
  return x;
}
class Foo {
  @decorate bar() {}
}
const f = new Foo();
console.log(f[Symbol.metadata][symbol]); // stuff

I don't know if this solves the actual concerns though. From what I understood, folks didn't like the setMetadata and getMetadata API. With a plain metadata object these "special" get and set methods go away.

22:57
<bakkot>
I guess "associated with the instance" is kind of wrong; rather, it's associated with the class prototype, if I'm reading this right
22:57
<Luca Casonato>
oh right, yeah in this case it would be associated with the prototype
22:59
<Luca Casonato>
but that doesn't change the general idea of using a plain object has the metadata holder rather than constructing that in the background via the context.setMetadata method
23:00
<Luca Casonato>
the example stays the same, even if the metadata is actually a property on Foo.prototype rather than on the f instance
23:21
<bakkot>
it seems like a high cost when each decorator would generally not require a class level decorator
coming back to this: fundamentally I guess it just does not seem like a high cost to require a class-level decorator to add information to the class itself. maybe I'm missing something, and it would in fact be really painful in practice, but right now Im' not seeing it.
23:25
<pzuraq>
I don't know what to say except that I am seeing it, personally
23:25
<pzuraq>
especially given that the simpler version of this API really wouldn't add much complexity to the language at all
23:25
<rbuckton>
but that doesn't change the general idea of using a plain object has the metadata holder rather than constructing that in the background via the context.setMetadata method
Something like context.setMetadata isn't easily transpiled
23:26
<rbuckton>
(unless it sets something on the class like the proposed Symbol.metadata)
23:27
<Luca Casonato>
right, that was also the API that folks didn't seem to like. Would a plain context.metadata object be easier to transpile?
23:28
<pzuraq>
the object would still need to be added to the target on Symbol.metadata
23:28
<rbuckton>
IIRC that was the approach in the proposal. It's a design the champion and stakeholders have discussed for multiple years to meet those design goals.
23:29
<Luca Casonato>
IIRC that was the approach in the proposal. It's a design the champion and stakeholders have discussed for multiple years to meet those design goals.
What was presented today has a context.setMetadata and context.getMetadata API.
23:30
<rbuckton>
My apologies, I'm OOF and wasn't able to attend plenary.
23:30
<Luca Casonato>
No worries :-)
23:31
<rbuckton>
The biggest problem with downleveling get/setMetadata is the size of the helper needed downlevel, as long as the end result is addressable via something like Symbol.metadata
23:33
<rbuckton>
Anything stored on the function of a method/accessor would be a non-starter as it would complicate every replacement decorator (in order to maintain the Metadata). The constructor or prototype is the only (mostly) reliable place.
23:34
<rbuckton>
Storing it on the instance for fields is also a non-starter since it would require construction to perform introspection, which is bad for DI and ORM scenarios
23:35
<pzuraq>
to clarify, you could potentially place metadata related to a method on Symbol.metadata on the final method itself
23:35
<rbuckton>
i.e., an ORM may need to know about circularities in the Object Model to optimize queries
23:35
<pzuraq>
but you can't put it on the method function passed to the decorator
23:35
<pzuraq>
because that requires each decorator to pass the metadata forward
23:36
<pzuraq>
only clarifying because that is one avenue that's being discussed, as it would make future extensions (e.g. function/parameter decorators) more consistent potentially
23:36
<pzuraq>
but it seems like there's strong pushback against parameter decorators so....
23:36
<rbuckton>
to clarify, you could potentially place metadata related to a method on Symbol.metadata on the final method itself
That overcomplicates the accessor vs field problem
23:36
<rbuckton>
Plus any differentiation with future function decorators
23:38
<pzuraq>
I agree it does overcomplicate those problems, but I'm not sure where parameter decorator metadata fits in otherwise
23:39
<pzuraq>
I suppose we could just flatten that down onto the class
23:39
<pzuraq>
but it becomes hard to figure out which parameter relates to which function
23:39
<pzuraq>
need to pass in something to key off of
23:39
<pzuraq>
if parameter decorators run after method decorators it becomes possible, you pass in the final method that the parameters are applied to
23:42
<shu>
i still think the answer to where parameter decorators fit in is that we do not have parameter decorators
23:46
<pzuraq>
totally valid opinion to have, but until we can say that definitively I would like to design in a way which does not preclude them
23:47
<pzuraq>
that said, I think metadata for existing agreed upon decorators is much more important, and would definitely prioritize a simpler API that can get consensus over one that leaves room for param decorators
23:52
<shu>
so i've read all the backlog
23:52
<shu>
and the github thread
23:53
<shu>
do i understand correctly the main pushback against bakkot's sketched solution is DX burden?
23:54
<pzuraq>
I would say that's the main pushback, yes
23:58
<pzuraq>
Secondary pushback would be cases where metadata does want to be shared between multiple libs
23:58
<pzuraq>
But that is less common
23:58
<shu>
it's fine for a thing to be possible but onerous; the question remains why a thing that's possible but onerous meets the bar for language inclusion
23:59
<shu>
arguments like "this is work all metadata producers have to do" as jordan has said seems to assume there are a lot of metadata producers
23:59
<shu>
are there?
23:59
<shu>
for a few frameworks to bear the burden seems... okay?