00:01
<rbuckton>
the disagreement i see is the motivation is thus ergonomics, which comes down to feelings, which we disagree on
there are more benefits than ergonomics, but that is one of the benefits.
00:02
<shu>
my universe of benefits for that proposal is either a new capability, or an ergonomic improvement. that may be a broader brush than what you think of as "ergonomics"?
00:02
<shu>
or am i misunderstanding
00:02
<shu>
there's performance but i thought we discarded that one
00:03
<littledan>
my universe of benefits for that proposal is either a new capability, or an ergonomic improvement. that may be a broader brush than what you think of as "ergonomics"?
what is Temporal?
00:03
<bakkot>
Temporal is a mix of new capabilities and ergonomics improvements
00:04
<shu>
i consider Temporal to be like 80% ergonomics
00:04
<shu>
20% performance in the "we are going to take over distribution" sense
00:05
<jschoi>
Re: Temporal, does “reducing ecosystem fragmentation” fall under ergonomics? Just wondering.
00:05
<nicolo-ribaudo>
Does “reducing ecosystem fragmentation” fall under ergonomics?
How is the ecosystem currently fragmented for function decorators?
00:06
<rbuckton>
we should probably have not included class decorators, yes; at one point they had additional expressivity and so I was ok with that on those grounds
This presumes class decorators have no value aside from somehow aggregating class element decorators, but that isn't the case. The registration semantics are critical for use cases like custom elements and packages like lit. There are also useful cases like @Callable, amongst others. Manual function application is terribly unergonomic for class declarations, and I think its terribly unergonomic for functions as well. Libraries like material-ui use function "decorators" in this way, and it makes the code far harder to reason over and pick apart.
00:06
<jschoi>
Sorry, was talking about Temporal.
00:07
<bakkot>
This presumes class decorators have no value aside from somehow aggregating class element decorators, but that isn't the case. The registration semantics are critical for use cases like custom elements and packages like lit. There are also useful cases like @Callable, amongst others. Manual function application is terribly unergonomic for class declarations, and I think its terribly unergonomic for functions as well. Libraries like material-ui use function "decorators" in this way, and it makes the code far harder to reason over and pick apart.
it does not presume they have no value. the claim is that the benefits are not worth the cost.
00:10
<rbuckton>

I like reverse pipes, and they were suggested as an area of exploration back in the early pipeline days. That said, I don't think that is readable in the more common cases, as examples like these often focus on unary functions, but that's rarely the predominant use case. What you would actually see is something like:

const index =
  route("/api/foo")(^^) <|
  authorized("Administrator")(^^) <|
  originCheck(^^) <|
  rateLimited(5, 1)(^^) <|
  function () {};

You most likely need to use double invocation here if you want to reuse existing decorators (despite those decorators needing to be even more defensive around the missing 2nd argument).

00:11
<rbuckton>
And I do not find that more readable in the slightest.
00:17
<rbuckton>
I would hope we would use indexes instead of names if we do param decorators
This is what we currently do in TS. Parameter names seem like a nice to have capability that is worth exploring as its useful for diagnostics purposes. for example, if your decorator performs some kind of route binding or validation and if that fails it throws an error. It's far more convenient to diagnose "The provided value is not supported on parameter 'foo'" than "The provided value is not supported on parameter 6". Whether we support parameter names is definitely a topic for discussion at stage 1.
00:19
<Justin Ridgewell>
Didn’t we agree that closed over unary-returning functions are the devil in the pipelines proposal?
00:19
<rbuckton>
my universe of benefits for that proposal is either a new capability, or an ergonomic improvement. that may be a broader brush than what you think of as "ergonomics"?
It provides both ergonomics benefits (decorator reuse, language consistency), and new capabilities (post decorate registration, function name reflection for diagnostics, metadata).
00:22
<Justin Ridgewell>
Sorry, me being cheeky isn’t needed here.
01:19
<rbuckton>
It depends on what capabilities we give to parameter decorators. In TypeScript, such a parameter decorator can only be used for recording metadata. It can't perform method replacement or run code on a per-invocation basis.
01:21
<rbuckton>
For constructor parameters, this is a convenient way to associate metadata for dependency injection containers, which is the predominant use case in projects like https://github.com/microsoft/vscode. For method parameters, this is a convenient way to bind HTTP route parameters for RESTful APIs.
01:24
<rbuckton>
The parameter decorators proposal described a large number of areas of exploration beyond what TypeScript's version supported, but not all of those capabilities are critical to an MVP version of the proposal. An MVP version I would be comfortable advancing would at a minimum have the same capabilities that such decorators in TS have: parameter index, method name and placement, and the ability to record metadata.
01:25
<Anthony Bullard>
Thanks for the response. I’ll think about this. My initial thoughts are that syntactic constructs should meet an incredibly high bar for inclusion in a language. Basically they need to enable a new language construct that wasn’t possible without it
01:25
<rbuckton>
There are a large number of examples on the explainer at https://github.com/tc39/proposal-class-method-parameter-decorators
01:26
<Anthony Bullard>
That’s my personal opinion anyway
01:27
<rbuckton>
Parameter decorators were added to TypeScript as a way to parallel what Java annotations or C# attributes can do, which is far more limited than a normal decorator. Even with that limitation, they saw a considerable amount of use in the TS ecosystem.
01:29
<rbuckton>
A number of the nice-to-haves were based on feedback from the TS community over the years. We don't allow method replacement, so TS parameter decorators couldn't be used for parameter validation without pairing them with a method decorator.
01:32
<rbuckton>
That was seen as a wart in the design, which prompted the proposed adoption of returning a callback that could intercept the bound argument. That turns out to be a very powerful capability, but is perhaps a power we may not want to grant.
01:34
<rbuckton>
having to manually number a series of pseudo-parameter decorators that are far detached from the actual code they represent is extremely unergonomic. Having the runtime provide the parameter index for you, and keeping the declarations physically adjacent to the parameter improves readability and is extremely convenient for refactors.
02:02
<jschoi>

