15:14 | <Rob Palmer> | Hello all. Plenary meeting begins in just under two hours. For those attending in person in Seattle, please arrive from 09:20 where you will be met in the F5 lobby. Breakfast will be served on the same floor as the meeting room from 09:30. |
15:33 | <shu> | i still don't see a zoom link |
15:43 | <Rob Palmer> | The entry-form containing the zoom link will be posted in the next 30 mins and I will notify here. |
16:20 | <Jack Works> | why we're always changing the meeting software 🤔 |
16:21 | <Rob Palmer> | The entry form is now available on the Reflector: https://github.com/tc39/Reflector/issues/461 |
16:22 | <Rob Palmer> | Jack Works: This is due to host room setup. The room has been built to work with Zoom, e.g. the AV is connected to an inaccessible Zoom server. We did try to get Google Meet running with no success. |
16:55 | <Rob Palmer> | We begin in 5 minutes! |
16:56 | <Rob Palmer> | This is our room for the week. |
16:59 | <ryzokuken> | looks great! |
17:02 | <shu> | Customer Engagement Center |
17:04 | <yulia> | looks really fancy |
17:04 | <yulia> | (im not present in any form today) |
17:09 | <Anthony Bullard> | Wish I was there |
17:14 | <msaboff> | @bakkot You should probably advertise somehow that you are recording for the late arrivals. |
17:25 | <bakkot> | msaboff: I'll say it again in my editor update |
18:09 | <shu> | dminor: not sure i understand that point. that sounds like mozilla-internal meeting wrangling |
18:09 | <ryzokuken> | I think the point they tried to make was that what Shane's mentioning now |
18:09 | <ryzokuken> | TG2 is run very differently |
18:10 | <ryzokuken> | for one, the agenda isn't set up clearly ahead of time |
18:10 | <ryzokuken> | we don't use TCQ but do use a simpler Google Meet queue |
18:10 | <shu> | ah i misunderstood then, it was about how TG2 is run, not mozilla? |
18:11 | <ryzokuken> | well, a bit of both I thought |
18:11 | <ryzokuken> | because of how TG2 is run, Mozilla cannot have structured internal discussions about the agenda a week ahead |
18:11 | <ryzokuken> | (IIUC, dminor will probably correct me) |
18:11 | <dminor> | Basically, it would be difficult for us to review proposals properly in advance given the way that TG2 is currently run, so we'd prefer to continue to do advancement in the main committee meetings |
18:12 | <shu> | dminor: okay, thanks |
18:15 | <littledan> | Async: Please share the link to the slides on test262 funding so we can reference them from the notes. |
18:25 | <Ashley Claymore> | https://ptomato.name/talks/tc39-2023-03/ |
18:25 | <Ashley Claymore> | agenda and notes updated |
18:28 | <Rob Palmer> | To meet Justin Grant's schedule constraint, we are suggesting Temporal will be at 13:00 (first thing after lunch) |
18:31 | <shu> | wow jordan sounds great |
18:31 | <shu> | kudos to these room mics |
18:31 | <apaprocki> | Do any other Ecma TCs have shared costs between member companies that attend? Curious if something like specific TC "dues" could work if rolled up into the yearly fee. |
18:32 | <apaprocki> | A lot of pain in companies contracting out work if they can't do it themselves is the burden of that internal process... |
18:35 | <ljharb> | it definitely seems like the primary purpose of member dues is so Ecma, not individual members, can fund shared needs. |
18:59 | <HE Shi-Jun> | not sure how renaming to limit/skip solve the problem ... |
19:00 | <Bradford Smith> | do all of the iterator helpers currently close the underlying iterator? |
19:00 | <rbuckton> | not sure how renaming to limit/skip solve the problem ... take across the ecosystem as well as other languages. |
19:01 | <littledan> | Do any other Ecma TCs have shared costs between member companies that attend? Curious if something like specific TC "dues" could work if rolled up into the yearly fee. |
19:01 | <rbuckton> | It's rather trivial to write a wrapper for an iterator that doesn't forward return |
19:01 | <littledan> | (and they consider this best practice in general) |
19:01 | <Rob Palmer> | We will return in one hour. If any of the remote attendees have feedback on AV etc please say it here. |
19:01 | <Bradford Smith> | I find "limit" less understandable than "take". If it helps avoid misunderstanding, I would expect that's only because one has to read the docs to understand what it does at all. |
19:10 | <peetk> | imo "limit" conveys very clearly that the iterator is closed, i guess because it sounds like SQL limit, and obviously SQL queries are not stateful; whereas "take" is much more ambiguous. but i guess this is a minority view! |
19:56 | <Bradford Smith> | Are there actually any iterator helpers in the proposal that do not close the underlying iterator? |
19:58 | <Justin Ridgewell> | They all either iterate everything (thus closing the underlying), or close when they early exit |
19:58 | <bakkot> | take is special in that take ends before exhausting the underlying iterator |
19:58 | <Bradford Smith> | My general expectation is that if I pass an iterator off to any other code, I should assume it is exhausted and not touch it again myself. |
19:59 | <bakkot> | whereas if you map or something the expectation is that it either you are exhausting it, which will naturally close the underlying iterator, or closing the map helper explicitly |
20:00 | <Justin Ridgewell> |
some , every , and find |
20:00 | <bakkot> | Justin Ridgewell: those don't produce new iterators though |
20:00 | <rbuckton> | Caveat being that some , every , and find return scalar results |
20:00 | <bakkot> | they are as it were "consumers" rather than "transfomers" |
20:01 | <rbuckton> | Though take ending before exhausting the iterator is a misconception. The fact it calls return is more of an optimization than a meaningful difference when it comes to sequence operators. |
20:02 | <bakkot> | by "an optimization", do you mean relative to the option of manually exhausting the underlying by calling .next repeatedly, or something else? |
20:03 | <rbuckton> | Yes. |
20:03 | <rbuckton> | If JS had no .return and the only way to close an iterator were to exhaust it, I would expect take to exhaust the iterator. |
20:04 | <rbuckton> | So its good that return exists, as it allows us to short-circuit such an expensive operation. |
20:05 | <rbuckton> | But I'm pretty sure that in every example of prior art in the ecosystem, where take is used it means "take X items and exhaust/close the underlying iterator" |
20:05 | <rbuckton> | If the iterator were backed by a database, I would expect take to close the connection when completed. |
20:05 | <rbuckton> | The alternative is resource starvation, which is a bad failure state. |
20:06 | <rbuckton> | If you want "consume X and not close", that operation is normally named something like read (at least, where IO is concerned) |
20:10 | <ljharb> | erights: i finished the iterator helpers "close the underlying iterator" change before lunch, and it passes all the proposed test262 tests as well as my own |
20:13 | <Rob Palmer> | We are bringing forward Async Explicit Resource Management to happen this afternoon. TCQ and draft schedule are updated accordinlgly. |
20:15 | <Richard Gibson> | rbuckton: isn't your claim about taking more being uncommon directly contradicted by the issue that prompted this discussion? |
20:16 | <rbuckton> | My impression is that the use case in that issue was a misuse of the API. Perhaps take may seem confusing in a vacuum, but not with adequate context |
20:19 | <littledan> | Why is it "Speaker's summary of key points" rather than "summary of key points" in the notes? |
20:19 | <Luca Casonato> | Didn't get to it due to time, but there is precedence for a preventClose /preventReturn option on the web: preventClose on ReadableStream.prototype.pipeTo and ReadableStream.prototype.pipeThrough . I am not necessarily in favour of adding that - but if we did, people may already be familiar with the opt out behaviour. |
20:19 | <littledan> | Why is it "Speaker's summary of key points" rather than "summary of key points" in the notes? |
20:21 | <Rob Palmer> | It can be written by anyone so please change the title if you like. The key is that the presenter ought to be at least approving the summary so that we have some kind of responsibility when distributing the load of writing these summaries. |
20:21 | <rbuckton> | The confusion is a consequence of choosing to build an API that is dependent on Iterator vs the notion of an iterable. As I understood it as the proposal was advancing, basing this on iterator meant we were in the realm of "one shot" or "single use" iterators, and that any kind of reusable iteration would rely on arrow functions. IIRC, all of the helper methods are exhaustive, either through repeated calls to .next or through the use of .return . I don't believe .take should be substantially different in this regard. I would much rather have an "opt-out" mechanism to avoid closing an iterator than breaking from the norm here. |
20:24 | <bakkot> | Definitely agreed that take not exhausting is not an option |
20:24 | <bakkot> | the question was just whether a different name could lead people to correctly intuit the semantics |
20:25 | <shu> | my intuition is no, unless the name is literally, like takeAndThenClose |
20:32 | <rbuckton> | The alternative, .limit , only really makes sense for numeric arguments. It becomes much less clear if you later adopt something like .limitWhile (vs. .takeWhile ). |
20:33 | <bakkot> | fun fact, Java has both limit and takeWhile |
20:34 | <bakkot> | (and no take ) |
20:36 | <apaprocki> | 64+32 Abseil: https://github.com/abseil/abseil-cpp/blob/master/absl/time/duration.cc#L15-L50 |
20:37 | <rbuckton> | Didn't get to it due to time, but there is precedence for a stream.pipeline(streams, { end: true }) https://nodejs.org/dist/latest-v19.x/docs/api/stream.html#streampipelinestreams-options |
20:38 | <rbuckton> | and readable.pipe(dest, { end: true }) . I'm not sure about the DOM APIs offhand |
20:39 | <Luca Casonato> | for DOM it'd be readable.pipeTo(writable, { preventClose: true }) |
20:39 | <rbuckton> | Yeah, I misread your comment as a question, sorry. |
20:49 | <shu> | waldemar: the core confusion from me is why do you trust multiple implementations to be correct and interoperable here, if you don't trust the spec to be correct (because it's so tricky to get correct)? |
20:49 | <shu> | like my goal isn't just a correct document, it's correct interopable implementations |
20:52 | <waldemar> | shu: It sounds like you're trying to fit the spec around one possible (and pretty problematic) implementation. The spec should be implementation-agnostic about internal details. |
20:53 | <shu> | in this case my understanding is that the bounds the champions are working to put in place are precisely so that it is implementable with that technique |
20:53 | <waldemar> | I'm also more interested in the ns vs µs question. |
20:53 | <shu> | (also why is the 64+32 impl problematic?) |
20:54 | <littledan> | I'm also more interested in the ns vs µs question. |
20:54 | <waldemar> | Elementary math: 64+32 can implement integral counts of subseconds. This is obvious. |
20:55 | <shu> | well, V8's position is still pro microseconds, but we won't block the proposal on it if implementation complexities and bad performance cliffs are addressed |
20:55 | <waldemar> | Not obvious: spec that explicitly manages two integers implements integral counts of subseconds. It's easy to get carries and overflows wrong, and you can't tell without examining the entire spec. |
20:55 | <shu> | i agree with you |
20:56 | <shu> | what i don't get is, why do you think that trickiness is best left for implementations to all figure out via implication? |
20:56 | <waldemar> | If you just want µs, then you can store durations in flat 64-bit integers and get a much more efficient implementation with a range of >500,000 years. |
20:56 | <shu> | indeed! i just want us |
20:56 | <shu> | but v8 has not been able to convince the champion group |
20:57 | <littledan> | If you just want µs, then you can store durations in flat 64-bit integers and get a much more efficient implementation with a range of >500,000 years. |
20:58 | <shu> | it's a nuanced conversation that's hard to tease apart |
20:58 | <shu> | it's not just absolute performance, it's the complexity around supporting optimized paths also |
20:58 | <shu> | it's philosophical objection |
20:58 | <waldemar> | Whether a difference in performance is significant depends on who is writing the benchmark ☺ |
20:59 | <shu> | apaprocki has given examples of other systems that support ns that temporal might want to interface with, which i don't really get at all |
20:59 | <apaprocki> | ns are common enough nowadays that it seems it would be limiting use cases unnecessarily by limiting to µs, e.g. node embeds v8 and would hopefully like to represent filesystem times without losing precision |
20:59 | <shu> | those other systems don't have ns as part of a date-time arithmetic library, they're raw ns counts |
20:59 | <shu> | they're int64s |
20:59 | <shu> | what i'm saying is it doesn't follow "ns are common enough -> ns need ot be supported in a fully featured date-time arithmetic library" |
21:00 | <shu> | you still can just put the raw ns count into a BigInt |
21:02 | <shu> | V8 position is:
|
21:02 | <apaprocki> | what i'm saying is it doesn't follow "ns are common enough -> ns need ot be supported in a fully featured date-time arithmetic library" |
21:02 | <shu> | great, it's fine to format them |
21:03 | <shu> | you need to do full arithmetic to ns precision? |
21:03 | <shu> | how is that useful? |
21:06 | <littledan> | I haven't found this as a hard requirement for us when I talked to the relevant groups inside of Bloomberg (except for certain algorithms like PTP which we probably wouldn't end up porting to JS) |
21:08 | <apaprocki> | there are certain feeds of information where the individual events are represented in ns precision and series of events could be displayed as offsets from an initial event (in essence, durations from an arbitrary epoch rather than UTC epoch) |
21:10 | <littledan> | I think using us would create somewhat of a risk, that Temporal might become obsolete (which is a surprising choice given how much else we decided to be super future-proof for). It's sort of clear that we don't really need to go more precise than ns. |
21:10 | <littledan> | (and a later evolution here would be really bad, given compat/interop risks) |
21:12 | <littledan> | yes (edited) |
21:15 | <littledan> | Good news everyone: The transcriptionist might be available for tomorrow! |
21:15 | <littledan> | (they got back to me by email) |
21:28 | <bakkot> | this isn't worth bringing up, but await is not reserved in strict mode, only in module code and async functions |
21:28 | <Michael Ficarra> | very very few people are aware of syntax being dependent on the start symbol |
21:29 | <ljharb> | bakkot: perhaps we should have Set.prototype.sort if the sort order is important? |
21:30 | <Michael Ficarra> | if you're going to explicitly manage the sort order, put it in an explicitly ordered container |
21:30 | <bakkot> | the problem is that when I care about the order it's because I care about insertion order specifically |
21:30 | <bakkot> | and you can't sort it into "insertion order" |
21:32 | <ljharb> | ah true, hm |
21:35 | <Michael Ficarra> | I know we don't have much else to go on, but I feel like we're taking these poll results way too seriously |
21:35 | <bakkot> | right now we're just hearing what they are |
21:35 | <bakkot> | no one has expressed anything about what to do with them |
21:41 | <Michael Ficarra> | for await has always felt like an awkward piece of syntax to me, though |
21:41 | <Michael Ficarra> | like I don't know if we should be using it to guide future syntax choices |
21:44 | <bakkot> | tbf if we're just picking something because we have to pick something, "difficulty of parsing" is a fine reason to choose - I just wouldn't want "difficulty of parsing" to prevent us from picking a thing we do all think is best |
21:44 | <littledan> | for await has always felt like an awkward piece of syntax to me, though |
21:46 | <justinfagnani> | as a code reader, I kind of want a syntactic note on the block that it may await at the end, not just on individual statements in the block |
21:46 | <justinfagnani> | like async on a function |
21:48 | <Rob Palmer> | justin, is this just syntax shock? I fully have the same initial reaction as you. I just recall many times when my initial reaction is later overcome once it goes into the language and you get used to it |
21:49 | <shu> | that's not much of an argument though, because you can make that about literally any syntax we choose? |
21:49 | <justinfagnani> | could be? |
21:49 | <shu> | "you'll get used to it" |
21:49 | <Rob Palmer> | That could be the JS motto. |
21:50 | <bakkot> | justinfagnani: yeah the original design was more like python's with or java's try-with-resources , which has that |
21:50 | <bakkot> | but we ultimately decided not that |
21:50 | <justinfagnani> | Would something like:
make it more clear that the block may yield at the end? |
21:50 | <justinfagnani> | bakkot: ok |
21:50 | <Mathieu Hofman> | FYI, Mark is not active on Matrix |
21:50 | <rbuckton> |
|
21:50 | <justinfagnani> | ok, thanks |
22:05 | <Chris de Almeida> | so... what just happened? |
22:05 | <shu> | sorry all didn't mean to make the decision space so complicated |
22:05 | <littledan> | no this was good |
22:05 | <littledan> | please read the summary at the bottom of the notes page and edit it or make comments as needed |
22:05 | <shu> | the only signal i got from the past 10 minutes is, the consensus was not just "we can all live with await using" but in fact "we are now convinced await using is the ideal, if achieveable" |
22:05 | <shu> | which is a good signal |
22:05 | <shu> | and backs up coming back next meeting |
22:06 | <rbuckton> | Having a block-level indicator was the issue blocking the async version using for the past few years. |
22:06 | <Chris de Almeida> | yes -- maybe we should ask for consensus on that summary conclusion.. I'm concerned we are not all on the same page |
22:06 | <littledan> | the only signal i got from the past 10 minutes is, the consensus was not just "we can all live with await using" but in fact "we are now convinced await using has broad support (and this is why I wanted to do a temperature check) |
22:06 | <littledan> | yes -- maybe we should ask for consensus on that summary conclusion.. I'm concerned we are not all on the same page |
22:06 | <littledan> | (I did ask everyone to review it, but we can come back and project it to force everyone to review it when we come back from the break) |
22:07 | <shu> | littledan: heh, i still don't like it! but i'm fine with it |
22:08 | <Chris de Almeida> | what's there atm makes sense to me -- just want to confirm expectations as it seemed we might have been going a different direction for a bit there |
22:21 | <shu> | i have lost my apartment internet due to what i assume is high winds in SF currently |
22:21 | <shu> | i don't have good enough cell service to do zoom, so looks like i am out for the remainder of today :/ |
22:26 | <shu> | wait maybe i have enough phone tether to do zoom |
22:26 | <shu> | it's like 90% packet loss |
22:27 | <apaprocki> | do you live in a dirigible? |
22:27 | <shu> | it's called san francisco, thank you |
22:28 | <sffc> | Frank Tang also said he's been in and out of power/internet |
22:32 | <littledan> | BTW here are my conclusion notes for the await using topic, please edit in the notes if you want to make changes: SummaryVarious grammars for async resource disposal were considered, including results from polls. The champion's preference became ConclusionThe committee resolves to attempt the syntax |
22:44 | <shu> | i am triggered about static private semantics |
22:44 | <Chris de Almeida> | same |
22:44 | <bakkot> | static private semantics are actually fine |
22:45 | <bakkot> | the problem is that class extends implies inheritance not just of instances but of the constructors themselves, which is wack |
22:46 | <littledan> | the problem is that |
22:46 | <bakkot> | yeah I use it myself |
22:47 | <bakkot> | but it should never have existed, it gives us the wild things like Promise.resolve not working unless bound (whereas Array.from does, for... reasons) |
22:54 | <Michael Ficarra> | we really need to figure out a more appropriate organisational scheme for well-known symbols than putting them all on Symbol |
22:55 | <Michael Ficarra> | I don't blame this proposal author for this choice, since we don't have committee guidance on the topic |
22:56 | <littledan> | we really need to figure out a more appropriate organisational scheme for well-known symbols than putting them all on Symbol __metadata__ |
22:58 | <Michael Ficarra> | littledan: yes, a single global namespace for everything is bad, whether that is globalThis or Symbol |
22:58 | <danielrosenwasser> | Hey all, Ron (rbuckton ) and I will be requesting a new agenda item this Thursday which will propose the preferred await using syntax for the Async Explicit Resource Management proposal. We're currently working on the grammar, but will let everyone know when the slides and changes are ready to review. |
22:58 | <Michael Ficarra> | ironically, that opinion is also on-topic for this topic |
22:59 | <shu> | i don't think a single global namespace is bad |
23:00 | <shu> | i think it's only ex ante bad but is mostly ok |
23:01 | <Chris de Almeida> | var doNotPolluteTheGlobalNamespace = {}; |
23:02 | <littledan> | Option 3 feels the most bizarre to me, since the intended usage of it needs to go back to the single namespace anyway |
23:02 | <Michael Ficarra> | shu: surely with time, we will have more than 1 built-in protocol that want to use the same simple name for one of their provided/required fields |
23:03 | <shu> | that's why i said ex ante bad |
23:03 | <Michael Ficarra> | none of these well-known symbols have particularly unique simple names |
23:03 | <shu> | my point is that when we come to that bridge it's usually not a big deal to work around |
23:04 | <Michael Ficarra> | shu: fair, though it would be nice to set a precedent for userland protocols, especially if we ever have a world with first-class protocols |
23:06 | <Ashley Claymore> | which class does the metadata get added to? If there was a class decorator which returns a new class, does that get it, or should it have to make sure it 'forwards' on `Symbol.metadata' ? |
23:06 | <rbuckton> | The final class |
23:07 | <rbuckton> | (I think) |
23:07 | <Ashley Claymore> | so might not work if the decorator freezes the class? |
23:07 | <rbuckton> | A good class decorator that performs replacement should either subclass with extends , or use .setPrototypeOf to emulate that approach, unless it is doing something very complex. |
23:09 | <ljharb> | either, or what? |
23:10 | <Ashley Claymore> | so Symbol.metadata would already be there on the class that is being decorated? Rather than added to the final class? |
23:11 | <rbuckton> | I'd have to recheck the spec |
23:13 | <shu> | i'm confused about kevin's use case |
23:14 | <bakkot> | two libraries which both want to use the key type |
23:14 | <bakkot> | including possibly two major versions of the same library |
23:14 | <bakkot> | you fundamentally cannot use these things at the same time |
23:15 | <bakkot> | because it's a shared global namespace |
23:15 | <shu> | is he saying programs will want multiple versions of the same decorator library in the same running app...? |
23:15 | <bakkot> | multiple versions of a library in the same app is a thing which happens constantly |
23:16 | <Luca Casonato> | rbuckton: if you want a shared global namespace in scripts, use globalThis ? why do we need to add a second global namespace? if you really want a global namespace, there already is one already |
23:17 | <littledan> | multiple versions of a library in the same app is a thing which happens constantly |
23:17 | <shu> | but... why is the app use two major versions of the same library in the same app? that happens? |
23:17 | <bakkot> | that happens constantly |
23:17 | <bakkot> | littledan: they can't share |
23:17 | <rbuckton> | rbuckton: if you want a shared global namespace in scripts, use reflect-metadata does, and one of the things we have sorely wanted to address with this proposal. |
23:17 | <bakkot> | like, that's the problem |
23:17 | <bakkot> | they use the same key |
23:17 | <shu> | it happens constantly? |
23:17 | <rbuckton> | We cannot mutate globalThis in a locked down environment like SES |
23:17 | <bakkot> | and coordinating it becomes the consumer's problem |
23:17 | <Jesse (TC39)> | the various layers of dependency hell |
23:18 | <littledan> | littledan: they can't share |
23:18 | <shu> | okay i think i'm getting the picture. currently the builders do some kind of deduplication / versioning at the build step for regular import/exports |
23:18 | <rbuckton> | Also, [Symbol.metadata] isn't necessarily a "global namespace" any more than a static property on the class is a global namespace. Because the [Symbol.metadata] property is a static property on a class. |
23:19 | <bakkot> | rbuckton: right, class fields are also a shared namespace, which is why string-named mixins was not a viable proposal |
23:19 | <littledan> | Symbol-named protocols are also not beyond Stage 1; I still like string-named mixins. |
23:20 | <rbuckton> | There's a difference between "shared namespace" and "global namespace" though. The 2nd term has more implications |
23:20 | <bakkot> | the names of all fields used in all decorators anywhere must be unique |
23:20 | <bakkot> | that's global |
23:20 | <rbuckton> | I want a mutable object because I don't want a shared global namespace. |
23:21 | <rbuckton> | The alternative to use globalThis mandates I do the worse thing |
23:21 | <bakkot> | rbuckton: but only you |
23:21 | <Michael Ficarra> | "be careful" assumes that all parties are coordinating, but in reality, pages and applications are often composed of many non-coordinating scripts |
23:21 | <bakkot> | I am OK with only typescript having to do the worse thing |
23:21 | <bakkot> | as long as everyone else falls into the happy path of the right thing |
23:21 | <rbuckton> | Its not only typescript, its every typescript user. |
23:22 | <ljharb> | TS users presumably would only use an interface TS provides, regardless of which option was chosen? |
23:22 | <littledan> | "be careful" assumes that all parties are coordinating, but in reality, pages and applications are often composed of many non-coordinating scripts |
23:23 | <Michael Ficarra> | littledan: and are those decorators always created by a single party or by coordinating parties? I doubt it |
23:23 | <nicolo-ribaudo> | You only have to worry about the set of decorators that a particular class uses. |
23:24 | <littledan> | Decorators from different libraries can usually be mixed, so the decorator author doesn't really know what this set is |
23:24 | <Michael Ficarra> | littledan: "not true for some cases" is not the bar we're trying to meet here |
23:24 | <bakkot> | ljharb: re: your queue item, the only reason I suggested a frozen object instead of a symbol is that a frozen object lets you get to the parent metadata |
23:25 | <ljharb> | makes sense, thanks |
23:27 | <rbuckton> | Symbol.for("foo") isn't much better than "foo" |
23:27 | <bakkot> | I didn't mention this, but the other downside of option 1 is that it is public-by-default, which is... very bad |
23:27 | <bakkot> | you can remember to be disciplined about it but people will not remember |
23:27 | <littledan> | I didn't mention this, but the other downside of option 1 is that it is public-by-default, which is... very bad |
23:27 | <bakkot> | no it isn't |
23:27 | <rbuckton> | I didn't mention this, but the other downside of option 1 is that it is public-by-default, which is... very bad |
23:28 | <bakkot> | it is not as a easy to use a weakmap as it is to use a string-named property |
23:28 | <rbuckton> | But option 2 has the same level of difficulty with weakmaps |
23:28 | <bakkot> | yes but that's the only way to use it, so that's fine |
23:29 | <bakkot> | like, as a practical matter, people are going to use public string-named properties with option 1, even when they don't intend to make a public API |
23:29 | <bakkot> | that is what is going to happen |
23:29 | <bakkot> | that is what "public-by-default" means |
23:31 | <rbuckton> | That is more about documentation and learning than it is about capability. If you tell folks, use WeakMap or Symbol if you're concerned about collisions, but strings or Symbol.for if you're not. Library authors will almost certainly avoid collisions, end user applications often won't need to. |
23:31 | <bakkot> | You have a lot more faith in the power of documentation to shape what happens than I do |
23:31 | <bakkot> | for that matter you also have more faith in the power to shape documentation |
23:31 | <rbuckton> | Assignments to context.metadata will never be so simple as context.metadata["a"] = b anyways |
23:32 | <littledan> | I really appreciate you being flexible here, bakkot ljharb Michael Ficarra . It's great that we're able to move forward and not have a big gap of metadata-less decorators |
23:32 | <rbuckton> | context.metadata is just an object. If you need to differentiate between a class, or a method, or a field you still have more work to do to avoid collisions, even in the WeakMap case. |
23:32 | <Justin Ridgewell> | Is the context object (not the context.metadata obj) consistent between all decorator invocations on a particular class? |
23:32 | <Justin Ridgewell> | Or is it a new object for every invocation? |
23:33 | <rbuckton> | Same object for every decorator on a single class |
23:33 | <rbuckton> | including the methods and fields. |
23:34 | <Justin Ridgewell> | If we had chosen Option 2 here, would there even have been a need for context.metadataKey at all? |
23:34 | <Justin Ridgewell> | We could have just keyed the WeakMap on context |
23:34 | <rbuckton> |
produces a single object with |
23:34 | <bakkot> | yeah you need it to be available after decoration time |
23:34 | <bakkot> | and you don't want to share the context object |
23:34 | <bakkot> | which has a bunch of decorator-time-only stuff on it |
23:34 | <Justin Ridgewell> | Ah, ok |
23:34 | <rbuckton> | sorry, I misread (despite your clarification). |
23:34 | <rbuckton> | context is not shared, only metadata is. |