00:39
<littledan>
but numeric literals having Object semantics feels it is unprecedented in all of PL. would be fascinating to see an exception
Don’t C++ custom literals enable exactly this? For my JS custom literals proposal, I assumed it would be Ok to follow that and allow those to return objects or primitives.
00:45
<littledan>
to be clear i don't mean that we wish to make standards positions private, i mean that i don't consider it my job to publicize
It doesn’t quite have to be your job to publicize it as such, but if you could give us (proponents of features) direction on what to say to others when they ask us about this, so as to accurately represent your position, that would be helpful. The scope of what you would like JS proposals to avoid has been a little ambiguous even to many committee members leading up to this meeting.
01:41
<justingrant>
it's so strange to me that IETF would explicitly not want to support sub-minute offsets

(catching up) Here's more context around IETF's reasoning, and more generally why restricting offset time zones to minutes seems OK to me:

Existing RFC3339 timestamp strings (which the new IETF spec, aka "IXDTF", extends) only support HH:MM in the offset, e.g. 2023-07-12T14:06-07:00. You can't use 07:00:01 or even 07:00:00 because parsers wouldn't recognize it. JS Date has the same same limit, BTW.

In the new IETF spec, they didn't want to change anything about the RFC3339 portion of the IXDTF timestamp, only the stuff in brackets after the timestamp is what's new. Otherwise, existing RFC3339 parsers would break for the before-brackets portion. Of course, that's not necessarily related to what's in brackets. We could have different precision for the in-brackets portion because there's no legacy.

But with IXDTF, the rule is that the RFC3339 offset must match the offset of the time zone in brackets. So 2020-01-01T00:00-05:00[America /Los_Angeles] is considered an error because the offset doesn't match the time zone.

For named time zones that have sub-minute precision, the new IETF spec handles it by being flexible about what "match" means: if the bracketed time zone's offset, when rounded to HH:MM, matches the offset in the RFC3339 portion of the string, then there's no error produced.

So 1970-01-01T00:00-00:45[Africa/Monrovia] is considered valid, even though Liberia's offset in 1970 was -00:44:30. The rounding hack simply tells the receiver not to throw an error in that case; it doesn't change the actual instant that the string represents. The instant described by "midnight on Jan 1 1970 in Liberia" is still 44:30 away from UNIX epoch:

Temporal.ZonedDateTime.from('1970-01-01T00:00-00:45[Africa/Monrovia]').toInstant();
// => 1970-01-01T00:44:30Z

Temporal does the same thing in reverse in ZonedDateTime.p.toString(): it formats the instant by rounding the offset to the nearest minute.

Anyway, that's how it works for named time zones. But what about offset time zones?

Because the offset in the RFC3339 portion of the string is constrained to HH:MM, the IETF folks felt that it'd be better to also limit the bracketed time zone to HH:MM too. There's nothing preventing us from extending the format in the future if there's customer demand, using the same rounding hack used for named time zones, so that 1970-01-01T00:00-00:45[-00:44:30] would also be allowed.

But it's not clear (to me at least) that this customer demand will ever materialize. Offset time zones were really only added to Temporal and IXDTF for backwards compatibility with Java. It's not clear how much usage of offset time zones there will be in Temporal. Partly this is because all IANA time zones today are on 15-minute boundaries. Sub-minute offsets haven't been official in any country since the 1970s, and even then it was rare. And offset time zones intentionally dispense with the main value of time zones in Temporal: the ability to automatically adjust timestamps for DST and other time zone weirdness.

Also, there's a storage advantage. If offset time zones are limited to minutes, then a Temporal.TimeZone can fit in a 16-bit union: 12 bits for offset time zones (±24h at minute-precision), 10 bits for the index into ~600 named time zones, and one bit to choose between them. Sub-minute offsets would require 50% more bytes to support a use case with questionable demand.

Finally, any user who really needs an offset time zone with sub-minute precision can create a custom time zone with granularity down to nanoseconds. Which they'd have to do anyways for time zones like TAI which don't have constant offsets (thanks leap seconds!) so you can't use an offset time zone anyways. AFAICT, there has never been a real-world time zone that has had a non-minute-aligned offset whose offset has never changed. So I'm kinda skeptical that "offset time zones at sub-minute precision" are real things.

P.S. - one concern raised was how RFC 5545 (aka iCalendar) supports second-precision offsets. But AFAICT, those offsets are never actually used for time zone identifiers. Rather, they're used to define the offsets of named time zones. And Temporal is already permissive with timestamp offset inputs, so we'll accept strings like 1970-01-01T00:00-00:44:30 which AFAICT is what RFC5545 needs.

Summary: restricting to minutes for built-in offset time zones seems like a safe initial bet that we can always extend later if needed.

Thanks for coming to my obscure TED talk.

02:29
<justingrant>
It still seems like we should stop returning Saigon and Kiev despite the lack of a Temporal.TimeZone.prototype.equals

There are two pieces required to fully solve this:

  1. Stop canonicalizing user-inputted IDs to canonical IDs that are sometimes outdated and/or varying across browsers. By bringing proposal-canonical-tz to Stage 3 and merging it into Temporal, this problem gets solved as soon as Temporal.TimeZone ships in implementations. Yay!
  2. Stop using outdated canonical IDs. Today this affects all IDs, but after (1) is done this will only affect IDs generated by ECMAScript itself, e.g. new Intl.DateTimeFormat().resolvedOptions().timeZone and Intl.supportedValuesOf('timeZone').

These two pieces are independent! Even though yesterday the committee agreed to hold (1) until Temporal.TimeZone ships, for (2) implementations are already free to return Europe/Kyiv, Asia/Kolkata, and Asia/Ho_Chi_Minh as canonical IDs. Firefox does this today, and Anba has argued (convincingly, IMO) that the FF behavior is more spec-compliant with current 402.

V8 and JSC don't do this today because they rely on CLDR and ICU which never update renamed IDs. But nothing stops ICU-using implementations from doing what Firefox does and overriding the ~20 zones in CLDR that use out-of-date names. If an ICU solution will take 2 years, could V8 and JSC in the meantime just add a hard-coded mapping table of 20 IDs? It's not like renames happen often: less than once per year is the average. If you, shu , and Frank wanted to do this badly enough, I suspect it could get done fast!

That said, it's a reasonable argument that doing (1) before (2), or at the same time, would reduce the negative impact to existing code because user-inputted zones wouldn't be affected.

My suggestion:

  • Let's get implementations building & shipping Temporal! After this plenary's normative changes are merged within a week or two, AFAIK there are no other large changes on the horizon.
  • IMO, V8 and JSC should really consider the 20-item hard-coded mapping table to work around CLDR's slow schedule. Could this work be paired with Temporal implementation instead of waiting until later? Could this work start now, and ship in a limited test to gauge the web-compat impact?