Reading through this, I’m a little surprised that we’re considering making async iterables support unordered buffering. But it’s an exciting capability. It might be especially useful when combining WHATWG Streams.

I feel that the default behavior of AsyncIterators, including AsyncIterators created from arrays of promises, should wait for each promise sequentially, like how for await (and Array.fromAsync) already do. The contract of async iterators implies stable sequentiality to me. I don’t know how strongly I feel about this.

I think that using a Rust-like bufferUnordered method is a good idea. It would make developers opt into unordered buffering. (I also slightly prefer bufferUnordered to buffered to clearly indicate the lack of stable order.) I don’t know how I feel about forEachConcurrent and findConcurrent.

Would bufferUnordered return an AsyncIterator that is indistinguishable from other AsyncIterators? Or would it return a new async-iterable type, like Rust’s BufferUnordered class?

02:06
<rbuckton>

A quick note regarding reusing a punctuator in place of void for discards. There are very few of these that are viable due to compound assignment:

// these are all already legal:
using *= f();
using /= f();
using %= f();
using += f();
using -= f();
using &= f();
using ^= f();
using |= f();
02:11
<nicolo-ribaudo>
Congrats to libjs for passing the most tests and being faster than V8/SM :)
02:19
<snek>
congrats to engine262 for being the slowest
02:31
<linusg>
just talked to canadahonk about this, apparently some of the V8/SM experimental flags have changed so slightly inaccurate :P
02:33
<linusg>
both rhino and nashorn take many hours to complete, check again in a few hours 😅
02:55
<bakkot>

jschoi: re:

I feel that the default behavior of AsyncIterators, including AsyncIterators created from arrays of promises, should wait for each promise sequentially

So, an async iterator doesn't actually do anything itself. It doesn't really make sense to compare the behavior of async iterators to the behavior of for await, because the iterator doesn't have any behavior on its own (buffer excepted).

Instead of talking about the behavior of an async iterator itself, we can talk about the behavior observed by consumers of an async iterator. A consumer like for await will see the same thing in all worlds discussed here (unless one is using the new buffering helpers), because for await waits for each promise to settle before pulling the next one, and so could not possibly observe promises settling out of order. The "can things settle out of order" question does not affect such consumers at all.

If we allow settling out of order, that would only be observable to consumers which do multiple calls of .next(). There's nothing in the language that does that right now, but you could do it yourself, in principle. Or, as proposed, you could do it with buffer or bufferUnordered (which would do multiple calls to .next() under the hood). With buffer, if you pull from it the way for await does, you would never see things happening out of order. So the only places this "settling out of order" behavior would be observable would be when manually calling .next() multiple times, or when using bufferUnordered.

Would bufferUnordered return an AsyncIterator that is indistinguishable from other AsyncIterators? Or would it return a new async-iterable type, like Rust’s BufferUnordered class?

First thing. The return value of all helpers would just be instances of AsyncIteratorHelper.

03:04
<bakkot>
On the topic of parameter decorators, I wonder if other people have looked through the examples in the readme of the proposal, and if so what their reactions are: https://github.com/tc39/proposal-class-method-parameter-decorators#ecmascript
03:05
<rkirsling>
it looks incredibly foreign to me
03:09
<rkirsling>
I have little experience with decorators in any language, but I'm at least used to the idea that they sit atop a method or function or whatever
03:22
<littledan>
Does eshost do as good a job as the engines’ own test262 runners at filling in all of the hooks and such?
03:36
<linusg>
pretty much, yep! 
03:37
<jschoi>

The framing here, from the perspective of the AsyncIterator consumer, makes sense. Promises’ settling out of order is unobservable by default to “higher-level” consumers like for await or AsyncIterator methods (higher-level = “do not directly call .next()).

I think it’d be good to put something like the explanation here into your Gist or your future explainer.

03:37
<linusg>
the main advantage of writing a custom runner is that spawning 100k processes is slow (~50k tests each running in sloppy and strict mode) 
19:19
<snek>
it takes like 4 minutes to run engine262 on test262 with its runner, but eshost apparently takes 2 hours lol