2022-09-01 [13:58:31.0354] Can I get write access to test262? [13:58:52.0185] Trying to update the group/groupToMap PRs made by another contributor, but I can't push without access. 2022-09-02 [09:07:30.0976] Justin Ridgewell: i just added you with write access, in theory CODEOWNERS should prevent you from merging but Write should allow you to force push to the PR; please lmk if theory doesn't hold [09:28:51.0497] Thanks [09:50:33.0114] < 24 hours to get your agenda items in for the next meeting! Looks like this will be a short one unless folks are waiting for the last possible second. [15:03:56.0082] ljharb (or any admin): can I be given write access to https://github.com/tc39/proposal-set-methods? šŸ˜… [15:20:57.0381] done [16:48:49.0262] ljharb re https://github.com/tc39/proposal-iterator-helpers/issues/117#issuecomment-1235980915 "i'd prefer it brand-check" - what do you actually want it to brand check? [16:49:05.0131] I'm confused about what the ask is [16:58:02.0516] instances of iterator [16:58:17.0160] so it throws if anyone extracts the getter and dot calls it on something different 2022-09-03 [18:18:56.0824] so an `instanceof` check, you mean? that doesn't seem that useful; you can do that yourself [22:05:49.0750] no, not an instanceof check, those are forgeable and don't work across realms. a brand check. [09:00:22.0548] ljharb: what brand do you imagine checking? there are a bunch of different built-in iterators in the language and the web platform, and they don't have a common brand [09:00:46.0177] the whole point of iterator being an interface is that the interface is implemented by a bunch of different classes, including userland classes [09:02:50.0840] IMO the appropriate level for a brand check here would be to revert the whole Symbol.toStringTag change in the first place... what a bad idea of a feature. Not clear if it makes sense to "chip away at it" as much as I'm sympathetic with the idea to try. [09:06:01.0455] it's not unthinkable to add a brand just for this purpose in https://tc39.es/proposal-iterator-helpers/#sec-iterator but I don't see the point [09:06:41.0126] (do we want to start telling people, they shouldn't be pasting iterator helpers onto a base class by messing with a prototype chain? that seems like a useful mode to me) [09:07:01.0926] * (do we want to start telling people, they shouldn't be pasting iterator helpers onto a base class by messing with a prototype chain? that seems like a useful mode to me) 2022-09-04 [18:42:16.0345] they do have a common brand now, itā€™s what Iterator.from provides [18:42:40.0929] and a userland class will be wrapped by a branded object. [08:36:39.0724] Iterator.from checks `instanceof Iterator` and returns the original object if that returns true [08:36:52.0231] so no, it does not provide a common brand [08:37:01.0436] * so no, it does not provide a common brand [10:33:56.0875] without first class protocols the only ways to check if something is an actual iterator is either rely on the prototype or exhaustively interrogate its methods [10:34:20.0633] * without first class protocols the only ways to check if something is an actual iterator is either rely on the prototype or exhaustively interrogate its methods [11:17:16.0208] This is one reason why I'm still wary of using Iterator rather than an Iterable. 2022-09-05 [18:13:02.0539] i didnā€™t realize that. It shouldnā€™t use instanceof - like everything else in the language, it should use a brand. [18:17:51.0847] no, it's an interface [18:17:54.0377] it's not a class [18:17:58.0963] I mean, it is also a class [18:18:30.0356] but there is no particular reason a userland instance needs to have the brand [19:14:15.0471] > <@ljharb:matrix.org> i didnā€™t realize that. It shouldnā€™t use instanceof - like everything else in the language, it should use a brand. how do you brand something whose definition is "has a next method that returns { value, done }" [19:15:56.0312] or if you subscribe to the other idea, "an object inheriting Iterator.prototype" [20:35:23.0409] objects in the language that inherit from a prototype also have a brand, thats checked in places. [20:38:35.0852] no i like [20:38:42.0553] i do not understand the mechanic by which this would work [10:17:26.0579] anything that's `instanceof Iterator` in the language would have an internal slot, which is what Iterator.from would check [10:28:14.0641] in the language or, presumably, the web platform? [10:28:28.0850] I suppose that would be possible but... why? [11:22:09.0722] > <@ljharb:matrix.org> anything that's `instanceof Iterator` in the language would have an internal slot, which is what Iterator.from would check how do they get the internal slot? they're just random objects [11:23:40.0028] oh are you saying Iterator.from would be the thing that produces objects with that slot [11:25:30.0272] technically the new object it returns has `[[Iterated]]` [11:25:31.0130] but [11:25:37.0717] it doesn't have to return the new object [11:26:10.0577] like if i run `Iterator.from({ next() {}, __proto__: Iterator.prototype })`, it should return that argument unchanged [12:26:30.0104] that doesnā€™t seem like what it should be doing at all. [12:27:17.0394] Array.from doesnt pass through return an arraylike object that has a proto of Array.prototype - it returns a proper array. So should Iterator.from. [12:28:31.0086] the definition of "proper iterator" _is_ "inherits from Iterator.prototype", in this context [12:44:30.0140] i don't think that is or should be the definition [13:00:34.0611] why? [14:08:11.0778] Iterator is not a concrete thing, I'd rather rename the method if that's the problem [14:15:40.0372] the whole point of Iterator.from is that it's becoming a concrete thing [14:15:49.0067] no its just that its giving it the prototype [14:16:05.0528] its a convenience for the methods [14:16:47.0742] ā€¦ and the methods do a wrap (to something with the slot) if they're `.call`ed on a random object? [14:17:33.0567] i don't understand what this means [14:17:41.0235] the `[[Iterated]]` slot you mentioned [14:18:21.0801] `[[Iterated]]` is just used for %WrapForValidIteratorPrototype%.next/return [14:18:33.0754] how can the next method retain internal state unless it has a place to put it? [14:19:11.0869] WrapForValidIteratorPrototype objects don't have any internal state [14:19:24.0161] [[Iterated]] is just the object they wrap [14:19:41.0461] well, the iterator record for it [14:20:57.0151] ok so like `map`. it has to hold on to the original iterator, and to the callback [14:21:15.0595] so presumably the iterator object returned by `map` holds that, in an internal slot [14:21:53.0713] they use closures [14:22:27.0105] so the iterator object doesn't use a shared `next` method, it makes a new one each time `map` is called? [14:22:39.0264] uhh [14:22:43.0674] it uses %IteratorHelperPrototype%.next [14:22:47.0801] * it uses %IteratorHelperPrototype%.next [14:22:48.0948] right. but that's a shared method. [14:22:55.0382] which is just %GeneratorPrototype%.next but fancy [14:22:56.0847] so it can't close over something that's unique to a given `map` call [14:23:10.0849] because it exists before `map` is ever called. [14:23:11.0878] * which is just %GeneratorPrototype%.next but fancy [14:23:24.0823] so where is that state held so that `next` can access it? [14:23:39.0873] same place that normal generators store it [14:23:50.0121] the only thing is [14:24:06.0149] you can grep for `[[GeneratorBrand]]` in the spec [14:24:06.0150] right but that's in a slot on the generator instance, no? [14:24:13.0324] https://tc39.es/ecma262/#sec-generatorvalidate [14:24:19.0829] this is the only way it tells them apart [14:24:28.0839] but that just tells you if it was a generator helper method [14:24:42.0969] tbh i'm not sure why we separate them at all, they just call `GeneratorResume` [14:25:04.0878] right. and [[GeneratorContext]] and [[GeneratorState]] are slots on the iterator object that hold the state [14:25:22.0708] yeah its a generator [14:25:27.0530] right [14:26:03.0805] and GeneratorValidate brand-checks the iterator. it doesn't matter what its [[Prototype]] is, it matters if it has the expected slots. [14:26:12.0585] ye [14:26:25.0083] so i assume that Iterator Helper methods all do the same validation [14:26:51.0015] iterator helper methods do not know about those brand checks, they perform them via calling stuff like `GeneratorResume` [14:26:57.0036] right but they still exist [14:26:59.0533] sure [14:27:01.0744] which means that `{ __proto__: Iterator.prototype }` would fail that check, and not be a usable receiver with the Iterator Helper methods. which means Iterator.from musn't ever return it. [14:27:17.0449] which means that Iterator.from always returns a brand-checkable object, one that GeneratorValidate will accept. [14:27:26.0938] uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh [14:27:27.0624] no [14:27:36.0444] what am i missing there? [14:28:00.0628] assuming this `let iterWithGeneratorSlots = [].values().map(x => x); ` [14:28:22.0541] `Iterator.from(iterWithGeneratorSlots)` passes it through unchanged because it inherits from %Iterator.prototype% [14:28:24.0787] but [14:28:57.0242] if you do `Iterator.from({ next() {}, __proto__: Iterator.prototype })` it also passes it through unchanged [14:29:04.0970] that's not doing any generator stuff [14:29:29.0694] if you do `Iterator.from({ next() {} })` that creates a %WrapForValidIteratorPrototype% object and returns it [14:29:30.0204] ok but what happens with `Iterator.from({ next() {}, __proto__: Iterator.prototype }).map(x => x)`? [14:29:37.0331] but that still doesn't have any generator slots [14:29:40.0615] cuz its not a generator [14:29:44.0860] its just a stupid wrapper [14:29:51.0977] > <@ljharb:matrix.org> ok but what happens with `Iterator.from({ next() {}, __proto__: Iterator.prototype }).map(x => x)`? that has generator slots cuz you called map [14:30:06.0286] ok, and `.map` doesn't care if its receiver has the slots? [14:30:07.0853] * ok, and `.map` doesn't care if its receiver has the slots? [14:30:12.0540] no it does not [14:30:15.0145] oof [14:30:19.0662] all it cares is that the receiver is an iterator [14:30:59.0446] https://gc.gy/130118458.png [14:32:13.0928] this is why `{ next() {}, __proto__: Iterator.prototype }` is valid [14:32:52.0882] with protocols you have to assume that the object is already created as some other shape, you're augmenting them with the functionality, implementing the protocol on top of something else [14:33:04.0619] i don't understand why, if everyone's going to `Iterator.from()` anyways to get the methods, we wouldn't want to unconditionally wrap - ie, to unconditionally `.map(x => x)` [14:33:24.0469] * i don't understand why, if everyone's going to `Iterator.from()` anyways to get the methods, we wouldn't want to unconditionally wrap - ie, to unconditionally `.map(x => x)` [14:33:32.0370] i think its pretty rare that you would *need* to use Iterator.from [14:33:34.0392] that way we have a consistent "real iterator" definition [14:34:06.0617] i think you'll want to do it any time you're dealing with a user-supplied iterator. which will be frequent. [14:34:27.0005] i mean, those are rare lol [14:34:27.0301] you'd want to maximally accept and normalize all possible iterators [14:34:33.0290] that's what `Promise.resolve` is good for too [14:34:36.0360] yeah i mean [14:34:41.0810] it normalizes thenables into Real Promises, which are always preferred [14:34:46.0635] if you're you, writing some sort of complex fancy library that has to deal with the world [14:34:49.0388] similarly i'd always want a Real Iterator, not just an "iterator" [14:34:51.0688] go for it [14:35:06.0469] this isn't just a "my unique coding style" thing tho, this is any package [14:35:25.0531] anything that accepts an iterator. just like anything that accepts a thenable always uses Promise.resolve or `await` to normalize it first into a real promise [14:35:35.0379] Iterator.from will be exceedingly common imo. [14:35:35.0989] its a nice convenient method yeah [14:35:38.0604] i was just pointing out [14:35:44.0264] its superfluous in 99% of cases [14:36:01.0138] so we made it not add extra overhead [14:36:01.0299] i don't think that's true [14:36:08.0795] i think 99% of cases will be dealing with untrusted iterators [14:36:19.0924] the case where you're iterating your own iterator are likely to be far rarer. (where "your own" doesn't deal with who the author is, but which chunk of code owns it) [14:36:36.0548] * the case where you're iterating your own iterator are likely to be far rarer. (where "your own" doesn't deal with who the author is, but which chunk of code owns it) [14:37:23.0449] "extra overhead" isn't a real problem (it can be optimized away), but a footgun like "sometimes it doesn't wrap" imo would be [14:37:27.0301] the genesis of this proposal was the observation that all web and js platform iterators already inherit from a shared %IteratorPrototype% [14:37:31.0109] * "extra overhead" isn't a real problem (it can be optimized away), but a footgun like "sometimes it doesn't wrap" imo would be [14:37:45.0242] and the remaining weird ones often use the `(function*(){})().next().__proto__` trick or whatever it is [14:37:45.0962] then whose don't need to wrap because they'll have the slots to begin with, so it doesn't matter what `Iterator.from` does for them [14:38:12.0240] why are we concerned with "overhead" for the highly unlikely case of someone doing `{ __proto__: Iterator.prototype }`? [14:38:42.0354] unlikely still means nonzero, and having to deal with that complexity (in the current case) is far more dangerous than "it's a bit slower if you do something super weird" (in the "always wrap" case) [14:38:59.0139] * unlikely still means nonzero, and having to deal with that complexity (in the current case) is far more dangerous than "it's a bit slower if you do something super weird" (in the "always wrap" case) [14:39:45.0721] i am lost now [14:40:36.0674] the overhead is when you wrap something that is already matching the "iterator with prototype" definition, which is most iterator objects flying around [14:41:08.0230] * the overhead is when you wrap something that is already matching the "iterator with prototype" definition, which is most iterator objects flying around [14:44:11.0723] anything created from the language or a generator or the web would/could already have the slots it needs. Itā€™d only be a custom iterator implementation thatā€™d need wrapping. How common are those? [14:44:33.0604] most custom ones already inherit from Iterator.prototype [14:44:46.0954] or they did, i haven't looked in several years [14:44:55.0217] i would assume they didn't delete that though lol [14:45:31.0244] the pattern is `[][Symbol.iterator]().__proto__.__proto__` [14:45:49.0173] or getPrototypeOf instead [14:47:35.0746] so anyway to handle the case where they don't, we have this `Iterator.from` helper, and you can throw that in random places as needed [14:47:49.0977] but it exists purely to paper over the prototype [14:48:43.0178] like just thinking about the code i write for my day-to-day work, i would basically never use `Iterator.from` [15:14:56.0504] > i think 99% of cases will be dealing with untrusted iterators i would guess well over 99% of code is internal, not in libraries, and in internal code you are not dealing with untrusted stuff, as a rule [15:19:10.0909] also I guess I am missing what the benefit of the internal slot is supposed to be [15:28:48.0186] I voiced an opinion, several years ago now, that I believed the iterator helper methods should always just do `this[Symbol.iterator]()` so that they would work for both `Iterator` *and* Iterables. Then, the presence of `Symbol.iterator` would be enough of a brand check (insomuch as it is the same amount of brand checking that `yield*` and `for..of` care about). [15:30:18.0451] > <@devsnek:matrix.org> most custom ones already inherit from Iterator.prototype Most custom "Iterators" I've seen are just `{ next() { ... }, [Symbol.iterator]() { return this; } }`. [15:40:59.0748] rbuckton: why would you ever be invoking an iterator helper method on something which was an iterable-and-not-iterator? [15:41:20.0412] what is an example of some code where that might come up? [15:51:22.0240] My original argument stems from my belief that Iterator is still the wrong level of abstraction. But aside from that, if the iterator helper methods were to only care about whether the object had a `next()` then we would have the same kind of duck typing we get with `.then()` on Promises. As a result, we end up needing a brand check of some kind which a custom iterator like `{ next() { ... } }` wouldn't have. [15:51:37.0395] * My original argument stems from my belief that Iterator is still the wrong level of abstraction. But aside from that, if the iterator helper methods were to only care about whether the object had a `next()` then we would have the same kind of duck typing we get with `.then()` on Promises. As a result, we end up needing a brand check of some kind which a custom iterator like `{ next() { ... } }` wouldn't have. [15:51:43.0883] that wouldn't be any different than the current proposal which just checks the [[Prototype]] - it's not a brand check if it's based on a public property. [15:52:15.0471] > <@rbuckton:matrix.org> Most custom "Iterators" I've seen are just `{ next() { ... }, [Symbol.iterator]() { return this; } }`. i agree, but why would those use Iterator Helper methods without being passed through `Iterator.from` first? [15:52:36.0703] Honestly I wish we'd left IteratorPrototype alone and had adopted a chainable wrapper object over Iterable, or just bare functions to work with `|>`, but we're probably already too far gone. [15:53:01.0718] i definitely do not want to argue about iterable vs iterator more [15:55:11.0971] > <@devsnek:matrix.org> i definitely do not want to argue about iterable vs iterator more I've never really changed my opinion, and the fact we're introducing an `Iterator.from()` that could have been an `Iterable.from()` (or some other name) that works over Iterables really reinforces that belief. [15:55:41.0087] as has been said many times, iterable isn't a thing. We don't have `Thenable.from` either. [15:56:04.0549] it's an adjective to describe the presence of a method. [15:56:13.0860] Iterable is a thing in the spec. Its an object with a `[Symbol.iterator]()` method. [15:56:15.0488] thats what an iterator is too [15:56:16.0623] iterators are kind of both, in that they're a thing and also a protocol [15:56:18.0309] its all a huge mess [15:56:25.0959] and yes, iterators are a mess [15:56:35.0857] Iterator.from always wrapping into a "Real" Iterator will help clean it up. [15:57:03.0941] (that built-in iterators all happen to be iterable isn't a part of the iterator contract, it's just a convenience these happen to have) [15:57:06.0034] According to the spec, a "Real" iterator is an object with a `next()` method that returns a `{ value, done }` object. [15:57:24.0839] The fact that built-in iterators happen to have a shared prototype doesn't matter to that definition. [15:57:41.0976] And the fact they have a shared prototype was always strange to me. [15:57:56.0504] js is indeed strange [15:58:49.0131] a real Promise is more than just a thenable. what i thought this proposal was doing was reifying a concept of a real iterator. [15:59:09.0794] TBH, I will almost never reach for iterator helpers when I could use a more fully-capable third-party library, which is the only reason I haven't pushed back harder against it. [16:00:01.0209] I don't think reifying `Iterator` will have anywhere near the impact that `Promise` did. At least, I certainly hope it doesn't. [16:00:23.0160] i think that it wouldn't on its own, but the iterator helpers themselves are why it will. [16:01:06.0542] i believe this proposal advancing will trigger a sea change in the way APIs are designed - everyone will start preferring lazy computation and passing around iterators instead of collections, which is a big shift from the current world where people tend to pass arrays. [16:05:33.0616] > <@ljharb:matrix.org> i believe this proposal advancing will trigger a sea change in the way APIs are designed - everyone will start preferring lazy computation and passing around iterators instead of collections, which is a big shift from the current world where people tend to pass arrays. I'm hoping it doesn't. It's the wrong abstraction. I hope it's relegated to the "I need to do this basic thing", and developers reach for the right abstraction for more complex scenarios. [16:08:06.0448] I honestly think that if `|>` had advanced more quickly we wouldn't be pursuing this at all. [16:08:54.0321] i really wish we could add things to the stdlib without every delegate being involved in every single decision of every function [16:09:18.0717] temporal achieved this by being large and complex [16:11:14.0165] > <@devsnek:matrix.org> i really wish we could add things to the stdlib without every delegate being involved in every single decision of every function This is a little more impactful than adding a single function though. [16:11:59.0066] everything is impactful in some way šŸ¤· [16:12:23.0715] and to be clear i didn't mean you specifically, i was just thinking about how this has been a proposal for like 3 years [16:12:43.0919] its depressing šŸ˜” [16:17:25.0820] in fairness it's mostly just that people pick it up and put it down [16:17:34.0935] it's advancing now because michael and I found time to get back to it [16:17:50.0431] not so much because of there being an insurmountable number of details [16:20:40.0858] Iterator helper methods _do_ only care about whether their receiver has a `next` method. But this is not at all the same kind of duck typing as with `.then` on promises, because it's on the _receiver_, not an arbitrary other thing; also nothing switches on its presence, just unconditionally attempts to call it. So it lacks the big two problems that thenables have, which are a.) consuming a string-named property on an _argument_, not just the receiver, and b.) changing behavior based on the presence or absence of the property instead of simply throwing in its absence [16:22:04.0627] > <@rbuckton:matrix.org> My original argument stems from my belief that Iterator is still the wrong level of abstraction. But aside from that, if the iterator helper methods were to only care about whether the object had a `next()` then we would have the same kind of duck typing we get with `.then()` on Promises. As a result, we end up needing a brand check of some kind which a custom iterator like `{ next() { ... } }` wouldn't have. * Iterator helper methods _do_ only care about whether their receiver has a `next` method. But this is not at all the same kind of duck typing as with `.then` on promises, because it's on the _receiver_, not an arbitrary other thing; also nothing switches on its presence, just unconditionally attempts to call it. So it lacks the big two problems that thenables have, which are a.) consuming a string-named property on an _argument_, not just the receiver, and b.) changing behavior based on the presence or absence of the property instead of simply throwing in its absence [16:23:27.0109] on that note, ljharb should we maybe merge https://github.com/tc39/agendas/pull/1233 now, so delegates get a chance to review? we can always back it out if approval doesn't come through [16:23:35.0448] > <@devsnek:matrix.org> i definitely do not want to argue about iterable vs iterator more * on that note, ljharb should we maybe merge https://github.com/tc39/agendas/pull/1233 now, so delegates get a chance to review? we can always back it out if approval doesn't come through [16:24:42.0799] anyway, I do want to strongly affirm that iterator helpers are precisely the correct abstraction for what they are [16:26:22.0043] if the helpers consumed iterables they either a.) produce single-shot iterables, which would be weird and confusing or b.) produce reusable iterables, which would be weird and confusing for other reasons, i.e. https://stackoverflow.com/a/28513908 [16:27:49.0311] "iterator helpers" or some equivalent are a solution common to most mainstream languages - java, rust, scala, c++ (boost), scala - and they work well [16:28:17.0893] * if the helpers consumed iterables they either a.) produce single-shot iterables, which would be weird and confusing or b.) produce reusable iterables, which would be weird and confusing for other reasons, i.e. https://stackoverflow.com/a/28513908 [16:28:34.0737] this is not uncharted territory here [16:29:42.0581] and I do expect them to get wide adoption, for the same reason they get wide adoption in other languages: they are the right abstraction to express what you want in a wide variety of scenarios, namely single-shot deferred computation [16:29:54.0494] * and I do expect them to get wide adoption, for the same reason they get wide adoption in other languages: they are the right abstraction to express what you want in a wide variety of scenarios, namely single-shot deferred computation [16:45:52.0531] ES2015 established syntactic support for Iterable with `for..of` and `yield*`, even "one-shot" Iterables with generators. The only reason iterator helpers can be used with these constructs is that they are also "one-shot" Iterables. The languages you've referenced with a preference for iterator's are all statically typed. A function can receive an iterator and *know* its an iterator. [16:47:29.0135] In JS, we are left with either "duck typing" or checking @@iterator. If @ljharb is correct, an ecosystem will be built around *receiving* iterators as well as producing them. And those functions may also need to check the input type. [16:48:59.0688] Since the ecosystem likes to write overloads, they need some way to check if the input is an Iterator. `next()` is not sufficient. It *is* Promise.p.then() all over again, even if it's a smaller case. [16:50:09.0458] Today the best way to do that overload check is to check for @@iterator, making the check for an Iterable. That at least still works for iterator helpers, but not for user defined `{ next() {}}`. [16:51:41.0504] all iterators are also iterables [16:51:44.0749] i think checking for `@@iterator` is fine [16:51:49.0704] * i think checking for `@@iterator` is fine [16:51:59.0948] Maybe a reified Iterator helps, but it is still just a "one-shot" Iterable as far as `for-of`, `yield*`, `[...iter]`, etc. are concerned. [16:52:29.0847] I do not expect there to be an ecosystem built around receiving iterators. why would there be? you can receive an iterable and consume it only once, and that works just as well. [16:52:36.0206] as for "passing iterators around" that would be interesting i guess, though i don't imagine it becoming that common [16:52:40.0504] looking at other languages like rust [16:52:43.0460] > <@devsnek:matrix.org> all iterators are also iterables This is false. All built-in iterators and generators, maybe. But not "all". [16:53:06.0110] yes you're right, all the ones that inherit from the prototype [16:53:15.0051] > <@devsnek:matrix.org> as for "passing iterators around" that would be interesting i guess, though i don't imagine it becoming that common This is exactly what @ljharb was describing earlier [16:53:27.0160] yeah i don't agree with the prediction [16:55:12.0348] but either way i don't think it is too problematic [16:57:08.0220] if the only way to know if something is an iterator is to consume it, then everyone will have to Iterator.from(x).map(x=>x) to be sure theyā€™re dealing with one. so why not build that into Iterator.from? [16:57:22.0194] the `.map` is not necessary [16:57:25.0171] it does nothing 2022-09-06 [17:08:22.0085] > <@devsnek:matrix.org> yeah i don't agree with the prediction I'd be more inclined to agree if we weren't making it so convenient. If these were just additions to built-in iterators and *maybe* generators, I'd be less concerned. Introducing a global `Iterator` and an adapter like `Iterator.from` feels more like TC39 blessing this as "the way", which I'm not comfortable with. [17:13:09.0883] Augmenting IteratorPrototype and making it easier to reach for just feels like another opportunity for Array.prototype-like patching that we've been dealing with for years, especially if people start feeling like the helpers available aren't comprehensive enough. [17:13:24.0232] * Augmenting IteratorPrototype and making it easier to reach for just feels like another opportunity for Array.prototype-like patching that we've been dealing with for years, especially if people start feeling like the helpers available aren't comprehensive enough. [17:18:03.0817] if pipeline moved forward [17:18:15.0836] i wouldn't be wholly against functions [17:18:27.0274] but without that there's no point even discussing it [17:59:24.0343] As much as I still prefer F#-style, if pipeline could settle on a topic I'd be happy. [18:01:47.0850] > <@devsnek:matrix.org> temporal achieved this by being large and complex Temporal is amazing for constructing date, time, and tz info. Its API for comparing dates/times is unfortunately ungainly since there's no mechanism for operator overloading, and the fact that `.now()` is detached into its own thing is exceedingly frustrating the times I've used it. [18:02:05.0624] It's like 10 steps forward and 5 steps back [18:05:52.0203] Determining whether an `Instant` occurs in the past is painfully verbose: ```js Temporal.Instant.compare(instant, Temporal.Now.instant()) < 0 ``` But it seems like the API design is very focused on "only one way to do it", regardless of convenience. [18:09:15.0350] I don't like `Temporal.Now` either! but it's always been a hard requirement from the plenary AFAIU [18:09:22.0262] * I don't like `Temporal.Now` either! but it's always been a hard requirement from the plenary AFAIU [18:14:05.0561] > <@rbuckton:matrix.org> Determining whether an `Instant` occurs in the past is painfully verbose: > ```js > Temporal.Instant.compare(instant, Temporal.Now.instant()) < 0 > ``` > But it seems like the API design is very focused on "only one way to do it", regardless of convenience. I hope nothing I've said caused you to get this impression; eliminating multiple ways to achieve the same thing is not something we've spent time on at all! there's no idiomatic `isBefore` / `isAfter` method because we had to draw the line somewhere [18:14:53.0819] you may want to subscribe to https://github.com/js-temporal/proposal-temporal-v2/issues/6 [18:14:56.0874] its interesting that `compare` is not an instance method [18:15:12.0543] I think a more general `compareTo` is better. [18:15:23.0916] > <@devsnek:matrix.org> its interesting that `compare` is not an instance method Its good as a static method for use with `.sort()` [18:15:34.0865] but either way i'm fine with this, people who care deeply about temporal apis are already working on this as has been linked šŸ˜„ [18:16:04.0939] > <@pchimento:igalia.com> you may want to subscribe to https://github.com/js-temporal/proposal-temporal-v2/issues/6 IIRC I commented on a thread about this in the proposal repo at one point [18:17:04.0236] > <@rbuckton:matrix.org> Its good as a static method for use with `.sort()` yeah personally i'd say just write an arrow function [18:17:07.0099] but this is the sort of thing [18:17:07.0859] Or maybe it was in matrix. I can't find the issue. [18:17:13.0052] i much prefer it existing at all [18:17:19.0648] to it going back and forth based on my opinion [18:17:23.0558] so šŸ¤· [18:20:56.0165] I really want to introduce generic comparison (not operators) at some point, i.e.: ```ts interface Equaler { equals(a, b): boolean; hashCode(x): number; } interface Comparer { compareTo(a, b): number; } ``` And allow you to pass an `Equaler` to a `Map`/`Set` constructor, and add things like a `SortedMap`/`StortedSet` like I put together in `@esfx/equaler`, `@esfx/collections-hashmap`, `@esfx/collections-hashset`, `@esfx/collections-stortedmap`, `@esfx/collections-sortedset` (which I wrote as a test bed to test out the implementation). [18:21:18.0850] * I really want to introduce generic comparison (not operators) at some point, i.e.: ```ts interface Equaler { equals(a, b): boolean; hashCode(x): number; } interface Comparer { compareTo(a, b): number; } ``` And allow you to pass an `Equaler` to a `Map`/`Set` constructor, and add things like a `SortedMap`/`StortedSet` like I put together in `@esfx/equaler`, `@esfx/collections-hashmap`, `@esfx/collections-hashset`, `@esfx/collections-stortedmap`, `@esfx/collections-sortedset` (which I wrote as a test bed to test out the implementation). [18:21:50.0708] I'd love to be able to have a `Map` whose keys are `URL` or `Temporal.Instant` without having to coerce to a string. [18:21:52.0384] Iā€™ve done similar work with only slightly different names. [18:22:31.0188] We had a relevant conversation about deep equality at the most recent SES meeting. [18:22:32.0399] > <@rbuckton:matrix.org> Augmenting IteratorPrototype and making it easier to reach for just feels like another opportunity for Array.prototype-like patching that we've been dealing with for years, especially if people start feeling like the helpers available aren't comprehensive enough. The patching of Array which we occasionally run into is almost entirely pre-ES6 libraries. People are not at all doing that these days, from what I can tell. So I don't really share this concern. Evangelism about not doing that worked, eventually, especially once we started actually adding useful stuff ever. [18:23:35.0006] SES meeting on deep equality, where we differentiate structural deep equality and deep equality protocols https://youtu.be/z_gXDSYKlWI [18:24:43.0638] Equality, hash, and compare protocols are in http://www.collectionsjs.com/ [18:25:35.0258] (CollectionsJS isnā€™t a viable project in its current form because I mispredicted some Array shims. Ooops.) [18:26:37.0919] `@esfx/equatable` has definitions for equality, comparability, structural equality, and structural comparability. [18:27:22.0987] Though my most recent npm publish (today) has a few issues I'm trying to fix. I just switched the hashCode generation to use native code on Node when possible and that's had some hiccups. [18:27:55.0960] * Though my most recent npm publish (today) has a few issues I'm trying to fix. I just switched the hashCode generation to use native code on Node when possible and that's had some hiccups. [18:28:00.0470] Adding protocols to the standard library probably means different Map and Set implementations or a very clever system for overloading their behavior. [18:29:30.0168] i really wish we had a `System.hash(v)` api [18:29:32.0363] Collections went the cheap route of random numbers and a weak map. It predates intrinsic Map and Set, so there it does some odd stuff. But, not surfacing information divined from pointers is important. [18:29:36.0391] so we could write our own collections [18:30:16.0110] Agreed. `@esfx/equatable` exposes a `rawHash(v)` API which is essentially the same. [18:30:34.0325] does that hash structurally or based on js identity [18:30:42.0224] I don't use pointers, I use the same hash identity that V8 uses for objects as keys in a map. [18:30:49.0614] JS identity. [18:30:54.0665] oh its a native fn? [18:31:02.0983] Yeah, I suspect thatā€™s still a side channel. [18:31:40.0973] feel free to `delete System.hash` :P [18:31:46.0954] > <@devsnek:matrix.org> oh its a native fn? When I can get away with it, yeah. Otherwise its a WeakMap and a random number as a fallback. [18:31:55.0386] oh nice [18:31:59.0567] that's basically how v8 works anyway [18:32:05.0430] well not a weakmap but random numbers yes [18:32:15.0268] At least, as soon as I finish wrangling breaking changes in my monorepo [18:35:53.0499] > <@kriskowal:matrix.org> Yeah, I suspect thatā€™s still a side channel. thinking about this more i don't think hash is a side channel [18:36:28.0684] you can't communicate with it [18:37:11.0461] as long as it's mixed with an actually random number [18:37:33.0454] i think every js engine that cares about this sort of thing does that anyway [18:37:36.0878] due to hash collision attacks [18:37:51.0016] * i think every js engine that cares about this sort of thing does that anyway [18:38:26.0122] yeah and because getting the address of an object in memory is one gadget which is used as a step in a lot of exploits [18:38:37.0323] oh right yeah do not use the address lmao [18:39:03.0157] I suspect none of the major engines would do it but if were were adding something like this we'd need to have a big loud note about including a good random value as a component [18:39:27.0054] i hear 4 is a great random number [18:39:27.0258] and it would be another source of nondeterminism, which... we should figure out a better story about adding those in general [18:41:27.0745] hmmmmmmMMMMMM [18:41:36.0801] actually no i'm dumb [18:41:58.0533] i was gonna say "does the hash actually have to be a transparent value" and then i realized how useless it would be if it was opaque lul [18:42:25.0347] * i was gonna say "does the hash actually have to be a transparent value" and then i realized how useless it would be if it was opaque lul [18:47:54.0717] It needs to be a number value (preferably uint32) to bucketize things efficiently. [19:15:06.0739] for the constraints of js i think it *must* be in u32 range otherwise you can't modulo it [19:15:26.0966] or bitwise it [19:19:51.0324] and u64 is outside the range of allowable array indices [19:32:13.0927] ok, I *think* I fixed my breaking changes. `@esfx/equatable` defines the following: - `Equatable` - A "protocol" involving two symbol-named methods (`[Equatable.equals](other)` and `[Equatable.hash]()`) indicating an object defines its own equality mechanism. - `Comparable` - A "protocol" involving one symbol-named method (`[Comparable.compareTo](other)`) indicating an object defines its own comparability mechanism. - `StructuralEquatable` - A "protocol" for `[StructuralEquatable.structuralEquals](other, equaler)` and `[StructuralEquatable.structuralHash](equaler)` - `StructuralComparable` - A "protocol" for `[StructuralComparable.structuralCompareTo(other, comparer)`. - `Equaler` - An "interface" describing an object with `{ equals(a, b), hash(x) }` methods, as well as a namespace object with default implementations (`defaultEqualer`, `structuralEqualer`, `tupleEqualer` (actually compares arrays), `tupleStructuralEqualer`), a `create` helper method to create an `Equaler` from callbacks, and a `combineHashes` function to help with complex hashCode construction (via bit shifting and XOR). - `Comparer` - An "interface" describing an object with `{ compare(a, b) }` methods, as well as a namespace object with default implementations (`defaultComparer`, `structuralComparer`, `tupleComparer`, and `tupleStructuralComparer`). There's also a `@esfx/equatable-shim` package that shims the `Equatable` and `Comparable` interfaces onto built-ins (and all of those methods are symbol-named, so no issues like with `.flatten`, etc.) [19:33:54.0166] The CollectionsJS deep equality protocol carried an ibid map to break cycles and allowed an override for the contentEquals of the children. [19:33:55.0287] I use the equality and comparison interfaces pretty heavily in the `@esfx/collections-*` packages as well as the `@esfx/iter-*` and `@esfx/async-iter-*` packages. [19:34:43.0658] Mine doesn't do ad-hoc structural equality, but rather expects something that would be structurally equal to something else to explicitly implement that structural equality. [19:35:35.0920] I haven't had much cause to use that part though, about 99% of my use cases have been shallow equality via custom `Equaler` and `Comparer` objects. [19:38:31.0409] If I were to propose to TC39, I'd primarily focus on Equaler (`{ equals(a, b), hash(x) }`) and Comparer (`{ compare(a, b) }`) support in collection classes, default implementations of each that would align with existing behavior in Map and Set for keys, and a `hash` function reachable from somewhere (even if it's just `Equaler.defaultEqualer.hash`). [19:40:29.0285] After that, maybe `Symbol.equals`, `Symbol.hash`, and `Symbol.compareTo` to hook equality and comparability on an instance. But at no point would any of that affect relational operators like `==`, `>`, etc. (overloading would be far out of scope). [20:44:30.0935] Doesnā€™t it return an iterator instance that has the slots of a generator? [20:58:47.0361] not exactly? it returns an iterator instance that has the slots of an _iterator helper_ [20:58:52.0425] which is not the same thing as a generator [21:00:04.0918] like you can't `(function*(){})().next.call(that helper thing)`; that will not work [21:00:28.0431] * like you can't `(function*(){})().next.call(that helper thing)`; that will not work [21:01:44.0007] I guess to be precise, the way it's written down it does have the same slots as a generator, but that's not actually observable by anything, just an editorial convenience [21:05:42.0315] anyway it is probably easier to talk about this in terms of observable behavior. there is very little observable difference between `Iterator.from(x)` and `Iterator.from(x).map(a => a)`. if there is a specific difference in observable behavior between the two you are worried about, post a code snippet and I can tell you what it does? 2022-09-08 [20:25:53.0587] ljharb: re https://github.com/tc39/ecma262/issues/404, I just read the original issue description again and saw you were asking about being able to write specifically `a < b`, which ecmarkup doesn't support even with https://github.com/tc39/ecmarkup/pull/481 - `<` and `&` are specifically excluded so that HTML parsers still work. Would you consider https://github.com/tc39/ecma262/pull/2901 to close [#404](https://github.com/tc39/ecma262/issues/404) or should I leave it open? [20:38:03.0484] i think itā€™s fine to go with best effort here [20:43:38.0190] I forgot: Before StageĀ 3, are champions supposed to reach out to multiple editors to get a sign-off for StageĀ 3? proposal-array-from-async has two reviewers, and one of them is an editor, but I donā€™t remember how to fulfill the criterion that ā€œall ECMAScript editors have signed off on the current spec textā€. [20:44:09.0088] as a rule, yes, if you want editors to review you should ping us [20:45:32.0389] Dang, that was my bad, then. So itā€™s probably too late to request StageĀ 3 for next week, and I probably should delay to Novemberā€¦ [20:48:12.0691] eh, we do pretty often advance things to "stage 3 pending editor review" or something like that [20:48:21.0387] fromAsync is simple enough that it's probably fine [21:38:52.0446] * Dang, that was my bad, then. So itā€™s probably too late to request StageĀ 3 for next week, and I probably should delay to November? [21:38:58.0049] Alright, sounds good, thanks. [03:16:11.0226] process proposal: let's switch to hedgedoc/hackmd for notes instead of gdocs so we could just write markdown and publish on github without having to convert formats [03:16:16.0654] * process proposal: let's switch to hedgedoc/hackmd for notes instead of gdocs so we could just write markdown and publish on github without having to convert formats [10:51:39.0763] for the folks who attended the incubator call today, the transcription is up [10:51:42.0782] it's not too bad! [10:51:53.0178] still needs a human touch obviously but slightly better than i thought [11:00:01.0124] how is it better than the plenary autotranscription if they both use google technology? [11:24:43.0582] if nothing else it's able to do attribution [11:26:28.0482] but I think the main thing was just that everyone had an accent the bot could handle; the biggest struggle for the bot is non-native accents [11:27:11.0103] oh yeah, I was literally just wondering that, most of the attendees had North American accents [11:31:44.0116] it's probably also slightly delayed? [11:31:49.0940] it wasn't live, i just got a doc at the end [11:40:03.0586] that is also part of it yeah [11:41:04.0633] the API actually gives me both "in progress" and "finalized" events, but the finalized events are often ~20-30 seconds delayed from the start of the vocalization they're transcribing, which I found is too long to try to edit in real time [11:41:16.0754] so I am using the less-good "in progress" events [11:41:41.0725] * the API actually gives me both "in progress" and "finalized" events, but the finalized events are often ~20-30 seconds delayed from the start of the vocalization they're transcribing, which I found is too long to try to edit in real time [11:42:04.0459] (they're not that different, though. a word or two here and there.) [13:21:19.0309] > <@jschoi:matrix.org> Dang, that was my bad, then. So itā€™s probably too late to request StageĀ 3 for next week, and I probably should delay to November? I was also hoping to get to Stage 3 for resource management, but I haven't heard back from my reviewers. [13:25:48.0978] Is there an easy way to @-mention the editors in a tc39 repo? I see groups for chairs, and ecma402-editors, but not for ecma262 editors. [13:38:17.0847] thereā€™s an editors group but Iā€™m not sure if itā€™s referencable by others, Iā€™ll look into it [13:38:38.0683] rbuckton: there was a lot of material given right at the deadline, it's not procedurally an issue of course but i'm personally not likely to have the time to give it a full review. still trying for a best effort [13:38:47.0685] * rbuckton: there was a lot of material given right at the deadline, it's not procedurally an issue of course but i'm personally not likely to have the time to give it a full review. still trying for a best effort [13:49:33.0410] > <@shuyuguo:matrix.org> rbuckton: there was a lot of material given right at the deadline, it's not procedurally an issue of course but i'm personally not likely to have the time to give it a full review. still trying for a best effort I appreciate what time you can take, thanks. [16:15:21.0456] bakkot: When looking at your Set methods presentation for next week (https://docs.google.com/presentation/d/1HCqPMsWiTtsn92gA3b1luVpnVHWVVR0iKaAE0marxkA/edit#slide=id.g13a69787e9f\_0\_0), Iā€™m starting to wonder is why we excluded Set.union, Set.intersection, etc. as static methods rather than instance methods. Why were static methods excluded, again? [16:15:36.0716] * bakkot: When looking at your Set methods presentation for next week (https://docs.google.com/presentation/d/1HCqPMsWiTtsn92gA3b1luVpnVHWVVR0iKaAE0marxkA/edit#slide=id.g13a69787e9f\_0\_0), Iā€™m starting to wonder is why we excluded Set.union, Set.intersection, etc. as static methods. Why were these excluded, again? [16:15:41.0878] I donā€™t see mentions of this option in the previous Set methods presentations. Static methods might be able to sidestep the issues with the ā€œ`this` Set uses internal slots and argument Sets use a symbol-based public APIā€ approach. The only discussion I can find about the static-methods option is in https://github.com/tc39/proposal-set-methods/issues/1, and I donā€™t really see any compelling reasoning against static methods given in there. [16:15:45.0471] * I donā€™t see much about this option in the previous Set methods presentations. It may be able to sidestep a lot of the issues with the ā€œ`this` Set uses internal slots and argument Sets use symbol-based public APIā€. The only discussion I can find about this is in https://github.com/tc39/proposal-set-methods/issues/1, and I donā€™t really see any compelling reasoning given in there. [16:16:05.0329] * bakkot: When looking at your Set methods presentation for next week (https://docs.google.com/presentation/d/1HCqPMsWiTtsn92gA3b1luVpnVHWVVR0iKaAE0marxkA/edit#slide=id.g13a69787e9f\_0\_0), Iā€™m starting to wonder is why we excluded Set.union, Set.intersection, etc. as static methods rather than instance methods. Why were static methods excluded, again? [16:16:39.0006] * I donā€™t see much about this option in the previous Set methods presentations. It might be able to sidestep the issues with the ā€œ`this` Set uses internal slots and argument Sets use symbol-based public APIā€ approach. The only discussion I can find about this is in https://github.com/tc39/proposal-set-methods/issues/1, and I donā€™t really see any compelling reasoning given in there. [16:16:55.0229] * I donā€™t see much about this option in the previous Set methods presentations. It might be able to sidestep the issues with the ā€œ`this` Set uses internal slots and argument Sets use symbol-based public APIā€ approach. The only discussion I can find about the static-methods option is in https://github.com/tc39/proposal-set-methods/issues/1, and I donā€™t really see any compelling reasoning against static methods given in there. [16:17:43.0906] * I donā€™t see mentions of this option in the previous Set methods presentations. Static methods might be able to sidestep the issues with the ā€œ`this` Set uses internal slots and argument Sets use a symbol-based public APIā€ approach. The only discussion I can find about the static-methods option is in https://github.com/tc39/proposal-set-methods/issues/1, and I donā€™t really see any compelling reasoning against static methods given in there. 2022-09-09 [06:01:01.0477] ryzokuken: I'm seeing a "you need permission" page when I try to fill out the in-person attendance form for the A CoruƱa meeting [06:01:17.0606] ah, shucks. Let me fix that. [06:57:37.0356] btw, thanks for the reminder dminor [06:57:58.0897] ICYMI: Next meeting info just dropped: https://github.com/tc39/Reflector/issues/446 [06:58:17.0021] please check it out and fill the signup form if you plan to attend at your earliest convenience, thanks! [10:57:49.0363] The doodle link on the 93rd Meeting reflector thread doesn't work [11:07:48.0710] A CoruƱa is lovely. My brother-in-law married a Galecian and their wedding was there. Be sure to take the time for a long walk around the shoreline if youā€™re visiting! 2022-09-10 [00:04:43.0838] could someone fill out the missing date/time info on the reflector post [00:04:45.0057] https://gc.gy/130498461.png [00:05:19.0822] well i guess the only thing really missing is the timezone, everything else can be inferred [01:31:57.0158] Thanks Gus - all fixed now. [01:44:47.0389] Next week's plenary is on the Tokyo JST timezone. That means the start time of 10am on Tuesday in Tokyo corresponds to: - Monday 6pm in Seattle (PT) - Monday 9pm in New York (ET) - Tuesday 2am in London (BST) - Tuesday 3am in Berlin (CET) - Tuesday 6:30am in Bengalaru (IST) - Tuesday 9am in Shanghai (CST) [01:46:09.0220] JST stands for "JavaScript Time" [01:49:16.0748] It's always JavaScript time ;-) [10:27:56.0374] javascript space telescope 2022-09-12 [00:48:39.0487] > <@jschoi:matrix.org> I donā€™t see mentions of this option in the previous Set methods presentations. Static methods might be able to sidestep the issues with the ā€œ`this` Set uses internal slots and argument Sets use a symbol-based public APIā€ approach. > > The only discussion I can find about the static-methods option is in https://github.com/tc39/proposal-set-methods/issues/1, and I donā€™t really see any compelling reasoning against static methods given in there. it does not sidestep the issue - the fundamental problem is "how do you get the data from a Set which you take as an argument", and taking two Sets as arguments instead of one doesn't help [00:51:44.0459] ignoring that and considering only questions of design, instance methods seem much more natural to me? that's how it works in Java/rust/etc also [00:51:48.0360] * ignoring that and considering only questions of design, instance methods seem much more natural to me? that's how it works in Java/rust/etc also [07:57:11.0128] hi delegates! the draft schedule has been linked from the reflector. [10:08:17.0252] rbuckton: Yo, in your Resource Management slides, it appears that slide 2 has several smaller slides embedded into it? These are *unreadably* small, fyi. It looks like they're actually meaningful to explaining the proposal motivations, tho, so you might want to format this differently. [10:12:56.0144] You can click into them for the full slide (in PowerPoint, at least) [10:18:21.0557] Can't do that on the web, and not willing to install a new office suite just to read slides. [10:20:36.0474] (And I'd hazard that a pretty small fraction of delegates are going to do so either, even if they *have* Powerpoint, since it involves downloading the file and loading them up in a new program.) So optimizing for web display seems prudent, imo. [10:32:00.0568] The slides are also present at the end of the deck as "Backup Slides", which seem to be visible in the web viewer. [10:32:28.0066] Ah, I suspected that might be the case, since the web viewer stops 6 slides from the end and won't show me those final ones. ^_^ [10:34:30.0999] (iow, I can get to slide 32 of 38 in the web viewer, but the Next button doesn't take me past that point) [10:35:03.0896] I'm not in a position to make any changes to the deck at the moment, so hopefully that workaround suffices. [10:36:01.0181] It doesn't, as I said. But you have a few days before the presentation anyway, so I hope it'll be fixed by then. (Hopefully by inlining the slides where they are meant to be displayed, as I assume you'll be showing those slides at that point in the presentation anyway.) 2022-09-13 [18:04:18.0540] i'm confused, i don't hear any audio coming out of jitsi (but i do hear jitsi sound effects) but i see the notes transcribing things [18:04:27.0323] * i'm confused, i don't hear any audio coming out of jitsi (but i do hear jitsi sound effects( but i see the notes transcribing things [18:04:30.0014] * i'm confused, i don't hear any audio coming out of jitsi (but i do hear jitsi sound effects) but i see the notes transcribing things [18:04:45.0769] maybe try refreshing? I hear audio [18:04:53.0557] rejoining didn't seem to help, i'll try force quitting the app and reopening it [18:05:13.0532] still nothing [18:05:26.0926] did you mute the tab? [18:05:42.0668] it's not a tab, it's the native iPad app i've used every other time [18:05:47.0148] ah, hm [18:05:59.0095] note that this isn't 8x8, it's Igalia's server [18:06:31.0751] ah, i thought igalia's server didn't work for us multiple times. either way i'm connected to it and it's not sending me audio :-( [18:06:58.0685] ljharb: I've had that issue and reconnecting to the meeting fixed it [18:07:03.0566] Igalia updated its Jitsi instance; I think it worked well after that (just not from Google's room). Maybe try joining via the browser if your app doesn't work? [18:07:09.0421] i've already tried that twice; i'll try one more time [18:08:08.0782] i do hear it through the web (a third try on the app didn't work) [18:08:22.0864] * i do hear it through the web (a third try on the app didn't work) [18:08:37.0191] why aren't we using 8x8? [18:09:05.0055] what's the difference between them? jitsi version? [18:09:11.0121] > <@littledan:matrix.org> Igalia updated its Jitsi instance; I think it worked well after that (just not from Google's room). Maybe try joining via the browser if your app doesn't work? yeah, the reason we switched to meet in the last meeting was because the room was set up to work with meet [18:09:42.0538] right, but we used the 8x8 for jitsi the last year or two, no? [18:10:11.0017] we had issues with it a few meetings ago [18:11:38.0752] there's a general jtsii app, it's just a different app from the 8x8 app [18:14:16.0081] the one i use is called "Jitsi Meet", which is from 8x8 - i'm not aware of another ipad-compatible jitsi app (altho maybe the search results are drowned out by keyword spam) [18:14:35.0384] it's worked fine since we started using jitsi, until now :-/ [18:14:38.0027] OK, yes, Jitsi Meet worked for me in the past with Igalia's servers [18:14:38.0079] * it's worked fine since we started using jitsi, until now :-/ [18:14:47.0672] yeah same, so i'm confused why it wouldn't be working now [18:15:16.0767] Jitsi Meet _should_ ideally work with our servers, but I have to admit that I just use the browser, even when connecting on my phone [18:16:03.0214] > <@michaelficarra:matrix.org> what's the difference between them? jitsi version? yeah I think the 8x8 servers were configured in too underpowered of a way [18:16:54.0956] Did I miss an announcement explaining why we donĀ“t have a professional stenographer this time? I thought that was the plan. [18:17:14.0876] Bradford Smith: I've submitted a request, and will be raising it at the ExeCom meeting in three weeks [18:17:21.0893] ah, thx [18:34:18.0022] Huh? What is this hardcoded logic, and why can't those people sign the form? [18:36:11.0005] littledan: ask ljharb for details [18:36:17.0732] it's for existing commits in the repo, though [18:36:19.0534] not for new PRs [18:36:51.0751] Please add your name, abbreviation and organization to the top of today's notes. [18:37:04.0543] yeah, when I started the IPR form I went back and solicited signatures for past contributors who I couldn't find IPR documentation of; sounds like it's time to do that exercise again [18:37:09.0196] I believe it's people who contributed long ago and aren't visibly marked as delegates on Github? something like that [18:37:33.0558] (everyone agreed to sign this form except Domenic; we still lack a paper trail for the Promise spec IPR) [18:39:28.0166] littledan: yes, i've started to do that, but they're hard to track down [18:39:38.0980] ah great, I appreciate that! [18:39:59.0407] feel free to reach out as well; it's an array or Set or something called "exceptions" in the script [18:40:23.0657] yeah could you link to that in the source, so I could help? [18:41:48.0469] https://github.com/tc39/ecma262/blob/main/scripts/check-form.js#L162-L202 [18:42:59.0797] this is so much better! [18:43:28.0393] dodged a bullet accepting "all truthy strings" [18:48:35.0346] ^ this is the sort of thing TG1 can help with I think [18:50:23.0921] yes, 100% [18:50:47.0728] i think chip's and my comments are directed at the actual domain-specific i18n stuff [18:50:51.0225] TG1? [18:50:58.0767] plenary [18:56:47.0955] could one of the DurationFormat people update the conclusion with a precise list of the things we just gave consensus for? [18:56:56.0992] will do [18:56:58.0258] I don't like having just "consensus for presented changes" but don't have time to fix it up [18:57:00.0136] thanks! [18:57:32.0682] I'm wondering, is DurationFormat "shippable"? Do we anticipate further changes? [18:58:16.0146] littledan: I believe so, but I can do a quick triage and let you know precisely. [18:59:14.0682] Great news! If so, maybe announce this specifically to the committee in a follow-on topic if there's time, since that wasn't quite clear so far? This is a nice conclusion to a string of fix-up presentations. [19:01:53.0375] Great news on the RFC side for Temporal. If we have consensus among the relevant parties for moving forward on this, I'm not sure we need to wait for formal publication before shipping this in browsers. (Isn't the IETF all about running code?) [19:06:43.0118] oh no, why is a string of eight digits a valid calendar name [19:07:51.0539] have you read the temporal 8601 grammar [19:08:12.0816] if I have I presumably wiped that from my memory after reading [19:08:20.0608] it makes me throw up a little in my mouth every time [19:08:28.0603] we did not invent formal grammar for this [19:08:40.0030] * we did not invent formal grammar for this [19:10:40.0985] hello everyone [19:16:24.0496] Is there an issue for this frozen calendar topic? [19:16:34.0602] I just noticed we adopted the agenda with this PR open: https://github.com/tc39/agendas/pull/1252 [19:17:03.0399] is that presenter in here? should we amend the agenda? [19:17:13.0148] (FWIW I'm skeptical of using frozen intrinsic objects here; I was pushing against custom calendars exactly because this sort of thing is likely infeasible) [19:18:13.0013] I don't understand the motivation for what Jordan is talking about; maybe this could be filed as an issue? [19:19:22.0239] +1 to Philip's point about the critical flag [19:20:00.0305] fwiw, this interpretation of the flag is also shared by the folks at IETF [19:21:54.0196] also note that there are other sorts of normalization around the spec, e.g., in Intl locales [19:22:05.0809] this seems analogous [19:23:22.0478] Yay Justin's back!!! [19:23:31.0238] ljharb: AFAIU the crux of the argument is that Temporal objects are not meant for interchange, and that they are already lossy wrt some input [19:23:46.0890] can presenter or someone capture what we did and did not get consensus for on the notes? [19:23:49.0565] * can presenter or someone capture what we did and did not get consensus for on the notes? [19:24:11.0552] I can [19:24:12.0974] https://github.com/tc39/proposal-temporal/issues/2403 is the issue [19:24:23.0381] i also understand there to be that there's no implication of the form "critical annotation implies serialized for further interchange" [19:24:29.0212] that doesn't sound like a compelling argument to add more lossiness [19:24:43.0811] but this isn't more lossiness [19:24:56.0340] this is just existing lossiness (lossiness via toString) [19:25:35.0084] the toString part is i think a separate item; i'm saying that i would expect/hope that Temporal could parse a string and give me sufficient info about what was in that string [19:25:51.0077] and my understanding is that that was never the case and won't be the case [19:26:04.0118] because of what frank was saying about "ignorable brackets" [19:26:22.0722] i understand the ignorable annotation stuff would be lost [19:26:24.0313] I think you might be misunderstanding the purpose of the critical flag here. It's just not relevant for Temporal [19:26:36.0333] yeah i'd like to understand your use case jordan [19:26:52.0721] i don't have a use case in mind - i just learned about this flag 20 minutes ago [19:27:10.0502] but it seems shortsighted to throw out data gathered during a difficult parse [19:27:10.0553] but you have a position -- that this be preserved for toString, what's the motivation for that position [19:27:32.0759] i only mildly care about preserving it in toString - i think it's important to have a way to get it from the object [19:27:37.0205] that doesn't follow for me, i don't see why that's shortsighted when other stuff is already thrown out? [19:27:42.0153] like `parsed.isCritical` or something [19:28:06.0627] yeah but _why_ [19:28:08.0479] "some stuff is thrown out so it's fine to throw anything else out" is a slippery slope argument. [19:28:28.0210] because it was in the string, and per the slide, "some consumers may care about it" [19:28:41.0913] if somebody cares about it then it seems important to preserve. if nobody cares about it then why support it at all [19:28:44.0795] yes, but _not_ via an instantiated Temporal object! [19:28:47.0111] * if somebody cares about it then it seems important to preserve. if nobody cares about it then why support it at all [19:28:57.0223] the consumer IS the temporal object, the code instantiating the temporal object [19:29:04.0975] I think the intention of the RFC _is_ that the flag is thrown out when parsed; it just says "do not ignore this annotation when you parse it"; and Temporal doesn't ignore it [19:29:05.0198] not the users of the instantiated object [19:29:19.0861] > <@pchimento:igalia.com> I think the intention of the RFC _is_ that the flag is thrown out when parsed; it just says "do not ignore this annotation when you parse it"; and Temporal doesn't ignore it right, exactly [19:29:39.0774] like does this come down to how it's called "Critical" [19:29:47.0806] what if it wasn't that, and was "Temporal parser don't ignore" [19:29:50.0028] err [19:29:57.0553] * what if it wasn't that, and was "Temporal parser don't ignore" [19:30:11.0089] lol but it's in an IETF standard. [19:30:22.0657] I would also be fine getting rid of the option to output it, for now šŸ˜„ [19:30:23.0772] let me rephrase [19:30:39.0385] > <@ljharb:matrix.org> lol but it's in an IETF standard. lots of IETF standards have things that get normalized out and don't need to be part of the post-parse representation [19:30:45.0018] what if "critical" had a very particular meaning in the IETF standard, and that meaning was "Temporal parser don't ignore" [19:30:46.0379] (e.g., locales, which we support) [19:31:09.0057] but temporal parser never ignores [19:31:12.0217] i understand that temporal doesn't do anything different based on the presence of the flag. and if nobody ever ends up with a use case where they need to know if the ! was present, then obviously it'd be fine. [19:31:20.0876] but that's only 1 of the 4 possible outcomes [19:31:26.0980] what i'm sensing is mainly there's more read into the "criticality" than what is actually meant [19:31:54.0184] by both IETF and the temporal champions [19:32:10.0382] either we have it, and it's needed; we have it, it's not needed; we don't have it, it's not needed; or we don't have it and it's needed. in 2 of those, everything's fine, in 1 of those, we have an extra unneeded bit on temporal instances, and in 1, somebody's use case is impossible [19:32:22.0009] is there a temporal channel or something we could take this to? I'd rather discuss the current topic here [19:32:22.0732] sigh [19:32:23.0803] why wouldn't we want to avoid the "it's impossible" outcome? [19:32:41.0775] * why wouldn't we want to avoid the "it's impossible" outcome? [19:33:08.0584] * either we have it, and it's needed; we have it, it's not needed; we don't have it, it's not needed; or we don't have it and it's needed. in 2 of those, everything's fine, in 1 of those, we have an extra unneeded bit on temporal instances, and in 1, somebody's use case is impossible [19:33:10.0928] anyway, for something that's supposed to be a function of only how the source text is formatted, only looking at raw sounds like the right idea [19:34:28.0145] what happened if called as function? [19:35:59.0479] IMO reusing ParseText seems better to avoid (unlikely) future mismatch [19:36:45.0188] > <@haxjs:matrix.org> what happened if called as function? Well, this is just a tagged string template; what's the question? [19:36:52.0406] I assume it will try to read `raw` prop ? what will happen if no `raw` prop? [19:36:56.0713] it will throw [19:37:03.0195] big lunch [19:37:26.0929] Sorry, I missed the time to reconvene? [19:37:36.0843] one hour and 23 minutes from now [19:37:44.0819] > <@bakkot:matrix.org> it will throw A little bit weird but maybe acceptable... [19:37:58.0285] don't all/most template tags behave like that? [19:38:01.0492] * don't all/most template tags behave like that? [19:38:07.0719] a lot of template tags only care about the cooked code [19:38:11.0035] ah k [19:38:12.0249] so no, it's somewhat unusual [19:38:13.0810] but only somewhat [19:38:24.0295] mostly they're not built to be used as functions directly [19:38:36.0742] but I'm going to do that until we have a way to dedent a non-source-text string [19:39:06.0723] which will be slightly awkward now because I have to escape `\`s to prevent them getting cooked before passing them [19:39:08.0035] but whatever [19:39:28.0057] I asked that because JSCIG discussed this proposal and someone asked that. Not sure everyone happy with throwing. [19:39:38.0075] see https://github.com/tc39/proposal-string-dedent/issues/45 for the "dedenting strings which are not source text" use case [19:39:59.0299] Justin Ridgewell: One thing I was going to ask if not for my terrible connection, is it seems odd that we respect the cooked value of some escaped characters(`\n`), but not others in this new proposal . Am I misunderstanding? [19:40:01.0248] HE Shi-Jun: do you know why they aren't happy with it? or can you ask? [19:40:37.0969] I think you're misunderstanding [19:40:52.0238] All escape sequences will be cooked, they're just cooked _after_ dedenting [19:41:24.0405] But `\n` has the following characters treated as if it were a newline, no? [19:41:33.0621] Is that true in all cooked strings? [19:42:09.0422] In the current implementation, it cooks first then dedents. [19:42:29.0858] > <@bakkot:matrix.org> HE Shi-Jun: do you know why they aren't happy with it? or can you ask? I will ask the question in the wechat group of JSCIG. [19:42:39.0417] So the `\n` turns into a newline, then dedenting finds the content after that as part of the common indentation calculation. [19:43:04.0523] In the PR, it calculates common indentation, dedents, then cooks the `\n` [19:43:32.0911] A `\x20` sequence would behave the same. [19:43:50.0553] Currently, cook first, then dedent (it only matters if it appears before any content chars) [19:43:57.0272] I looked at the slides again, and I see what I expect [19:43:58.0438] Proposed, dedent first, then cook [19:44:00.0146] My apologies [19:44:31.0189] My only concern is that we aren't special casing newlines [19:44:56.0203] Thanks for following up Justin [19:45:10.0293] i zoned out for a bit, are we coming back at 2100 PT? [19:45:30.0526] shu: yes [19:45:35.0635] thanks [19:45:40.0492] * shu: yes [19:46:16.0857] * My only concern was that we were special casing newlines [19:52:05.0831] Since this is my first meeting, I wanted to understand the protocol. The meetings can take _up to_ the four days, but only if the agenda takes us that long? [19:52:24.0127] the amount of stuff on the agenda waxes and wanes over the years [19:52:34.0332] the trend recently has been more undersubscription than oversubscription [19:52:45.0060] for most of TC39 i've attended in years past, we've often been quite stretched for time [19:52:47.0832] this agenda is especially short [19:53:15.0059] so yes, we have 4 days allotted, but may end early (i hope so!) [19:53:31.0836] Awesome, this is a tough schedule from CST [19:53:38.0718] it heavily depends on a lot of complicated factors... like timezones [19:55:11.0828] also some might've deferred their presentations in favor of giving it at the next meeting in person (and same with pulling forward for the last one). [19:55:27.0504] * also some might've deferred their presentations in favor of giving it at the next meeting in person (and same with pulling forward for the last one). [19:56:59.0034] Justin Ridgewell: what happens if you do ``String.dedent`\invalid```? [19:57:20.0414] ugh, markup. String.dedent but you use an invalid escape in the template. [19:58:00.0086] Currently, it would have `[undefined]` and `['\\invalid']` [19:58:24.0075] It should be the same after the PR [19:58:27.0675] (I hope) [19:59:13.0570] I mean when used as a tag directly, not when used as a wrapper for another tag [19:59:42.0743] that's reasonable behavior for passing to the wrapped tag, in the tag-wrapping case, but when used as a tag directly it gives you a string; what string does it give you? [19:59:56.0301] It throws as part of the `String.cooked` implementation [20:00:00.0426] ah great [20:00:14.0103] I could not find that in the spec text [20:00:14.0946] [`CookTemplateStringsArray`](https://tc39.es/proposal-string-dedent/#sec-cook-template-strings-array) [20:00:27.0543] oh, indeed, I see that [20:00:28.0980] 7.C [20:00:35.0149] seems like it should be a SyntaxError but otherwise yes good [20:57:25.0989] Justin Ridgewell: https://github.com/tc39/proposal-string-dedent/pull/67 [20:57:44.0510] We are resuming plenary in 2 mins! [21:03:37.0595] you can turn down the connection quality [21:21:43.0429] so we only have message, no error name? [21:22:05.0319] https://github.com/tc39/proposal-shadowrealm/pull/372/files#r966197227 [21:22:22.0656] that's the specific normative note that @littledan is referencing to. [21:23:37.0502] note, this isn't just Mathieu and me, Caridy proposed something sort of in between (not as concrete as I'd do it but I don't want to be too picky) [21:23:59.0959] IMO the `name` doesn't give you very much, but also it's not a big deal to make an observable Get [21:25:13.0849] Note, whether there's an observable Get, and whether the contents of the message are totally implementation-defined, are two separate questions [21:26:32.0445] My position is that it's simply overkill to avoid the Get; I think it'd be fine to use the approach Mathieu suggests, of first checking [[ErrorData]] and then doing GetOwnProperty and then using it only if it's a value [21:29:24.0861] > <@jridgewell:matrix.org> It throws as part of the `String.cooked` implementation wait why would this throw? tagged templates are allowed to have invalid escapes [21:30:15.0210] it's only for non-tagged [21:31:02.0696] when you use String.dedent to wrap a tagged template it doesn't throw [21:31:19.0821] but if you use it directly as a tag it should throw, because the original code would have thrown without `String.dedent` [21:34:51.0869] > <@bakkot:matrix.org> but if you use it directly as a tag it should throw, because the original code would have thrown without `String.dedent` I don't agree with this. Is there an issue I can comment on? [21:34:52.0225] ``` String.cooked`\invalid` ``` throws [21:35:25.0344] When you're concatting the values, it sees an `undefined`, and throws [21:35:26.0200] Michael Ficarra: what... would you want it to do [21:35:36.0149] would you want it to interpolate the string "undefined"? [21:35:41.0370] * Michael Ficarra: what... would you want it to do [21:35:56.0374] there is no issue for this because there is no other imaginable semantics, but you can make one to propose some other unimaginable semantics if you want [21:35:59.0436] cooked should still be undefined but raw should be dedented [21:36:04.0780] that's what it is [21:36:20.0736] but again, if you use it as a tag _directly_, there is no "cooked" vs "raw" distinction [21:36:24.0258] you get a string out, not an array [21:36:32.0972] and the string has to be a string [21:36:36.0871] So, ``` String.dedent`foo` ``` performs `String.cooked` internally, because it's the default tag implementation. [21:36:45.0419] Etherpad link? [21:37:00.0859] ``` String.dedent(String.raw)`\invalid` ``` wouldn't throw an error [21:37:03.0696] The notes link is in the Reflector [21:37:19.0079] the reflector link is in the channel topic [21:37:42.0607] * please don't post direct URLs in this logged public channel! * (reflector links are ok) [21:40:23.0020] * ``String.dedent(String.raw)`\invalid``` wouldn't throw an error, ``String.dedent(String.cooked)`\invalid``` would [21:40:32.0730] we should put that in the MOTD [21:40:40.0188] * ````String.dedent(String.raw)`\invalid``` wouldn't throw an error, ``` String.dedent(String.cooked)`\invalid` ``` would [21:41:04.0634] we should put it at the top of the reflector post in big red letters [21:41:19.0418] * ``` String.dedent(String.raw)`\invalid` ``` wouldn't throw an error, ``` String.dedent(String.cooked)`\invalid` ``` would [21:41:30.0333] we should do the twitch chat thing, every 60 seconds or so a bot posts a reminder here [21:42:09.0291] Twitch chat would just automod the link away before it propagates [21:43:25.0088] One thing I want to confirm, does `Reflect.get(#{x:1}, "x"` work or throw? I suppose it should throw? [21:43:37.0973] it works; why would it throw? [21:43:56.0829] (I assume anyway) [21:43:57.0860] if `#{x:1}.x` works then that should certainly work [21:44:02.0609] since they're the same operation [21:44:23.0833] If Reflect works, so new Proxy(#{x: 1}, {}) also works?? [21:45:12.0246] `{ __proto__: #{} }` doesn't work though [21:45:52.0809] hm, hax makes a good point [21:45:54.0648] ljharb: eh, "str"[0] works [21:46:09.0262] but `Reflect.get("str", 0)` does not [21:46:10.0756] yeah true [21:46:31.0658] > <@haxjs:matrix.org> If Reflect works, so new Proxy(#{x: 1}, {}) also works?? No, this would throw; Proxy targets need to be objects, not primitives [21:46:34.0012] Currently Reflect API throws for all primitives. [21:47:20.0373] it makes sense that Reflect shouldn't work for anything that can't be a Proxy target, since reflect's only supposed to be for proxy traps [21:47:21.0093] there was a somewhat detailed look into whether R&T could be Proxy targets, and Caridy noted that, given the Proxy invariants, this would not be remotely useful [21:47:40.0933] I think there is an open issue about which existing APIs should work [21:47:44.0333] it would be useful for observation, just not really changing the results [21:47:46.0345] which might have discussion of Reflect [21:48:12.0300] ljharb: IIRC the currently discussed issue was raised by you? [21:48:15.0067] the brand checking thing [21:48:19.0151] yes [21:48:21.0106] did you ever come up with a concrete use case? [21:48:35.0010] i haven't written anything up, no. [21:48:51.0076] one of them tho is for debugging, to be able to tell users what kind of value it is [21:49:21.0744] test frameworks, node, https://npmjs.com/object-inspect, etc all do similar things with existing boxed primitives [21:50:44.0917] I think there is a conflict, on one side, we might want record/tuple could be used as replace of object/array in most cases, on the other side, we need to keep consistency with current API design, and many APIs treat primitives/objects very different. [21:51:16.0770] i agree. R&T occupy a very weird space where they're conceptually both objects and primitives, so it's hard to know what the best tradeoffs are between DX and consistency and existing axioms [21:51:22.0232] * i agree. R&T occupy a very weird space where they're conceptually both objects and primitives [21:52:00.0962] i don't like this idea but i'm not entirely sure why [21:52:04.0125] * i agree. R&T occupy a very weird space where they're conceptually both objects and primitives, so it's hard to know what the best tradeoffs are between DX and consistency and existing axioms [21:52:58.0463] Another interesting case was raised in our JSCIG meeting, someone ask whether class { constructor() { return #{} } } works... [21:53:13.0487] shu: What Web API's for ShadowRealms do you have questions about Safari 16 supporting? [21:53:55.0227] HE Shi-Jun: might be worth raising on the queue [21:54:03.0337] msaboff: my question is 1) what part of ShadowRealms did Safari 16 ship, since web API integration isn't yet finished, 2) was it a mistake, as saam suggested on twitter [21:54:19.0226] ljharb: Did you end up developing a use case for the other issue we discussed, of the Record prototype? The current state of the proposal is still that Records have a null [[Prototype]] [21:54:34.0884] no, i haven't written anything up yet [21:54:36.0824] +1 to not calling `.join` [21:54:40.0286] that was always crazy [21:54:59.0415] > <@rricard:mozilla.org> HE Shi-Jun: might be worth raising on the queue can someone raise that? I am not sure my mic work because I use a different computer today [21:55:11.0304] one of very few places we defer to a method lookup by string [21:55:16.0971] ljharb: also feel free to bring up the debug use case in tcq [21:55:45.0203] > <@shuyuguo:matrix.org> msaboff: my question is 1) what part of ShadowRealms did Safari 16 ship, since web API integration isn't yet finished, 2) was it a mistake, as saam suggested on twitter msaboff: Do ShadowRealms in Safari 16 support any Web APIs at all? e.g., AbortController, TextEncoder [21:57:59.0809] also looks like undefined values are printed as "undefined", not empty [21:58:47.0408] > <@littledan:matrix.org> msaboff: Do ShadowRealms in Safari 16 support any Web APIs at all? e.g., AbortController, TextEncoder I do think the ShadowRealms we have support the Web APIs. [22:00:46.0711] Oh, that's a relief. So if the list of web APIs ends up matching (and I can't imagine what kind of semantic mismatch might exist), the only mismatch would be the error message semantics, which is unlikely to be much of a compatibility issue [22:00:55.0945] have we considered just not boxing these things even in sloppy mode [22:01:01.0742] how can you observe the stringification result of Symbol? [22:01:02.0615] that would be a weird divergence in sloppy mode [22:01:05.0744] > <@littledan:matrix.org> msaboff: Do ShadowRealms in Safari 16 support any Web APIs at all? e.g., AbortController, TextEncoder * I don't think the ShadowRealms we have support the Web APIs. [22:01:05.0772] littledan: is the list of web APIs finalized? [22:01:11.0892] like, the list Exposed=* stuff [22:01:15.0251] but you should not be in sloppy mode so I don't care if there are weird divergences [22:01:23.0172] * but you should not be in sloppy mode so I don't care if there are weird divergences [22:01:26.0283] I tried Object.prototype.toString, `"" + ...` and with Object wrapper for Symbol, they don't work [22:01:27.0476] shu: Yeah this has been stable for more than a month and is generally landed upstream [22:01:33.0985] okay, great [22:01:50.0975] Jack Works: String(Symbol()) [22:01:51.0249] shu: `#[0]` and `#[0n]` have the same toString [22:02:03.0100] > <@bakkot:matrix.org> have we considered just not boxing these things even in sloppy mode Yes, but it would break "Object(value) always returns an object" [22:02:11.0307] throw [22:02:12.0908] Michael Ficarra: right, thanks [22:02:14.0149] I guess [22:02:20.0051] or just make a copy instead of a wrapper [22:02:57.0378] * shu: `#[0]` and `#[0n]` have the same toString [22:03:40.0154] IMO we should decide on whether to introduce a brand check based on use cases today, rather than promises in the ES6 era [22:04:10.0532] the use cases remain the same. [22:05:47.0416] then those aren't invariants, those are just properties [22:06:04.0031] Rob Palmer: do we have other topics for today? [22:06:24.0798] Michael Ficarra will be next [22:06:37.0897] note that "a primitive has a wrapper" is another "invariant-esque property" [22:06:43.0439] * note that "a primitive has a wrapper" is another "invariant-esque property" [22:06:51.0375] is it one you care about [22:06:53.0262] what invariant? [22:06:54.0016] it is not one I care about [22:06:56.0009] bakkot: yes; tons of old on the web will likely break if that property is broken [22:06:59.0754] * @bakkot yes [22:07:21.0734] * bakkot: yes; tons of old on the web will likely break if that property is broken [22:07:41.0602] The old code on the web doesn't use R&T [22:07:50.0622] * The old code on the web doesn't use R&T [22:08:18.0228] no, but the old code includes shims like es5-shim, and people *will* pass R&Ts to those shimmed methods. and some of them shim even in modern engines. [22:08:42.0846] > <@msaboff:matrix.org> I don't think the ShadowRealms we have support the Web APIs. Our Web API support in ShadowRealms is behind an experimental flag, which is off by default. [22:08:52.0053] the shims are not written in sloppy mode are they? [22:08:55.0934] > <@ljharb:matrix.org> no, but the old code includes shims like es5-shim, and people *will* pass R&Ts to those shimmed methods. and some of them shim even in modern engines. I am OK with that [22:09:16.0099] i am not [22:10:07.0366] we definitely should not be trying to maintain the property that old code works when you pass it new values [22:10:09.0910] the backwards compat promise is that unmaintained sites continue to work [22:10:24.0683] it is not sites continue to work regardless of what modifications they make [22:10:33.0627] i'm not sure how simple that is given that people update third-party dependencies they don't control. [22:10:38.0927] but fair enough [22:10:52.0607] there exists a fair amount of code in the wild that preferred `Object(value) === value` to test for objects instead of `typeof value === "object" && value !== null || typeof value === "function"`. Not boxing would cause code that expects to be safe to evaluate to become unsafe. [22:11:49.0762] Object(#{}) === #{} would be false, since it is not an object [22:11:51.0690] > <@msaboff:matrix.org> I don't think the ShadowRealms we have support the Web APIs. Oh wow I somehow missed the word "don't" here. So, now this makes a compatibility matrix for ShadowRealms that I was hoping we could avoid. [22:12:16.0659] > <@devsnek:matrix.org> Object(#{}) === #{} would be false, since it is not an object Correct. That's the expected behavior. [22:12:29.0560] > <@littledan:matrix.org> Oh wow I somehow missed the word "don't" here. So, now this makes a compatibility matrix for ShadowRealms that I was hoping we could avoid. ha so did i, i read your response first [22:12:45.0067] msaboff: given that i'm asking something radical: i'd consider this a mistake and a respin would be nice, if possible [22:12:50.0641] > <@littledan:matrix.org> Oh wow I somehow missed the word "don't" here. So, now this makes a compatibility matrix for ShadowRealms that I was hoping we could avoid. The Web APIs are currently behind an experimental flag that is off by default. [22:12:51.0196] but of course, safari rel-eng makes the decision [22:13:02.0721] Throwing would be unexpected and has the potential to break code paths that are expected to not throw for anything. [22:13:04.0632] I would not have guessed Records & Tuples to break a language that already has string primitives with both numeric index properties and a named property [22:13:10.0472] msaboff: is ShadowRealm unflagged or on-by-default? [22:13:17.0947] Thanks whoever is helping on notes [22:14:13.0744] > <@shuyuguo:matrix.org> msaboff: is ShadowRealm unflagged or on-by-default? I believe that ShadowRealms themself are on, but Web API support is behind an experimental flag which is off by default. [22:14:41.0335] What would be the point of creating a Proxy for a record/tuple? [22:15:03.0916] msaboff: hmm, i see. at the risk of forward interop, i think a respin would be good if at all possible [22:15:17.0497] You can't create a proxy for a number or string [22:15:29.0372] > <@rbuckton:matrix.org> What would be the point of creating a Proxy for a record/tuple? not much of one, to be sure. [22:15:42.0532] leobalter: no that's not a good thing! [22:15:51.0935] problem solved? https://gc.gy/130751150.png [22:16:10.0294] @shu littledan I am checking on the true status of Web APIs and ShadowRealms in Safari 16. I'm looking at the current ToT WebKit. [22:16:12.0674] > <@gibson042:matrix.org> I would not have guessed Records & Tuples to break a language that already has string primitives with both numeric index properties and a named property I can't tell what this means [22:16:24.0868] msaboff: thank you [22:17:12.0867] shu: I believe the Web API on by default could lead to unwanted usage if we eventually drop anything from what is currently offered [22:17:56.0715] leobalter: but SRs being shipped unflagged is not good for forward compat [22:18:13.0923] if that is the case, maybe it isn't [22:18:27.0297] > <@bakkot:matrix.org> I can't tell what this means that we already have much precedent in the String type, and it's not clear to me what benefits would come from deviating [22:19:01.0544] shu: I understand that, and I've been talking to WebKit people all day at TPAC. My šŸ™Œ reaction was to the least blast of impact [22:20:53.0558] is anyone talking right now [22:20:54.0440] Richard Gibson: what specific deviation are you referring to? [22:21:00.0446] yes [22:21:00.0988] oh nvm [22:21:17.0914] I am not sure I understand the brand-checking issue. What `Object.p.toString.call(Object(#{}))` returns as current draft?? [22:22:08.0099] @bakkot: `Object(#{ā€¦})` returning anything other than a wrapper object [22:22:22.0580] "\[Object record\]" [22:22:29.0735] > <@haxjs:matrix.org> I am not sure I understand the brand-checking issue. What `Object.p.toString.call(Object(#{}))` returns as current draft?? * "\[Object record\]" [22:22:42.0223] * @bakkot: `Object(#{ā€¦})` returning anything other than a wrapper object [22:22:43.0722] Richard Gibson: the benefit is not introducing a new kind of wrapper object [22:22:52.0103] I would like to only introduce new kinds of things if we want them [22:22:53.0579] So we already have brand check via Object.p.toString ? [22:23:16.0980] Object.p.toString can be faked with Symbol.toStringTag [22:23:39.0785] so would need to check if the value has the symbol, but that can be faked with a proxy [22:23:49.0827] shu: from my end, this release is forcing me to prioritize the shadowrealms work internally, I keep committed to make sure we mitigate the risk of impact. I'm trying this through resolution for the last parts needed to unlock regular implementation. That's why I summarize them, I wanted to make sure I'm not missing anything. [22:23:51.0191] Promise does not have a brand check that has no side effects [22:24:13.0293] leobalter: understood [22:24:16.0852] you can brand check a promise? [22:24:47.0248] > <@bakkot:matrix.org> I would like to only introduce new kinds of things if we want them at the cost of decades of intuition, supported even in the recent past with Symbol and BigInt? [22:24:49.0369] You can but it may execute user code. I don't know if that's a requirement for other brand checks [22:24:51.0294] Bradford Smith: `{ __proto__: null, toString() { return "#{" } }` would satisfy your example and not be a record wrapper. [22:25:21.0945] Mathieu Hofman: that's true. but `Promise.resolve(p) === p` ends up being "fine" in practice. i'd certainly prefer a robust approach, ofc. [22:25:44.0286] * Mathieu Hofman: that's true. but `Promise.resolve(p) === p` ends up being "fine" in practice. i'd certainly prefer a robust approach, ofc. [22:25:45.0998] oh with Promise.resolve right [22:26:18.0035] agree: fine to go ahead without brand check [22:26:31.0049] unconvinced: something is needed to address brand check [22:26:31.0220] Richard Gibson: it is not clear to me why this intuition is valuable? [22:26:41.0670] ljharb this feels kind of like "your scientists were so preoccupied with whether they could they didn't stop to think if they should" [22:26:43.0098] like, who cares whether it is an actual wrapper or a copy? who is that important to? [22:27:03.0520] shu: also, our membrane framework at Salesforce deletes all the Web APIs from a ShadowRealm and we don't rely on the errors (we have userland mechanisms to capture details cross realms). We won't ship the membrane framework using ShadowRealms for at least 6 months, guaranteed. [22:27:03.0609] to users who want to realize they accidentally wrapped a primitive. it happens, albeit rarely. [22:27:15.0211] Any reason not to have Records have a prototype that is frozen and has a `valueOf` method? [22:27:24.0832] then you couldn't have a record with a `valueOf` key [22:27:26.0538] leobalter: i am not concerned about SF, it is clear enough that y'all can push updates out if needed [22:27:56.0163] > <@bakkot:matrix.org> like, who cares whether it is an actual wrapper or a copy? who is that important to? there's lots of code that uses `Object(ā€¦)` as an "is not primitive" predicate [22:27:58.0919] ljharb: it could have an own `valueOf` key, just like an object. [22:28:04.0288] Richard Gibson: that would not be broken by my proposal [22:28:12.0812] shu: once again, I'm trying to mitigate the impact by usage of the feature. It's what I can do at this point. [22:28:26.0788] what is temp checking RN? [22:28:29.0307] rbuckton: so then you wouldn't be able to safely `.valueOf` on a record. there was a strong desire to avoid that kind of problem. [22:28:31.0531] bakkot: that could be significantly more expensive than `Object(0)` [22:28:48.0731] > <@jackworks:matrix.org> what is temp checking RN? "Do we care strongly about brand checking for record wrappers?" [22:28:51.0243] We opened such a Pandora's box by letting folks customize Object.prototype.toString tags. [22:29:03.0029] yep, and we shouldn't have [22:29:23.0625] we could have pulled toStringTag from ES6 and left time to come up with a better solution, but we didn't do that (and i was too green to realize i could have insisted) [22:29:34.0150] Having `Object(#{ arbitrarilyLargeRecord })` convert the record to an object seems expensive for such a test. [22:29:41.0010] * we could have pulled toStringTag from ES6 and left time to come up with a better solution, but we didn't do that (and i was too green to realize i could have insisted) [22:29:43.0510] yeah, like half of the symbols were a mistake [22:30:04.0234] most of javascript was a mistake tbh [22:30:10.0089] bigints are good though [22:30:22.0842] and throwing them all on a big string-based namespace under `Symbol` is both ironic and stupid [22:30:45.0111] and making Symbol.for symbols different from strings lol [22:30:46.0978] that's fair, but I don't think it would be expensive in practice - how expensive is `Object.entries`? (It wouldn't be a deep conversion, to be clear) [22:30:54.0160] I still wish all `Symbol.toStringTag` were actually getters that brand checked like for the TypedArray prototype. Then we'd solve all brand check problems [22:31:18.0979] > <@mhofman:matrix.org> I still wish all `Symbol.toStringTag` were actually getters that brand checked like for the TypedArray prototype. Then we'd solve all brand check problems and if i'd thought of that in 2014 then i'd have suggested it, but i didn't come up with it til it was too late :-( [22:31:49.0720] altho i'm pretty sure it would still be web-compatible to change them all into those now, it's just that the committee at large likely doesn't care enough to want to spend time on that. [22:32:47.0834] If we don't have a prototype, could we have a `Record.unwrap(wrappedRecord)` (or other name) that throws on non-record, and non-wrapped-records? It could act as a brand check and give you a `valueOf` workaround. [22:33:18.0711] that's what the champions think is ill-fitting. [22:33:48.0138] record primitives could also have an own Symbol.toPrimitive method. there's lots of ways to solve it, but it seems unpalatable to some. [22:34:40.0009] > <@rbuckton:matrix.org> Having `Object(#{ arbitrarilyLargeRecord })` convert the record to an object seems expensive for such a test. * that's fair, but I don't think it would be expensive in practice - how expensive is `Object.entries`? (It wouldn't be a deep conversion, to be clear) [22:37:41.0565] can someone advance the queue? [22:38:30.0280] is this really an FYI for committee? [22:38:57.0437] is there feedback R&T champions are specifically looking for from TC39 and not just from TS? [22:39:25.0437] well it's implementer feedback from tooling - e.g., "if we do XYZ, a linter or type-checker cannot catch ...." [22:40:04.0622] danielrosenwasser: is it though? [22:40:07.0481] what's the XYZ here? [22:40:09.0561] It is? [22:40:14.0999] there are also lots of TS users in committee, and this all ties together, so it's good to get more developer feedback here [22:40:22.0917] * there are also lots of TS users in committee, and this all ties together, so it's good to get more developer feedback here [22:40:26.0007] like I'm missing what the feedback for the proposal actually is [22:40:31.0974] that's all fine, but i'm looking for the actual ask [22:40:32.0794] I am in general in favor of such feedback [22:40:33.0350] Agree TS is very important to consider in any proposals. [22:40:50.0272] it is not a general thing that proposals lay out what TS integration looks like [22:41:25.0928] A big takeaway: TS raised a reasonable compatibility risk, Bloomberg investigated this and found that the breakage was much less than some other TS upgrades have been [22:41:43.0561] but... did the proposal itself need changing? [22:41:44.0756] the compatibility risk is based on our choice of typeof (in the language!) [22:41:49.0772] okay [22:41:50.0368] FWIW we also looked at how flow models its core types. And the story is different there as they are generally stricter about modelling things like primitive vs object and readonly [22:41:57.0403] > <@shuyuguo:matrix.org> but... did the proposal itself need changing? No, but they're explaining why [22:42:03.0630] i see [22:42:19.0233] IMO this is pretty relevant to JS developers [22:42:46.0764] I am glad to hear that TS is exploring how to make this work and the champions think it will probably work with minimal breaking changes, if that is the intended takeaway? [22:43:17.0277] > <@bakkot:matrix.org> I am glad to hear that TS is exploring how to make this work and the champions think it will probably work with minimal breaking changes, if that is the intended takeaway? IMO yes, but the champions can confirm [22:44:43.0780] I have to drop, thanks all [22:48:35.0114] > <@bakkot:matrix.org> like I'm missing what the feedback for the proposal actually is My 2 cents here - the state of this proposal poses a set of possible design directions for type-checkers. In the case of TypeScript, for example, we must decide whether our current object-like hierarchy can also model records and tuples, or if it must create a completely separate type hierarchy (or perhaps something in between if we think very hard). Bloomberg investigated how disruptive choosing one path would be, and wanted to provide their feedback on the experience. So it's relevant to discuss here because maybe there are ideas/thoughts from the committee, or maybe there are possible suggestions for the champions on how the proposal can make adjustments. [22:49:33.0050] Someone please take my place helping with notes - to the extent I was a help at all [22:49:43.0469] > <@anthonybullard:matrix.org> Someone please take my place helping with notes - to the extent I was a help at all I can do it [22:49:50.0304] Thank you nicolo-ribaudo ! [22:51:13.0790] danielrosenwasser: thank you, that's a very helpful summary [22:52:26.0446] does `\p{Surrogate}` only match unpaired surrogates? [22:52:27.0586] yeah probably my takeaway was too strong, but it's just my personal opinion, how I understand it. You notice both the champions and Daniel are refraining from drawing such a strong reading... [22:53:00.0381] I imagine it does in `u` mode [22:55:51.0342] The spec text of this proposal is delightfully short! [22:55:55.0432] +1 to this proposal advancing [22:55:57.0747] danielrosenwasser: I guess I think TC39 probably isn't going to be all that helpful for suggestions for how TS should represent or typecheck stuff, as a rule, 'cause we don't really have the tradeoffs internalized for what breakages are acceptable and etc [22:57:37.0455] šŸ‘ļø Unicode says to use the Replacement Character [22:58:45.0704] > <@bakkot:matrix.org> danielrosenwasser: I guess I think TC39 probably isn't going to be all that helpful for suggestions for how TS should represent or typecheck stuff, as a rule, 'cause we don't really have the tradeoffs internalized for what breakages are acceptable and etc Maybe not all of TC39, but TC39 has a number of TS users in it who may weigh in. There are a lot of things we discuss that not everyone can have opinions on. [23:02:24.0476] I'm definitely such a person. I just don't think I have feedback in my capacity as a TC39 member, vs as a person who writes TS, if that makes sense? [23:02:25.0474] waldemar: Current slice() may break a well formed string into non well formed pieces. I am considering possible extensions of slice notation proposal (not current, because current draft do not include string) might solve that. [23:03:32.0805] > <@bakkot:matrix.org> I'm definitely such a person. I just don't think I have feedback in my capacity as a TC39 member, vs as a person who writes TS, if that makes sense? I guess I feel like, it's *good* if delegates bring different aspects of their expertise/experience into the committee [23:03:45.0548] (so, no, it doesn't make sense to me) [23:04:22.0295] well, it's more a question of what the committee is? the committee is a good venue for discussing JS, the language, and so is a good place for discussions like "what changes can we make to the proposal to make it easier for TS to typecheck, if they're having difficulties" [23:04:57.0731] but I don't think it is a good venue for discussing "what are the tradeoffs TS should make when typechecking this feature we've proposed", even if that's a subject I do have opinions on [23:05:22.0920] i was approaching it from a pure time efficiency standpoint. it seemed to me at the time there was risk of delegates getting nerdsniped with no material effect on the proposal, which didn't seem like a good use of time [23:05:48.0139] it is maybe a good place for questions like "how do we expect this proposal to be used?", as data for the TS team to use to make decisions about those tradeoffs, but I didn't really hear a question of that form in this discussion [23:08:09.0886] This is good feedback. We had a mix of items, some were about sharing the outcomes of our research, others were items we explicitly wanted feedback on. We did not make it clear which were which. [23:08:19.0037] * This is good feedback. We had a mix of items, some were about sharing the outcomes of our research, others were items we explicitly wanted feedback on. We did not make it clear which were which. 2022-09-14 [17:52:00.0408] Sorry, off-topic, but could we do a quick test if showing my slides works? [17:55:48.0880] Is the video conference live? [17:56:00.0815] I see waiting for host [17:56:07.0453] it is not started yet [17:56:08.0860] Me too. We need a host, yes. [17:56:13.0793] waiting for an igalian to do so :) [17:56:15.0185] ok thanks Brian [17:56:25.0301] Hehe [17:59:16.0969] > <@rauschma:matrix.org> Sorry, off-topic, but could we do a quick test if showing my slides works? very on-topic! :D top tip: sometimes have to restart the browser if only just given permission to share screen for the first time [17:59:54.0648] Yeah, already did that (the screen sharing background helps with testing). [18:01:39.0974] I guess you can try screen sharing now? [18:09:35.0378] Are we ready to get started? [18:09:53.0949] haven't we already started? [18:10:12.0621] we have in fact already started [18:10:14.0245] axel has been presenting for like 5 minutes [18:14:10.0513] Oh! A problem on my end [18:15:41.0141] what is meant by "a wrapping API" here? [18:16:29.0962] isn't `Iterable.from()` already a wrapping API? it's just that most builtin iterators are/will be pre-wrapped [18:16:30.0022] something like Jquery [18:16:45.0948] * isn't `Iterable.from()` already a wrapping API? it's just that most builtin iterators are/will be pre-wrapped [18:16:55.0701] where you do `$(document.querySelectorAll(...))` and then get a new thing that has a bunch of helper functions [18:17:36.0034] how is that different than what we do? [18:17:50.0536] you don't need to wrap most of the time [18:17:51.0132] A real example of "wrapping API" [18:17:57.0528] Emitter proposal [18:18:06.0464] https://github.com/tc39/proposal-emitter [18:18:07.0751] like if you do `map.values().filter()` there's no explicit wrapper [18:18:16.0238] right, builtins are "pre-wrapped" [18:18:21.0717] (or some better way to describe it) [18:18:26.0372] yeah, that's kinda my mental model [18:19:02.0724] Emitter proposal also use function style. [18:19:46.0254] ```js const { on, map, filter, run } = Emitter run( on(document, 'click') , filter(ev => ev.target.tagName === 'BUTTON') , map(ev => ({ x: ev.clientX, y: ev.clientY })) , coords => console.log(coords) ) ``` [18:20:00.0822] that's applicative style, no? [18:21:44.0112] Axel Rauschmayer (self-employed): re builtin modules, pending that proposal advancing, short answer is no, not in the cards (shu's queue item covers this also) [18:22:00.0434] * Axel Rauschmayer (self-employed): re builtin modules, pending that proposal advancing, short answer is no, not in the cards (shu's queue item covers this also) [18:23:24.0999] it's iterable ONCE, which is the important point [18:24:28.0590] iterators are kind of lying by implementing Symbol.iterator [18:25:25.0274] snek: wait, you are in favor of using iterable helper functions as Axel proposed? [18:26:08.0988] shu: no I think they were saying iterator helpers as functions (conditional on pipe operator) [18:26:26.0246] we need a better word than "functions" here [18:26:46.0547] non-this-value-users [18:27:09.0894] "standalone functions" vs "methods" imo [18:29:21.0016] yes that's good [18:31:05.0767] Axel Rauschmayer (self-employed): for clarity; consensus typically means "some explicit yes's and no explicit no's" and does not imply or require universal enthusiasm :-) [18:32:12.0296] I'm primarily in favor of the standalone function approach because its more flexible and is composable with third-party packages without the need for prototype patching (which is obviously bad). Yes that puts more of a dependency on pipeline, but I think pipeline can advance once the topic variable issue is addressed. [18:34:33.0333] to be clear i was concerned about wasting work on consensus, not work on spec text [18:35:59.0961] oh god, a superclass of all collection types would be as bad an idea as Object.prototype already is [18:36:32.0117] haha oh no please no [18:36:37.0721] `class TCPConnection extends Collection` [18:36:49.0655] we could just call it `FragileBaseClass` [18:36:52.0134] oh wait sorry wrong channel [18:36:58.0591] why do so many people have this same bad idea? [18:37:20.0824] ecosystem can/does have chaining-style via wrapping. And given the limited number of helper methods I'm still more likely to reach for 3rd-party. [18:38:45.0171] rbuckton: we have plans to add a lot more [18:38:54.0091] remember the current proposal is what we consider "minimal" [18:39:09.0708] so many more [18:39:19.0966] okay not *that* many [18:39:22.0349] i closed a lot of issues/prs for more methods [18:39:22.0885] like a dozen? [18:39:31.0645] * i closed a lot of issues/prs for more methods [18:40:20.0064] https://github.com/tc39/proposal-iterator-helpers/issues?q=is%3Aissue+is%3Aclosed+label%3A%22good+follow-on+proposal%22 [18:40:32.0669] But until you do, and as long as there is an iterator helper I need that isn't in that list, I'm still bouncing between methods and functions. _Until we have pipeline_, but if we have pipeline I'd still rather have functions. [18:42:38.0160] we have 15 min underflow during this session, we might want to just let this topic go over by 15 min? [18:43:08.0051] especially given that this presenter is an invited expert, it would be nice to be more lenient with the timebox [18:43:30.0136] I don't think these functions would be global, correct Axel Rauschmayer (self-employed) ? [18:43:41.0854] I'm assuming they would be in a global namespace, like Math [18:43:59.0089] what would we call it tho - "Iterable" isn't a "thing", it's a trait [18:44:35.0280] I have all of these as functions (`@esfx/iter-fn` and `@esfx/async-iter-fn`), and wrapping via a `Query` class (`@esfx/iter-query` and `@esfx/async-iter-query`). All of these are iterable (multi-shot if source returns a new itererator each time, single shot if the source returns the same iterator each time). [18:44:37.0135] to be fair, iterators aren't a thing either, but the helpers proposal makes a *wrapped* iterator A Thing, via `Iterator.from` [18:44:45.0237] That's a great point, but is there a concern with there being a global for the trait? [18:44:54.0448] it's just weird [18:45:05.0113] because wrapping iterators makes sense; wrapping iterables i'm not sure does [18:45:15.0832] `Iterable.from(set)` wouldn't be a Set, for example [18:45:18.0602] * `Iterable.from(set)` wouldn't be a Set, for example [18:45:20.0752] And if you do `Iterator.from(x).map()`, `Query.from(x).map()` is pretty much the same. [18:45:27.0677] I agree, but that is kind of the way that Rust traits get compiled down [18:46:21.0104] C#'s IEnumerable is reusable (I believe), but that has super weird performance implications [18:46:30.0756] * C#'s IEnumerable is reusable (I believe), but that has super weird performance implications [18:46:32.0913] No, it's an Iterable, like the name of the namespace - not that class or type, but a type that implements that trait [18:46:53.0363] JS doesn't have a type system like that tho [18:47:03.0613] It would be strange for functions in Iterable namespace to return a Set [18:47:10.0928] i was going to mention this on the queue but how we explained reusability in the past is via functions. for example how do you make `for..of` reusable, you wrap it in a function that you call multiple times. [18:47:17.0612] it would also be strange for them to return things that are not reusable [18:47:21.0983] I wish this proposal hadn't conflated using the function style with the change to iterables; using functions is a reasonable request, but operating on iterables is not [18:48:13.0207] > <@devsnek:matrix.org> i was going to mention this on the queue but how we explained reusability in the past is via functions. for example how do you make `for..of` reusable, you wrap it in a function that you call multiple times. now the `for..of` is not relevant itself, you could be manually consuming an iterator or you could be using a generator or whatever, you just end up with a nice abstraction boundary of a function. this was also a big point with `Number.range` if anyone remembers that. [18:48:13.0510] you could extend iterator.prototype and have `FancyIterator.from(thing).fancyMethod()` etc [18:48:14.0750] seems fine [18:48:21.0723] re shu 's queue item - `function filter(iterable, filterer) { return Iterator.from(iterable[Symbol.iterator]()).filter(filterer); }` i think? [18:48:33.0434] I agree with that Michael Ficarra . I wish static methods or namespaced sets of functions are a better approach - and much better when we get pipes [18:48:44.0729] I could imagine a `Query.use(...fns)` that returns something that mixes in a bunch of functions as methods that can then be used for chaining, i.e.: ```js // built-in Query.from(ar).map()// filter(), etc. const MyQuery = Query.use(groupBy, join, groupJoin); MyQuery.from(ar).groupBy() // join(), etc. ``` [18:49:06.0016] but also, the language has had built-in `Array.prototype.map` forever while underscore had `_.groupBy` or whatever, and that was fine; the ecosystem things don't necessarily need to look like built-in things [18:49:09.0102] (to shu's point) [18:50:08.0583] * I could imagine a `Query.use(...fns)` that returns something that mixes in a bunch of functions as methods that can then be used for chaining, i.e.: ```js // built-in Query.from(ar).map()// filter(), etc. const MyQuery = Query.use({ groupBy, join, groupJoin }); // subclass Query, patching in functions as methods MyQuery.from(ar).groupBy() // join(), etc. ``` [18:51:24.0508] also the language _will always_ have `Array.prototype.map`, so it's not like we can avoid having method-based things in the stdlib at this point [18:51:27.0313] The `.use` concept could work with `Iterator`, though (i.e., subclass `Iterator`, mix in and wrap the provided methods). [18:51:44.0478] i think as a way of choosing defaults for the standard library, i see no compelling reason aside from taste to deviate from what we have been doing since the language's inception with prototype methods [18:51:50.0481] the functional style is easily polyfilled [18:51:58.0832] let those adherents import a library, that seems sufficient? [18:53:04.0490] if/after pipeline has landed, i think there will be compelling reasons. but until then, i agree that there isn't. and i don't think proposals should wait for that. [18:53:15.0779] s/after/if/ [18:53:20.0582] * if/after pipeline has landed, i think there will be compelling reasons. but until then, i agree that there isn't. and i don't think proposals should wait for that. [18:53:27.0981] yes thanks, edited [18:53:41.0586] > <@shuyuguo:matrix.org> let those adherents import a library, that seems sufficient? My concern is having to mix functions from a 3rd party with methods on `Iterator.prototype`, makes for hard to read code. [18:53:52.0270] it wouldn't be hard to read with pipeline tho :-) [18:53:58.0194] ljharb: just like we shouldn't have to wait for a way to list all intrinsics, right? šŸ˜‰ [18:53:59.0632] rbuckton: that seems unavoidable [18:54:04.0445] JS is not a functional style language [18:54:12.0838] it has some combinators here and there [18:54:15.0078] > <@ljharb:matrix.org> if/after pipeline has landed, i think there will be compelling reasons. but until then, i agree that there isn't. and i don't think proposals should wait for that. Is there anything pipeline is waiting on aside from picking the topic? [18:54:16.0878] yep! i'm on your side for that one, altho ofc we still need that "way" [18:54:34.0112] * yep! i'm on your side for that one, altho ofc we still need that "way" [18:54:50.0068] ljharb: I hope to hear your support for that later then šŸ™‚ [18:55:15.0543] if you want to use more things in a method-based style, you can write a thing extending `Iterator.prototype` and put more methods on it [18:55:18.0689] that works fine [18:55:23.0359] `Iterator` has no slots [18:55:29.0967] and will never have slots [18:55:39.0693] even if it did, extending `Iterator` would give you them [18:56:44.0715] Bradford Smith: re your queue topic, you don't have to implement a bunch of stuff, you just `__proto__: Iterator.prototype` [18:57:24.0178] to be clear, I am very, very opposed to function-based style even in a world in which we have pipeline [18:57:30.0368] I do not think pipeline meaningfully changes this conversation [18:58:35.0862] > <@bakkot:matrix.org> to be clear, I am very, very opposed to function-based style even in a world in which we have pipeline Is there any special reason ? [18:58:40.0788] `Array.prototype.map` already exists, and will always exist [18:58:54.0183] mapping over iterators should work like mapping over arrays [18:59:01.0216] not with completely different style and completely different syntax [18:59:04.0786] the "consistency" arguments presented so far are very myopic IMO [18:59:27.0794] > <@bakkot:matrix.org> if you want to use more things in a method-based style, you can write a thing extending `Iterator.prototype` and put more methods on it and then we need multiple inheritance to mixing them together `Library1Iterator.prototype` and `Library2Iterator.prototype` [18:59:34.0933] ISTM to boil down to "my code is already functional style, it'd be nice if i didn't need a 3p library to keep that style" [18:59:41.0528] i daresay that's a minority? [19:01:22.0266] you must see this https://github.com/fantasyland/fantasy-land šŸ˜‚ [19:01:26.0732] both clauses of that are a minority [19:01:35.0974] people who avoid third party libs, and codebases that are predominantly functional [19:01:49.0130] > <@jackworks:matrix.org> you must see this https://github.com/fantasyland/fantasy-land šŸ˜‚ the current iterator helpers champion is a contributor to that [19:02:02.0813] Michael Ficarra in particular [19:05:23.0527] if not pipeline, the `::` call syntax would also alleviate some of this burden of swapping styles [19:05:31.0300] don't remember what the feeling on this at the time was tho [19:06:41.0502] A bigger problem than style is semantics. See the problem that Kevin and I raised. [19:11:11.0475] If talking about semantics , I also have the concern, should we extend Iterator too much? IMO, iterator should be simple and only use as underlying mechanism, why not use a separate concept for data transformation? Like Java Stream, or Emitter proposal? [19:13:26.0630] java streams would have been on iterator if they could have [19:13:35.0583] but the existing iterator interface, in Java, has `.remove` and stuff [19:13:46.0519] and has distinct `hasNext` and `next` methods [19:13:50.0077] which are awkward with helpers [19:13:53.0830] those facts are the only reason Stream exists [19:14:06.0931] I can try to track down the mailing list discussions from when Stream was introduced [19:14:26.0611] but we don't have those problems, so we don't need to introduce a new thing [19:14:27.0744] which is nice [19:16:20.0179] But we have other problems like Iterator interface. There are confusions on what Iterator means in the ecosystem. For example, Iterator helpers actually require TS to change the definition of Iterator. [19:17:02.0470] That seems like an extremely minor problem, given that we're designing a language which will be in use for decades [19:17:36.0793] I don't think it's a "extremely minor problem". [19:17:47.0617] TS will rename Iterator to IteratorLike [19:17:48.0893] it will be fine [19:19:14.0903] it will be a ecosystem breaking change [19:19:22.0273] Yeah, TS always have the way to do incompatible change, but obviously it have cost ,not only TS itself, but also the whole ecosystem [19:19:47.0926] sure. but that's kind of an unavoidable cost when building on top of a standard, outside that standard, no? [19:19:57.0519] I suspect there are relatively few things which use the `Iterator` type, and it is a very easy migration to do [19:20:07.0508] use Iterator as IteratorLike, and ABikeSheddingNameIterator as Iterator is good IMO [19:20:27.0605] relative to the design of the language for the next several decades, the cost of that particular breaking change is small [19:20:29.0987] Again, it's not only TS problem, we also change the Iterator in the spec from a Interface(protocol) to concrete class (prototype). [19:20:40.0274] in the spec it'd be both. it's already both, it's just that the concrete class isn't really exposed to users, and this proposal would expose it. [19:20:57.0382] * in the spec it'd be both. it's already both, it's just that the concrete class isn't really exposed to users, and this proposal would expose it. [19:20:58.0939] speaking as editor of the specification, the name of the interface in the spec is basically the lowest possible priority [19:21:03.0458] > <@bakkot:matrix.org> relative to the design of the language for the next several decades, the cost of that particular breaking change is small (ESM & CJS co-op: šŸ‘€) [19:21:05.0698] * speaking as editor of the specification, the name of the interface in the spec is basically the lowest possible priority [19:21:15.0774] Jack Works [19:21:28.0088] that particular breaking change was _much_ more serious [19:21:33.0646] > <@bakkot:matrix.org> I suspect there are relatively few things which use the `Iterator` type, and it is a very easy migration to do In TypeScript? Actually there are a fair amount of folks using `Iterator` directly, changing that would be breaking, but the interface `Iterator` doesn't have to align with the value `Iterator`. [19:21:49.0102] > <@bakkot:matrix.org> speaking as editor of the specification, the name of the interface in the spec is basically the lowest possible priority I don't mean the cost of spec editors, but the cost of changing concept which js programmers/educators already have. [19:23:34.0631] > <@rbuckton:matrix.org> In TypeScript? Actually there are a fair amount of folks using `Iterator` directly, changing that would be breaking, but the interface `Iterator` doesn't have to align with the value `Iterator`. Which is also why I've been fairly confident in saying "not every Iterator has a [Symbol.iterator] method" and "not every Iterator inherits from %IteratorPrototype%", because it's come up often enough over the last few years. [19:24:16.0297] sure, but that's what `Iterator.from` is for - and iterator helpers would push all the authors of those iterator-likes to in fact make them have both of those things [19:24:48.0028] I have myself written iterators which don't inherit from Iterator.prototype, but writing iterators manually is a pretty unusual thing to do, and having to add `__proto__: Iterator.prototype` to such things in the future is not such a large cost, I think. [19:27:03.0684] I guess "{__proto__: Iterator.prototype}" doesn't work in some runtime (deno?) [19:27:07.0971] it does [19:27:14.0099] deno deletes the Object.prototype accessors [19:27:15.0405] not the syntax [19:27:23.0320] it's a required part of the spec [19:27:24.0021] syntax works everywhere [19:27:32.0099] ljharb: re: your comment in the queue. With the exception of `yield* "abc"`, `for(const x of "abc")`, and `..."abc ` (i.e., very explicit actions on a supplied iterable), I really do think any new API that accepts an `Iterable` should restrict it to Object iterables. [19:29:56.0711] Pretty much every other use case where you end up spreading a string is probably a bug (except `Array.from`). I'd argue that if you wrote `new Set(value)` and `value` was a string, its most likely a bug. If a new API accepted an iterable argument, I'd push hard for requiring you to do `[..."abc"]` if you really wanted to pass in code points. [19:31:33.0393] `forEach` shouldn't be in the middle of a chain [19:31:48.0336] that would be something like `.tap`. [19:32:22.0599] for `tap`, see this thread, particularly my last comment: https://github.com/tc39/proposal-iterator-helpers/issues/13#issuecomment-1210164187 [19:32:33.0304] Justin Ridgewell: what is your abbreviation? [19:32:40.0305] The `undefined` return value is my my hated part of `Array.p.forEach`. [19:32:43.0610] JRL [19:33:03.0068] https://github.com/tc39/notes/blob/6f7e075341e435f22777b07a3ee5141442d2d8a7/delegates.txt#L231 [19:35:38.0782] I disagree, I feel `indexed()` is over complicated, and passing in a counter is much easier to reason over and better for refactoring. The fact that we pass a counter and *not* the source as a 3rd arg like we do for Array is indicative enough that its not an index. [19:36:15.0737] erights: so i'm looking, and now i can't find the file i remember looking at - certainly you'll have https://github.com/ljharb/get-intrinsic/blob/main/index.js, but in test262 it's all single lines of code in individual test files, like https://github.com/tc39/test262/blob/6e61dd7754e7c94ebcf3ee679cb8db3c54a37b50/test/built-ins/ThrowTypeError/length.js#L16-L19 - which isn't a single location, but at least means there's a canonical way to "get at" the intrinsic [19:36:51.0696] we don't provide the source on array reduce/reduceRight, either, and that argument is rarely used anyways, so i don't think that indicates anything [19:36:58.0767] > <@rbuckton:matrix.org> I disagree, I feel `indexed()` is over complicated, and passing in a counter is much easier to reason over and better for refactoring. The fact that we pass a counter and *not* the source as a 3rd arg like we do for Array is indicative enough that its not an index. * we don't provide the source on array reduce/reduceRight, either, and that argument is rarely used anyways, so i don't think that indicates anything [19:37:02.0154] I've taken to think of the "iterator helpers" as "one shot iterable helpers that happen to be on Iterator.prototype and can be accessed by any iterable using Iterator.from()" [19:37:30.0347] i agree with that mental model, but i don't think that speaks for or against "counter"? [19:38:12.0441] > <@ljharb:matrix.org> i agree with that mental model, but i don't think that speaks for or against "counter"? Sorry, that comment wasn't related to the "counter" discussion. [19:40:24.0505] rbuckton: I expect to do a fair amount of `document.querySelectorAll(...).values().map().find()` etc [19:40:29.0897] There's a difference in intention. `.reduce` is an aggregation operation producing a scalar value. It's perfectly reasonable to expect `.map` and `.filter` to care about a counter. `.map` with a counter can be used to map into even/odd rows. `.filter` with a counter could reasonably be used to skip every other value. Those cases exist with Array `.map` and `.filter` today, and being able to refactor to iterator helpers seems like a good thing. [19:40:53.0678] re strings, i guess we could have an AO like `IsContainer` or something, that returns true for Object, and eventually Record and Tuple, and require that in the helpers - and then Strings would never be iterated by default [19:42:31.0653] Are tuples concat spreadable? [19:42:53.0904] Apparently. [19:45:13.0695] to confirm, whats the problem with iterable strings? that they are iterable at all, or that they don't iterate over the expected contents? [19:45:43.0910] > <@rick.button:matrix.org> to confirm, whats the problem with iterable strings? that they are iterable at all, or that they don't iterate over the expected contents? tab wrote a article explained that [19:45:50.0534] ooh [19:46:00.0741] https://www.xanthir.com/b4wJ1 [19:46:28.0834] > <@rick.button:matrix.org> to confirm, whats the problem with iterable strings? that they are iterable at all, or that they don't iterate over the expected contents? Its bad for refactoring, and doesn't match user expectations. ``` ["abc"].flatMap(x => x); // ["abc"] ["abc"].values().flatMap(x => x).toArray(); // ["a", "b", "c"] if we don't limit to objects ``` [19:46:38.0880] ah I see [19:46:59.0687] (iow we should have done `String.prototype.codeUnits()` and `String.prototype.codePoints()` and not had `String.prototype[Symbol.iterator]` at all) [19:47:11.0976] ^ was just going to saythat [19:47:13.0328] * (iow we should have done `String.prototype.codeUnits()` and `String.prototype.codePoints()` and not had `String.prototype[Symbol.iterator]` at all) [19:47:28.0565] but alas [19:47:51.0635] > <@ljharb:matrix.org> (iow we should have done `String.prototype.codeUnits()` and `String.prototype.codePoints()` and not had `String.prototype[Symbol.iterator]` at all) could we add `codeUnits` and `codePoints` now? [19:47:56.0887] absolutely, we just need a proposal and consensus (so, easy, right?) we wouldn't ever be able to unbreak strings tho :-( [19:48:02.0232] * absolutely, we just need a proposal [19:48:05.0739] * absolutely, we just need a proposal and consensus [19:48:13.0121] * absolutely, we just need a proposal and consensus (so, easy, right) [19:48:18.0677] * absolutely, we just need a proposal and consensus (so, easy, right?) [19:48:25.0173] * absolutely, we just need a proposal and consensus (so, easy, right?) we wouldn't ever be able to unbreak strings tho :-( [19:48:27.0854] How about `.graphemes()`? [19:48:31.0472] > <@haxjs:matrix.org> could we add `codeUnits` and `codePoints` now? * How about `.graphemes()`? [19:48:40.0794] yes please, altho then you'll be pointed to Intl.Segmenter [19:48:55.0144] > <@rbuckton:matrix.org> How about `.graphemes()`? I guess graphemes are locale related [19:48:58.0456] `delete String.prototype[Symbol.iterator]` ez [19:49:13.0061] and for good reasonā€”grapheme cluster segmentation is locale-sensitive [19:50:10.0176] Swift use locale-independent grapheme cluster (I don't remember the correct term), but may have some issues (I don't fully know). [19:50:30.0347] i'm mad at unicode, or maybe just all human beings, for making graphemes differ based on locale [19:51:04.0162] > <@ljharb:matrix.org> absolutely, we just need a proposal and consensus (so, easy, right?) > > we wouldn't ever be able to unbreak strings tho :-( Serious question: Would a `.codePoints` proposal really get much traction, or would it get too much pushback that We Already Have the Default String Iterator? [19:51:13.0577] Just like JS have compatible requirements, unicode also, so .... [19:51:31.0197] `[Symbol.iterator]()` is utterly unergonomic tho [19:51:49.0650] Array.values() vs `Array[Symbol.iterator]` šŸ˜… [19:52:13.0174] > <@jschoi:matrix.org> Serious question: Would a `.codePoints` proposal really get much traction, or would it get too much pushback that We Already Have the Default String Iterator? * Array.values() vs `Array[Symbol.iterator]` šŸ˜… [19:54:30.0025] I don't think you can safely interleave `next()` and `return()` because of `finally` since that would put your source in a very weird state (pre-emptying the current `await` that might be in a `try..catch..finally`, etc.) [19:55:26.0492] with an actual generator that's definitely true [19:55:34.0903] but generators have an internal queue of those calls, so no problem there [19:55:54.0626] Michael Ficarra: Could you craft a real-life code example of a usecase for interleave next/return [19:55:55.0812] ? [19:56:11.0308] > <@haxjs:matrix.org> Array.values() vs `Array[Symbol.iterator]` šŸ˜… Nice. I figure that the `.codePoints()` proposal would be bundled with code-unit iterator(s?) and make the point that ā€œwe should encourage developers to use `for (p of str.codePoints())` rather than `for (p of str)` as much as possibleā€. [19:56:32.0809] we should not encourage developers to do that [19:56:40.0890] `for (p of str)` is fine [19:56:58.0884] no objections to having a `codePoints` helper though [19:57:26.0666] msaboff: I just keep delegates.txt open in another tab when I am taking notes [19:57:33.0218] We should all put our abbreviation in the jitsi display name [19:57:34.0626] > <@bakkot:matrix.org> `for (p of str)` is fine I do suppose it comes down to how much one agrees with https://www.xanthir.com/b4wJ1 ā€¦ [19:57:48.0248] > <@bakkot:matrix.org> `for (p of str)` is fine It's not clear what p is. [19:57:57.0281] jschoi: I agree with that thing but that ship has sailed [19:58:03.0542] strings _are_ iterable, we can't take that back [19:58:25.0488] `Symbol.iteratorV2` but don't put it on string.prototype (sorry tdz post) [19:58:37.0562] I'd rather see `for (p of str.codePoints())` because its more intentional. I've never been a fan of the disparity between `str[i]` and `str[Symbol.iterator]()`. [19:58:43.0431] * `Symbol.iteratorV2` but don't put it on string.prototype (sorry tdz post) [19:59:00.0160] The default string iterator canā€™t be made illegal, but developer guidance about it can change, right? Not that I feel that strongly one way or the other about what we should do about the situation myselfā€¦ [19:59:13.0789] > <@bakkot:matrix.org> strings _are_ iterable, we can't take that back yeah we can't, but at least linter could warn that if we give people other better options. [19:59:19.0057] > <@bakkot:matrix.org> strings _are_ iterable, we can't take that back * The default string iterator canā€™t be made illegal, but developer guidance about it can change, right? Not that I feel that strongly one way or the other about what we should do about the situation myselfā€¦ [19:59:23.0646] I don't think developer guidance helps with the actual problems in that essay [19:59:42.0629] Fair enough. [20:00:04.0371] I guess it helps with the "no correct way to iterate a string" thing [20:00:26.0676] but not the "infinite descent" thing, or the "accidentally passing it to something like the Set constructor" thing [20:00:48.0889] TS (or other type checker) can warn that (theoretically) [20:01:11.0750] > <@bakkot:matrix.org> but not the "infinite descent" thing, or the "accidentally passing it to something like the Set constructor" thing * TS (or other type checker) can warn that (theoretically) [20:01:29.0602] it can already warn about passing a string where an iterable is expected, though [20:01:33.0503] can and possibly should [20:01:46.0778] don't need new developer guidance for that [20:02:11.0087] (maybe a job for tslint rather than TS proper) [20:02:38.0073] > <@bakkot:matrix.org> it can already warn about passing a string where an iterable is expected, though In that case, being explicit with `.codePoints` would be nice for the compiler as well as human readers, right? Thatā€™s kind of a case where developers ā€œshouldā€ use `.codePoints` instead of the default iterator. [20:02:46.0506] Unfortunately, TS doesn't really have "warnings", per se. Every diagnostic has the same level. [20:03:10.0919] every diagnostic is a warning, that's what `// ts-expect-error` is for :P [20:03:15.0888] jschoi: yeah that's fair [20:03:19.0798] > <@nicolo-ribaudo:matrix.org> We should all put our abbreviation in the jitsi display name +1 (and Jitsi should make it even clearer who is currently talking even if someone else is screen sharing) [20:03:56.0585] I'd much rather pass a `str.codePoints()` into something that expects an iterable when I know I want the code points, vs `[...str]` (both because the former is clearer and the latter is eager) [20:04:18.0364] ā€¦Though come to think of it, we probably should call it something like `.byCodePoints()` or `.codePointStrings()` or something. Because the language already uses ā€œcode pointsā€ to refer to *integers*: `String.codePointAt` returns integers. [20:04:25.0672] > <@aclaymore:matrix.org> +1 (and Jitsi should make it even clearer who is currently talking even if someone else is screen sharing) Ashley Claymore: 1000% this [20:04:36.0859] (and yes, you could do `str[Symbol.iterator]()` to not be eager). [20:04:54.0422] I now put jitsi in full screen in tile mode on my left monitor, and the etherpad on the right monitor [20:05:23.0398] > <@jschoi:matrix.org> ā€¦Though come to think of it, we probably should call it something like `.byCodePoints()` or `.codePointStrings()` or something. Because the language already uses ā€œcode pointsā€ to refer to *integers*: `String.codePointAt` returns integers. ugh, yeah [20:08:55.0732] Is it possible for us to have some sort of coordination during note taking, or has something like that been attempted? Three people live editing the transcription gets very frustrating [20:10:01.0240] And does the transcription bot just get a single stream of audio, or would it have a way of detecting the speaker and including those annotations? [20:10:25.0638] just a single stream of audio [20:10:28.0177] Kinda wish we had a `char`-like concept in JS (at least, the C# version that is always a wide char) that wasn't just `Number`/`String` [20:11:09.0960] Too bad we ran out of quotes to use for it [20:11:17.0848] * Too bad we ran out of quotes to use for it [20:11:19.0474] it is in principle possible to write something which talks to the Jitsi API to detect the current speaker but that would be a lot of work [20:11:27.0543] PRs welcome though https://github.com/bakkot/transcribe-to-gdocs [20:11:46.0852] I think the latest version of Jitsi already has this though, right? [20:12:05.0224] has what? [20:12:11.0605] has live transcriptions output to google docs? no it does not [20:12:52.0000] not to gdocs, to some sort of log, I can look for the PR later [20:12:54.0116] > <@rbuckton:matrix.org> Kinda wish we had a `char`-like concept in JS (at least, the C# version that is always a wide char) that wasn't just `Number`/`String` Note sure we have good use case of `char`? [20:13:25.0677] > <@haxjs:matrix.org> Note sure we have good use case of `char`? Comparing characters in a way that does involve looking up charcodes? [20:15:29.0946] Itā€™d have been better for everyone if it was never named ā€œcharā€ in Java but rather ā€œutf16unitā€. :ā€™) [20:16:57.0499] Yeah, char has connotations of ASCII, or at least 8-bit character [20:17:18.0528] But maybe not to your workaday JS developer [20:19:11.0834] Itā€™s my opinion that, because ā€œcharacterā€ has so many different meanings (8/16/32-bit code units, code points, combining clusters, grapheme clusters), itā€™s too ambiguous and should generally be banned from technical documentation and APIs and replaced by more specific phrases. But thatā€™s meā€¦ā€¦ [20:19:35.0198] The word is a real source of confusion though; thereā€™s a reason why it takes up basically a whole section of the Unicode FAQ. [20:19:43.0928] At this point in time, that's probably correct [20:20:43.0943] "character" in the JS spec, used in the regex processing part, means _either_ code point or code unit depending on whether the current regex is `/u` or not [20:21:03.0777] that's a fun one [20:24:03.0518] oof [20:24:29.0768] * Itā€™s my opinion that, because ā€œcharacterā€ has so many different meanings (8/16/32-bit code units, code points, combining character clusters, grapheme clusters), itā€™s too ambiguous and should generally be banned from technical documentation and APIs and replaced by more specific phrases. But thatā€™s meā€¦ā€¦ [20:25:06.0998] It seems like Strings, when looked from the modern landscape are at least as complex as time. [20:25:19.0878] mmmmmmm no time seems harder still [20:25:37.0088] In terms of representation, manipulation, and inspection [20:26:33.0849] I probably need to sit down and write that thought out to sanity check myself [20:28:23.0509] I'm sure the Temporal champions would very quickly disabuse me of that proposition [20:28:23.0750] Strings are hard if only because text is hard, and text is hard because human writing systems are nuts. Then again, time is nuts too, so. [20:28:43.0026] * Strings are hard if only because text is hard, and text is hard because human writing systems are nuts. Then again, time is nuts too, so. [20:29:05.0339] There are a lot of similar problems there actually [20:29:29.0972] For much of the same reasons [20:29:47.0375] At least strings in JS support operators. Temporal, unfortunately, does not :/ [20:30:34.0089] > <@jschoi:matrix.org> Itā€™s my opinion that, because ā€œcharacterā€ has so many different meanings (8/16/32-bit code units, code points, combining character clusters, grapheme clusters), itā€™s too ambiguous and should generally be banned from technical documentation and APIs and replaced by more specific phrases. But thatā€™s meā€¦ā€¦ maybe we could use "rune" (rust, go use that term?) [20:30:35.0692] strings probably shouldn't've supported operators [20:30:43.0139] lexicographic ordering is locale-dependent [20:30:56.0848] concatenation is crazy with combining characters [20:31:11.0523] `===` is crazy with canonicalization and normalization [20:31:12.0835] > <@haxjs:matrix.org> maybe we could use "rune" (rust, go use that term?) I almost forgot about runes in rust [20:31:48.0724] > <@bakkot:matrix.org> strings probably shouldn't've supported operators agree, but many usage of strings in the languages actually are used for symbol/keys, not for text. Though we have another "symbol" :) [20:31:58.0125] A rune by any other name would yet be a number. [20:32:26.0334] I hesitate to mention that Unicode does have more quote characters. [20:32:52.0221] aw yeah, Left-Pointing Double Angle Quotation Mark [20:33:12.0979] > <@kriskowal:matrix.org> I hesitate to mention that Unicode does have more quote characters. I made this point above. There are languages (Erlang I think) that don't use an enclosure for chars [20:33:24.0927] There was a lovely hack for "generics" in Go that employed a source-to-source transform and aboriginal brackets. [20:35:08.0648] I was wrong, Elixir uses the pattern `?` to get the code point [20:35:35.0961] Thereā€™s a fundamental, philosophical question here: When two types have an equivalence relation, when should they be unified? In this case, should code units be unified or separated from integers? But itā€™s a far more general problem than that. [20:35:38.0484] (My opinion is that number is a fine representation for char/rune in a language with a unified number type. Itā€™s consistent with the rustic aesthetic.) [20:35:41.0523] Which might solve some usecases for the desire for characters, but not enough [20:36:37.0454] I think what people want is to type something like `?šŸ˜€` and get the code point(s) [20:37:06.0705] But there is probably _a lot_ wrong with that idea [20:37:31.0917] I probably should stop prognosticating on such matters at this hour [20:37:42.0680] > <@kriskowal:matrix.org> A rune by any other name would yet be a number. * Thereā€™s a fundamental, philosophical question here: When two types have an equivalence relation, when should they be unified? In this case, should code units be unified or separated from integers? But itā€™s a far more general problem than that. [20:38:17.0961] I can tell you what _I_ want is to be able to query the kernel terminal discipline for how many columns a string is going to render into in the connected tty without having to pre-render them all, but I also know Iā€™m not going to get that ever. [20:39:30.0122] Some would call my motivating use case esoteric: emoji + tty + roguelike [20:41:24.0109] But as bakkot mentioned, string concatenation only hints at the problem. If a streaming an emoji with combining characters is interrupted by a write flush, the tty is compelled to render the incomplete sequence, followed by the remaining incomplete sequence, and the outcome is not consistent. [20:41:50.0492] ā€¦Have any text-based roguelikes attempted to use all of (printable) Unicode for its symbols, using a pan-Unicode bitmap font like GNU Unifont? But wrong channel, I guess. [20:41:57.0547] That is why emoji are largely not fit for tty [20:41:57.0594] * ā€¦Have any text-based roguelikes attempted to use all of (printable) Unicode for its symbols, using a pan-Unicode bitmap font like GNU Unifont? But wrong channel, I guess. [20:42:43.0508] Yes, and on the web, youā€™re not going to know enough about your string until you run it by font metrics. [20:42:47.0249] But much more essential characters face the same problems I'm sure (CJK, Devanagari?) [20:43:16.0562] Hangul, for certain. [20:43:35.0293] And of course the hypothetical code page of combining tengwar and tehtar. [20:43:36.0126] I never used Hangul in a tty scenario [20:43:58.0762] Emoji display is different than emoji characters; you donā€™t necessarily need combining characters or variation sequences just to have the characters themselves printed on a streaming TTY, as long as the TTY supports SMP characters. [20:44:02.0911] Iā€¦thinkā€¦ [20:44:11.0404] Hangul evidently have both combining and non-combining glyphs depending on when they entered unicode. [20:44:51.0586] That is surprising, Hangul is a very simple, small script - I wonder how they would have entered unicode at different times? [20:44:54.0165] As far as I know, modern Hangul entered Unicode all at once, both composed and decomposed. [20:44:58.0901] Maybe historical glyphs? [20:45:13.0818] Otherwise, they wouldnā€™tā€™ve been able to create the special character-name rules for the composed characters. [20:45:17.0478] There are I think 3 historical glyphs that are obsolete [20:45:54.0651] I haven't spoken or written Korean in any meaningful respect in 17 years, so that's probably wrong [20:47:13.0351] ā€¦Yeah, the Hangul Syllables block was entirely added in Unicode 2.0 / 1996. Though itā€™s all modern of course. [20:47:34.0876] then again some syllables could be viewed as hypothetical [20:47:57.0821] > <@rkirsling:matrix.org> then again some syllables could be viewed as hypothetical No obsolete glyphs in unicode, but we have Linear B? [20:51:10.0595] For what itā€™s worth, as far as I know, every syllable combination encoded in Hangul Syllables is in actual use. I do not have data to back this up. [20:51:25.0910] > <@rkirsling:matrix.org> then again some syllables could be viewed as hypothetical * For what itā€™s worth, as far as I know, every syllable combination encoded in Hangul Syllables is in actual use. I do not have data to back this up. [20:51:35.0937] 7 obsolete Hangul letters, 5 simple characters, 2 obsolete _ssang_(double) characters. Would love to hear what _ssang-hieut_ sounded like... [20:53:17.0999] > <@rkirsling:matrix.org> then again some syllables could be viewed as hypothetical A lot of the bizarre ones are used for onomatopoeia [20:55:25.0656] > <@kriskowal:matrix.org> And of course the hypothetical code page of combining tengwar and tehtar. Hopefully not on the same screen as emoji... [20:56:36.0566] > <@anthonybullard:matrix.org> Hopefully not on the same screen as emoji... šŸ§ā€ā™€ļø? [20:56:49.0582] Code blocks (and code-point order) were never meant to be meaningful for users; theyā€™re artifacts of encoding history and optimization. This is what Unicode says, but I think Unicode could do a better job of showing this. Maybe by presenting human-user-friendly pages of writing-system repertoiresā€¦ [20:57:33.0118] I mean, the ones that exist need to exist by virtue of being valid combinations, but [20:57:45.0253] * Code blocks (and code-point order) were never meant to be meaningful for users; theyā€™re artifacts of encoding history and optimization. This is what Unicode says, but I think Unicode could do a better job of showing this. Maybe by presenting human-user-friendly pages of writing-system repertoiresā€¦ [20:57:47.0781] > <@jschoi:matrix.org> Code blocks (and code-point order) were never meant to be meaningful for users; theyā€™re artifacts of encoding history and optimization. > > This is what Unicode says, but I think Unicode could do a better job of showing this. Maybe by presenting human-user-friendly pages of writing-system repertoiresā€¦ By running all the codepoints through AES, like map keys in Go. [20:58:02.0956] can folks hear me? [20:58:17.0577] ryzokuken if you just said "jschoi would you mind sharing your screen", yes [20:58:18.0796] otherwise no [20:58:23.0378] ah, yes [20:58:26.0995] I did šŸ™ˆ [20:58:56.0212] kind of unclear whether these would all see use: ķ›Ŗ ķ›« ķ›¬ ķ›­ ķ›® ķ›Æ ...is why I said hypothetical [20:59:20.0014] if it were just combining parts, then those would be possible but you wouldn't necessarily dwell on 'em [21:00:47.0411] Iā€™m sorry, give me a minute. Technical difficulties. [21:02:22.0714] Michael Ficarra: do you want to put conclusions from previous presentation in the notes? [21:03:23.0580] Can anyone hear me? [21:04:25.0523] (Iā€™m a little confused on whether Iā€™m supposed to go up right now. I canā€™t hear anyone right now.) [21:04:31.0647] yes [21:04:39.0944] we're waiting for you [21:04:46.0789] did you try clearing browser cache? [21:05:06.0292] there's been some people speaking so if you can't hear it's on your end [21:05:16.0199] jitsi reset my audio out/in devices, which might be the issue? [21:05:20.0569] had to manually change it to the right one [21:06:04.0503] my ios app still has no audio (and apparently nobody could hear me speak either) so i can only get it to work on the web [21:06:06.0995] youā€™re on! [21:06:25.0476] i was also unable to get audio on ios [21:20:07.0156] nicolo-ribaudo: your audio is harshly loud, btw, not sure if that's something you can adjust [21:29:35.0728] * nicolo-ribaudo: your audio is harshly loud, btw, not sure if that's something you can adjust update: it's good now! [21:29:45.0075] what last question (capture) means? I suppose it should work like `Array.from` which have the third argument to provide `this`? [21:37:03.0474] oh, i c. it has been fixed minutes ago :) [21:40:07.0379] `has` is ambiguous ( hasKey / hasValue ) šŸ˜‚ [21:40:46.0566] This is where we have Bradleyā€™s conversation about covariant and contravariant sets. [21:41:23.0285] Set.prototype.hasKey ~ CoSet.prototype.hasValue [21:42:25.0688] Would the MVP for this be to only allow union/intersection with a Set (i.e., via brand check)? [21:43:28.0204] rbuckton: no, because the interface we use is observable and can't change in the future [21:44:12.0056] I'm not clear on why this can't change? Or is it because `Set` is subclassable? [21:44:55.0904] you could either subclass Set or add Set.prototype properties to observe the API we're consuming (or lack of it) [21:45:20.0004] it would force our hand to use new symbols in the future I guess [21:45:47.0323] The point of throwing an error for anything other than a branded `Set` would be to allow us to loosen that restriction in the future. [21:47:26.0529] `map.keySet()`, `map.valueSet()` faƧades? [21:47:37.0599] rbuckton: no, that still doesn't work [21:48:13.0140] a set subclass could be passed today with an overridden `has` that side effects, which wouldn't be called if you touched the argument's slots instead of using the public API [21:48:32.0180] it would then break (start side effecting) if we began using the string-based API of the argument [21:48:53.0223] this design would force us to either continue touching internal slots (bad) or use a Symbol-based API [21:49:20.0729] I agree with Kevin that a good design principle is that wrong things should be obviously wrong, if possible [21:49:34.0665] hm, i think my queue item got skipped [21:49:47.0705] ljharb: I don't think so, I see it [21:49:57.0443] oh weird, i don't. i'll refresh [21:49:58.0057] ljharb: was there another one? [21:50:11.0355] nah ok, it's there, tcq just glitched i guess (i just deleted it, so now it's supposed to be gone) [21:50:37.0444] * nah ok, it's there, tcq just glitched i guess (i just deleted it, so now it's supposed to be gone) [21:50:38.0555] its glitching for me too, so I thought I skipped it on accident šŸ˜“ [21:50:38.0938] consistency is hard [21:51:18.0302] now I don't see it either [21:51:40.0770] ljharb: can you add it again? I'll move it up [21:51:54.0323] i mean i deleted it on purpose :-) [21:51:58.0300] ah [21:52:08.0095] alright, I misunderstood [21:52:35.0750] Petting a cat as if it were a dog works sometimes. [22:02:37.0338] We could also have something like this: ```js Set.prototype[Symbol.asSet] = function() { return this; } ``` Where `[Symbol.asSet]` is expected to return `{ [Symbol.iterator](), get size(), has(value) }` Instead of two set-protocol-specific symbols, you have one, which on a set or set subtype would just return `this`. [22:04:16.0007] Aye, and `Map.prototype.keySet` and `Map.prototype.valueSet` that provide faƧades with varying `has` behavior. [22:04:47.0504] Well, `valueSet` oddly not valuable. [22:05:45.0877] Sec [22:05:51.0677] > <@kriskowal:matrix.org> Aye, and `Map.prototype.keySet` and `Map.prototype.valueSet` that provide faƧades with varying `has` behavior. Or just `new Set(map.keys())`, and `new Set(map.values())` [22:06:29.0720] I see youā€™re implying `Map.prototype[Symbol.asSet]` that produces a faƧade that behaves consistently with the Set protocol. Thatā€™s reasonable. [22:06:56.0706] `new Set(map.keys())` is comparably expensive. [22:07:27.0823] rbuckton: yes that is also a reasonable option [22:08:34.0664] is it possible to, make only two native, unmodified sets to read internal slots (so they're in the fast path) [22:08:50.0085] and all other cases go in the slow but predictable path [22:09:00.0982] some day! [22:11:54.0896] > <@ljharb:matrix.org> oh weird, i don't. i'll refresh I also see some weird things happen on the queue before this topic start, and I refreshed the page. šŸ˜… [22:12:59.0064] in elixir you can do `some_set |> MapSet.union(%MapSet{map: your_map})` [22:13:13.0152] * in elixir you can do `some_set |> MapSet.union(%MapSet{map: your_map})` [22:13:31.0412] off-topic, I hope the queue could have emoji like šŸ‘ļø on each item, so I can just show my support without add another +1. [22:14:27.0208] I feel like we are struggling to defend indefensible positions at this point. Who would actually want an array passed to set union/intersection to operate on its indices? [22:15:03.0669] > <@haxjs:matrix.org> off-topic, I hope the queue could have emoji like šŸ‘ļø on each item, so I can just show my support without add another +1. Thanks, that's nice feedback indeed. [22:15:29.0975] > <@michaelficarra:matrix.org> I feel like we are struggling to defend indefensible positions at this point. Who would actually want an array passed to set union/intersection to operate on its indices? If you wanted that, you could just use `array.keys()`. [22:17:16.0787] unfortunately it appears we do not yet have a shared goal here, which is making it impossible to debate solutions [22:19:02.0222] well put, ptomato [22:20:23.0646] Justin Ridgewell: not only keys/values, might also entries šŸ˜… [22:21:07.0371] I believe TS doesn't solve IndexedSet issue? [22:24:00.0612] Or do the slow thing and have `.intersection` do `new Set(other)` and always operate on sets. :/ [22:24:10.0462] Have `union` check for `size`? [22:25:13.0972] hot take: don't sort NaN [22:26:34.0078] see also: donā€™t pet cats [22:26:44.0013] see also: donā€™t use maps as sets [22:28:33.0298] (Ron: I see youā€™re not in the queue for asSet. Iā€™d like to hear that argument.) [22:28:42.0876] (Alas, would have liked to.) [22:29:55.0242] uuhh I do not recall intending to have Set/Map APIs overlap so they're interoperable [22:30:04.0785] can anyone definitively refute that? [22:31:26.0829] I don't recall that being an intent, but do recall having a consistent API was intentional. [22:31:49.0440] apparently Waldemar recalls such an intent [22:32:06.0562] and has argued as such with https://github.com/tc39/proposal-collection-normalization [22:32:58.0456] (imo related to the conflicting but dually true mental models of Sets only having keys, vs only having values) [22:33:04.0675] * (imo related to the conflicting but dually true mental models of Sets only having keys, vs only having values) [22:34:51.0734] lmao thenables is a perfect example of getting this design wrong [22:35:10.0647] I don't understand how we can be so far apart on this right now [22:39:08.0008] i think if there _were_ more affordances for symbol-based names, we'd be back at square one [22:39:20.0596] rbuckton: +1 to your suggestion of `obj[Symbol.asSet]()` return an object implementing whatever we decide to define the API of "set" to be [22:40:34.0083] I don't love 'keys()` as the API name of the "iterate over the contents of a set" method. This discussion is an example of why it's not great. [22:40:34.0225] Bradford Smith: the downside of something like that is that it's a bit broad; you can't rely on finer-grained subsets of capabilties [22:40:48.0481] like something could have *some* properties of a set and not others [22:41:05.0197] but we're forcing ourselves to group them all together with that kind of design [22:41:17.0317] i think subsets of random classes is like [22:41:21.0779] way too big of a problem [22:41:41.0447] i like asSet [22:41:59.0015] i think i am also not a fan of having a public string-based API and a Symbol-based API where there's overlap in the semantics [22:43:18.0913] shu: Array.prototype.values? [22:43:48.0029] Michael Ficarra: i don't follow [22:44:07.0338] values duplicates [Symbol.iterator] on array [22:44:08.0748] shu: there's a bunch of string-named methods that are equivalent to a Symbol-named one (in this case Symbol.iterator) [22:44:10.0404] but i think that is OK [22:44:16.0208] that's complete overlap [22:44:21.0968] that seems fine to me [22:44:25.0850] shu: I don't interpret rbuckton's suggestion as having a Symbol-based API. It could just as easily be that we decide that Set.prototype.intersection requires its argument to have an `asSet()` method, and that method must return an object that is iterable and has `has()` and `size`. [22:44:37.0437] NaN is not the only value for which the "return a-b" sort comparator is inconsistent. [22:44:46.0338] shu: are we talking about partial overlap? [22:44:58.0240] Bradford Smith: i wasn't responding to rbuckton's but to kevin's suggestion of `@@SetHas` and `@@SetSize` [22:45:37.0514] i am now wondering how long until this proposal morphs into the first class protocols proposal [22:47:18.0991] Michael Ficarra: yeah the partial overlap is where a lot of my dislike comes from. concretely, today, there's the public string-based API for Maps that's, like, Set-like enough because we don't have additional algorithmic constraints stipulated by union and intersect. kevin's proposal for the symbol API is now like, "actually, even more set-like, in a different namespace, with this small delta in guarantees" [22:47:22.0812] `Symbol.queryInterface` when? [22:47:47.0711] shu: ah gotcha [22:48:46.0198] that's what i meant originally by "ad hoc protocol" [22:48:50.0201] or at least, the ad hoc-ness [22:49:00.0557] any kind of virtual dispatch always runs into this problem: what constraints does this method have that aren't reflected in its type? [22:49:48.0464] no, that's actually not what i'm saying [22:50:07.0951] but it's late, i don't think it's too important for me to be clear here for the proposal [22:51:12.0368] `set.intersection(new Set(array))`, done [22:51:33.0317] i don't expect this at all [22:52:09.0408] I don't expect this either. Maybe if the only requirement was that it was iterable, but not if we want intersection to be speedy. [22:52:12.0124] ljharb: I dont' think that reasoning holds, because `new Set(map)` is useless [22:52:34.0726] Just because something can create a set with elements doesn't mean it's appropriate for functions that receive sets. [22:52:49.0298] that's not the reasoning i used [22:52:59.0511] `new Set(map)` doesn't make a set that conceptually matches the input [22:53:04.0102] `new Set(array)` however does [22:53:12.0699] * `new Set(map)` doesn't make a set that conceptually matches the input [22:53:48.0452] Michael Ficarra: but one last attempt: it's a public API evolution problem. if version 1 has one set of virtually dispatched methods, i think having version 2 where there's a new set of virtually dispatched methods where some of them conceptually overlap with the version 1 set of methods is Not Good [22:54:40.0384] What if its: "If the argument is set-like use it like a set. If the argument is iterable, make a set from it and use that. Otherwise, throw"? [22:54:49.0338] * What if its: "If the argument is set-like use it like a set. If the argument is iterable, make a set from it and use that. Otherwise, throw"? [22:59:44.0670] rbuckton: and what makes something set-like? [23:00:39.0975] Per the consensus, `size` (-ish), `has()`, and `keys()` I suppose. [23:03:29.0355] bakkot: you said you had wanted your proposal to be precedent setting. do you consider the result, which you disliked, to still be precedent setting (i.e. that we're sticking with naive string-named method duck typing)? [23:03:48.0791] * bakkot: you said you had wanted your proposal to be precedent setting. do you consider the result, which you disliked, to still be precedent setting (i.e. that we're sticking with naive string-named method duck typing)? [23:04:03.0934] I think the precedent-setting part was talking about where we put the symbols lol [23:04:08.0061] we didn't get that far [23:04:27.0819] that's what i'm asking [23:04:36.0247] do you consider this signal against protocols [23:04:47.0946] or do you consider it a one-off decision that they were a poor fit here [23:04:52.0585] well [23:04:58.0667] also with all the special casing we discussed, it would be hard to see this as precedent setting [23:04:59.0272] I want to not consider it precedent because I think it's a mistake [23:05:32.0238] then i look forward to the counterarguments for when protocols come back :) [23:05:38.0506] the arguments i heard from the other side seemed fairly general [23:05:48.0977] and intend to argue against using this design in the future in all the situations I'd argue against perpetuating any other historical mistake [23:05:55.0992] shu: no, the first-class protocols is primarily a facility for users to more easily create and consume protocols like the ones that are (sometimes) used by built-ins and syntax [23:06:05.0977] it is still good for users to do that [23:06:20.0282] yeah Symbol.iterator is still enough precedent for protocols [23:06:35.0251] Symbol.iterator was obviously good, I hope we are agreed? [23:06:44.0801] though I guess I should have asked waldemar or mark their opinions on it [23:06:47.0417] Michael Ficarra: okay, even if we do not apply it to builtins? [23:06:59.0901] even if we inconsistently apply it with built-ins, yes [23:07:05.0732] i see [23:07:10.0926] it's just as useful for building a healthy ecosystem [23:07:28.0351] i prefer nominal personally [23:07:35.0359] i agree with the need to signal a promise of conformance to some contract [23:08:20.0071] * i agree with the need to signal a promise of conformance to some contract [23:08:57.0845] bakkot: I don't know what we agree on anymore [23:11:18.0344] i guess ron's idea is pretty much nominal [23:11:35.0234] we discussed this some at the end. I don't hate that option, but I do dislike that it has subtle performance characteristics; I would prefer to make the performance characteristics more explicit by making the user do the iteration of the iterable themselves [23:11:40.0194] > <@rbuckton:matrix.org> What if its: "If the argument is set-like use it like a set. If the argument is iterable, make a set from it and use that. Otherwise, throw"? * we discussed this some at the end. I don't hate that option, but I do dislike that it has subtle performance characteristics; I would prefer to make the performance characteristics more explicit by making the user do the iteration of the iterable themselves [23:12:16.0652] i agree with that about explicit performance characteristics, unsurprisingly [23:12:36.0276] if we have nominal interface checking might as well just make it throw if it doesn't have it [23:13:07.0965] yes it's not JS-y but neither is having strong built-in behavior contracts? [23:15:11.0213] the "eagerly coerce values" behavior is one of the largest original sins of JS [23:15:49.0619] glad iterator helpers is at least starting to move away from that by guarding against `NaN` in `take` instead of just coercing it to _zero_, of all things, like `slice` does [23:16:12.0668] i'd expect erights would say the same about the "override mistake" and hidden intrinsics needing to be fixed instead of cargoculted forever [23:16:20.0293] bakkot: šŸ¤« you'll expose us [23:16:43.0503] override mistake is an original sin but nowhere near as large of one [23:17:03.0305] everyone has a sacred anticow they want to see slaughtered, and if we're condemned to repeat JS's mistakes forever, nobody'll be happy [23:17:21.0187] it makes much more sense to me to ack JS's mistakes and fix them wherever we feel we can get away with it [23:17:32.0200] override mistake is just a case of the world model implicit in the Old Scripture being lost [23:17:48.0169] i.e. prototypes being actually prototypical and designed to be cloned to make new instances [23:18:06.0074] instead of just being delegates [23:20:16.0523] The idea was that "new Foo" is "Foo.call({ ...Foo.prototype })"? [23:22:01.0592] yes [23:22:02.0227] https://en.wikipedia.org/wiki/Self_(programming_language)#:~:text=Instead%20of%20having,as%20prototypes. [23:22:09.0285] > <@shuyuguo:matrix.org> i agree with the need to signal a promise of conformance to some contract wait if you agree with this why are you on board with the thing I said I was going to do [23:22:18.0970] that doesn't signal conformance at all [23:22:26.0116] or are you agreeing in general but not this specific case [23:23:01.0767] i agree in general not with symbol-based methods [23:23:21.0341] i also think the current pervasive string-named duck typing way does signal conformance, in a really shitty way [23:24:41.0456] time for sleep [00:07:47.0246] > <@ljharb:matrix.org> i'd expect erights would say the same about the "override mistake" and hidden intrinsics needing to be fixed instead of cargoculted forever What is "override mistake"? [00:14:58.0228] the thing where `'use strict'; let x = { __proto__: Object.freeze({ prop: 0 }) }; x.prop = 1;` throws instead of assigning to a property on `x` shadowing the thing on the prototype [00:15:09.0063] iirc that if an inherited property is nonwritable, and you try to write to it, it throws [00:15:43.0852] is it proven to be web incompatible to change that? Iā€™m assume it has [00:17:12.0656] in TDZ a while back Rob Palmer said > The override mistake is the biggest of all the mistakes I would like to see fixed. Igalia investigated this on our behalf 3 years ago (I think it may have been Joyee?) and found that Lodash relies on the exception thrown in the bad case. [00:17:15.0484] so presumably yes? [00:44:40.0248] Btw is the bot magically doing better this month or do we still want a stenographer? [01:23:32.0950] I took notes for a few hours, and I still want a stenographer [01:41:40.0509] Aside from the delegate naming issue, are there bot technologies that we should be adopting and havenā€™t done, that might improve the core accuracy of transcription ? [01:49:44.0782] The main problem I continue having is that the speech-to-text API we use doesn't work well if your English doesn't have a "common" accent, making it very hard to edit its transcription of non-native speakers (me included) [01:49:58.0653] * The main problem I continue having is that the speech-to-text API we use doesn't work well if your English doesn't have a "common" accent, making it very hard to edit its transcription of non-native speakers (me included) [01:50:10.0130] But I don't think we can fix it in the bot [01:59:11.0867] For me itā€™s also that the bot is slower than the stenographer. For me to be of any use taking notes I have to add a 5-10 second delay to my audio. Which further means I canā€™t interact with what is happening. [04:35:54.0502] > <@aclaymore:matrix.org> For me itā€™s also that the bot is slower than the stenographer. For me to be of any use taking notes I have to add a 5-10 second delay to my audio. Which further means I canā€™t interact with what is happening. This is the worst part of note taking - barely being able to Fully process the presentation, let alone participate in the discussion [04:53:28.0456] OK, thanks for the feedback, I will keep going with the request to Ecma. [05:31:22.0493] > <@bakkot:matrix.org> the thing where `'use strict'; let x = { __proto__: Object.freeze({ prop: 0 }) }; x.prop = 1;` throws instead of assigning to a property on `x` shadowing the thing on the prototype So why this is "mistake"? [05:35:08.0898] > <@ljharb:matrix.org> is it proven to be web incompatible to change that? Iā€™m assume it has I remember this was ES5 decision to align with getter/setter behavior, so seems no chance to change even we can go back ES6 era. [05:36:44.0972] yes, this decision was made in the ES5 era [05:38:29.0609] > <@bakkot:matrix.org> in TDZ a while back Rob Palmer said > > > The override mistake is the biggest of all the mistakes I would like to see fixed. Igalia investigated this on our behalf 3 years ago (I think it may have been Joyee?) and found that Lodash relies on the exception thrown in the bad case. Still not get why this is the "biggest mistake"... [05:39:06.0428] I guess that was a heavily qualified statement; other mistakes are sort of clearly not on a path to be fixed [05:39:20.0380] (like, I'd love it if we could fix the mistake of typecasts all over the place...) [05:39:37.0380] (and undefined casting to NaN in particular! that is literally the worst) [05:42:11.0984] As the SES folk will tell you, the override mistake prevents simplistic freezing of all the primordials. Freezing the global object helps ensure robustness and opens up efficiencies for running semi-isolated tasks in the same runtime enviromnment. Whether this is the "biggest" mistake depends on your own personal value judgements. I have already made my peace with other "mistakes" like typeof null. [07:43:14.0674] For example [07:44:09.0227] After you freeze the Function.prototype, MyOldES5Class.toString = ... will be an error, which is very common in the ES5 era [07:45:02.0221] If Function.prototype is not frozen, doing this will not change F.prototype.toString, but define a new own property on MyOldES5Class [08:14:13.0012] But u still can use Object.defineProperty to add `toString`? [08:15:24.0154] you can, yes - but most code never uses that [08:16:39.0224] Yeah, it requires u to change code, but if someone want to use SES, they very likely need to change some codes. [08:39:28.0406] Unfortunately, it's not "change some code" most of the time, it's "patch node_modules". 2022-09-15 [17:48:31.0682] > <@aclaymore:matrix.org> For me itā€™s also that the bot is slower than the stenographer. For me to be of any use taking notes I have to add a 5-10 second delay to my audio. Which further means I canā€™t interact with what is happening. I will tweak the bot a little for this evening to make it more eager at the cost of being a little less accurate, which be a good tradeoff; we'll have to see. [17:57:10.0086] no host again? [17:58:49.0476] Appears not [17:59:15.0375] I can start it,give me a few seconds [18:00:53.0865] I don't think it asked for the code [18:01:05.0814] * I don't think it asked for the code [18:01:12.0237] You may need to refresh now to get in [18:01:17.0905] The meeting is started [18:13:15.0814] one second [18:13:46.0521] audio issue, will be sorted in a moment [18:28:21.0292] Michael Ficarra: yes to your queue question, afaict [18:28:29.0652] it is basically a const with some extra semantics [18:28:40.0502] I figured, but want to confirm [18:29:10.0082] const bindings can be closed over and don't ever *become* TDZ once they are bound, this is kind of the opposite of consts [18:29:40.0994] wait what [18:29:47.0832] how can `using` _become_ TDZ? [18:30:16.0877] after disposal I would assume that's what happens [18:30:28.0041] what that would be crazy [18:30:31.0334] does it just keep its current value? [18:30:33.0745] i hope that doesn't happen, let me read spec draft again [18:30:37.0919] it just calls @@dispose i thought [18:30:40.0868] it doesn't do any binding magic [18:31:20.0333] it's probably more useful to developers to TDZ the binding [18:32:19.0682] doesn't `let` have this same syntactic quirk? [18:32:25.0116] i am strongly opposed uninitializing the binding after disposing [18:32:43.0877] i'm also pretty sure that's not what the current proposal does [18:32:45.0608] this would be the first time we would move *to* a TDZ [18:32:58.0665] we're still a memory-safe language so I don't really see why this is an important thing to do [18:33:20.0272] it would just discourage accidental use of something that's been disposed [18:33:26.0588] it would be easier to identify bugs [18:33:32.0896] I think it's not unreasoable to move it to TDZ, it would prevent you from using a variable which is already meant to not be used anymore [18:33:45.0779] it would complicate what little more hope we have of optimizing away TDZ [18:33:54.0925] unless the disposal protocol is meant to be used on things that remain useful after disposal? [18:34:08.0463] the accidental use case would need to be from someone's disposal callback, so it'd only come up if you did `using x = {[Symbol.dispose]() { /* variable which is closed over that is also a using binding \*/ } };` [18:34:22.0375] * the accidental use case would need to be from someone's disposal callback, so it'd only come up if you did `using x = {[Symbol.dispose]() { /* variable which is closed over that is also a using binding` \*/ } }; [18:34:24.0855] the bar for messing with bindings should be very high [18:34:35.0979] > <@littledan:matrix.org> the accidental use case would need to be from someone's disposal callback, so it'd only come up if you did `using x = {[Symbol.dispose]() { /* variable which is closed over that is also a using binding` \*/ } }; IMO this case is just not worth our design energy [18:34:36.0074] littledan: no? a closure could escape [18:34:50.0470] oh, oops [18:34:59.0620] * the accidental use case would need to be from someone's disposal callback, so it'd only come up if you did `using x = {[Symbol.dispose]() { /* variable which is closed over that is also a using binding \*/ } };` [18:35:16.0305] ```js { using db = getConnection() setTimeout(() => db.query("..."), 100); } // disposes the connection ``` [18:36:02.0086] why *do* we allow const there? [18:36:07.0040] * why *do* we allow const there? [18:36:21.0185] it kind of seems like something that'd be web compatible to disallow, since it'd be unlikely someone ships that code [18:36:25.0410] moving it back into tdz is super weird [18:36:48.0178] > <@shuyuguo:matrix.org> moving it back into tdz is super weird pdz, "permanent dead zone" [18:37:13.0947] I guess implementers of the disposal protocol need to handle `use-after-dispose` anyway; moving to TDZ could help if it removed that need for them but it wouldn't [18:37:52.0111] Uhm right, it wouldn't because the disposable value can still escape even if the binding doesn't [18:38:00.0376] You just have to reassign it to a variable [18:38:50.0074] poison pill the value šŸ‘æ [18:39:26.0792] who? what? [18:39:31.0855] you can only `using` a revocable proxy, and disposal revokes it :-p [18:39:35.0746] * you can only `using` a revocable proxy, and disposal revokes it :-p [18:40:39.0840] michael it sounds like you want a language that doesn't start with java and end with script [18:41:17.0946] I really want to know whether it is ever reasonable to use a value after disposal [18:41:28.0253] or if our intent is that that is never appropriate [18:41:49.0677] a file handle could be reopened, or a DB connection? [18:41:50.0547] i think it is reasonable [18:41:54.0926] if it is not reasonable, we should do what we can to surface an error when that reuse happens [18:42:02.0548] * a file handle could be reopened, or a DB connection? [18:42:04.0322] RAII doesn't always mean "irrevocably unusable" [18:42:13.0346] sometimes you just piggyback on RAII scope to do things like locking mutexes [18:42:16.0092] or temporarily unlocking [18:42:18.0762] I think it's OK that this is the responsibility of the implementer of the disposal protocol [18:42:20.0802] those values remain usable [18:42:41.0074] objects with casual state machines are normal. double return on an iterator, double close, &c [18:42:51.0219] hey, I must have missed this slide! [18:49:19.0191] hot take: we should take everything in contextlib and explicitly avoid it [18:53:15.0363] we should normalize larger timeboxes for larger proposals [18:56:37.0447] I would be opposed to a timebox extension to discuss things we are not even considering at the moment [19:03:17.0430] yeah error cause seems weird since you'd need to mutate the other exception. AggregateError seems correct [19:04:45.0268] love me some AV issues [19:04:56.0938] > <@michaelficarra:matrix.org> I would be opposed to a timebox extension to discuss things we are not even considering at the moment IMO it is important that we give adequate time to this discussion, and most of that is on the proposal [19:05:17.0625] (especially since this is for stage advancement, so it should be especially prioritized) [19:06:32.0742] I don't understand ljharb's comment about concurrent errors--is that explaining why this model does or doesn't make sense? [19:07:06.0976] also +1 to avoiding processing nested AggregateErrors by default [19:07:14.0090] it's replying to kevin's statement about using cause instead of AE. kevin claimed something akin to "AE is for errors that occur at roughly the same time", and i was adding that i think "at the same time" isn't part of the mental model for me. [19:07:18.0193] btw I still feel `using [x] = iterable` being valid is quite the footgun. Can someone explain why it is not? [19:07:35.0805] that will usually throw immediately, no? [19:07:39.0641] because `using` will not be in scope? [19:07:42.0095] * it's replying to kevin's statement about using cause instead of AE. kevin claimed something akin to "AE is for errors that occur at roughly the same time", and i was adding that i think "at the same time" isn't part of the mental model for me. [19:07:51.0636] * because `using` will not be in scope? [19:08:03.0775] šŸ¤” hmm, okay [19:08:37.0327] `Array.prototype[Symbol.dispose] = () => {}` [19:08:48.0961] I guess a linter would help catch the unbound reference as well [19:11:05.0818] Don't we have plenty of experience in other GC'd languages which do something like `using` but don't introduce such a new form of TDZ? [19:11:16.0231] those languages don't create closures nearly as often [19:11:54.0730] what is the new tdz, i missed it [19:12:32.0120] snek: scroll up, search for TDZ [19:12:36.0455] > <@bakkot:matrix.org> those languages don't create closures nearly as often huh, maybe we should go through this case-by-case [19:12:50.0722] > <@devsnek:matrix.org> what is the new tdz, i missed it it's that the `using` binding should *enter* a TDZ when the scope ends [19:13:19.0435] like after the block executes it sets the binding to ~uninitialized~? [19:13:22.0853] snek: current slide [19:13:27.0559] i don't see slides [19:13:39.0574] i wlll reload [19:13:57.0229] ok i see [19:14:07.0314] console.group()/console.groupEnd()? [19:14:27.0280] it's a fair point that it's weird to "dispose" of something and have it still be around - disposal implies chucking it into the trash forever [19:14:44.0300] to be fair, the points are the slide are being made about the object reference, not the binding [19:14:45.0436] I agree with shu here; this isn't about freeing the memory [19:14:55.0822] This isn't C [19:15:06.0401] * to be fair, the points on the slide are being made about the object reference, not the binding [19:15:11.0430] This is about the release of resources associated with an object [19:15:17.0996] this would be valid right? `using x = y(); let xEscape = x; setTimeout(() => consume(xEscape), 100)` [19:15:18.0076] What if I need disableable is a key in a map? [19:15:26.0824] I may need to clean the entry at a later point. [19:15:45.0339] snek: that is the point about introducing a const alias on the slide [19:15:52.0213] Justin Ridgewell: would `const x = ; using x;` work? or would you need like `using y = x;` and just not use the y [19:15:55.0326] ah i see yeah [19:16:23.0090] * Justin Ridgewell: would `const x = ; using x;` work? or would you need like `using y = x;` and just not use the y [19:16:46.0798] IMO the burden of proof for use cases is on the other side; bakkot should explain what important errors are prevented by this TDZ (since it's a lot of extra work at multiple levels to provide this) [19:17:01.0564] attempting to use a file handle after closing it [19:17:02.0094] ljharb: just change the const to using, right? [19:17:05.0293] or literally anything else [19:17:35.0397] well, IMO this error should be given to you by the file implementation [19:17:42.0291] (as we've been discussing) [19:17:44.0425] i mean like if you need to use it as a key in the map, you'd just save it in a separate variable [19:18:06.0707] so I'm very confused about what I've been missing. Maybe there could be a utility class bulit-in which implements this "casual state machine" as Kris put it [19:18:43.0941] ljharb: then yes, that or the other way around `using x = ; const y = x;` [19:19:25.0050] i think i am convinced that we should do TDZ [19:20:14.0066] maybe we should take a break from this topic and come back to `using` afterwards [19:20:25.0520] while also knowing that this requires prayers for implementors [19:20:57.0868] yeah I'm leaning toward having TDZ as well, since the arguments of re-using the disposed object are about the object, and I don't see a good reason to re-use a disposed binding [19:21:22.0166] it forces you to explicitly ref it if you want to reuse it which seems good [19:21:37.0116] bakkot: I agree it's better to avoid reference the disposed thing, but could linter solve the problem? [19:21:55.0430] i don't think a linter can solve that, it requires knowledge of the runtime behavior of the program [19:22:05.0736] the linter can just say "don't close over using" [19:22:06.0642] > <@littledan:matrix.org> well, IMO this error should be given to you by the file implementation it would be nice if it did but I don't see why we want the language to do that for you? [19:22:08.0461] it doesn't need to be smart [19:22:14.0460] for example `{ using x = y(); myArray.forEach(() => thingWith(x) }) }` this is valid [19:22:15.0266] yeah all of this "TDZ" stuff could be added to any version of this proposal that we've discussed over the past several years [19:22:26.0718] shu: but we have higher-order functions on arrays and iterators and such [19:22:47.0771] > <@devsnek:matrix.org> for example `{ using x = y(); myArray.forEach(() => thingWith(x) }) }` this is valid TS may have "call immediate" concept later? [19:22:48.0369] then your linter needs to do escape analysis [19:23:55.0119] every linter is now also a symbolic interpreter [19:23:58.0387] * every linter is now also a symbolic interpreter [19:24:20.0771] > <@bakkot:matrix.org> it would be nice if it did but I don't see why we want the language to do that for you? so, in general, no? I don't want the language to have half-working state tracking mechanisms that libraries will need to duplicate. [19:24:43.0183] the duplication of state is *necessary* anyway for soundness [19:24:54.0862] what concept is this, and why would a possible future TS concept block a JS language feature? [19:25:00.0414] there are two competing mental models here: 1) `using` being about single-use, and 2) `using` being about registering functions to call on lexical scope exit [19:25:22.0587] i don't see those are competing [19:25:28.0905] one of those is the use case and the other is the mechanism [19:25:37.0220] > <@shuyuguo:matrix.org> there are two competing mental models here: 1) `using` being about single-use, and 2) `using` being about registering functions to call on lexical scope exit I think current proposal more close the 1, not 2, if 2, we should choose "defer" syntax like Go. [19:25:48.0379] is this about naming? [19:25:52.0182] is this because it's called @@dispose? [19:26:00.0618] I'm in 100% agreement with all the arguments that Ron is making [19:26:03.0569] not for me [19:26:04.0964] yes, +1 to Ron [19:26:16.0295] function f() { let x = 3; return () => x; }; f()(); is 3 == why would "using x" be different? I'm missing something somewhere. Is KG saying "x" should become undefined after its dispose is called? [19:26:34.0668] I don't think "we have lamented TDZs" speaks for all of us. [19:26:59.0545] > <@bradfordcsmith:matrix.org> function f() { let x = 3; return () => x; }; f()(); is 3 == why would "using x" be different? I'm missing something somewhere. Is KG saying "x" should become undefined after its dispose is called? it'd be a TDZ error, like if you did `x; let x;` [19:27:31.0522] so it would throw an error [19:27:40.0079] > <@bradfordcsmith:matrix.org> function f() { let x = 3; return () => x; }; f()(); is 3 == why would "using x" be different? I'm missing something somewhere. Is KG saying "x" should become undefined after its dispose is called? I am saying it should be _an error_, not undefined [19:27:56.0174] and it should be an error because you are attempting to access a binding after the binding has been disposed [19:28:21.0055] I am confused by the "not discoverable" claim [19:28:24.0459] that seems... super discoverable? [19:29:00.0130] the use case here (at least the use case i am interested in) is resource management. i think the tdz provides an important guard against misuse when taking advantage of that use case. (i would also not be interested in advancing a "golang defer" proposal) [19:29:14.0860] > <@shuyuguo:matrix.org> is this about naming? * the use case here (at least the use case i am interested in) is resource management. i think the tdz provides an important guard against misuse when taking advantage of that use case. (i would also not be interested in advancing a "golang defer" proposal) [19:29:39.0938] i'm really not sure when i would want to use this without the tdz [19:30:19.0000] if anyone has an example of when you would want to use this without a tdz i would be interested [19:30:36.0223] To be honest, I like TDZ, but I can also live without TDZ. [19:32:05.0367] If there was an "use stricter", I would like it have TDZ šŸ˜‚ [19:33:55.0692] > <@devsnek:matrix.org> i'm really not sure when i would want to use this without the tdz same, and the only response given was "aliasing bindings is hard", which I do not buy in the slightest [19:34:20.0268] This is a naive question:. Would it not be possible to throw on capturing the using binding instead of a TDZ? [19:34:35.0206] i think throwing on capture would be too strict [19:34:44.0918] for example if you use array.forEach [19:34:54.0819] that fulfills the requirement of completing within the block [19:35:13.0708] and actually [19:35:18.0856] if you had to alias for all captures [19:35:28.0311] you'd lose the ability to catch aliases that were too lenient [19:35:45.0699] unless you manually `undefined` all of them at the end of the scope [19:35:56.0335] True [19:35:56.0882] which is sort of a recursive loop back to "i want to clean things up at the end of a scope" [19:36:32.0101] Just running through my head other ways to solve the issues involved here [19:37:50.0502] yeah i think we should probably not advance the proposal today [19:37:56.0050] lots of things for people to think about [19:38:17.0943] the concept is TS could have the type info that the function would be call immediately, so will not extend the lifetime of the bindings captured by the closure. I don't mean this should block something. Just want to discuss whether the argument could be solved by tools (not by language). [19:38:36.0484] i don't use TS though [19:38:48.0258] except for at work [19:40:02.0276] bakkot: what if theoretically it was written as `use(resource, onDispose = undefined)` [19:40:34.0895] Isn't the second form for passing resources that may not have a dispose method itself, and there is not a desire to wrap it? [19:41:07.0254] personally i'd be fine with the proposal not having the disposablestack api [19:41:14.0830] it seems trivially implementable in userland it think? [19:41:16.0267] * it seems trivially implementable in userland it think? [19:41:22.0685] > <@anthonybullard:matrix.org> This is a naive question:. Would it not be possible to throw on capturing the using binding instead of a TDZ? I think it's too strict, unless we have block param proposal advanced which might support syntactical call immediate semantic. [19:44:27.0461] Second one could be `useWith`? [19:57:47.0371] the "web platform collaboration" queue item is also sort of a blocking issue that I want to get on the record [20:00:16.0005] I already raised this issue in GitHub https://github.com/tc39/proposal-explicit-resource-management/issues/95 ; I hope this can be followed up on before Stage 3 [20:03:39.0206] dminor: I'd like to understand better why Mozilla is unconvinced by the need for syntax; I think this has been explained well since the beginning. [20:06:21.0422] The discussion we had is that we would like to see more evidence as to why try/finally is not adequate to solve these use cases [20:06:31.0483] > <@ljharb:matrix.org> you can only `using` a revocable proxy, and disposal revokes it :-p ... honestly I don't hate that [20:06:34.0054] I guess maybe I do hate that [20:06:39.0683] it's a fun idea though [20:06:44.0505] bad, but fun [20:07:09.0127] if anyone doesn't hate it, i made a terrible terrible mistake [20:07:15.0852] if it weren't for the identity discontinuity I would not hate that [20:07:35.0297] > <@dminor:mozilla.org> The discussion we had is that we would like to see more evidence as to why try/finally is not adequate to solve these use cases One of my main motivations is related to how `try..finally` is *not* adequate to solve these cases given the complex nesting that needs to occur when working with multiple resources. [20:08:06.0590] since not everyone even uses a linter, which is an uncontroversial best practice, let alone a type system, which is not an uncontroversial best practice, i don't think solving it with tooling is sufficient [20:08:42.0198] > <@dminor:mozilla.org> The discussion we had is that we would like to see more evidence as to why try/finally is not adequate to solve these use cases I believe developers don't tend to make good enough use of try/finally since it's too wordy, and just leak things instead--I think this is why many other languages have added this construct despite also having try/finally (itself a validation) [20:08:59.0954] it will be good to collate evidence here, I agree, but I think we can do that [20:09:21.0963] dminor: Is there an issue tracking your feedback, so we can collect this information there? [20:09:27.0480] > <@ljharb:matrix.org> it kind of seems like something that'd be web compatible to disallow, since it'd be unlikely someone ships that code re the "why do we allow const in for-loop heads", https://github.com/tc39/proposal-explicit-resource-management/issues/96#issuecomment-1239940758 [20:09:29.0614] > <@dminor:mozilla.org> The discussion we had is that we would like to see more evidence as to why try/finally is not adequate to solve these use cases I believe the README already give the solid motivations? For example, It's too hard to manage multiple resource correctly... [20:09:53.0247] `try..finally` also has the limitation of suppressing exceptions from the body, which are valuable for both logging and error recovery purposes. [20:10:10.0248] so here's a use case where i don't want tdz: recursive mutexes. to be sure, it's expressible even in the case of a TDZ via additional aliasing but that is not something i want to type. my intuition here is that the usual extreme badness about closing over stack-lifetimed variables is memory safety, which is not the footgun here. so my expectation is that most objects would throw at runtime in _some_ way after being disposed of anyways, instead, for example, accessing random memory. if TDZ throws a runtime error, i expect that to be net the same effect, except with extra implementation burden (at least the investigative portion, if not also the implementation complexity portion) [20:12:51.0055] > <@shuyuguo:matrix.org> so here's a use case where i don't want tdz: recursive mutexes. to be sure, it's expressible even in the case of a TDZ via additional aliasing but that is not something i want to type. > > my intuition here is that the usual extreme badness about closing over stack-lifetimed variables is memory safety, which is not the footgun here. so my expectation is that most objects would throw at runtime in _some_ way after being disposed of anyways, instead, for example, accessing random memory. if TDZ throws a runtime error, i expect that to be net the same effect, except with extra implementation burden (at least the investigative portion, if not also the implementation complexity portion) This matches my intuition as well. Disposable objects should guard against use that is inconsistent with their state regardless as to whether you used `using` or `let/const`. However, such a guard is not *mandatory* as there are valid use cases for disposables that can be reused, such as re-opening a connection. [20:13:49.0954] Enforcing this both in the object itself and in the `using` binding (by introducing a new TDZ) seems excessive. [20:15:50.0968] Could we have an example of reusing so I can understand it more easy? thank u! [20:16:34.0458] > so here's a use case where i don't want tdz: recursive mutexes. to be sure, it's expressible even in the case of a TDZ via additional aliasing but that is not something i want to type. Can you write out the example there? [20:19:24.0671] meh, i don't find that compelling at all [20:19:37.0247] > <@haxjs:matrix.org> Could we have an example of reusing so I can understand it more easy? thank u! Since we don't have `using void`, essentially: ```js const connection = new Connection(); connection.open(); { using _ = connection; ... } // connection is closed connection.open(); { using _ = connection; ... } // connection is closed ``` [20:20:20.0071] We want to guarantee the connection is closed in both the normal and exceptional cases, so that we can reopen it following the block. [20:20:52.0187] This is a bit contrived, for a more real world example I'll have to spend more time putting something together. [20:22:00.0472] so in those case you aren't... reusing the binding [20:25:16.0317] This example seems weird to me... [20:27:33.0458] Why we can't write `using conn = Connection.open()` twice and let `Connection` class do the reusing of underlying connections? [20:28:31.0238] bakkot: something like https://gist.github.com/syg/26e303748b5ebc3ed5206a2b875293fb [20:28:59.0744] err there's a typo there [20:29:56.0205] > <@bakkot:matrix.org> so in those case you aren't... reusing the binding No, sorry. That example relates to general reuse of a disposable. [20:30:57.0068] i'd also like to better understand what the badness is with closing over a disposed thing [20:31:07.0842] like, what do you expect to happen, if it's not a runtime error, since that's what the TDZ gives you [20:31:23.0893] is it "it might do some other stuff before getting to the error point"? [20:31:37.0885] are your errors generally recoverable? is it bad that it did some other stuff? [20:32:43.0670] it is potentially bad that it did some other stuff, certainly [20:32:53.0666] As far as binding reuse, the example is not much different than the example in your issue: ```js { using x = foo(); cache.set(x.url, data); ... setTimeout(() => cache.delete(x.url), 100); } ``` [20:32:55.0453] but more generally, the language should give you an error at the point at which it is obvious you have made a mistake [20:33:18.0794] my contention is that in practice, it does, because most objects would throw in some fashion at runtime after having its internal resources disposed [20:33:36.0768] if we had a static TDZ then i would not be of this opinion [20:33:51.0909] > <@rbuckton:matrix.org> As far as binding reuse, the example is not much different than the example in your issue: > ```js > { > using x = foo(); > cache.set(x.url, data); > ... > setTimeout(() => cache.delete(x.url), 100); > } > ``` that seems like it is a mistake - you're using `x` after it's been disposed. it seems like the language should prevent you from doing that. [20:34:10.0378] that's the philosophical difference [20:34:25.0222] if you explicitly want to use the object after it's been disposed, you should put it in a binding other than the one which is going to get disposed. [20:34:29.0669] Yes, you can create another `const` to capture `x.url` to close over it, but that seems awkward just to enforce something via the binding that the disposable itself also needs to enforce internally. [20:34:30.0799] i do not think it is a mistake to reuse `x` after it's been "disposed", which i take to mean no more than "had some scope exit function ran" [20:34:51.0348] a scope exit function named `Symbol.dispose`, like from `DisposableStack` [20:34:59.0184] it's not like I am making up the word "dispose" here [20:35:06.0847] that's why i asked is it a naming issue earlier [20:35:17.0224] i thought ron named it thus cribbing from C# terminology [20:35:21.0442] also the proposal is about resource management [20:35:24.0249] > <@bakkot:matrix.org> that seems like it is a mistake - you're using `x` after it's been disposed. it seems like the language should prevent you from doing that. Not if `x.url` isn't related to the memory/native resource/etc. that `x` is holding. [20:35:49.0177] i am sorry to say i'm not sure how either side can be swayed here [20:36:06.0813] if seems to boil down to i think this pattern isn't a mistake, while you do [20:36:12.0493] > <@rbuckton:matrix.org> Not if `x.url` isn't related to the memory/native resource/etc. that `x` is holding. I mean that if I saw that code snippet in any codebase, I would assume it was a mistake and ask the author to rephrase it [20:36:28.0385] if i saw that in C++ or Java i would! [20:36:35.0186] but memory safety isn't an issue here! [20:37:46.0588] I'm concerned that introducing a new TDZ to enforce this is overkill. It will impact host implementations and introduce complexity for valid cases (by requiring a `const` alias), for almost no added benefit when disposables also need to guard themselves. [20:38:12.0238] memory safety isn't an issue, but the whole concept of this proposal is that you are tying the lifetime of a resource to a specific binding. like, that's why it makes sense to have a thing happen at "scope exit" - because once you leave the scope, you are no longer able to use the binding. [20:38:18.0114] except that you are, through closures which outlive the binding. [20:38:33.0005] i hear you, but i have it layered the opposite way in mind [20:38:39.0360] but if you are able to reuse the binding after the scope has exited, it does not make sense to tie the lifetime of the resource to the scope [20:38:51.0149] Calling `x[Symbol.dispose]()` doesn't explicitly free memory. If you didn't have `using` the object would still be resident in memory. It merely informs the object it should dispose of any relevant resources it holds. [20:39:06.0892] the useful thing of this proposal, regardless of its name and the name of `Symbol.dispose`, is to register a thing to happen at "scope exit", which IME extends beyond resource management [20:39:26.0785] that would be Go's `defer`, which is a reasonable alternative to this proposal [20:39:30.0628] so i see no compelling reason to build in a hairshirt for resource management, because that's an enabled use case, not the sole value to me [20:39:30.0746] however, that is not this proposal [20:39:57.0851] it is this proposal mechanically via an object method? [20:40:23.0226] Unfortunately, go's `defer` doesn't help with inconsistent resource management APIs in the web and NodeJS platforms. `defer` isn't composable in the same way that `[Symbol.dispose]` is. [20:41:17.0925] Yeah I see making a symbol-based protocol for disposal as an extremely useful part of this proposal [20:41:24.0071] Also, Go's `defer` is function-scoped, not block-scoped, which is a very coarse grained lifecycle. [20:41:51.0060] > <@shuyuguo:matrix.org> it is this proposal mechanically via an object method? you can use it for the same effect, but you can also use `try finally` for the same effect. everything about the shape of the API - the introduction of a binding, the name of the method, the fact that it is called `using` - implies it is for resource management. that is the thing it is for, that is the problem it is solving. [20:42:07.0338] it is nice that you can also use it for registering a thing to run at scope exit [20:42:21.0812] but if we wanted to introduce specifically "register a function to run at scope exit", that would not look like this proposal [20:42:51.0777] * it is nice that you can also use it for registering a thing to run at scope exit [20:42:54.0932] * but if we wanted to introduce specifically "register a function to run at scope exit", that would not look like this proposal [20:43:36.0922] But that isn't the only problem it solves, even if its the most common case. You're suggesting we introduce a new TDZ mechanism, and that feels very heavy handed. [20:43:51.0888] i find having an object registered with it valuable [20:44:01.0945] it genuinely feels _more surprising_ to me to have the binding outlive the scope than not. [20:44:29.0867] since the whole design of the proposal assumes that the end of the scope is when you are done with the thing [20:44:38.0006] * since the whole design of the proposal assumes that the end of the scope is when you are done with the thing [20:44:58.0187] `using` is essentially a special form of `const`, and `const` values remain immutable. Introducing TDZ makes it mutable since its value (or whether you can even inspect that value) can change. [20:45:16.0208] `const` also has tdz. [20:45:25.0955] it is no more mutable than `const` is. [20:45:29.0915] again, i contend, the existing intuition that we need TDZ and the footgun is bad is because RAII is mostly used in languages in conjunction with stack-lifetimed bindings, so memory safety becomes an issue [20:45:30.0818] only until it is initialized. [20:45:49.0415] that intuition doesn't really apply here [20:45:50.0470] > <@bakkot:matrix.org> it is no more mutable than `const` is. It's definitely more mutable than `const` is. [20:46:01.0372] in that it has two points at which it changes rather than one? [20:46:02.0603] I mean [20:46:07.0385] that is technically "more" but like [20:46:12.0811] not fundamentally different. [20:47:37.0162] > <@shuyuguo:matrix.org> so here's a use case where i don't want tdz: recursive mutexes. to be sure, it's expressible even in the case of a TDZ via additional aliasing but that is not something i want to type. > > my intuition here is that the usual extreme badness about closing over stack-lifetimed variables is memory safety, which is not the footgun here. so my expectation is that most objects would throw at runtime in _some_ way after being disposed of anyways, instead, for example, accessing random memory. if TDZ throws a runtime error, i expect that to be net the same effect, except with extra implementation burden (at least the investigative portion, if not also the implementation complexity portion) wouldn't this be `using mutex.lock()` not `using mutex`? [20:47:54.0656] like how it works in other languages [20:47:55.0768] * like how it works in other languages [20:48:53.0836] I prefer not to introduce the TDZ unless it is a major blocking concern as I'm not convinced its warranted. That said, I have already put together a PR to implement it if it becomes necessary for advancement. [20:49:30.0546] > <@devsnek:matrix.org> wouldn't this be `using mutex.lock()` not `using mutex`? More like `using lck = mutex.lock()` (or previously `using void = mutex.lock()` if you didn't need the binding). [20:49:44.0685] yeah, but that gets rid of the problem with needing an alias [20:49:49.0336] did you see the example? [20:49:54.0767] > <@shuyuguo:matrix.org> again, i contend, the existing intuition that we need TDZ and the footgun is bad is because RAII is mostly used in languages in conjunction with stack-lifetimed bindings, so memory safety becomes an issue I don't really write that much C++ these days; I don't think that's where my intuition is coming from. my intuition is coming from the fact that the end of the scope is when we call the dispose method. the only reason that "end of scope" is a sensible place to call this method is because the binding is _going out of scope_, so that you can't using it in the code after the scope. so we should throw an error if, through a closure, you use the binding after that point. [20:50:06.0727] uhhh i guess not? [20:50:20.0076] i might've missed stuff i scrolled way up [20:50:24.0846] snek: https://gist.github.com/syg/26e303748b5ebc3ed5206a2b875293fb [20:50:46.0973] hmmm ic [20:50:59.0978] i guess that is a way to do that [20:51:04.0894] bakkot: i understand your viewpoint, i think, but it is not my viewpoint [20:51:30.0689] shu: in your viewpoint, why is the end of the scope a sensible place to be running code associated with this binding, then? [20:52:35.0464] because that's the syntactic affordance to lump together a transaction-like operation [20:53:03.0247] that's a reasonable reason to run code at the end of a scope, like `defer` (except for the function-vs-block thing). [20:53:11.0731] but why is that a reason to run code _associated with a particular binding_? [20:53:42.0509] because JS is OO and i also prefer to associate state with my code instead of making new closures, since chances are it's already structured with objects with state? [20:53:55.0042] > <@bakkot:matrix.org> but why is that a reason to run code _associated with a particular binding_? well, because empirically, you often want to both bind to something and dispose of it [20:54:11.0434] and C++ experience shows this is *good enough* [20:54:23.0707] littledan: if you are thinking of "dispose", you are not thinking of "lumping together a transaction-like operation" [20:54:34.0347] i guess shu i would say if you want something with that exact api you should probably be making an alias to signal your intent for it to escape the scope [20:54:39.0215] i get how that's annoying though [20:54:59.0012] > <@shuyuguo:matrix.org> because JS is OO and i also prefer to associate state with my code instead of making new closures, since chances are it's already structured with objects with state? I do not really understand how that's responsive to my question? [20:55:11.0660] that's a reason to run code associated with a particular _object_, but not a particular _binding_ [20:55:37.0551] the thing which registers code to be run is the introduction of the binding [20:55:44.0026] * the thing which registers code to be run is the introduction of the binding [20:56:05.0346] snek: and i would say that's not something i want to type, given that in practice my hypothesis is most objects who have had their internal state disposed would throw anyway, and errors are not recoverable IME in practice so i'm also not too worried about "doing bad things before the object got to the point of throwing the error" [20:56:57.0539] yeah i guess [20:57:01.0055] the sole existing example of a thing which is disposable in the language, iterators-as-created-by-generators, do not throw when you use them after calling their disposal method. [20:57:02.0446] what if the api of your mutex was just different [20:57:35.0952] let's take a step back. i don't see either side being swayed by these lines of argument [20:57:41.0628] how do we move forward? [20:58:01.0253] We are resuming plenary in 2 mins! Is rbuckton around? [20:58:20.0572] well, it might be worth thinking about the problem more than one day [20:58:22.0868] `using(with-tdz) x = y()` [20:58:42.0261] nicolo-ribaudo: are you around to present if Ron is not? [20:58:57.0538] but if we are permanently stuck, I dunno, vote? unless you want to use your implementor veto to say you are unwilling to implement it, in which case, I guess it goes forward without tdz. [20:58:57.0788] bakkot: well yes, agreed to that [20:59:15.0176] I agree most opinions of bakkot , but I don't think this should be a block issue. I still think it could be solved by static analysis tools. [20:59:23.0276] It seems extremely soon to declare ourselves permanently stuck. We made a ton of progress today, I think [20:59:30.0791] static analysis can't solve this unless it gets a lot better [20:59:36.0610] i would need to do what mark asked and actually investigate the implementation difficulty before saying i am unwilling to implement [20:59:38.0226] let's keep bringing this topic back to committee to ensure we get broad review and keep making progress [20:59:43.0589] * i would need to do what mark asked and actually investigate the implementation difficulty before saying i am unwilling to implement [20:59:57.0830] the whole reason it's called _temporal_ dead zone is because it's temporal, not lexical; it's quite hard to analyze statically [21:00:26.0001] but it has not risen to that level of time commitment for me yet [21:00:44.0667] > <@bakkot:matrix.org> static analysis can't solve this unless it gets a lot better yeah we need rust compiler -like tool... hope it won't as slow as rust compiler šŸ¤Ŗ [21:01:02.0625] linear-typescript [21:01:32.0149] we could modify prepack [21:01:42.0141] did prepack ever start working? [21:01:46.0268] prepack sort of works [21:01:49.0424] if you only give it simple es5 [21:01:51.0643] everything I ever ran it on it either did nothing or ran forever [21:02:02.0753] * if you only give it simple es5 [21:02:28.0447] shu i do wonder like [21:02:56.0432] your example requires a pretty good understanding of some complex programming concepts [21:03:01.0902] * Rob Palmer: tcq needs advancing [21:04:22.0892] snek: if the problem to solve is common footguns that befall beginner programmers, a lint that prevents closing over `using` bindings at all but allowlists Array combinators is probably sufficient [21:04:35.0086] šŸ˜” [21:11:05.0774] current pattern match `when (${xxx} with {...})` is too tedious...šŸ˜­ [21:13:03.0591] bindings must be explicit; how could that be less tedious? [21:14:00.0314] Yeah syntax is hard. [21:14:15.0224] scala is not a language I would hold up as an example of a mature and cohesive programming language [21:14:45.0635] I don't even think the people who work on Scala would claim that [21:14:55.0693] it's not even their goal [21:15:44.0540] > <@bakkot:matrix.org> scala is not a language I would hold up as an example of a mature and cohesive programming language There are many languages have similar feature, not only scala [21:16:41.0509] yeah I just thought it was funny to introduce the feature by talking about scala and then say the goal is cohesiveness [21:17:07.0656] All those languages have something in common: you have to be at least this tall to ride. [21:17:24.0332] oh look, a 10th meaning of `this` [21:17:51.0605] šŸ‘‰ [21:18:01.0232] Kris Kowal: are you saying JS is a language for short kings [21:18:51.0929] > <@bakkot:matrix.org> yeah I just thought it was funny to introduce the feature by talking about scala and then say the goal is cohesiveness I think the cohesiveness is about destructuring and pattern match? [21:19:34.0819] wait who says calls can't be the target of an assignment? [21:19:38.0982] "cannot be the target of an assignment" ehhhh that is not as true as it should be but almost is true [21:20:30.0170] > <@shuyuguo:matrix.org> Kris Kowal: are you saying JS is a language for short kings No, but valid [21:20:34.0920] IIRC IE can do that in the past but it is a Reference Error? [21:20:54.0982] > <@michaelficarra:matrix.org> wait who says calls can't be the target of an assignment? it could, but give u referenceerror [21:21:15.0911] HE Shi-Jun: depends on the reference returned by the call [21:21:53.0826] I can't write an ECMAScript function that returns such a reference but there can be host-provided built-ins that do [21:22:26.0164] > <@michaelficarra:matrix.org> HE Shi-Jun: depends on the reference returned by the call so how can function return something won't cause ref error as assigment target? [21:22:55.0141] > <@michaelficarra:matrix.org> I can't write an ECMAScript function that returns such a reference but there can be host-provided built-ins that do Oh, that would be cool! šŸ¤© [21:23:16.0711] HE Shi-Jun: IE used to provide built-ins that did this for interacting with VB scripts [21:25:41.0655] Maybe this proposal should only allow const/let declaration, not assigment. [21:29:18.0082] > <@michaelficarra:matrix.org> I can't write an ECMAScript function that returns such a reference but there can be host-provided built-ins that do no we made that illegal I think? [21:29:40.0736] correct [21:31:05.0684] when did we do that? [21:31:11.0957] I really like this proposal, but I think the InstanceExtractor is a kind of odd case--I hope this kind of feature is used mostly for cases where, what you have on the LHS could've done the inverse on the RHS [21:31:50.0612] similarly, IMO we should add the object extractor syntax only in conjunction with a corresponding expression syntax (and filed https://github.com/rbuckton/proposal-extractors/issues/2 about this). I'm fine with it being included for Stage 1 though. [21:39:06.0698] I like ThisOne(a, b), but I'm a little hesitate on ThisOne { a, b } [21:39:52.0945] `const { Map(foo): { bar, baz: { quzzz } } } = obj;` ? [21:40:05.0761] i.e. move the function name to the property being extracted, rather than the RHS [21:40:43.0645] no? [21:41:01.0680] heh, i mean in terms of getting away from `Thing{` but yeah [21:54:24.0792] There's ambiguity when people say "Stage $n concern"--sometimes people mean, an entry requirement, sometimes people mean something to do within that stage [21:54:42.0289] I think this has caused miscommunication in the past; maybe we need other ways to refer to this [21:54:54.0645] I think it means the latter [21:55:23.0218] was yulia's big document about pattern syntax mentioned at all [21:56:10.0181] the epic? [21:56:12.0743] someone mentioned the epic [21:56:40.0159] > <@littledan:matrix.org> I think this has caused miscommunication in the past; maybe we need other ways to refer to this For example, "Stage $n *entry* requirement", "Stage $n *exit* requirement", "Topic for investigation *during* Stage $n" [21:57:21.0693] > <@shuyuguo:matrix.org> someone mentioned the epic I think they mentioned epoch (which can be a homonym for epic in some kinds of English) [21:57:31.0406] but yeah it's just been allusions [21:57:45.0477] tersness is less important than symmetry for me [21:57:50.0364] symmetry is the compelling thing that this has [21:58:04.0077] https://github.com/codehag/pattern-matching-epic [21:58:09.0466] oh! oops [21:58:15.0246] if anyone hasn't seen this [21:58:18.0915] it is a good read [21:58:29.0478] there was also a google doc somewhere [21:58:48.0411] oh its linked as "my analysis" in the readme cool [21:58:54.0717] I'm a little agree this is "just more clever" in most cases without pattern matching, but pattern matching won't add it unless it is in the destructing [21:59:17.0096] rbuckton: Revisiting examples could also be good; I don't think the InstantExtractor is a very intuitive use case [21:59:19.0191] It's just symmetry to constructor/factory. [21:59:56.0892] So if u need to look inside to understand what factory do, u also may need do the similar thing. Abstraction always have cost. [22:00:41.0675] bakkot: pattern matching subsumes switch and i would argue is way more intuitive at first glance than extractors/unapply/etc [22:00:59.0486] depends on whether pattern matching has Symbol.matcher [22:01:18.0693] i see what you're saying there, yes [22:01:44.0771] but i don't think the issue mark is talking about with extractors is "it invokes a protocol", since we have lots of examples of that [22:05:18.0469] mark was saying match has a lot of syntax, which I definitely agree with [22:05:45.0500] i think that is a matter of fact, yes [22:07:21.0154] tc39 hats for note takers [22:07:51.0207] "I took notes at a TC39 meeting and all I got was this tshirt" tshirts [22:08:03.0732] I agree it has a lot of syntax, but I also find pattern matching so valuable that its more than worth it. [22:08:33.0094] > <@devsnek:matrix.org> tc39 hats for note takers I was about to announce I have a hat to give away, but I only have one and have become attached to it. [22:08:56.0332] Rob Palmer: sacrifices must be made [22:09:05.0041] I have two, but they are both well loved. [22:25:53.0764] thanks nicolo-ribaudo for this pr. this makes my implementation of compartment proposal much easier. [22:25:56.0271] this is turning into kingdom hearts [22:26:51.0384] are you ready for me to show up dressed up as goofy with a keyblade [22:27:11.0888] always [22:27:12.0251] yes [22:27:27.0464] Thanks nicolo-ribaudo! [22:27:31.0140] yay congrats nicolo-ribaudo ! [22:32:46.0292] if Object.freeze(), does that mean it can't be do brand check? [22:33:30.0458] there's no brand to check, you get a plain object back (but frozen) [22:33:45.0213] yes in that case there is no Record exotic object [22:33:50.0124] > <@haxjs:matrix.org> if Object.freeze(), does that mean it can't be do brand check? ok i hear that it's just ordinary objects. fine. [22:49:09.0033] wait do boxed records exist or not [22:49:12.0743] i thought this gets rid of them [22:49:18.0466] this would get rid of them [22:49:19.0640] * this would get rid of them [22:49:36.0153] what is all this about debugging [22:49:39.0220] i.e. passing a record to `Object` just makes a `Object.create(null)` [22:49:50.0069] that if you ran into one of these it should be debuggable [22:49:58.0258] hmmm [22:50:01.0251] so like [22:50:28.0504] there would be a differenec between `Object.create(null, { a: { value: 1 } })` and `Object(#{ a: 1 })`? [22:50:35.0584] even though the point is that they emit identical things? [22:50:49.0526] also freeze it [22:50:56.0155] but no difference between those two, other than that [22:51:02.0013] * but no difference between those two, other than that [22:51:06.0811] there isn't, i think jordan is saying boxed primitives are important from his experience, so even if this isn't a boxed primitive, he wants the provenance to be programmatically discoverable [22:51:08.0328] right with freezing [22:51:19.0162] but we don't do that for any other thing [22:51:31.0718] well, we have a boxed primitive for the other things [22:51:44.0505] if provenance is the problem obviously we need PNVI-ae-udi [22:51:45.0987] well but this isn't a boxed primitive (and around we go :) ) [22:51:49.0139] > <@shuyuguo:matrix.org> there isn't, i think jordan is saying boxed primitives are important from his experience, so even if this isn't a boxed primitive, he wants the provenance to be programmatically discoverable maybe replay.io is a good solution for such debugging flows [22:51:54.0722] to be clear i don't endorse his view [22:53:10.0063] i don't think "someone had a feature request on a library of mine" is a signal [22:53:30.0465] waldemar: `typeof thing === "record"` [22:53:46.0538] provenance of objects sounds like a fun devtools exercise [22:53:51.0406] not a language feature [22:54:39.0558] Is there any other built-in (primitive or otherwise) where (without modifying prototypes) `a == b` throws? That seems kind of bad, especially since people frequently do `a == null` tests. [22:54:59.0893] hm that's interesting [22:55:20.0169] can `==` throw? [22:55:21.0457] To jump ahead and answer Waldemar's question: typeof! [22:55:25.0448] yes `==` can throw [22:55:31.0906] oops rickbutton sniped me [22:55:38.0659] it can invoke arbitrary code [22:55:48.0226] Yeah, if you have a bad `Symbol.toPrimtive` or `valueOf`, etc. But not for any existing built-ins. [22:55:49.0937] this is news to me [22:55:59.0169] but as far as default behavior, the null check is a common pattern [22:56:12.0611] `'a' == { valueOf: () => null[0] }` [22:57:10.0085] oh i see i was confused by the recursive calls using `!` [22:57:18.0837] there is a little `? ToPrimitive` [22:57:43.0520] also `groupBy` results [22:57:49.0893] which have null proto [22:58:19.0624] how have i never noticed that `==` fails on null proto objects [22:58:21.0119] that is nuts [22:58:47.0910] More and more reason to never use `==`. [22:59:03.0622] it's fine as long as the RHS is `null` [22:59:09.0816] just not for anything else, ever [22:59:24.0176] it's fine if both sides have same type [22:59:25.0699] the `== null` unary operator [23:03:41.0931] > <@devsnek:matrix.org> how have i never noticed that `==` fails on null proto objects `Object.create(null) == null` doesn't throw? [23:04:47.0076] `Object.create(null) == ''` does though [23:05:01.0402] yes. That's what I said in the meeting :) [23:05:06.0520] compare to null is safe [23:05:20.0084] Travel information to Spain is here: https://github.com/tc39/Reflector/issues/446 [23:05:21.0722] the reason the example in the PR throws is because we are comparing to a non-null primitive [23:10:10.0981] Too tired to read the spec for module namespace. But trying in a console: ``` const m = await import('data:text/javascript,export default {};') Reflect.ownKeys(m); // ['default', Symbol(Symbol.toStringTag)] Reflect.getPrototypeOf(m); // null m == null; // false ``` [23:36:03.0712] shu: https://github.com/tc39/proposal-explicit-resource-management/issues/97 is the issue for TDZ for `using` bindings if you want to continue there [05:08:35.0282] The ecmarkup lint capabilities are getting quite nice, maybe one day it will be a full language server! [08:03:13.0993] possibly someday, but right now it's mostly a huge mess of regexes [08:03:22.0784] it's remarkable how far regexes will get you [14:20:27.0598] > <@nicolo-ribaudo:matrix.org> The ecmarkup lint capabilities are getting quite nice, maybe one day it will be a full language server! I was working on this, but I haven't had much time recently 2022-09-19 [17:10:34.0882] Michael Ficarra: I can't get the slides of first class protocol proposal (https://docs.google.com/presentation/d/1HnxJl4Iodf3I23e-ZDkw4F1LEkMRGUBFq6xxR0a9a_k/edit#slide=id.g3e3a1a53c0_0_0 ) now (access denied). [09:21:38.0900] HE Shi-Jun: yeah our IT department broke all of our google docs links when they transitioned us to the Microsoft stuff, despite my protests [09:23:04.0134] we should probably do more to archive slide presentations when they were given... rwaldron and allenwb used to do some of this way back when, but we don't seem to have kept up. [09:24:07.0126] agreed [09:24:26.0620] HE Shi-Jun: where did you find that link? [09:25:08.0100] I'm assuming that is the presentation you were looking for [09:31:37.0059] Michael Ficarra: link to the dead presentation is in the readme https://github.com/tc39/proposal-first-class-protocols#what-does-it-look-like [09:32:22.0164] cool, I'll just inline the appropriate content 2022-09-20 [17:54:52.0519] > <@haxjs:matrix.org> Michael Ficarra: I can't get the slides of first class protocol proposal (https://docs.google.com/presentation/d/1HnxJl4Iodf3I23e-ZDkw4F1LEkMRGUBFq6xxR0a9a_k/edit#slide=id.g3e3a1a53c0_0_0 ) now (access denied). That link is fixed now. Let me know if you find any others. [22:59:33.0848] Oops, document.getElementById("foo") is 4-5x slower then document.getElementById("fooba") in Blink... This bug (seems have been fixed in Canary) surprised me... https://bugs.chromium.org/p/chromium/issues/detail?id=1365267 2022-09-22 [04:53:09.0919] reminder: if you plan to attend the next (nov/dec) meeting in person, please let us know ASAP by filling up the signup form. I reposted the link in the reflector for visibility. 2022-09-26 [14:15:26.0681] bakkot: can you point me to the actual diff of https://github.com/tc39/ecma262/pull/2819, since that's unicorning? [14:15:34.0183] finally getting around to implementing it [14:16:31.0446] ah wait it loaded after ~10 tries [14:31:22.0516] shu: you can append `/files` to the end of PR url to get the diff view, which does not include all the spam [14:31:44.0018] that doesn't let you see the PR message but at least it lets you see the change [14:32:19.0642] thanks 2022-09-27 [12:17:51.0967] Are all the tc39 delegates in the tc39 GitHub org? [12:18:28.0440] In other words: if someone on GitHub claims to be in tc39 but they are not in the org, can I assume that they are trolling? [12:18:45.0542] * In other words: if someone on GitHub claims to be in tc39 but they are not in the org, can I assume that they are trolling? [12:19:20.0148] I believe that is the goal but I would not be surprised to learn we've missed some people [12:21:46.0511] Specifically, this user: https://github.com/frank-dspeed [12:22:34.0251] that person does not look like they are on tc39 to me [12:23:41.0068] nicolo-ribaudo: you'd have to ask them what member company they represent and then confirm with the company and check https://www.ecma-international.org/about-ecma/members/ [12:25:06.0904] Thank you! Their comment has been already marked as spam so I'm going to assume that they are just trolling [13:02:06.0537] yulia: is there a tracking bug for FF shipping group/groupToMap to stable? [14:41:44.0719] nicolo-ribaudo: yes, that user is 1000% not in the tc39 org [14:41:55.0109] looks like Japan's opening up: https://www.mofa.go.jp/ca/fna/page22e_000921.html [14:46:58.0947] bakkot: are you real eager to use it or to see if the name can stick? [14:54:38.0849] eager to use it [14:55:29.0080] I saw chrome is shipping in canary and was wondering how long it will be before it's available everywhere [14:55:31.0429] * I saw chrome is shipping in canary and was wondering how long it will be before it's available everywhere 2022-09-28 [00:06:40.0827] I created one now: https://bugzilla.mozilla.org/show_bug.cgi?id=1792650