Let me know how I can help!

02:39
<Richard Gibson>

if the bracketed time zone's offset, when rounded to HH:MM, matches the offset in the RFC3339 portion of the string, then there's no error produced

justingrant I was wondering about how this rounding handled midpoint values like -00:44:30 or +00:44:30 (specifically "ties away from zero" vs. "ties toward positive infinity" vs. "ties toward even"), but I don't see any mention of it at https://www.ietf.org/archive/id/draft-ietf-sedate-datetime-extended-08.html or https://github.com/ietf-wg-sedate/draft-ietf-sedate-datetime-extended/blob/main/draft-ietf-sedate-datetime-extended.md . Are you sure you're not thinking of Temporal InterpretISODateTimeOffset step 8.c.i RoundNumberToIncrement(candidateNanoseconds, 60e9, "halfExpand")?

02:45
<shu>
It doesn’t quite have to be your job to publicize it as such, but if you could give us (proponents of features) direction on what to say to others when they ask us about this, so as to accurately represent your position, that would be helpful. The scope of what you would like JS proposals to avoid has been a little ambiguous even to many committee members leading up to this meeting.
my suggestion there is you should redirect the people who ask about this back to V8 instead, instead of relaying it on behalf of V8
03:20
<shu>

There are two pieces required to fully solve this:

  1. Stop canonicalizing user-inputted IDs to canonical IDs that are sometimes outdated and/or varying across browsers. By bringing proposal-canonical-tz to Stage 3 and merging it into Temporal, this problem gets solved as soon as Temporal.TimeZone ships in implementations. Yay!
  2. Stop using outdated canonical IDs. Today this affects all IDs, but after (1) is done this will only affect IDs generated by ECMAScript itself, e.g. new Intl.DateTimeFormat().resolvedOptions().timeZone and Intl.supportedValuesOf('timeZone').

These two pieces are independent! Even though yesterday the committee agreed to hold (1) until Temporal.TimeZone ships, for (2) implementations are already free to return Europe/Kyiv, Asia/Kolkata, and Asia/Ho_Chi_Minh as canonical IDs. Firefox does this today, and Anba has argued (convincingly, IMO) that the FF behavior is more spec-compliant with current 402.

V8 and JSC don't do this today because they rely on CLDR and ICU which never update renamed IDs. But nothing stops ICU-using implementations from doing what Firefox does and overriding the ~20 zones in CLDR that use out-of-date names. If an ICU solution will take 2 years, could V8 and JSC in the meantime just add a hard-coded mapping table of 20 IDs? It's not like renames happen often: less than once per year is the average. If you, shu , and Frank wanted to do this badly enough, I suspect it could get done fast!

That said, it's a reasonable argument that doing (1) before (2), or at the same time, would reduce the negative impact to existing code because user-inputted zones wouldn't be affected.

My suggestion:

  • Let's get implementations building & shipping Temporal! After this plenary's normative changes are merged within a week or two, AFAIK there are no other large changes on the horizon.
  • IMO, V8 and JSC should really consider the 20-item hard-coded mapping table to work around CLDR's slow schedule. Could this work be paired with Temporal implementation instead of waiting until later? Could this work start now, and ship in a limited test to gauge the web-compat impact?

Let me know how I can help!

thanks for the detailed plan, i'd hate for it to get lost in the matrix chat, an issue to capture it would be great.

for (2), good to know it's independent. i won't be the one to drive this work, so Frank, who's much closer to the i18n and ICU teams, would be the one for you to convince to do the heavy lifting. frankly i just don't have the domain expertise and don't have a nose for the impact here to make a decision

03:59
<bakkot>
do I read the schedule correctly that there's a 60 minute underflow before lunch?
03:59
<bakkot>
is there any thought of moving stuff up or is all the other stuff fixed in time?
07:28
<Rob Palmer>
We're open to ideas on filling the morning schedule.
07:52
<bakkot>
I ask mainly because I would like to know if I will miss anything if I sleep during the time that is currently dead
07:52
<bakkot>
that being 2am-4am pacific time
07:53
<bakkot>
i.e. hours that I would very much like to sleep through if I am not going to be missing anything
07:53
<Rob Palmer>
We will begin by asking for agenda items to fill the time.
08:03
<sffc>
my slides: https://docs.google.com/presentation/d/1MKceo1Pn1PvuMz1WkzGwIpbT5qRNZVZRxY3rgcPJOKI/edit#slide=id.p
08:07
<littledan>
We are likely to do a review of Stage 2 proposals during the spare time in the morning, and a presentation of research by people here in UiB in the afternoon, but details tbd for each.
08:12
<Rob Palmer>
We have brought forward Nicolo's Optional Chaining into this morning. Plus the two additions Dan mentioned.
08:17
<Michael Ficarra>
I have seen this exact complaint about not being able to shrink wasm memory before in one of the wasm issue trackers
08:17
<Michael Ficarra>
they're aware of a need here
08:18
<littledan>
Isn't this just an issue at the tooling level, when it comes to single-threaded Wasm?
08:18
<bakkot>
https://github.com/WebAssembly/design/issues/1397
08:27
<justingrant>

@shu: thanks for the detailed plan, i'd hate for it to get lost in the matrix chat, an issue to capture it would be great.

https://github.com/tc39/ecma402/issues/806. Feedback welcome!

08:33
<justingrant>

if the bracketed time zone's offset, when rounded to HH:MM, matches the offset in the RFC3339 portion of the string, then there's no error produced

justingrant I was wondering about how this rounding handled midpoint values like -00:44:30 or +00:44:30 (specifically "ties away from zero" vs. "ties toward positive infinity" vs. "ties toward even"), but I don't see any mention of it at https://www.ietf.org/archive/id/draft-ietf-sedate-datetime-extended-08.html or https://github.com/ietf-wg-sedate/draft-ietf-sedate-datetime-extended/blob/main/draft-ietf-sedate-datetime-extended.md . Are you sure you're not thinking of Temporal InterpretISODateTimeOffset step 8.c.i RoundNumberToIncrement(candidateNanoseconds, 60e9, "halfExpand")?

