2025-05-01 [11:57:26.0768] I’m working on [#3581](https://github.com/tc39/ecma262/pull/3581) (Array.fromAsync). I’m figuring out the last two esmeta errors in [this job](https://github.com/tc39/ecma262/actions/runs/14781083646/job/41499977134?pr=3581). It looks like Array.from’s iteration machinery has changed a lot since I last checked. Now Array.from uses a new IteratorStepValue operation. There’s no analogous AsyncIteratorStepValue operation yet, is there? [12:03:49.0924] Correct [12:03:55.0128] Would it be worth for the Array.fromAsync pull request to define new AsyncIteratorStepValue, AsyncIteratorStep, and AsyncIteratorNext operations? [12:04:07.0239] No, probably not until there's more stuff which uses it [12:04:09.0220] * Would it be worth for the Array.fromAsync pull request to define new AsyncIteratorStepValue, AsyncIteratorStep, and AsyncIteratorNext operations, to match Array.from’s algorithm? [12:05:53.0805] You can use the underlying operations, though [12:06:32.0107] IteratorNext works fine on async iterators I think [12:06:57.0067] and then after awaiting the result you can use IteratorComplete and IteratorValue [12:08:23.0861] which I guess is pretty much what you're doing already, except manually calling .next instead of using IteratorNext, which is fine [12:08:47.0583] don't worry too much about esmeta errors; if they don't look like actual errors you can ignore them [12:09:24.0650] it isn't capable of handling everything in the spec and there's a file we can use to mark things as expected errors if we decide it's an esmeta bug [12:10:28.0991] in this specific case, yes, it looks like it's because of not recognizing the new IfAbruptCloseAsyncIterator macro, which makes sense; macros are hard to typecheck and we don't have any explicit marking for them [12:29:07.0148] Thank you very much for your great help. 2025-05-03 [10:22:42.0260] Is the content I added implicitly given somewhere? Or is it a mistake? (CompileAtom is not explicitly defined for production `Atom :: \ AtomEscape`, but is defined for `AtomEscape`) [10:27:00.0937] https://tc39.es/ecma262/#sec-algorithm-conventions-syntax-directed-operations > Unless explicitly specified otherwise, all chain productions have an implicit definition for every operation that might be applied to that production's left-hand side nonterminal. The implicit definition simply reapplies the same operation with the same parameters, if any, to the chain production's sole right-hand side nonterminal and then returns the result. 2025-05-04 [08:37:09.0833] Is this correct? For RegExp: `/[\p{Hex}]/u`: https://tc39.es/ecma262/#sec-compiletocharset For production ` UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue`, `s` is `Hex`, in step 2 it calls `UnicodeMatchPropertyValue(General_Category, s)` UnicodeMatchPropertyValue (https://tc39.es/ecma262/#sec-runtime-semantics-unicodematchpropertyvalue-p-v) 2. Assert: v (in this case, `Hex`) is a property value or property value alias for the Unicode property p (in this case, General_Category) listed in PropertyValueAliases.txt. https://unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt And in https://unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt, there is no entry starts with `gc ; Hex` so this assert should fail. Did I miss something? Thanks! [08:37:58.0270] * Is this correct? For RegExp: `/[\p{Hex}]/u`: https://tc39.es/ecma262/#sec-compiletocharset For production ` UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue`, `s` is `Hex`, in step 2 it calls `UnicodeMatchPropertyValue(General_Category, s)` `UnicodeMatchPropertyValue` (https://tc39.es/ecma262/#sec-runtime-semantics-unicodematchpropertyvalue-p-v) 2. Assert: `v` (in this case, `Hex`) is a property value or property value alias for the Unicode property `p` (in this case, General_Category) listed in PropertyValueAliases.txt. https://unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt And in https://unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt , there is no entry starts with `gc ; Hex` so this assert should fail. Did I miss something? Thanks! [09:06:13.0933] yeah that looks like a bug [09:06:52.0918] you should open an issue and cc `@mathiasbynens` [09:28:51.0800] https://github.com/tc39/ecma262/issues/3586 [09:59:18.0932] Doesn't that fail the early error? [10:00:21.0659] (The one that says it's a Syntax Error if that Assert would fail.) [10:01:27.0408] Or am I missing the crux of the example? [10:04:38.0803] `/[\p{Hex}]/u` is intended to be legal, I am pretty sure [10:04:42.0514] certainly it is treated as such [10:04:51.0935] * certainly it is treated as such in actual implementations [10:06:28.0618] oh, actually, that early error rule is okay, because "Hex" appears in Table 70. [10:06:42.0586] * oh, actually, that early error rule passes, because "Hex" appears in Table 70. [10:45:13.0214] PR to fix: https://github.com/tc39/ecma262/pull/3587 2025-05-05 [13:15:43.0660] With regards to the Stage 4 criterion “pull request has been sent to tc39/ecma262 or tc39/ecma402, as appropriate, with the integrated spec text”, is Stage 4 for Array.fromAsync blocked by [#2942](https://github.com/tc39/ecma262/pull/2942) merging into main because its pull request ([#3581](https://github.com/tc39/ecma262/pull/3581)) is based on #2942? This is assuming that the editors sign off on #3581, which is blocking both Stage 3 and Stage 4. [13:20:33.0703] No [13:20:53.0503] Or rather, to be precise, it is blocked from merging into main, but that's fine [13:21:41.0097] Excellent, thank you. It sounds like I can request Stage 4 for Array.fromAsync at this month’s plenary, assuming that #3581 gets editor sign-off. [13:22:44.0437] Yes, and also you should add it to the agenda when you're ready without first waiting for the editors; editors generally prioritize reviewing things which are on the agenda 2025-05-06 [21:23:44.0661] Is this an Annex B only test? https://github.com/tc39/test262/blob/93d63969bccbf8b4471b7c7fadc875099b7668d3/test/language/literals/regexp/S7.8.5_A1.4_T2.js#L4 It constructed a RegExp like this: `new RegExp('\\' + String.fromCodePoint(8204))` It parsed as IdentityEscape. In the main spec it is `[~UnicodeMode] SourceCharacter but not UnicodeIDContinue`, (btw 8204 is a UnicodeIDContinue), but in annex B it is ` [~NamedCaptureGroups] SourceCharacter but not c [+NamedCaptureGroups] SourceCharacter but not one of c or k ` [21:23:55.0723] * Is this an Annex B only test? https://github.com/tc39/test262/blob/93d63969bccbf8b4471b7c7fadc875099b7668d3/test/language/literals/regexp/S7.8.5_A1.4_T2.js#L4 It constructed a RegExp like this: `new RegExp('\\' + String.fromCodePoint(8204))` It parsed as IdentityEscape. In the main spec it is `[~UnicodeMode] SourceCharacter but not UnicodeIDContinue`, (btw 8204 is a UnicodeIDContinue), but in annex B it is ``` [~NamedCaptureGroups] SourceCharacter but not c [+NamedCaptureGroups] SourceCharacter but not one of c or k ```` [21:24:01.0073] * Is this an Annex B only test? https://github.com/tc39/test262/blob/93d63969bccbf8b4471b7c7fadc875099b7668d3/test/language/literals/regexp/S7.8.5_A1.4_T2.js#L4 It constructed a RegExp like this: `new RegExp('\\' + String.fromCodePoint(8204))` It parsed as IdentityEscape. In the main spec it is `[~UnicodeMode] SourceCharacter but not UnicodeIDContinue`, (btw 8204 is a UnicodeIDContinue), but in annex B it is ``` [~NamedCaptureGroups] SourceCharacter but not c [+NamedCaptureGroups] SourceCharacter but not one of c or k ```` [21:27:35.0494] (also for language/literals/regexp/S7.8.5_A2.4_T2.js) 2025-05-07 [02:02:30.0685] CharacterClassEscape[UnicodeMode] :: [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } Is it missing a [+UnicodeSetsMode] version of those 2 production? otherwise I cannot find a way to parse `/^\p{Basic_Emoji}+$/v` [02:02:39.0627] * ``` CharacterClassEscape[UnicodeMode] :: [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } ``` Is it missing a [+UnicodeSetsMode] version of those 2 production? otherwise I cannot find a way to parse `/^\p{Basic_Emoji}+$/v` [03:26:20.0323] In the spec, `+UnicodeSetsMode` only occurs in conjunction with `+UnicodeMode`. (i.e., roughly, `USM` implies `+UM`, or `+USM` is a subset of `+UM`), so any RHS guarded by `[+UM]` 'succeeds' for all cases of `+USM`. [03:26:51.0212] I think. [03:28:19.0938] * In the spec, `+UnicodeSetsMode` only occurs in conjunction with `+UnicodeMode`. (i.e., roughly, `+USM` implies `+UM`, or `+USM` is a subset of `+UM`), so any RHS guarded by `[+UM]` 'succeeds' for all cases of `+USM`. [04:08:18.0340] oh, I checked all Pattern, all Pattern[+USM] is also marked as [+UM] [04:29:13.0221] yup [10:25:47.0522] I want to proposal a method for finding the item in an iterable which has the largest value according to some function, for example "find the person with the largest age" or whatever. This comes up a lot IME, enough to be worth having in the standard library even though it's like a four or five lines to do with a loop or `.reduce`. There's two natural ways to do this: either take a function from input items to a number, or take a comparator. both work, first is often more convenient, second is strictly more general. Thoughts? We could in principle support both. (Even in the same function, just by switching on `callback.length === 1`, but... not that option). [10:25:50.0905] * I want to proposal a method for finding the item in an iterable which has the largest value according to some function, for example "find the person with the largest age" or whatever. This comes up a lot IME, enough to be worth having in the standard library even though it's like a four or five lines to do with a loop or `.reduce`. There's two natural ways to do this: either take a function from input items to a number, or take a comparator. both work, first is often more convenient, second is strictly more general. Thoughts? We could in principle support both. (Even in the same function, just by switching on `callback.length === 1`, but... not that option.) [10:28:13.0403] I suppose one way to solve the dilemma is to have a function which lifts a `T -> number` mapper to a `(T, T) -> { -1, 0, 1 }` comparator, and expect people to use that, as in `people.maxByComparator(Compare.by(person -> person.age))`. [10:28:23.0027] (java calls the latter operation `Comparator.comparing`) [10:31:18.0117] * I want to make a proposal for a method for finding the item in an iterable which has the largest value according to some function, for example "find the person with the largest age" or whatever. This comes up a lot IME, enough to be worth having in the standard library even though it's like a four or five lines to do with a loop or `.reduce`. There's two natural ways to do this: either take a function from input items to a number, or take a comparator. both work, first is often more convenient, second is strictly more general. Thoughts? We could in principle support both. (Even in the same function, just by switching on `callback.length === 1`, but... not that option.) [10:35:55.0695] Isn't this the same API design question we had with `uniqueBy`? You can either give a mapper or a comparator, and we probably just want both. [10:36:23.0108] wouldn't this be less efficient? [10:36:55.0073] Pretty similar, yeah, although the "comparator" for uniqueBy is not a comparator in the sense of "a function which can be passed to `.sort`", whereas it is here [10:37:43.0416] same big-O, but requires computing 2x as many calls of the `T -> number` function, yes [10:39:58.0017] I actually am kind of coming around to the idea of switching on the `.length` of the callback [11:07:59.0209] A comparator for unique has to compare against all previous unique values. O(N^2) A comparator for largest only has to compare against the current winner. O(N) [11:08:47.0338] This does sound useful. I currently reach for `.sort(c).at(-1)` when in a pinch [11:10:15.0541] Effectively, this would be sugar for something like this, yes? ``` people.reduce((acc, p) => p.age > acc.age ? p : acc) ``` [11:11:45.0081] * Effectively, this would be sugar for something like this, yes? ``` people.reduce((acc, person) => person.age > acc.age ? person : acc) ``` [11:17:47.0739] Isn't that good enough for this use case? [11:23:00.0146] I mean, isn't a for loop good enough for this use case? [11:23:17.0823] Reduce has the "empty list" exception which is annoying IMO [11:23:39.0017] for a winner like method I'd rather an empty set returns undefined as the winner [11:25:26.0155] `reduce` is basically the same kind of hammer as a for loop. Personally I like it when the language provides common, simple operations even when they're already achievable with the language's existing general purpose tools. [11:25:41.0578] ehhhhh no I was definitely planning on proposing this where it's an exception if you call it on an empty list [11:25:51.0317] https://es.discourse.group/t/array-prototype-winner/1015/ [11:26:10.0531] ("winner" is a terrible name) [11:27:05.0384] > <@bakkot:matrix.org> ehhhhh no I was definitely planning on proposing this where it's an exception if you call it on an empty list Only a weakly help opinion. I'd be curious what other languages do (the ones that can't return a fancy maybe type) [11:27:25.0224] > <@bakkot:matrix.org> ehhhhh no I was definitely planning on proposing this where it's an exception if you call it on an empty list * Only a weakly held opinion. I'd be curious what other languages do (the ones that can't return a fancy maybe type) [11:28:54.0922] Passing an initial value to reduce to avoid the throw is annoying because you can't easily pass `undefined` as that will get passed as an argument, so now need to handle that extra case on the comparator [11:29:06.0643] You can avoid this by passing a sentinel value as the second argument, e.g. `{ age: -Infinity }` in the example case. [11:29:32.0529] Sure, now do that with a complex type with more than one prop :) [11:31:06.0673] Returning undefined I can always `?? error()` to get back to the exception behavior. Going from exception to undefined is more work [11:32:11.0687] ``` people.reduce((acc, person) => person.age > acc?.age ?? -Infinity ? person : acc, null) ``` [11:32:47.0121] python's `max` has an optional `default` argument to use in case of empty list, and throws if the list is empty and no default is provided [11:32:51.0212] which seems pretty reasonable [11:33:27.0120] other languages return fancy maybe types [11:33:39.0244] https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#max-java.util.Comparator- [11:34:17.0291] https://docs.rs/itertools/latest/itertools/fn.max.html [11:34:30.0248] a default that is only used for empty sounds good, that isn't passed to the comparator [11:35:31.0253] god this language could've been so much better if we had a built-in Maybe in the early days [11:35:55.0174] Or allowed any breaking changes ever. [11:35:56.0104] And monoid protocols [13:05:43.0103] > <@aclaymore:matrix.org> Only a weakly help opinion. I'd be curious what other languages do (the ones that can't return a fancy maybe type) So Rust has both `max` and `max_by` methods on iterators where the later takes a comparator function and the former only works with values that implement “Order”, so mainly numbers etc In Rust’s case they return an Option type then None if the list is empty, so `undefined` in the js equivalent. https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.max_by [13:06:23.0545] > <@aclaymore:matrix.org> Only a weakly help opinion. I'd be curious what other languages do (the ones that can't return a fancy maybe type) * So Rust has both `max` and `max_by` methods on iterators where the later takes a comparator function and the former only works with values that implement “Order”, so mainly numbers etc In Rust’s case they return an Option type then None if the list is empty, so `undefined` in the js equivalent. https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.max_by That being said, option is a fancy return type, so doesn’t help here. But I do like the max and max_by names better. [13:06:51.0543] > <@aclaymore:matrix.org> Only a weakly help opinion. I'd be curious what other languages do (the ones that can't return a fancy maybe type) * So Rust has both `max` and `max_by` methods on iterators where the later takes a comparator function and the former only works with values that implement “Order”, so mainly numbers etc In Rust’s case they return an Option type then None if the list is empty, so `undefined` in the js equivalent. https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.max_by That being said, Option is a fancy return type, so doesn’t help here. But I do like the max and max_by names better. [13:09:40.0892] Maybe empty vs unaryarrays are the true JS option type, as you can't `null.map`. I tried that in a codebase once when I was in my wild youth phase [13:09:52.0007] * Maybe empty vs unary arrays are the true JS option type, as you can't `null.map`. I tried that in a codebase once when I was in my wild youth phase  [13:23:59.0270] `max` and `max_by` are the right names but rust has them exactly backwards :( [13:24:35.0119] `sort` takes a comparator, `sortBy` would take a `T -> number` [13:24:39.0775] ditto max and maxBy [13:24:55.0682] * ditto `max` and `maxBy` [13:25:10.0054] I guess the `T -> number` one is called `max_by_key` [13:25:39.0362] * I guess the `T -> number` one is called `max_by_key` in rust [13:26:09.0163] but yeah I think the natural naming is `max` taking an optional comparator and `maxBy` taking a mandatory `T -> number` [15:41:38.0096] This is it, yes. Both variants are needed, and this is the right naming/assignment. [15:46:36.0516] @bakkot:matrix.org throwing or returning a special value for empty iterators? [16:02:01.0696] Michael Ficarra throwing but with an optional second `default` argument to return in that case, like python does [16:03:06.0568] though I guess that's annoying in the specific case that you want to use the default comparator but provide a default [16:03:10.0822] oh well I guess [16:03:18.0628] yeah I think that's what I would do as well [16:03:33.0694] still not 100% convinced it's needed, but if we do have it, that's how I would do it [16:06:49.0157] I definitely want `unique`/`uniqueBy` more [16:07:58.0061] I forget: given that we have no array prototype methods, how would those work? on iterator.prototype but returning array? [16:08:41.0037] I guess they could return an iterator, ok [16:09:08.0618] just kind of weird to have an iterator that uses O(all previous items) memory [16:31:24.0875] yeah that was the feedback I got at the last presentation [16:31:38.0806] it's weird but I don't think it's *surprising* if you consider for even a second what it's doing [16:32:50.0440] and I don't think that's fatal to the proposal 2025-05-11 [04:40:47.0817] bakkot if we have max on iterators, we should also have min and minmax [06:20:40.0941] I think TabAtkins suggested the idea of having a general comparator inverter [07:24:08.0718] min yes, minmax no [14:15:43.0164] why not minmax? [14:38:31.0012] just doesn't come up enough to be worth it IME 2025-05-12 [18:59:00.0084] `std::minmax` seems common enough in C++, though I haven’t had time to dig into specific reasons why people have been using it: https://github.com/search?q=std%3A%3Aminmax+language%3AC%2B%2B+&type=code [18:59:41.0818] * `std::minmax` seems common enough in C++, though I haven’t had time to dig into specific reasons why people have been using it: https://github.com/search?q=std%3A%3Aminmax+language%3AC%2B%2B+&type=code https://sourcegraph.com/search?q=context:global+std::minmax&patternType=keyword&sm=0 [20:33:51.0979] two orders of magnitude less results than `std::max` though 2025-05-13 [00:24:38.0120] Aapo Alasuutari Regarding https://github.com/Igalia/webengineshackfest/issues/48, I suggest getting in touch with TC53 if you haven't yet (even though that's not about a subset of JS, if you are working on embedded devices it's very relevant) [14:00:47.0889] > <@nicolo-ribaudo:matrix.org> Aapo Alasuutari Regarding https://github.com/Igalia/webengineshackfest/issues/48, I suggest getting in touch with TC53 if you haven't yet (even though that's not about a subset of JS, if you are working on embedded devices it's very relevant) Hoo, interesting. I was not aware of this.