Good catch. You're right, the rounding is a Temporal solution, not something in the IETF spec. Let's discuss among the Temporal champions whether it's wroth trying to get this into the IETF spec, or whether it's too niche for us to care about pushing it into that spec.
08:46
<rbuckton>
Python's contextlib has a very tight coupling between decorators and context managers, such as contextlib.ContextDecorator: https://docs.python.org/3/library/contextlib.html#contextlib.ContextDecorator
08:50
<Luca Casonato>
On the topic of source phase imports, please vote on the keyword (or suggest other keywords): https://github.com/tc39/proposal-source-phase-imports/issues/54
08:53
<Luca Casonato>
And you can discuss here: https://github.com/tc39/proposal-source-phase-imports/issues/53
09:11
<littledan>
the new example should be new a?.()
09:11
<littledan>
I thought the example new a?.b() should already be legal (but would not be so useful)
09:12
<eemeli>
Do we have any valid syntax yet that considers the LHS in any way before attempting evaluation of the RHS?
09:14
<bakkot>
(a.b) = c being legal is an accident of history
09:15
<rbuckton>
a = { b: x };
a = ({ b: x });
( { b: x } = a );
( ({ b: x }) = a ); // does not work
09:15
<bakkot>
we made ([x]) = b illegal
09:15
<rbuckton>
so we are not consistent in all assignment cases
09:19
<Andreu Botella>
You can also treat this as being precedence-related, right?
09:19
<Andreu Botella>
whether ?. is prioritized over =
09:19
<bakkot>
not with the example on screen, no
09:19
<Michael Ficarra>
Andreu Botella: no?
09:19
<HE Shi-Jun>
(a.b) = c being legal is an accident of history
yeah, it's strange. Much strange that we support (a.b)=c but not (test?a:b)=c which was supported in some other languages.
09:19
<Michael Ficarra>
Andreu Botella: definitely not
09:20
<rbuckton>
Its easy enough to say that (a?.b) is not a valid simple assignment target
09:20
<Michael Ficarra>
HE Shi-Jun: you're right, that is a strange inconsistency
09:22
<bakkot>
we could say a?.b = c is only legal in statement position
09:22
<rbuckton>
syntactically a?.b = c would likely be an OptionalChainAssignment, where the ?.b = c = d = 42 is part of the chain
09:22
<bakkot>
that would be kind of odd but like
09:22
<bakkot>
fine
09:22
<HE Shi-Jun>
a = b.x = c?.y = d = e = 42; this case is interesting, what's the behavior as current draft?
09:23
<rbuckton>

If you translate this example to the "setter-function" case, it is consistent:

a = b.x = c?.setY(d = e = 42);

would assign undefined to a and b.x

09:24
<HE Shi-Jun>
so a and b.x would be undefined instead of 42? 🤔
09:24
<rbuckton>
yes
09:24
<rbuckton>
maybe weaker than Statement and allow at ,?
09:25
<bakkot>
yeah, that also works
09:25
<bakkot>
really anywhere except the RHS of an assignment expression
09:26
<bakkot>
though, if the goal is to avoid observing the value, you do want "only in statement position" probably
09:26
<nicolo-ribaudo>
The goal is to "accidentally" observe the value
09:26
<rbuckton>
It should be feasible to forbid a = b?.x = c in the grammar
09:26
<bakkot>
x = (0, a?.b = c) assigns what value to x? undefined or c?
09:26
<nicolo-ribaudo>
i.e. something like a = (b?.c = d) might still be ok, assigning undefined
09:29
<rbuckton>
Not sure I want a?.b = c where c is evaluated if a is undefined. The point is to avoid the evaluation of c if it isn't going to be used, otherwise it is not a valid refactor from if (a) a.b = c
09:30
<rbuckton>
a?.b ?= c?
09:30
<littledan>
a?.b ?= c?
Maybe? It feels like one ? should correspond to one instance of short-circuiting, but this has two ? to point to the same thing
09:30
<bakkot>
Not sure I want a?.b = c where c is evaluated if a is undefined. The point is to avoid the evaluation of c if it isn't going to be used, otherwise it is not a valid refactor from if (a) a.b = c
I agree but I also agree with the concern about evaluating the RHS, which makes me not want this proposal (in the current form)
09:31
<littledan>
it feels like ne pas in French--agreement
09:32
<rbuckton>
ah, c'est vrai
09:32
<rbuckton>
(though I admit my french is limited and rusty)
09:33
<littledan>
same
09:35
<rbuckton>
a?.b is often intended to be read more like a ? .b or "if a exists then a.b", thus a?.b = c would be intended to be read as a ? .b = c or "if a exists then a.b = c".
09:38
<rbuckton>
Maybe? It feels like one ? should correspond to one instance of short-circuiting, but this has two ? to point to the same thing
Yeah, I don't like it but it would be a way to clarify what happens to the RHS. It's questionable how this would work with compound assignment or prefix/postfix increment/decrement however.
09:40
<Michael Ficarra>
eemeli: I think you need to review what stage 1 means
09:40
<Michael Ficarra>
you are asking nonsensical questions
09:40
<Michael Ficarra>
a solution is not accepted to stage 1; a problem space is
09:41
<rbuckton>
I would like us to investigate this at Stage 1 to see if we can find a way to resolve concerns raised by some delegates. I think this would be very valuable to have in some form and is worth pursuing, even if we need to find unique syntax to accommodate concerns.
09:41
<nicolo-ribaudo>
a solution is not accepted to stage 1; a problem space is
I think Eemeli's point is that this is not something that needs a solution at all
09:41
<Michael Ficarra>
yes, often when a proposal is "overcooked", we end up in this kind of a situation
09:42
<Michael Ficarra>
people get too hung up on the specifics of a potential solution
09:42
<bakkot>
(fwiw I think that the MessageFormat proposal had the same problem)
09:42
<Michael Ficarra>
unfortunately, without them, it can be difficult to understand the problem space
09:43
<rbuckton>
I would say the problem space is "allowing assignment with similar ergonomics as optional chaining currently allows: avoiding repetition and handling conditional member references based on whether a part of the LHs is null/undefined"
09:46
<bakkot>
Bradford Smith: I do not think it will be hard to specify this
09:46
<rbuckton>
We can at least block a = b?.c = d via a static semantics rule, even if not in the grammar.
09:46
<bakkot>
or to write parsers for it
09:46
<rbuckton>
We block const a via static semantics, so this doesn't seem that bad
09:47
<bakkot>
like I expect this to be about an order of magnitude easier to specify and implement than the hideous async (x) cover grammar
09:47
<bakkot>
which, granted, I wouldn't want any new features of that complexity
09:47
<bakkot>
but this one doesn't seem bad at all
09:48
<littledan>
arrow functions should've been like ^x => y or something
09:48
<nicolo-ribaudo>
I know that I should have not written a spec for a stage 0 proposal, but the way it can be specified is nicolo-ribaudo.github.io/proposal-optional-chaining-assignment/
09:48
<littledan>
everything would be way easier in that case
09:48
<Michael Ficarra>
λx. y
09:49
<bakkot>
sidebar: is someone breathing directly into one of the microphones?
09:49
<rbuckton>
We want to allow a?.b = c where its on the LHS, but disallow a = b?.c = d where its on the LHS and RHS, but not disallow a = b?.c where its on the RHS only. Possible with production parameters maybe, especially if the assignment is part of the OptionalChain production
09:49
<Bradford Smith>
Bradford Smith: I do not think it will be hard to specify this
Well I expect you're more familiar with the details of the grammar than I.
09:50
<eemeli>
(fwiw I think that the MessageFormat proposal had the same problem)
Agreed. We really should've explicitly gone for stage-1 for Intl.MessageFormat a couple of years earlier, when the work in its WG started under Unicode.
09:51
<ryzokuken 🇳🇴>
It's hard to foresee these issues ahead of time tbf
09:51
<rbuckton>
Well I expect you're more familiar with the details of the grammar than I.
We do some similar grammar gymnastics with ??
09:51
<bakkot>
We want to allow a?.b = c where its on the LHS, but disallow a = b?.c = d where its on the LHS and RHS, but not disallow a = b?.c where its on the RHS only. Possible with production parameters maybe, especially if the assignment is part of the OptionalChain production
production parameter works, yes - have a new [IsStatement] flag or whatever, present only on AssignmentExpression, and then Expression sets the flag and no other use of AssignmentExpression sets it
09:51
<bakkot>
alternatively you can just have an early error with prose
09:52
<rbuckton>
alternatively you can just have an early error with prose
Yeah, an EE is probably easiest.
09:52
<nicolo-ribaudo>
ryzokuken 🇳🇴 Rob Palmer TCQ is at the previous agenda item
09:52
<ryzokuken 🇳🇴>
oops
09:53
<ryzokuken 🇳🇴>
ptomato (at TC39, limited availability): could you add your item again?
09:53
<nicolo-ribaudo>
ptomato (at TC39, limited availability): could you add your item again?
It's still there
09:53
<nicolo-ribaudo>
Or at least, I see it there
09:54
<bakkot>
"how should the committee proceed wrt the pipeline operator" -> we should not proceed with the pipeline operator
09:55
<Michael Ficarra>
personally, I think the pipeline operator may need a full re-justification
09:55
<bakkot>
(sorry to be blunt; in my defense it's 3am)
09:55
<Michael Ficarra>
(reviewed in the context of the language as it is today, not how it was when originally justified)
09:56
<ryzokuken 🇳🇴>
I think given all that transpired with pipeline, maybe it makes sense to deviate from both semantics and try to come up with something unique that would be a decent compromise?
09:56
<Andreu Botella>
it's odd that test262 seems to strongly rely on cleanupSome to test some GC things
09:56
<nicolo-ribaudo>
personally, I think the pipeline operator may need a full re-justification
I would like to hear how it fits with the protocols proposal, since they both solve 'I want "methods" without the bad^TM modifications to its prototype that I do now own'
09:57
<nicolo-ribaudo>
I like throw expressions
09:58
<Michael Ficarra>
same
09:58
<nicolo-ribaudo>
I like them even in a world with do expressions
09:58
<Michael Ficarra>
I really wish I could get some time to work on protocols again
09:59
<Michael Ficarra>
editor work unfortunately takes up most of my time allocated to TC39, and iterator helpers (and follow-ons) are definitely more popular in the community
10:03
<Andreu Botella>
it seems like if cleanupSome is withdrawn, it would have to be added to the test262 infrastructure
10:03
<rbuckton>
The direction that the pipeline operator took has had significant pushback from the community. There's a tremendous amount of interest in the feature, but choice to use Hack-style pipes didn't sit well with some of the major libraries in the FP community.
10:03
<Andreu Botella>
maybe in a simplified way, without taking a callback
10:04
<Rob Palmer>
Please could you write this (in an appropriate way) in the summary notes for this topic, Ron.
10:04
<rbuckton>
i accidentally a word. I've edited the comment
10:04
<rbuckton>
re: do expressions, I think some proposals like pattern matching are depending on it.
10:04
<rbuckton>
not to say that they can't work around that.
10:04
<bakkot>
yeah, though pattern matching is even more syntax than do is
10:04
<bakkot>
it is so much syntax
10:05
<rbuckton>
pattern matching is extremely valuable though, and I think is definitely worth its weight.
10:05
<bakkot>
yeah I'm not saying any of these things shouldn't be pursued, considered in isolation (except maybe pipeline)
10:05
<ptomato (at TC39, limited availability)>
which implementations have cleanupSome anyway? I don't think it works in most of them, at least not unflagged
10:05
<bakkot>
just that I think the community would be better served by us focusing on stdlib stuff over syntax, at the margin
10:06
<ptomato (at TC39, limited availability)>
it may well be that the test262 infrastructure that uses cleanupSome, was only added for testing cleanupSome
10:06
<Andreu Botella>
https://github.com/tc39/test262/blob/main/test/built-ins/FinalizationRegistry/gc-has-one-chance-to-call-cleanupCallback-for-object.js
10:06
<Michael Ficarra>
I believe HE Shi-Jun was interested in championing the function.sent proposal
10:07
<Andreu Botella>
that test doesn't seem to be specifically for cleanupSome
10:07
<Andreu Botella>
and it uses asyncGC, which uses cleanupSome internally
10:07
<bakkot>
it does kind of claim to be testing cleanupSome?
10:07
<bakkot>
at least, that's what the info section has
10:07
<Andreu Botella>
it includes cleanupSome in the features it uses, because otherwise engine262 and maybe other engines will not pass the right flags
10:08
<Andreu Botella>
but I don't think it is testing cleanupSome
10:08
<Andreu Botella>
I might be wrong though
10:08
<ptomato (at TC39, limited availability)>
well that's what I meant by my original question - I suspect that most/all consumers of test262 might just never run this test
10:08
<ptomato (at TC39, limited availability)>
anyway, I'll add this to the agenda for the next test262 maintainers meeting. I'm not too familiar with these tests
10:09
<Andreu Botella>
I ran into this when testing the interaction of AsyncContext with the FinalizationRegistry callback, and seeing what other FR tests did
10:11
<bakkot>

rbuckton: re: throw; it occurs to me that possibly

ThrowExpression: `throw` AssignmentExpression [lookahead ≠ ,]

might also work?

10:12
<bakkot>
in combination with a [lookahead ≠ throw] restriction in ExpressionStatement, to avoid ambiguity
10:13
<bakkot>
it's a little bit weird, but I think it avoids the throw a, b problem
10:14
<bakkot>
and lookahead restrictions at the end of productions are precedented in IfStatement
10:15
<rbuckton>
That could work, and is far simpler than what I was thinking, though it does mean that ThrowStatement and ThrowExpression wouldn't be symmetrical.
10:15
<bakkot>
yeah, but you only notice the asymmetry as an author (or implementer), not as a reader
10:15
<bakkot>
since as a reader you would simply never encounter throw a, b in expression position, so it would not come up
10:16
<rbuckton>

The alternative I had was this:

Expression :
  ThrowExpression
  CommaExpression

CommaExpression : // the old Expression production
  AssignmentExpression
  CommaExpression `,` AssignmentExpression

And you could potentially even drop ThrowStatement since it would be fully covered by ExpressionStatement (rather than a lookahead restriction in ExpressionStatement).

10:17
<bakkot>
the main place I'd expect you to notice the restriction as an author would be like function f(x = throw new Error('argument is not optional'), y) {]
10:18
<bakkot>
but, that case is one which is hard for readers who are familiar with ThrowStatement to read, so I am ok with authors having to deal with the restriction in that case
10:19
<rbuckton>
With the grammar I mention above, rather than the ambiguity of throw in an initializer, you would be forced to write it as function f(x = (throw new Error(...)), y) which helps with the ambiguity, with the downside that 99% of the places you'd want to use throw requiring parens.
10:20
<rbuckton>
I like your approach though, since I'd venture to guess that the number of throw statements that use , is vanishingly small.
10:21
<bakkot>
pretty small, though probably not vanishingly
10:21
<bakkot>

in particular, stuff like

let obj = {
  x: condition ? val : throw new Error('condition is not satisfied'),
  y,
};
10:21
<bakkot>
so it's still a little annoying
10:22
<bakkot>
but, no ambiguity.
10:22
<bakkot>
and you fix it with parens and go on with your life
10:22
<rbuckton>
pretty small, though probably not vanishingly
Yeah, minifiers probably do that with throw statements today.
10:22
<bakkot>
oh, sorry, yes, lots of throw statements with , because of minifiers
10:22
<rbuckton>
I'm happy with that though. If you really wanted to use , in your throw expression, you could parenthesize.
10:22
<bakkot>
minifiers love commas
10:23
<rbuckton>
oh, sorry, yes, lots of throw statements with , because of minifiers
But probably very few hand-written statements, I would venture to guess.
10:23
<bakkot>
agreed
10:23
<bakkot>

reading the old thread, I have a comment which reads

Note the comma after the throw. How would you propose to forbid it? Would you even want to?

I don't know why it didn't occur to me that you could trivially forbid it with a lookahead...

10:24
<rbuckton>
I am happy with ThrowExpression : `throw` AssignmentExpression [lookahead != `,`]
10:24
<rbuckton>

reading the old thread, I have a comment which reads

Note the comma after the throw. How would you propose to forbid it? Would you even want to?

I don't know why it didn't occur to me that you could trivially forbid it with a lookahead...

or me. its only been what, 5 years?
10:24
<bakkot>
since that comment, almost exactly two years, but for the proposal in general yes
10:26
<bakkot>

in particular, stuff like

let obj = {
  x: condition ? val : throw new Error('condition is not satisfied'),
  y,
};
I do hope implementations / parsers are able to give a good error message in this case ("try wrapping the throw expression in parentheses")
10:26
<bakkot>
annoying technical restrictions like this chafe a lot less when you are told immediately how to fix them
10:27
<bakkot>
seems like it ought to be possible
10:27
<rbuckton>
I do hope implementations / parsers are able to give a good error message in this case ("try wrapping the throw expression in parentheses")
TypeScript does this for quite a few grammar errors.
10:28
<bakkot>
good good
10:28
<rbuckton>
I posted your suggestion here: https://github.com/tc39/proposal-throw-expressions/issues/10#issuecomment-1633978974
10:42
<rbuckton>
Do we care about other restrictions aside from ,? any infix operator has the same kind of precedence issue, i.e., throw a = b as a statement vs. as an expression. Right now assignment isn't much of an issue in the proposal because the proposal does not allow ThrowExpression to be a valid assignment target, but other operators like &&, ||, ??, etc. would have a different precedence. That said, you kind of may want to be able to write a && throw b || c, but throw b || c; has a different meaning.
10:45
<rbuckton>
Forcing parentheses (i.e., (throw err)) does solve all of those precedence concerns, though.
10:47
<bakkot>
does it have the same issue? wouldn't a && throw b || c parse as a && (throw b || c), like a && yield b || c does?
10:48
<rbuckton>
throw is currently specified as a UnaryExpression, so it doesn't have the same precedence as yield. a && yield b || c isn't legal.
10:49
<rbuckton>
YieldExpression is AssignmentExpression, so it can't be on the RHS of &&.
10:49
<bakkot>
ah, right
10:49
<bakkot>
I forget yield is weird
10:50
<rbuckton>
And one of the motivators for throw was to use it with ??, i.e. const a = b ?? throw new Error(), so it wouldn't work as yield precedence without parens.
10:52
<rbuckton>
But that's also an alternative to my CommaExpression idea. Instead, just make ThrowExpression an AssignmentExpression with the same trailing [lookahead != `,`] restriction. That would mean you could write a, throw b, but not throw a, b, which is a bit weird, tbh.
10:53
<bakkot>
I am not super worried about humans writing comma expressions
10:53
<bakkot>
they almost exclusively come up when reading minified code, in my experience
10:53
<bakkot>
occasionally in loop heads but I don't anticipate much use of throw there either
10:54
<bakkot>
so while I agree that it would be weird that you could write a, throw b but not throw a, b, my actual concern is preventing you from writing the second thing, and since I don't think anyone would write the first thing the inconsistency doesn't bother me
10:58
<rbuckton>
Do you have a position on the precedence for other infix operators differing between the statement and expression forms, or was , your only concern?
11:00
<bakkot>
Do we care about other restrictions aside from ,? any infix operator has the same kind of precedence issue, i.e., throw a = b as a statement vs. as an expression. Right now assignment isn't much of an issue in the proposal because the proposal does not allow ThrowExpression to be a valid assignment target, but other operators like &&, ||, ??, etc. would have a different precedence. That said, you kind of may want to be able to write a && throw b || c, but throw b || c; has a different meaning.
a && throw b || c does worry me. I'll have to think more about the tradeoff between that ambiguity and forcing more parens.
11:01
<bakkot>
it is a little less worrying that the , case because throw b || c isn't really a thing which comes up today, even in minified code, so I am less worried about people misreading it
11:01
<rbuckton>
Would you agree that forcing parens is a working solution, even if only as a fallback?
11:01
<bakkot>
yes, forcing parens solves the ambiguity
11:01
<rbuckton>
it is a little less worrying that the , case because throw b || c isn't really a thing which comes up today, even in minified code, so I am less worried about people misreading it
But minifiers, though..
11:01
<bakkot>
even minifiers don't output throw b || c in my experience
11:02
<littledan>
when you hear "dataflow", think "reactivity"
11:02
<rbuckton>
I expect that they do emit throw a && b though, since they often use && as a substitute for if
11:02
<Michael Ficarra>
littledan: FRP?
11:04
<bakkot>
I expect that they do emit throw a && b though, since they often use && as a substitute for if
not that I can recall seeing. that's equivalent to if (!a) throw a; throw b;, but I think that pattern is rare enough to not have been special-cased
11:04
<bakkot>
&& as a substitute for if is mainly useful when the rhs of the if is an expression
11:06
<bakkot>
looks like esbuild does in fact implement that, so it's just that I haven't run into it because it's rare enough
11:09
<bakkot>

another option, which I am... only kind of serious about, would be

`throw` AssignmentExpression [lookahead ∈ {`)`, `}`, `;`, EOF} ]
11:09
<bakkot>
this would be fine if everyone used semis consistently
11:10
<rbuckton>
Why would you disallow )?
11:10
<bakkot>
that's an allowlist, not a denylist
11:10
<Michael Ficarra>
the grammar sees source post-ASI
11:10
<rbuckton>
Ah, sorry. I see.
11:11
<bakkot>
the grammar sees source post-ASI
oh, hm. that's a fair point.
11:11
<rbuckton>
ish. true for most parsers, but the spec says "parse it. if parse fails, see if it parses after inserting ;"
11:11
<Michael Ficarra>
yes, it would have to be otherwise invalid
11:12
<bakkot>
in this case it would be though
11:12
<rbuckton>
the grammar has to see source pre-ASI for ASI to work.
11:12
<Michael Ficarra>
yeah
11:12
<rbuckton>
EOF isn't defined in the spec though.
11:13
<Michael Ficarra>
I thought we had a way to assert on end of input
11:16
<rbuckton>
"end of input" is mentioned only once in terms of White Space. We also have something like "parsed...with no tokens left over" for cover grammars
11:17
<rbuckton>
and "with no tokens left over" is mentioned in The Syntactic Grammar as well when discussing the Script and Module goals.
11:18
<rbuckton>
"end of the input stream" is mentioned in the rules for ASI
11:18
<bakkot>
the EOF isn't necessary because of the ASI thing
11:18
<bakkot>
strike it from my suggestion
11:18
<rbuckton>
Also, ] should be allowed as well.
11:18
<bakkot>
if you had a ?? throw b at the end of the program, ASI would add a ; so it would parse
11:19
<bakkot>
yup, agreed on ]
11:19
<rbuckton>
And maybe { for something like class extends a || throw b {?
11:19
<bakkot>
also should add :
11:19
<rbuckton>
for case?
11:19
<bakkot>
for a ? throw b : c
11:19
<bakkot>
might be easier to enumerate operators which should be disallowed instead, really
11:20
<rbuckton>
Ah, yes. but also case. There are a lot of tokens to consider and its possible that list would need to change if/when new syntax is added.
11:20
<bakkot>
yeah
11:22
<rbuckton>
Yeah, I think its easier to restrict to all of the infix operators, or maybe pull out part of OtherPunctuators in the lexical grammar.
11:32
<rbuckton>
It helped to write the using implementation in engine262 when writing tests as a way to verify both the implementation and the test itself.
11:32
<Bradford Smith>
Does the current process call for reviewers specifically to review the test262 tests? And if so, are there published guidelines for how to review them?
11:33
<ryzokuken 🇳🇴>
no, reviewers review the spec
11:33
<ryzokuken 🇳🇴>
test262 tests are reviewed by test262 maintainers
11:35
<ptomato (at TC39, limited availability)>
stage 3 reviewers are hereby enthusiastically invited to review the tests, though!
11:35
<ptomato (at TC39, limited availability)>
it really helps the maintainers if the real experts on a proposal weigh in
11:35
<rbuckton>
Though I'd contributed to test262 in the past, I found it very difficult to get started on the tests for using as I found the documentation was somewhat lacking in terms of how to set up the environment, and I had trouble running the tests on Windows and had to use WSL.
11:36
<ptomato (at TC39, limited availability)>
would you like to bring that up in #test262-maintainers:matrix.org and maybe contribute better documentation for that use case?
11:36
<rbuckton>
Plus there is a lot of hunting around to figure out what files you need to add to includes: [] for some assertions. The experience of working with test262 in an editor like VSCode wasn't great.
11:37
<rbuckton>
would you like to bring that up in #test262-maintainers:matrix.org and maybe contribute better documentation for that use case?
I can bring it up, but it would be hard to document myself if I don't actually have a strong grasp of what needs to be documented.
11:37
<ptomato (at TC39, limited availability)>
this is valuable feedback and I'd love to have a follow up on it
11:39
<rbuckton>
I forwarded the messages to the maintainers chat
11:39
<rbuckton>
What msaboff is saying is exactly why I wrote an implementation for engine262 to verify the tests themselves were accurate.
11:40
<bakkot>
I know michael used polyfills to exercise the iterator helpers tests
11:46
<littledan>
I think it's kinda inconsequential whether the reviews happen before or after tests are written, and it'd be fine to shift this later. I'd be uneasy about potentially weakening "Stage 3" which is why I like the numbering Michael used.
11:48
<Willian Martins>
Maybe stage 3 🔴 and 3 🟢?
11:49
<Andreu Botella>
Stage 3⁺ and Stage 3₋
11:52
<Jesse (TC39)>
3.-0 and 3.+0
11:56
<shu>
littledan: i don't think it is actually, it should happen before tests are written
11:56
<shu>
reviews can trigger non-implementation-motivated normative changes, no?
12:00
<littledan>
please advance the queue
12:01
<nicolo-ribaudo>
I think it's kinda inconsequential whether the reviews happen before or after tests are written, and it'd be fine to shift this later. I'd be uneasy about potentially weakening "Stage 3" which is why I like the numbering Michael used.
Adding a stage before stage 3 makes stage 3 stronger, but not doing so doesn't make it weaker
12:02
<bakkot>
in my ideal world, implementations would start at stage 2.75, and would write tests, and then champions would do the work of getting those tests into test262 proper, and then get stage 3
12:03
<littledan>
not sure why my topic was converted to a reply and pushed up
12:03
<littledan>
I'd prefer to wait to raise this separate topic
12:12
<Rob Palmer>
We will take the photo on the mezzanine floor at 14:20
12:20
<Chris de Almeida>
Jesse (TC39): Michael Ficarra please let me know if you would indeed like to sacrifice the Decimal continuation for a continuation of the stage/process discussion
12:24
<Jesse (TC39)>
yes, sacrifice is OK
12:27
<Michael Ficarra>
I would accept additional time for the process topic
12:29
<HE Shi-Jun>
what diff between getUint8Clamped and getUint8 ?
12:31
<bakkot>
there is no difference
12:33
<Michael Ficarra>
they could literally be the same function object
12:36
<bakkot>
this proposal feels like a good reason for us to have introduced the "someone must explicitly second for it to advance"
12:39
<nicolo-ribaudo>
they could literally be the same function object
+1, like for [][Symbol.iterator] === [].values
12:40
<shu>
what is the .name
12:40
<nicolo-ribaudo>
I think "values"
12:40
<shu>
`"getUint8(Clamped)"`
12:40
<Michael Ficarra>
we only have 1 choice there
12:40
<shu>
oh no i meant for the DataView methods
12:40
<Michael Ficarra>
since the non-clamped one already has a name
12:41
<shu>
boo
12:46
<HE Shi-Jun>
let's add a directive: "no coercing" 😂 for the old APIs
12:46
<Michael Ficarra>
no need
12:52
<Michael Ficarra>
omg that padStart one was disgusting
12:53
<Christian Ulbrich>
I'd prefer 'ky'.padStart(5, Number)!
12:59
<Michael Ficarra>
I can see people relying on primitive-to-string conversion
12:59
<Michael Ficarra>
I know Java devs love it
13:03
<Christian Ulbrich>
I never used coercion for params and I would not let someone pass in a review, if there were to use it...
13:09
<Christian Ulbrich>
TypeScript types for WebAPIs are usually stricter, than the APIs is, i.e. they won't allow using types, that are actually "supported" by coercion.
13:09
<ryzokuken 🇳🇴>
I can see people relying on primitive-to-string conversion
if I got a dime for every dependency that required it
13:11
<Christian Ulbrich>
Although I have to say, that TypeScript is often too ambitious, dis-allowing undefined in many (WebAPI) places...
13:13
<rbuckton>
Although I have to say, that TypeScript is often too ambitious, dis-allowing undefined in many (WebAPI) places...
Do you have examples? IIRC, most of our DOM-specific libs are generated from WebIDL.
13:14
<Luca Casonato>
Anecdote here: a fun TypeScript case (WHATWG not TC39 api) on deciding when coercion is ok vs not ok. https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1568
13:20
<Michael Ficarra>
so what do TypeScript developers use to convert String->Number?
13:21
<Michael Ficarra>
do they actually use the full variety of options as appropriate?
13:21
<Christian Ulbrich>
Hm. I kind have to retract my argument, having looked at my own code and blaming TypeScript, indeed I am using sth. like parseFloat(value) < 5 and I do rely on parseFloat(undefined) returning NaN ... and NaN < 5 being false...
13:21
<ljharb>
having parseFloat return NaN for a non-string input seems ok to me too tho
13:22
<Christian Ulbrich>
I think it returns NaN because undefined is coerced into 'undefined':)
13:23
<ljharb>
right - but i think it would be reasonable to return NaN because it's not a string, as well, instead of throwing
13:23
<Christian Ulbrich>
this is somewhat related to stuff, that TS does not like comparing with undefined, which to me totally makes sense... and seemingly not only me
13:33
<Jesse (TC39)>
do we document these kinds of things? Does this go, e.g., in the how-we-work document?
13:33
<Michael Ficarra>
yes, we've recently started documenting these sorts of things
13:34
<Michael Ficarra>
I'm sure Kevin will PR it after we're done
13:34
<ryzokuken 🇳🇴>
would this be an invariant then?
13:34
<Michael Ficarra>
no
13:34
<ryzokuken 🇳🇴>
I see, just a recommendation?
13:34
<Michael Ficarra>
https://github.com/tc39/how-we-work/pull/119
13:34
<Michael Ficarra>
a convention
13:34
<ryzokuken 🇳🇴>
I see
13:38
<Christian Ulbrich>
rbuckton: I only skimmed through my code, at first glance I only found HTMLInputElement['value'], this is typed as string, where in reality™ it also accepts null to reset the value...
13:41
<littledan>
littledan: FRP?
I mean like generically, React and signals and all that stuff. I think FRP is in that space too but I haven't really looked into it.
13:41
<nicolo-ribaudo>
rbuckton: I only skimmed through my code, at first glance I only found HTMLInputElement['value'], this is typed as string, where in reality™ it also accepts null to reset the value...
It also accepts "" to reset the value, right?
13:43
<Christian Ulbrich>
It also accepts "" to reset the value, right?
It certainly does not accept undefined, because this gets coerced to 'undefined' and sets the value to 'undefined'...
13:43
<shu>
bakkot: we got consensus for not rounding non-integral, right?
13:45
<shu>
bakkot: btw i would like to discuss the thing i put on the queue, which is while i'm happy with requiring explicit coercions, the coercions people will reach for is like, String() and Number() which create wrapper objects, and not incantations like +"". this is a performance footgun imo but maybe is not a big deal
13:45
<bakkot>
we did not
13:45
<shu>
oh i missed that, i thought we got consensus for rounding... huh
13:45
<shu>
there was opposition to that?
13:45
<bakkot>
sffc said he'd want more time to review implications for intl
13:45
<shu>
ah okay
13:46
<nicolo-ribaudo>
String(a number) does not create a wrapper object, right?
13:46
<bakkot>
String() and Number() don't create wrapper objects though
13:46
<bakkot>
only new String
13:48
<shu>
oh the [[Call]] behavior is different!
13:48
<shu>
awesome
13:48
<shu>
i mean not awesome for me, embarrassing for me to have forgotten that
13:48
<shu>
but great, no concern then
13:51
<Ashley Claymore>
all that C++ you're writing pushing out the JS again
13:53
<Michael Ficarra>
honestly, changing from stage numbers to stage names seems like a good idea
13:53
<Michael Ficarra>
where the names are the things that each stage is meant to signal
13:54
<shu>
i don't disagree
13:54
<shu>
but you're opening yourself up to like, an order of magnitude more hours of bikeshedding
13:54
<Chris de Almeida>
if we're bikeshedding the stage name, 2 splitting into to 2.a, 2.b seems better to me than 2, 2.75
13:54
<littledan>
I think Rust went through this detailed bikeshedding exercise at some point
13:54
<ryzokuken 🇳🇴>
well, we technically have names
13:54
<littledan>
2.b doesn't sound enough like "almost 3" to me
13:54
<Chris de Almeida>
why does it need to?
13:55
<shu>
because it is supposed to be almost 3
13:55
<ryzokuken 🇳🇴>
strawperson/proposal/draft/...
13:55
<Chris de Almeida>
2.z
13:55
<Michael Ficarra>
Chris de Almeida: we've had a request for that
13:55
<bakkot>
so that we don't argue about design decisions
13:55
<eemeli>
I've been mostly posting this on TDZ, but I seriously think we should go with stages 1, 2, e, π, 4.
13:55
<bakkot>
the reason to signal "almost stage 3" is because we want to explicitly signal "do not keep arguing about design"
13:55
<eemeli>
Then we'd have two three-ish stages.
13:56
<ryzokuken 🇳🇴>
I think renaming stage 3 is going to be hard
13:56
<Michael Ficarra>
eemeli: no
13:56
<ryzokuken 🇳🇴>
a lot of things out there use that
13:56
<ryzokuken 🇳🇴>
they might not depend as much on lower stages (like babel bundles IIRC?)
13:59
<sffc>
sffc said he'd want more time to review implications for intl
I'm a bit concerned about integral numbers because it is more likely to cause data-driven exceptions. Actually the realm of data-driven exceptions is something we should discuss in plenary.
14:01
<bakkot>
data-driven exceptions seem better than data-driven not-the-right-answer
14:02
<sffc>
There's a big difference between "not the right answer" and "best effort answer". In Intl and i18n we're very much driven by doing a best effort acknowledging that we can never be always exactly "right".
14:04
<bakkot>
I think for APIs which accept integers, passing a non-integral value is generally a programmer error, rather than being a case where there is only a best-effort answer
14:05
<bakkot>
and I generally think programmer errors should be program exceptions, rather than trying to get a best-effort result
14:05
<Michael Ficarra>
RE the "spiraling", the thing we need to keep in mind is that it's fine if we have an implementation during stage 2.75 (Dan suggested polyfills/transpilers, but it can also be an engine), it's just the idea is to avoid recommending for general implementation, which is where that aggregate work is extremely high
14:05
<ljharb>
a best-effort answer doesn't necessarily mean you can't restrict inputs
14:05
<ljharb>
it just means the output doesn't have to be perfect
14:08
<rbuckton>
rbuckton: I only skimmed through my code, at first glance I only found HTMLInputElement['value'], this is typed as string, where in reality™ it also accepts null to reset the value...
It appears that, while we handle [LegacyNullToEmptyString] on method parameters, we don't seem to handle it for properties.
14:10
<shu>
There's a big difference between "not the right answer" and "best effort answer". In Intl and i18n we're very much driven by doing a best effort acknowledging that we can never be always exactly "right".
if "correctness" is generally not a design principle in Intl and that domain, and it's instead "approximation", then i can see where you're coming from
14:10
<shu>
for 262 at least "approximation" is most definitely not the design principles for new APIs
14:12
<rbuckton>
rbuckton: I only skimmed through my code, at first glance I only found HTMLInputElement['value'], this is typed as string, where in reality™ it also accepts null to reset the value...
Filed as https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1596. If you have other cases, I encourage you to report them at https://github.com/microsoft/TypeScript-DOM-lib-generator or http://github.com/microsoft/TypeScript.
14:15
<bakkot>
shu: I do think that, given that the committee is receptive to breaking with precedent for coercing stuff in at least some cases, it is maybe worth asking to break with precedent for any new TA things
14:15
<bakkot>
to avoid the awful user code coercions
14:15
<shu>
yeah, the TA problem is narrowly solvable
14:15
<shu>
it'd be nice to solve it generally but i'll take any improvement obv
14:16
<bakkot>
on the "coercing objects to strings is useful" point, one of the things I will ask about next time I bring this up is, just don't coerce objects to number, and continue coercing to string
14:16
<bakkot>
since, granted, there is some utility to coercing things like URL to string
14:16
<bakkot>
(even if I personally would prefer people do it explicitly)
14:16
<shu>
i'd also take "built-in toString methods only" but that's not that nice and hurts polyfills
14:17
<Christian Ulbrich>
rbuckton: Quite the service! Thanks for creating the bug. From my mind, there were other issues, I'll report them once I have some more time, currently only ~30 //@ts-ignore in our code base, not too bad. The other thing, was with NodeListOf being iteratable (sic!) but I have to give this a more thorough look on modern TypeScript (we are currently at 4.6.2.
14:18
<shu>
actually let's generalize that, it'd be cool to have the dynamic extent of argument + receiver coercion to throw on user code, even if they continue to coerce
14:21
<sffc>
for 262 at least "approximation" is most definitely not the design principles for new APIs
I think this is an appropriate line to draw
14:23
<bakkot>
a best-effort answer doesn't necessarily mean you can't restrict inputs
as a concrete example: "give me the best 2 candidate locales" is a well-posed question with only an approximately correct answer. "give me the best 2.5 candidate locales" is an ill-posed question, just as much as "give me the best NaN candidate locales" is. throwing is the right response to ill-posed questions.
14:25
<sffc>
I'm happy to iterate on the language surrounding when ToIntegerIfIntegral should be used versus truncation
14:56
<Richard Gibson>
I'm having difficulty in coming up with any scenario where we would prefer truncation other than for consistency with existing APIs. It's just such a mess that e.g. -0.2 is accepted as a non-negative integer or max + 0.1 is rejected where max - 1 + 0.1 is accepted as equivalent to max - 1.
15:07
<sffc>
I'm having difficulty in coming up with any scenario where we would prefer truncation other than for consistency with existing APIs. It's just such a mess that e.g. -0.2 is accepted as a non-negative integer or max + 0.1 is rejected where max - 1 + 0.1 is accepted as equivalent to max - 1.
So you have every right to disagree with this example, but something like truncating "123.4 minutes" to "123 minutes" in Intl.DurationFormat is not necessarily bad, especially if (and again, people are welcome to disagree) we have a path toward making the fractional digits work in the future.
15:34
<Richard Gibson>
I definitely do disagree; that's a clear case where the truncation would be bad because "123.4 minutes" has a valid interpretation that should not be silently discarded in favor of equivalence with "123 minutes", making future support for respecting the fractional part more difficult. This is an analogue of the motivating use case in Temporal Durations, which couldn't lean on the fuzziness inherent to ECMA-402 formatting (that might leave a sufficient gap for future extension, but then again might not) as justification.
15:53
<sffc>
The counter-point is that if we were to enable that type of extension in the future, it's not inherently bad that older engines operate with the approximate behavior. Many programmers will not think about catching the exception in older engines, causing those browsers to needlessly break when they would otherwise get close-but-not-quite-right output.
15:54
<sffc>
As an example, we executed on this successfully when we deployed the "interpret strings as decimals" change in Intl.NumberFormat.prototype.format.
16:51
<TabAtkins>
I'm with sffc here that this is a very debatable case that has a reasonable argument for truncation. (But I'm generally for the "stop coercing/truncating everywhere" proposal.)
16:58
<TabAtkins>
just that I think the community would be better served by us focusing on stdlib stuff over syntax, at the margin
I don't think we need to set these against each other, but I do agree we need way more stdlib investment in this group. (And I need to finish my own contribution to that, the seeded-random proposal.)
17:11
<TabAtkins>
The justification of "make everything method-chainable" is still valid. It would be good to do another review of everything trying to do similar things. But I don't think protocols clash in any meaningful way.
17:12
<TabAtkins>
Like if you squint they're both doing similar things (playing in the method space, without messing with prototypes) but protocols use-case, justifications, and abilities are quite distinct.