00:00 | <bakkot> | re: waldemar's point, I agree that more general async dataflow would be great, and is something we should explore, though I think I'd still want this proposal for simple case |
00:02 | <justinfagnani> | re: Mark's comments now... when you see a ton of code that's accidentally serial instead of parallel, you really wish for a better syntax for all of this that doesn't encourage bad behavior |
00:06 | <HE Shi-Jun> | re: waldemar's point, I agree that more general async dataflow would be great, and is something we should explore, though I think I'd still want this proposal for simple case |
00:09 | <rbuckton> | I'm fairly certain a cover grammar is feasible for await using , the big question is whether what I have put together is correct. Given the NLT restrictions, an await using declaration must have the first identifier in the binding list on the same line as await using , and that is always a syntax error in the expression case. Binding patterns aren't permitted in using , so there is no ambiguity with await using [x] . |
00:10 | <shu> | i'm gonna level with you rbuckton, i do not have enough brainpower left today to vet that cover grammar |
00:10 | <shu> | though i'm more interested in how hard it is to implement in a recursive-descent parser anyhow |
00:10 | <shu> | i'll try to put time aside before plenary tomorrow to look, but... i also have a presentation tomorrow first thing so also no promises |
00:14 | <rbuckton> | The gist of it is, the cover is identical to AwaitExpression, but UnaryExpression would fail to parse await using x when x is on the same line. AwaitUsingDeclaration however would be able to consume the cover along with a trailing [no LineTerminator here] BindingList , which seems pretty much equivalent to CoverParenthesizedExpressionAndArrowParameterList and CoverCallExpressionAndAsyncArrowHead |
00:16 | <shu> | that... sounds reasonable |
00:16 | <rbuckton> | Though I'll admit, cover grammars in the spec today sometimes seem a bit hand-wavy in a couple places. |
00:16 | <shu> | and i just do a bounded look ahead await using and see if it's an NLTH identifier |
00:17 | <shu> | in +Await contexts |
00:17 | <rbuckton> | In TS I'd just do two-token lookahead in +Await |
00:17 | <rbuckton> | That is one benefit of await using over async using . For await using , both uses of the cover are in +Await, while for async using , only one is. |
00:18 | <shu> | and await using without a binding list is unaffected? |
00:19 | <shu> | well, is supposed to be, according to the cover |
00:19 | <rbuckton> | In TS I'd just do two-token lookahead in +Await using (I was experimenting with all three syntax options). |
00:20 | <shu> | is TS a hand-written recursive-descent? |
00:22 | <rbuckton> | and await using on its own, or anywhere else legal for a UnaryExpression, should end up treated as an AwaitExpression. |
00:22 | <shu> | yes, that is what i meant |
00:25 | <rbuckton> | From my understanding of cover grammars, we would eagerly parse CoverAwaitExpressionAndAwaitUsingDeclarationHead, but fail to parse the rest of ExpressionStatement. We could then retry the parse as part of AwaitUsingDeclaration, reusing the cover, and be able to successfully continue to parse. Then static semantics kick in and validate that the CoverAwaitExpressionAndAwaitUsingDeclarationHead is a valid AwaitUsingDeclarationHead (e.g., await [NLT] using ) |
00:25 | <shu> | i am happy enough to go forward with stage 3 |
00:27 | <rbuckton> | I will amend the slides with a summary of these changes and wait to see if Waldemar is able to provide feedback in the meantime. |
02:53 | <Michael Ficarra> | is there anything we need to do to get Decimal on the overflow, or will it be taken care of? |
03:09 | <littledan> | is there anything we need to do to get Decimal on the overflow, or will it be taken care of? |
03:10 | <Michael Ficarra> | of course, I just wanted to record it on the list of overflow items |
06:15 | <bakkot> | ljharb: I made some slides just for mark, if we have time tomorrow, PTAL: https://docs.google.com/presentation/d/1s1IZSo24JpMsI_NponP8vvIKUazld62lcleKF976Ppc/edit?usp=sharing |
14:01 | <Richard Gibson> | ljharb: I made some slides just for mark, if we have time tomorrow, PTAL: https://docs.google.com/presentation/d/1s1IZSo24JpMsI_NponP8vvIKUazld62lcleKF976Ppc/edit?usp=sharing v -mode, which has a wider set of reserved punctuators and semantics for doubled punctuators (https://github.com/tc39/proposal-regexp-v-flag#how-is-the-v-flag-different-from-the-u-flag and https://arai-a.github.io/ecma262-compare/snapshot.html?pr=2418#prod-ClassSetCharacter ) |
14:42 | <rbuckton> | Are we ensuring that RegExp.escape is future proof against potential new syntax? Should we be concerned if the output changes in a later version if we have to escape something new? We could choose to be intentionally over-aggressive with escapes, if we're not already. |
14:53 | <rbuckton> | Also, rather than extending u-mode to allow other escapes, we could escape non-u-mode syntax characters using a hexadecimal representation that is legal in all modes. So, instead of adding \- , we could choose to escape it as \x2d . Same for \= (\x3d ) and \, (\x2c ) |
14:53 | <rbuckton> | I'm not saying we shouldn't extend u-mode, but this is an option if we decide not to. |
15:12 | <rbuckton> | Regarding the "exhaustive list of contexts", keep in mind that several proposals add other contexts:
At a quick glance, I think this means that |
15:14 | <rbuckton> | If there's a chance we want RegExp.escape to always remain stable, it may be worth going over the RegExp syntax investigation I did at https://rbuckton.github.io/regexp-features/features/ to ensure we're future-proof against other syntax we may choose to adopt later. Though, I admit that's not a completely exhaustive list. |
15:15 | <Chris de Almeida> | I've just had to reference the notes as I had to leave early yesterday, and the conclusion/summary for each agenda item was a nice help |
15:23 | <Jesse (TC39)> | how does scheduling of overflow stuff happen? asking for a friend |
15:24 | <bakkot> | note the changes would need to be more substantive for dealing with |
15:25 | <bakkot> | the list of reserved punctuators already includes # , so it would be escaped also, which would cover x -mode line comments too, thankfully |
15:26 | <rbuckton> | If there's a chance we want & (used in (?&name) for recursive named capture group matching, and (?(R&name)A|B) in conditionals to test for recursion of a group). |
15:26 | <bakkot> | For example, we may never do recursive matching, but it still might be a good idea to escape & needs to be escaped anyway for v-mode |
15:26 | <rbuckton> | the list of reserved punctuators already includes (){}[]|,.?*+-^$=<>\ |
15:26 | <bakkot> | it does say "etc" |
15:27 | <Chris de Almeida> | pull request to the agenda |
15:27 | <Rob Palmer> | The best way is to PR the agenda as that guarantees all chairs will see it. But normally messaging the chairs in matrix is enough. I will say that after we add Ron's overflow, there is not much chance of more overflow. |
15:27 | <rbuckton> | Yeah, but that's somewhat unclear. If it were to escape A , for example, that would be a problem for https://github.com/tc39/proposal-regexp-buffer-boundaries |
15:28 | <Chris de Almeida> | there's already o-f for async ex res mgmt - 30 mins. is there an additional item from Ron? |
15:29 | <bakkot> | It does also say it's only including punctuators, which would not include A |
15:29 | <Chris de Almeida> | oh... there was only a spare 25 minutes in the schedule to begin with |
15:30 | <rbuckton> | Plus that list doesn't match the explainer currently, so there doesn't seem to be a definitive source of truth. Maybe that's a stage 2 concern, but if the point of the slides is "RegExp.escape is safe", then its important to clarify how safe. |
15:44 | <eemeli> | Presumably it's sufficient to guarantee that RegExp.escape() safe for its own RegExp , rather than being safe forever. |
15:45 | <bakkot> | Well, that depends on whether anyone starts depending on it not escaping certain things |
15:51 | <bakkot> | rbuckton: Updated the slides to list proposed contexts as well, and went through all the ones you listed in your research doc as well |
15:51 | <bakkot> | I'm kinda tempted to just say it escapes every ascii punctuator except _ , since I've listed I think all of them except the two quotes and backtick at this point |
15:51 | <bakkot> | I did also update it to include line terminators so you can't break out of x -mode line comments, which is something I'd previously neglected |
15:53 | <rbuckton> | That's why I posed the questions earlier. Do we need to ensure RegExp.escape() is consistent for all time? If so, do we do that my making a best guess as to what potential syntax characters we might encounter in the future, and will that limit us in terms of what new syntax we can add? Or do we aggressively escape anything that is not alpha-numeric (or equivalent unicode characters)? |
15:54 | <rbuckton> | I'm kinda tempted to just say it escapes every ascii punctuator except _ might even be worth escaping since it has meaning as part of some control verbs in Perl. |
15:54 | <bakkot> | I think we should commit to not using _ for anything ever |
15:54 | <bakkot> | v-mode had that discussion already when they decided not to include it in the double-punctuator reservations |
15:55 | <rbuckton> | Perl has (*positive_lookahead: ... ) , for example |
15:56 | <bakkot> | ah, that seems more like it's being used as an identifier character, and doesn't need to be escaped any more than any other identifier character |
15:57 | <rbuckton> | PCRE also uses ` , ' , " , and % for callouts. |
15:57 | <rbuckton> | I'm not sure we'll ever do callouts, but you can never be certain. |
15:57 | <bakkot> | ok I will just say every ascii punctuator |
15:57 | <bakkot> | except _ |
15:58 | <bakkot> | And note that we might be able to make it less aggressive |
15:58 | <rbuckton> | That's fine with me. |
15:59 | <bakkot> | re: future constraints, this does mean that we're committing that backslash + punctuator is only ever going to mean the punctuator, but that is I think a good limit to impose |
15:59 | <rbuckton> | PCRE also uses ' is actually used quite a bit across RegExp engines, primarily as an alternative to <> for named capture groups. |
16:03 | <rbuckton> | re: future constraints, this does mean that we're committing that backslash + punctuator is only ever going to mean the punctuator, but that is I think a good limit to impose |
16:04 | <bakkot> | Sorry, by "no" do you mean "no one uses backslash + punctuator to mean anything other than the punctuator"? |
16:04 | <rbuckton> | Sorry, by "no" do you mean "no one uses backslash + punctuator to mean anything other than the punctuator"? |
16:05 | <rbuckton> | I think it would be safe to say that we also would never consider \ +punctuator to mean anything other than the punctuator. |
16:06 | <rbuckton> | There are other ways to introduce syntax that would be more meaningful than, say, whatever \~ might mean. |
16:56 | <shu> | chairs, am i still up first today? if so i'll be about 2-3 mins late |
16:57 | <Chris de Almeida> | chairs, am i still up first today? if so i'll be about 2-3 mins late |
16:57 | <shu> | thanks for confirmation |
16:58 | <shu> | (reason being i still don't have home internet and have to wait till 10 to kick people out of the meeting room i booked) |
16:59 | <Chris de Almeida> | should be fine -- room still fairly empty over there |
17:05 | <Willian Martins> | I love this deck. |
17:06 | <Andreu Botella> | wait, at what stage is shared structs? |
17:06 | <HE Shi-Jun> | Is that only me can't see shared screen? |
17:06 | <Andreu Botella> | I can see it |
17:07 | <Chris de Almeida> | maybe you have something else pinned? |
17:07 | <Chris de Almeida> | in top left, is there a button to switch to shared content? |
17:08 | <HE Shi-Jun> | exit and rejoin, still can't see shared screen 😠|
17:09 | <Chris de Almeida> | using app or browser? |
17:09 | <ryzokuken> | wait, at what stage is shared structs? |
17:09 | <HE Shi-Jun> | app |
17:10 | <Andreu Botella> | oh, I was Ctrl+Fing for "shared" in the proposal lists and couldn't find it |
17:10 | <HE Shi-Jun> | it works now! |
17:10 | <ryzokuken> | well, ideally that'd imply Stage 0 🙈 |
17:10 | <Chris de Almeida> | it's missing from the proposals repo... |
17:10 | <littledan> | "Shared structs" have always been part of Shu's "structs" proposal. |
17:10 | <HE Shi-Jun> | ok, i can see the screen now. not sure what happened , may be just network issue. |
17:11 | <ljharb> | stage 1 (and zero) proposals are in a separate list |
17:11 | <Chris de Almeida> | yeah it;s still missing from the list |
17:12 | <Chris de Almeida> | https://github.com/tc39/proposals/blob/main/stage-1-proposals.md |
17:12 | <Andreu Botella> | yeah, I was searching in all lists, but I was searching for "shared" and couldn't find it |
17:12 | <ljharb> | "fixed shape objects" is in the list |
17:12 | <ljharb> | that was what it was presented as when it got stage 1, i assume |
17:12 | <Chris de Almeida> | ohhhh |
17:12 | <Chris de Almeida> | quick PR incoming |
17:13 | <ljharb> | Chris de Almeida: i'm not sure that's appropriate |
17:13 | <Andreu Botella> | Maybe this is just me, but the name "isolate" shouldn't necessarily guide the direction of the language /s |
17:13 | <ljharb> | at stage 1 the proposal name should describe the problem, and "shared structs" seems like a solution to me |
17:14 | <littledan> | Maybe this is just me, but the name "isolate" shouldn't necessarily guide the direction of the language /s |
17:15 | <littledan> | at stage 1 the proposal name should describe the problem, and "shared structs" seems like a solution to me |
17:15 | <ljharb> | fair enough |
17:17 | <Chris de Almeida> | I think it's reasonable to expect better parity between the title in the tc39/proposals repo and the title on the proposal repo itself |
17:17 | <littledan> | Note: I believe Shu is using the term "closed" in a mathematical sense, about how these graphs don't point to each other. |
17:18 | <littledan> | and "mutators" refers to the executing code (which mutates the heap--even if it's purely functional) |
17:27 | <ljharb> | i usually default to whatever's on the agenda at advancement time in the proposals table |
17:27 | <ljharb> | but i agree that it would be nice if champions kept that in sync :-) |
17:48 | <Luca Casonato> | shu: The origin isolation is not really an issue for us in Deno, because our security model ensures that only a single tenant can execute code within a single process. Essentially the effect of cross origin isolation is the default for us. There are some server side runtimes, notably Cloudflare Workers, that run multiple tenants within a single process. They disallow all high precision timers and shared memory entirely. |
17:52 | <Andreu Botella> | can't you treat a reference to a SAB from inside a shared struct as if it was a per-isolate SAB object |
17:52 | <Andreu Botella> | different from any other SAB object pointing to the same backing store in the same isolate |
17:56 | <Luca Casonato> | Technically probably possible - the identity continuity seems pretty hard (but probably possible). I think the biggest problem is wether this should work, because magic object cloning is not something we have right now. Also what if you have a custom class that extends SAB? |
17:57 | <Andreu Botella> | Is there a need for identity continuity? You can currently clone a SAB without identity continuity with HTML's structuredClone(sab) |
17:57 | <Andreu Botella> | But I guess it would be needed for some use cases |
17:58 | <Luca Casonato> | Yes, but there you have an explicit transfer |
17:58 | <Andreu Botella> | Oh, right, this would be an assignment transforming into a clone behind the scenes |
17:58 | <Luca Casonato> | With shared structs, assignment is transfer/publish, which means there is no explicit call that needs to be made to transfer |
17:59 | <Luca Casonato> | sounds confusing to users |
18:12 | <shu> | Andreu Botella: you can't make assignment a hidden clone anyway, because you need to clone it into a particular target realm, and a shared struct assignment is more like a broadcast |
18:14 | <Andreu Botella> | you'd also want struct.sab === struct.sab , and that would require an extra per-isolate map |
18:15 | <shu> | yeah |
18:16 | <Luca Casonato> | You could make the assigment assign the SAB backing store into the shared struct, and then make the property access on the SAB create the JS object on demand - but that sounds slow and ugly and likely difficult to integrate |
18:16 | <Luca Casonato> | But yeah, to fix identity discontinuity you'd need a backing store -> js object map per isolate |
18:18 | <shu> | i think the DX of SAB objects themselves just don't matter |
18:19 | <shu> | since you can only use them via TA objects |
18:19 | <shu> | so to introduce a new kind of SAB object that can be put into shared structs seems the simplest solution to me |
18:20 | <littledan> | You could make the assigment assign the SAB backing store into the shared struct, and then make the property access on the SAB create the JS object on demand - but that sounds slow and ugly and likely difficult to integrate |
18:22 | <Luca Casonato> | the inability of SAB to point to JS values (with cycle collection) is a fundamental limitation. This is why I like how shared structs do not include the ability to be backed by SABs--it would be a completely different thing. |
18:22 | <littledan> | oh sorry I was going on a random tangent because I misunderstood |
18:24 | <rbuckton> | mark: re yield . I'm not sure what the champion's position is on this, but I think my preference is that context isn't preserved. If it isn't preserved, there's an opportunity for a userland runtime to set context when calling .next() , which could be useful for something like a dataflow library. |
18:25 | <bakkot> | (I have the opposite preference - yield should not be meaningfully different than await here) |
18:25 | <rbuckton> | yield is meaningly different from await though. |
18:26 | <bakkot> | Not for the purposes of this API |
18:26 | <HE Shi-Jun> | Both sides seems reasonable 😂 |
18:26 | <bakkot> | In both cases the syntax is creating a continuation callback to be called at a future point, and that continuation should capture the current state |
18:26 | <littledan> | it would probably be helpful to look into the experience in Node.js, where this feature has long existed without such support in yield. Has this led to bugs? We should be able to find out. |
18:27 | <bakkot> | it would probably be helpful to look into the experience in Node.js, where this feature has long existed without such support in yield. Has this led to bugs? We should be able to find out. |
18:27 | <littledan> | No one uses yield so it doesn't come up |
18:27 | <bakkot> | no one uses generators either |
18:28 | <rbuckton> | shouldn't this show up in generators all the time? |
18:28 | <rbuckton> | "no one" is far too strong. TypeScript uses them internally, and there are userland runtimes that rely on them. |
18:28 | <bakkot> | that's an exaggeration of course, but yeah like Ron says most uses of generators IME are simple enough that it doesn't end up being relevant. to see this in real life you have to do the next call on a subsequent turn |
18:28 | <nicolo-ribaudo> | For generators that are resumed asynchronously, wouldn't the context be preserved by the async helper used to resume the generator (a callback, a promise.then , etc)? |
18:30 | <yulia> | dumb question: there is no chance that "context" will be confused with the decorators context? Asking because I just heard context so many times and got reminded that it can be kind of meaningless because it can mean anything. Totally not a blocking concern but wondering if anyone else had the same thought |
18:30 | <rbuckton> | If yield did preserve context, I'd argue we need a mechanism to turn this off on an as-need basis otherwise we'd block a number of valid use cases. |
18:30 | <ljharb> | are beginner devs using node's async stuff now? |
18:30 | <bakkot> | I would be OK with a yield.nocontext or something I guess |
18:30 | <shu> | dumb question: there is no chance that "context" will be confused with the decorators context? Asking because I just heard context so many times and got reminded that it can be kind of meaningless because it can mean anything. Totally not a blocking concern but wondering if anyone else had the same thought |
18:31 | <littledan> | dumb question: there is no chance that "context" will be confused with the decorators context? Asking because I just heard context so many times and got reminded that it can be kind of meaningless because it can mean anything. Totally not a blocking concern but wondering if anyone else had the same thought |
18:31 | <rbuckton> | I would be OK with a yield variant to use. |
18:32 | <yulia> | i don't have a concrete alternative and context isn't horrible. I don't know if the collision would really take place, just hadn't thought about it |
18:32 | <rbuckton> | A number of languages with an AsyncContext -like mechanism also have some mechanism of explicitly affecting async flow control. |
18:32 | <yulia> | i'll make an issue |
18:32 | <littledan> | The thing is, an AsyncContext instance is more like a single variable |
18:32 | <HE Shi-Jun> | I would be OK with a yield.foo will have diff semantic out of generator, don't like such syntax :P |
18:33 | <rbuckton> | A number of languages with an |
18:34 | <bakkot> | hm. I'll have to think more about yield . |
18:34 | <bakkot> | I could be convinced it should not wrap, probably |
18:34 | <rbuckton> | The thing is, an AsyncContext instance is more like a single variable AsyncLocal<T> , though that is backed by something called a "Call Context" |
18:37 | <ljharb> | tbh "context" is a better name for this proposal than for the decorator property, if we had to pick one |
18:39 | <yulia> | thats fair, up until today i was taking AsyncContext as a name for granted |
18:39 | <littledan> | let's call it "util" |
18:39 | <yulia> | oh no, what have i done |
18:39 | <littledan> | AsyncUtil |
18:40 | <Ben Newman (Apollo, @benjamn on GH)> | the meaning of "context" is highly context-dependent, unfortunately |
18:40 | <rbuckton> | context is a general purpose term, I'd hate for us to relegate it to a single purpose. |
18:40 | <shu> | apaprocki: i believe you but BBG is a closed-shop ecosystem, so i wouldn't weigh it too much as predictive of ecosystem integration pains for JS at large |
18:41 | <apaprocki> | understood, merely relaying experience that for the end users, who are really just writing JS, it wasn't confusing for them to understand why it wasn't working and how to fix it |
18:50 | <ljharb> | eemeli: pretty sure it's not polyfillable |
18:52 | <bakkot> | That's the problem. In the cases I'm concerned with, the generator is provided by the user to a third party library. You want the library to handle the complexities involved with async context flow control, not the author of the genrator. You want them to not be concerned about choosing which so, "the generator is provided by the user to a third party library" seems like exactly the case where we want
Maybe we should say that any library which consumes iterators in this way needs to juggle contexts properly? but on the other hand it's not clear to me how that's even possible here - how would the library ensure that the second half of the generator runs in the correct context? |
18:52 | <Ben Newman (Apollo, @benjamn on GH)> | strawdog idea: you could wrap Generator.prototype.next |
18:53 | <bakkot> | but how does the library get the original context? |
18:53 | <littledan> | when the queue opens back up, please feel free to ask questions about AsyncContext, even much more basic ones, about how it works at all. |
18:53 | <rbuckton> | I'd expect, at least roughly, that the context value remains referenced until run 's callstack is exhausted and any Promise created is garbage collected. |
18:55 | <rbuckton> |
.next() . That said, I'm fine if context propagates over yield if we have a mechanism to affect async flow control. |
18:56 | <ryzokuken> | note: we'll have to go upto 10m into lunch because of the delays |
19:01 | <justinfagnani> | is anyone else not seeing the slides on Zoom? |
19:01 | <Jesse (TC39)> | yeah |
19:01 | <Jesse (TC39)> | oops, I mean, I am seeing the slides |
19:01 | <danielrosenwasser> | quick refresh? |
19:02 | <justinfagnani> | ah, that did it |
19:02 | <justinfagnani> | thanks |
19:04 | <shu> | i would like the conversation to come back to what littledan was proposing on "whether we want this feature" |
19:04 | <shu> | all these details beg the question of our already having consensus on that |
19:04 | <bakkot> | I do wish we had more examples yeah |
19:04 | <bakkot> | this is a big complex thing |
19:04 | <bakkot> | so I want to see it being useful for a bunch of things |
19:05 | <bakkot> | and I trust justin that it is useful for all the enumerated things, but I can't visualize how yet |
19:05 | <littledan> | Chengzhong Wugave a good presentation in WebPerfWG about this |
19:05 | <rbuckton> | Hmm. that example feels odd to me, since execution for the generator doesn't actually start until you call yield propagates context then I'm not even sure a flow-control mechanism would help, since flow control would probably only affect entry to the generator, not reentry via next() . |
19:05 | <littledan> | Maybe next meeting, this can be given to TC39 again |
19:07 | <Lenz Weber-Tronic (phryneas)> | bakkot the most pressing issue I can think of at this time is in servers, where functions need to access stuff related to the current request. At this point it's an absolute pain of passing the current request context down and down and down in method arguments, and it's easily lost. |
19:07 | <Lenz Weber-Tronic (phryneas)> | node has AsyncLocalStorage for that, but any framework that wants to support more platforms than that is at a loss at this time. |
19:09 | <bakkot> | Lenz Weber-Tronic (phryneas): I believe you but I need to see it written out |
19:09 | <justinfagnani> | there's both a question why it's useful, but why it's valuable as a language feature (which is the inability of userland code to correctly wrap all closure-storing APIs or intercept await ) |
19:09 | <rbuckton> | bakkot: I've used to thread request context information for web requests, such as the current authenticated user, request message, etc. Similar to HttpContext.Current in .NET (which uses the same mechanisms) |
19:09 | <justinfagnani> | Angular's zones.js problems with await as an example |
19:10 | <Andreu Botella> | shu: Chengzhong Wu and me are going to prototype a V8 implementation to see performance and integration with task attribution |
19:11 | <Lenz Weber-Tronic (phryneas)> | bakkot how exactly would "written out" look in this case? Just trying to figure out how to best give you the example. Imagine you have a call stack that is 50 calls deep. Either you have a , context argument in every of those functions, or the one function at depth 50 can call getCurrentRequest() which wraps requestContext.get() |
19:11 | <bakkot> | Lenz Weber-Tronic (phryneas): written out meaning, like, code |
19:11 | <shu> | Andreu Botella: in blink as well? any benchmarks in mind? |
19:11 | <danielrosenwasser> | I very much don't have expertise to weigh in on this API, so I can just give trust that in the current direction; but it sounds like the feature works "in the abstract". I wish there was a prototype or sample codebase so that we could have a sample in which it could be demonstrated:
and see how that composes in practice. And I'm fine with discussing that in stage 2. |
19:11 | <littledan> | Andreu Botella: in blink as well? any benchmarks in mind? |
19:12 | <bakkot> | i.e. assume this API exists. what does code using it look like, concretely, that would run if it were in the language |
19:12 | <shu> | littledan: it can't be just "welcome", i'm asking how andreu plans to "see performance"? |
19:12 | <shu> | we know it's possible to implement |
19:13 | <apaprocki> | i.e. assume this API exists. what does code using it look like, concretely, that would run if it were in the language |
19:13 | <littledan> | littledan: it can't be just "welcome", i'm asking how andreu plans to "see performance"? |
19:13 | <littledan> | and yeah the burden should be on us to prove that it's good. |
19:13 | <Andreu Botella> | Yeah, we'll be looking into that. We don't yet have any benchmarks in mind, but this is still very early on |
19:13 | <Andreu Botella> | like, we were literally discussing this earlier today |
19:13 | <Lenz Weber-Tronic (phryneas)> | bakkot it does exist, in some form, in node An example would be the NextJs |
19:13 | <shu> | it doesn't have to be a real benchmark |
19:14 | <shu> | i'm just wondering how you plan to verify anything |
19:14 | <shu> | (not being flippant if i sounded that way) |
19:14 | <Chengzhong Wu> | In Node.js we have several micro-benchmarks that we can port to AsyncContext: https://github.com/nodejs/node/tree/main/benchmark/async_hooks |
19:15 | <Chengzhong Wu> | And we can adopt OpenTelemetry's real world use cases for benchmarking if needed. |
19:15 | <shu> | sorry let me be clearer |
19:16 | <shu> | the performance concern is not that AsyncContext itself will be too slow |
19:16 | <shu> | it's fine for new features to be slow |
19:16 | <shu> | the way this feature must be implemented is In The Deep at the engine level |
19:16 | <shu> | which means it affects performance of all executions even if they don't use the feature |
19:17 | <shu> | i would like to see things that suggest that this feature can in fact be pay-as-you-go (or close to it), and executions that don't use the feature don't suffer performance regressions |
19:17 | <shu> | oops, missed an operative "not" above |
19:17 | <Ben Newman (Apollo, @benjamn on GH)> | V8 is already saving/restoring the v8::Context::{Get,Set}ContinuationPreservedEmbedderData today, which is close to what this proposal needs |
19:17 | <shu> | please, i know how V8 works |
19:17 | <Ben Newman (Apollo, @benjamn on GH)> | I know! |
19:18 | <littledan> | Yeah, it will be a clear requirement that this doesn't slow down V8. We can the existing public V8 benchmarks to verify (and I know you have CI that will also verify this after it lands). |
19:18 | <shu> | but that thing is set by the embedder in a very bounded way, in a way that V8 folks aren't 100% happy with anyway |
19:18 | <shu> | for this to become JS programmable opens up new unknowns we should understand |
19:18 | <littledan> | I'm very encouraged by how TaskAttribution landed and is always on in Chrome, apparently without performance overhead |
19:18 | <Ben Newman (Apollo, @benjamn on GH)> | fair enough / good to know |
19:18 | <littledan> | but that thing is set by the embedder in a very bounded way, in a way that V8 folks aren't 100% happy with anyway |
19:19 | <shu> | fair, i'll try to understand this unhappiness deeply so i can articulate it |
19:20 | <Justin Ridgewell> | Yeah it'd be great to have a name brainstorm here (in an issue, not during plenary). https://github.com/tc39/proposal-async-context/issues AsyncLocalStorage , which is AsyncLocal-Storage and not Async-LocalStorage. |
19:21 | <HE Shi-Jun> | I still like AsyncLocal which make the analog to ThreadLocal in other langauges. |
19:21 | <HE Shi-Jun> | We don't have notes of current topic? |
19:22 | <Justin Ridgewell> |
context.run(libraryTakingAnIterator(…)) , in which case both call and init time would be equivalent |
19:22 | <Andreu Botella> | An "async context" in common parlance would seem to refer to the entire async-local map, rather than to an entry |
19:22 | <Andreu Botella> | so there's also that |
19:22 | <Justin Ridgewell> | We don't have notes of current topic? |
19:24 | <HE Shi-Jun> | It's lunch, not an official presentation |
19:25 | <HE Shi-Jun> | especially zoom do not have auto subtitle :( |
19:25 | <Justin Ridgewell> | shu: Chengzhong Wu and me are going to prototype a V8 implementation to see performance and integration with task attribution AsyncContext , and be like 0.00001% slowdown for code that is. |
19:26 | <Justin Ridgewell> | I believe the current node addon impl has that guarantee |
19:26 | <Ben Newman (Apollo, @benjamn on GH)> | possible jargon to distinguish between whole-map and individual items: "supertext" (not a real word) and "subtext"? |
19:26 | <Ben Newman (Apollo, @benjamn on GH)> | I agree this is a common ambiguity when talking about context, even at a linguistic level |
19:31 | <Justin Ridgewell> | Zoom does, but I don't know how to enable it |
19:41 | <shu> | my hope goes with you |
19:45 | <shu> | waldemar: so, re: the C++ release fence. in short, you are correct that in the C++ memory model the release fence doesn't sync-with without a corresponding acquire operation on another thread. the way V8 (and JVM) reason about this i think is more at the ISA level, per ISA. like, we think a store-store fence ( the maybe manual inline assembly is better here? idk |
19:45 | <shu> | in any case V8 mixes C++ generated code and our own generated code liberally anyway, since it's a JIT |
19:45 | <shu> | and i've never wrapped my head around reasoning at the C++ memory model level |
19:45 | <shu> | because of course taht doesn't exist for our own generated code |
19:45 | <shu> | so i generally try to reason about it by divining what ARM guarantees, then trying to shape C++ to generate the right thing |
19:46 | <shu> | (or what x86 guarantees etc) |
19:47 | <shu> | in fact, V8 also does the even more un-specified thing around atomics where we just bitcast addresses to std::atomic s |
19:47 | <shu> | but i think that behavior may finally be getting specced? |
19:53 | <shu> | omg it's this sub-thread that was keeping my notification at 1 |
19:54 | <shu> | and now i've made it worse for other people, sorry |
19:59 | <rbuckton> | I may be a minute or two late getting back. My dogs need a bio break and don't care about the plenary schedule. |
20:02 | <rbuckton> | I may be a minute or two late getting back. My dogs need a bio break and don't care about the plenary schedule. |
20:08 | <bakkot> | ljharb: was it es-shims which deletes it? for the notes |
20:08 | <ljharb> | es6-shim , specifically. core-js may, i'm not sure |
20:09 | <bakkot> | (I just missed the name) |
20:09 | <Justin Ridgewell> | my hope goes with you AsyncLocalStorage , my apps are losing native async /await performance due to my need to polyfill |
20:09 | <littledan> | Worth also noting is that node is already eating performance with usage of |
20:09 | <Justin Ridgewell> | We already live in a slow world, and this API should be much faster than the status quo |
20:09 | <shu> | the hard line is "no speedometer regressions" |
20:09 | <shu> | hard-ish |
20:10 | <littledan> | the hard line is "no speedometer regressions" |
20:10 | <shu> | godspeed you! async contexter |
20:11 | <littledan> | what is this referencing? |
20:11 | <shu> | https://en.wikipedia.org/wiki/Godspeed_You!_Black_Emperor |
20:12 | <Jesse (TC39)> | great stuff |
20:12 | <Ben Newman (Apollo, @benjamn on GH)> | the ! placement triggered the memory for me |
20:17 | <shu> | does anyone have a link to these slides? |
20:17 | <ryzokuken> | does anyone have a link to these slides? |
20:18 | <shu> | ty |
20:18 | <Justin Ridgewell> | I was always more into Explosions in the Sky |
20:23 | <Chris de Almeida> | < 10 mins for this item |
20:27 | <rbuckton> | Is ns precision useful to scientific calculations, or are they more likely to depend on sub-nanosecond values? |
20:28 | <bakkot> | re: nanoseconds and microseconds, https://www.youtube.com/watch?v=9eyFDBPk4Yw |
20:29 | <rbuckton> | More to the point that computer-derived wall clock time isn't the only source of time that Temporal.Instant and .Duration might be useful for. |
20:29 | <littledan> | I think the interop case doesn't really relate to durations |
20:30 | <bakkot> | I'm sorry, quarter nanoseconds? |
20:30 | <bakkot> | why |
20:30 | <littledan> | it fit into the bits? |
20:30 | <bakkot> | https://github.com/abseil/abseil-cpp/blob/b6de7b80325514018d38de2c4dee1254258c4b31/absl/time/duration.cc#L30-L31 |
20:30 | <bakkot> | sigh |
20:30 | <bakkot> | yeah that's the reason |
20:31 | <apaprocki> | yeah, they decided to do that.. in our equivalent class, we opted just for storing nanoseconds and not quarterns like abseil |
20:31 | <rbuckton> | That and the following two lines about calculating fractional nanoseconds, but I suppose that wouldn't matter if they didn't have fractional nanoseconds to begin with. |
20:32 | <shu> | that abseil thing exactly characterizes where the interop argument falls down when you tug on the chain |
20:32 | <shu> | "why did they do it? well... because it fit" is not a good first principles argument |
20:32 | <shu> | but anyways we'll have ns |
20:33 | <Richard Gibson> | does abseil expose that data or just keep it internally for arithmetic? |
20:33 | <apaprocki> | it wasn't just because it fit, but because they stated a need for 0.5 ns + 0.5 ns |
20:33 | <apaprocki> | they didn't explain where they have that requirement |
20:33 | <apaprocki> | just that it exists |
20:33 | <shu> | v8's position is there is no good reason, and certainly not on the web |
20:34 | <littledan> | that abseil thing exactly characterizes where the interop argument falls down when you tug on the chain |
20:34 | <littledan> | v8's position is there is no good reason, and certainly not on the web |
20:34 | <shu> | the philosophical objection is actually stronger than than "there might be uses" |
20:35 | <shu> | it's "where you think you should be using nanoseconds, you are fooling yourself with the extra precision, with very few exceptions" |
20:35 | <littledan> | yeah I guess I see that and don't like the philosophy. |
20:35 | <shu> | yes, and we don't have consensus on it anyways |
20:35 | <apaprocki> | it's "where you think you should be using nanoseconds, you are fooling yourself with the extra precision, with very few exceptions" |
20:35 | <shu> | that doesn't relate to temporal |
20:36 | <shu> | you can use BigInts |
20:36 | <littledan> | yes, and we don't have consensus on it anyways |
20:36 | <shu> | except where law/regulations say they must be passed around... it's not about philosophy, but about preventing foot guns when moving values from one system to another through js |
20:37 | <shu> | like ns timestamps don't need the extra complexity of temporal |
20:37 | <shu> | sometimes it's formatting |
20:37 | <shu> | which... is a different thing? |
20:37 | <apaprocki> | because you are generically binding to typed database tables or schemas for services, etc. it's a giant foot gun if developers can't take a duration from Postgres and represent it as a duration in js without loss |
20:37 | <apaprocki> | somehow knowing they need to not use the built-in type and use a string or unrelated type.. it's extremely not ergonomic |
20:38 | <littledan> | this is one of the key reasons for it being in the standard library rather than just telling people to use Moment |
20:38 | <shu> | first of all, postgres is ms precision? |
20:38 | <waldemar> | Indiana has (at least) 11 time zones: https://en.wikipedia.org/wiki/Time_in_Indiana |
20:39 | <apaprocki> | first of all, postgres is ms precision? |
20:39 | <Chris de Almeida> | 🙊 |
20:39 | <shu> | oh really? |
20:39 | <apaprocki> | yes.. haven't found a modern system that hasn't already upgraded (if they didn't start out ns) |
20:39 | <apaprocki> | like rust had the benefit of starting with ns because it started much later, but python upgraded over time via PEPs |
20:40 | <shu> | anyway we're not going down microseconds road |
20:40 | <bakkot> | no, everything now uses ns |
20:40 | <shu> | and i would like to evict this conversation from my brain |
20:40 | <bakkot> | shu: good good, gotta make room for the conversation about time zone name canonicalization differences between TZDB and CLDR |
20:40 | <shu> | i am having lunch |
20:41 | <apaprocki> | hm https://www.postgresql.org/docs/current/datatype-datetime.html |
20:43 | <apaprocki> | there is an extension that allows up to 9 |
20:43 | <bakkot> | ah that's what I get for not reading past the table |
20:44 | <ryzokuken> | there is an extension that allows up to 9 |
20:46 | <apaprocki> | there's a bit of drift between databases (unlike programming languages).. oracle supports ns fully, mssql is 100 ns precision iirc, but the point is that they are < 1us |
20:53 | <Chris de Almeida> | 10 mins on this item |
21:05 | <apaprocki> | justingrant: thanks for doing this! Literally just starting the 2023a firedrill right now... :D |
21:10 | <bakkot> | how do people feel about parameter decorators |
21:10 | <Chris de Almeida> | cautiously... cautious |
21:12 | <justingrant> | justingrant: thanks for doing this! Literally just starting the 2023a firedrill right now... :D |
21:13 | <ljharb> | i feel a lot better about parameter decorators than i do about supporting/encouraging DI patterns |
21:13 | <shu> | how do people feel about parameter decorators |
21:17 | <ljharb> | something i do want is the ability to mark constructor arguments as automatically stored in a public, or private, field. but that could be done potentially with a class decorator, i suppose |
21:18 | <Lenz Weber-Tronic (phryneas)> | something i do want is the ability to mark constructor arguments as automatically stored in a public, or private, field. but that could be done potentially with a class decorator, i suppose |
21:18 | <HE Shi-Jun> | how do people feel about parameter decorators |
21:18 | <littledan> | how do people feel about parameter decorators |
21:19 | <ljharb> | Could that class decorator know the name of those constructor parameters? |
21:19 | <littledan> | parameter decorators, or something else in this space, are definitely part of the program of, "how do we find a standard, unified way to solve all of the problems that people are widely doing through language extensions" |
21:19 | <shu> | as a general philosophy i do not want more and more metaprogramming needing to be supported at runtime |
21:19 | <HE Shi-Jun> | I also want function decorators. 😀 |
21:19 | <Lenz Weber-Tronic (phryneas)> | how do people feel about parameter decorators |
21:20 | <shu> | my hot take is that we need to standardize different phases of evaluation in JS |
21:20 | <bakkot> | They are very commonly used in code I have touched over the last few years. I think the code would have been significantly more complicated without them. |
21:21 | <bakkot> | parameter decorators, or something else in this space, are definitely part of the program of, "how do we find a standard, unified way to solve all of the problems that people are widely doing through language extensions" |
21:21 | <bakkot> | I never signed up for that program |
21:21 | <HE Shi-Jun> | as a general philosophy i do not want more and more metaprogramming needing to be supported at runtime |
21:21 | <bakkot> | I am explicitly opposed to solving all of the problems that people are doing through language extensions |
21:21 | <ljharb> | showing me lots of code examples that are ExcessiveNounHavers doesn't make me feel good about the patterns :-/ just because a lot of people write X code in JS doesn't mean JS should support patterns common in X codebases. |
21:21 | <shu> | It seems if we have class decorators, people eventually would ask for "decorate everything". |
21:21 | <littledan> | I am explicitly opposed to solving all of the problems that people are doing through language extensions |
21:22 | <Chris de Almeida> | I'm generally apprehensive about too much hidden magic that makes grok difficult for grug brain |
21:22 | <shu> | sorry i'm being very flippant this meeting |
21:22 | <bakkot> | DI is the canonical example of hidden magic ime |
21:22 | <Lenz Weber-Tronic (phryneas)> | I have the exact opposite experience NestJS has some very nice usages, fore example the
|
21:22 | <bakkot> | like I have used it in talks as an example of that thing |
21:22 | <shu> | yes |
21:22 | <bakkot> |
|
21:22 | <Lenz Weber-Tronic (phryneas)> | But I agree that there are very ugly examples as well |
21:22 | <shu> | more generally this all strikes me as optimizing for the author |
21:23 | <littledan> | DI is the canonical example of hidden magic ime |
21:23 | <shu> | which is the wrong audience to optimize for |
21:23 | <shu> | sometimes it's, like, not too bad |
21:23 | <shu> | in this case it is bad |
21:23 | <littledan> | I do have to admit that, with decorators evaluated at class evaluation time, they are sort of a better fit than extractors/pattern matching evaluated each time the function runs. |
21:24 | <ljharb> | i think param decorators and param pattern matching/extractor "something" are quite different |
21:24 | <ljharb> | the use cases, anyways, even if the capabilities are similar |
21:24 | <littledan> | more generally this all strikes me as optimizing for the author |
21:25 | <ljharb> | imo we want to optimize for the person reading/maintaining the code after the author produces it that's a far more frequent and important audience. |
21:25 | <bakkot> | ??? isn't this sort of a core goal of programming language design? Like, if it's at the expense of the end user (e.g., for performance), then that's bad, but all else being equal, we do want to optimize for the author? |
21:25 | <ljharb> | iow, writability < < < readability |
21:25 | <littledan> | oh you meant author at the expense of reader! |
21:25 | <shu> | yes, correct |
21:25 | <danielrosenwasser> | I was also a little confused |
21:25 | <danielrosenwasser> | maybe all the Daniels were confused |
21:25 | <Chris de Almeida> |
|
21:25 | <ljharb> | code that's easy to write but hard to read is not what i would call good code |
21:25 | <shu> | sorry, not author vis a vis user, but writer vs reader |
21:26 | <ljharb> | counterpoint: that's often the same audience |
21:26 | <littledan> | Yeah, I mean, I wouldn't really be a fan of some of the decorators used in this presentation |
21:26 | <HE Shi-Jun> | and? |
21:26 | <Chris de Almeida> | fair |
21:27 | <shu> | what is the argument for it? |
21:27 | <shu> | "people ask for it" is usually not sufficient |
21:28 | <ljharb> | JS also is in a position where a ton of people come to it from different languages, and they write lots of code that matches the idioms of their source langs that does NOT match JS idiom |
21:28 | <ljharb> | ie the "java devs write java in every language" sentiment (not just picking on java here, ofc) |
21:28 | <Chris de Almeida> | ImplImplImplImplBuilderImpl |
21:29 | <ljharb> | excessive nouns, indeed |
21:29 | <apaprocki> | I'd say something like "it allows you to easily reuse code that would otherwise be repeated (boilerplate), or, more importantly, omitted because the author doesn't want to bother due to the size of the boilerplate" |
21:29 | <apaprocki> | for things like standard parameter validation checks across a large codebase |
21:29 | <ljharb> | validation checks i 100% agree - that's not the same thing as the extensive metaprogramming demonstrated in the preso |
21:29 | <littledan> | JS also is in a position where a ton of people come to it from different languages, and they write lots of code that matches the idioms of their source langs that does NOT match JS idiom |
21:30 | <bakkot> | valid(x) is almost exactly the same amount of code as @valid , and as a bonus also works with destructured parameters |
21:30 | <ljharb> | sure. it's just not necessarily influenced for the better. |
21:30 | <Ashley Claymore> | I do have to admit that, with decorators evaluated at class evaluation time, they are sort of a better fit than extractors/pattern matching evaluated each time the function runs. |
21:30 | <Lenz Weber-Tronic (phryneas)> | validation checks i 100% agree - that's not the same thing as the extensive metaprogramming demonstrated in the preso |
21:30 | <Chris de Almeida> | agree that validation seems reasonable as does ORM use case.. request mapping.. I have trouble imagining how the scope can be narrowed though |
21:31 | <shu> | i deeply hate ORM |
21:31 | <shu> | but that's personal |
21:31 | <HE Shi-Jun> | maybe all the Daniels were confused |
21:31 | <littledan> | the function returned by the decorator does run each time, so a bit like a cached extractor |
21:31 | <ljharb> | obligatory https://seldo.com/posts/orm_is_an_antipattern/ |
21:31 | <bakkot> | sidebar: this is I think way too much detail for a stage 1 presentation |
21:31 | <Jesse (TC39)> | i like the idea of ORM but have never found one that meshes with how I want it to work |
21:31 | <Chris de Almeida> | what do you mean you don't like doing a complete 1-1 of your data model in the frontend? |
21:32 | <bakkot> | stage 1 needs like 1 slide on potential API |
21:32 | <ljharb> | i mean, look at all the times use of an ORM has allowed a seamless transition between backing databases! |
21:32 | <bakkot> | 2 maybe |
21:32 | <shu> | sidebar: this is I think way too much detail for a stage 1 presentation |
21:32 | <shu> | i should think that deserves discussion time more than detailed semantics |
21:32 | <Chris de Almeida> | you've convinced me |
21:33 | <apaprocki> | sidebar: this is I think way too much detail for a stage 1 presentation |
21:33 | <bakkot> | I have probably been guilty of this too because I fall in love with proposals and flesh them all out in my head before bringing them to committee |
21:33 | <bakkot> | but that stuff mostly ought to go in the repo rather than the presentation |
21:34 | <littledan> | to be fair to Ron, this is 9 years coming; this is very thought out even if we are having a hard time processing it all at once. |
21:35 | <Justin Ridgewell> | Does anyone else get a strong "corporate java project" vibe from the code? |
21:35 | <Justin Ridgewell> | I really need to catch up with this matrix logs |
21:36 | <HE Shi-Jun> | sidebar: this is I think way too much detail for a stage 1 presentation |
21:36 | <shu> | naive question: can you "just like" parse the parameters of the toString() 'd original method in a method decorator, and... use that? |
21:37 | <bakkot> | but if not show many use cases people will refuse it because of no enough use cases?? |
21:37 | <bakkot> | the "here is what the type of the target field should be" part is less appropriate |
21:37 | <ljharb> | naive question: can you "just like" parse the parameters of the |
21:37 | <shu> | ah, indeed, minification |
21:37 | <shu> | thanks |
21:39 | <ptomato> | Does anyone else get a strong "corporate java project" vibe from the code? |
21:40 | <bakkot> | the latter is also a valid reason to not add something though |
21:40 | <bakkot> | e.g., there are languages where constructing code at runtime and evaluating it is a core technique |
21:41 | <Chris de Almeida> | I do not miss the era of DI being the new shiny |
21:41 | <bakkot> | but I don't want people to use that technique in JS and would actively oppose features which enabled it (though, of course, that ship has sailed) |
21:41 | <Justin Ridgewell> | https://matrix.to/#/!WgJwmjBNZEXhJnXHXw:matrix.org/$ub45qHDXteYxSbmwfzPGXe-KTZXA2oRYer99mr5tPrY?via=matrix.org&via=igalia.com&via=mozilla.org |
21:43 | <Justin Ridgewell> | I mean I think DI is a very divisive programming technique? but IMO we should separate "this proposal would enable X footgun" and "this proposal would enable X programming technique that I don't like" |
21:44 | <Justin Ridgewell> | I'm not blocking, but god I hope I never have to work on a codebase that uses this style. |
21:45 | <Lenz Weber-Tronic (phryneas)> | but I don't want people to use that technique in JS and would actively oppose features which enabled it (though, of course, that ship has sailed) |
21:47 | <ljharb> | btw for function decorators can we just decide that decorated function declarations aren't hoisted? or is it more complex than that |
21:48 | <shu> | that would be extremely weird |
21:48 | <shu> | that means decorated functions declarations become non-letrec'ed together |
21:48 | <shu> | which is... extremely weird |
21:49 | <Justin Ridgewell> | I've used a lot of function foo() { foo = function () {} } memoized declaration wrappers, and I'd like to stop doing that. |
21:51 | <bakkot> | I'd say there are frameworks heavily based on that, and also frameworks for the same purpose not using this at all. You probably won't get happy working in a team that loves using these techniques, but that team would find ways of doing so either way - so why not make it easier for them? It will not eradicate the option of working without these features. |
21:51 | <bakkot> | and like |
21:51 | <bakkot> | I think we should not make it easier for them so that they don't do it |
21:52 | <Lenz Weber-Tronic (phryneas)> | the "that technique" in the bit you quoted was "constructing code at runtime and evaluating it" |
21:53 | <bakkot> | yeah, the point was that sometimes features enable you to do things that we, as language designers, don't want to encourage you to do. that is how I feel about this style of DI. |
21:59 | <msaboff> | TypeScript ≠JavaScript. They don't need to be the same. I think that would be a false goal of the committee. They serve different purposes. Developers choose various tools and language extensions in solve their problems. |
22:02 | <shu> | i think that's a 4d chess space that deals with developer mindshare and respective tech giants' soft power etc |
22:02 | <shu> | i have a hard time, attractive as it is, to adopt a more absolutist line like TS and JS can and should just stay separate |
22:03 | <bakkot> | My hope is that new projects don't adopt TS decorators |
22:03 | <bakkot> | Old projects staying on TS decorators I don't really have a problem with |
22:03 | <msaboff> | Maybe I should say that we shouldn't add something to JS because it is in TS, ... |
22:04 | <shu> | agreed |
22:04 | <littledan> | TS and JS are pretty aligned already, and this is important and valuable for Bloomberg. But yes I agree completely that we shouldn't just upstream TS features into JS uncritically. |
22:04 | <shu> | i take msaboff's statement to be stronger than that |
22:05 | <Lenz Weber-Tronic (phryneas)> | Luckily, there are only two TS runtime features that are not JS features, decorators being one of them - so that's not a long-term concern :) |
22:06 | <shu> | in your opinion, do you think that is a stable equilibrium |
22:06 | <Lenz Weber-Tronic (phryneas)> | The TS team committed to not adding anything before ECMAScript Stage 3 half a decade ago, and so far they kept that |
22:07 | <HE Shi-Jun> | but I don't want people to use that technique in JS and would actively oppose features which enabled it (though, of course, that ship has sailed) |
22:10 | <HE Shi-Jun> | that would be extremely weird |
22:11 | <Justin Ridgewell> | Ashley Claymore: I would love if calling Promise.all({ foo: bar }) just worked like MM suggests |
22:12 | <msaboff> | Maybe I'm pushing back an a theme that seems to be prevalent during this meeting, and that is JS should unify the related ecosystems. I think that is the wrong target. We need to be about craeful evolution of the JS language and ensuring compatibility among the various implementations. That requires saying NO to some proposals for a variety of valid reasons. |
22:17 | <rbuckton> | something i do want is the ability to mark constructor arguments as automatically stored in a public, or private, field. but that could be done potentially with a class decorator, i suppose super() . |
22:19 | <HE Shi-Jun> | Ashley Claymore: I would love if calling |
22:19 | <HE Shi-Jun> | Oh it was closed, could champion reopen that ? |
22:19 | <Chris de Almeida> | I think there was an item above this |
22:20 | <bakkot> | I agree, yes the ship has sailed. I would accept JS never have decorators, but if we already have class decorators, it's wrong to me to not having function decorators, param decorators, etc. eval |
22:20 | <bakkot> | but that said, in exactly the same way, I don't want us to add new ways to make it easier to have eval |
22:21 | <bakkot> | this is the same way I feel regarding the argument that we have method decorators so should also have parameter decorators |
22:22 | <rbuckton> | This was going to be my point about the potential of parameter decorators to maybe have better performance than
|
22:22 | <ljharb> | Oh it was closed, could champion reopen that ? |
22:24 | <bakkot> | ljharb doesn't the "if there's more than one argument and the first is not iterable, throw" mostly address the bug thing? |
22:24 | <ljharb> | yes potentially, i haven't discussed it with ashley yet |
22:25 | <justinfagnani> | Decorators are ultimately about targeted/declarative meta-programming. Without them we'd have no way to ergonomically metaprogram over class fields (and before accessor no way at all). Is it not in scope to metaprogram in a similar way over parameters? |
22:25 | <rbuckton> | to be fair to Ron, this is 9 years coming; this is very thought out even if we are having a hard time processing it all at once. |
22:26 | <bakkot> | Decorators are ultimately about targeted/declarative meta-programming. Without them we'd have no way to ergonomically metaprogram over class fields (and before |
22:26 | <ljharb> | also "metaprogramming is desirable" isn't necessarily a universal belief |
22:27 | <justinfagnani> | talk about ships that sailed in JS though |
22:27 | <bakkot> | the eval ship sailed too but like |
22:27 | <bakkot> | we don't need to add more eval |
22:27 | <ljharb> | that we've allowed one form of a capability does not mean we should open the floodgates |
22:28 | <shu> | i don't even like DSLs! |
22:28 | <rbuckton> | I think bakkot's point is also spot on. Java has an overuse of classes for everything, and this is shoehorning a bunch into functionality into classes because we want it to be class method param decorators |
22:28 | <shu> | i have been radicalized despite my PL and compilers upbringing |
22:28 | <justinfagnani> | this isn't eval, or close. But metaprogramming in JS is as fundamental as the object model, 'x' in o , o[x] , for (k in o) etc |
22:29 | <shu> | what do you mean by metaprogramming? those constructs you listed are not metaprogramming |
22:29 | <ljharb> | overuse of classes? i've seen that in plenty of JS/TS codebases |
22:29 | <shu> | at least not in my head |
22:29 | <justinfagnani> | i don't even like DSLs! |
22:29 | <bakkot> | I haven't really seen this in 8 years of this feature in TS. It may happen, but certainly not frequently. BooksAPI example a really clear example of that? |
22:29 | <bakkot> | There's no reason to make that a class at all except that it's the only way you can get parameter decorators |
22:29 | <Justin Ridgewell> | I think the code samples in the slides demonstrated it already? |
22:29 | <bakkot> | In any other context those functions would be separate functions |
22:30 | <rbuckton> | Only in that it is a fairly limited example. NestJs has better examples. These often are decorated at the class level as well. |
22:30 | <shu> | tagged template literals sailed too! |
22:30 | <justinfagnani> | what do you mean by metaprogramming? those constructs you listed are not metaprogramming |
22:30 | <littledan> | Sorry for causing delay! |
22:31 | <shu> | i see that as reflection |
22:31 | <shu> | when i say metaprogramming i specifically mean reflecting code as data that can be manipulated |
22:31 | <shu> | if you are reflecting data as data, i don't consider that metaprogramming |
22:31 | <shu> | somewhat confusingly, you sometimes hear this referred to as "homoiconicity" from the schemers |
22:32 | <littledan> | I've had other proposals fail to advance explicitly because of a lack of sufficient real world examples, so I may have overcorrected a bit... |
22:33 | <littledan> | if you are reflecting data as data, i don't consider that metaprogramming |
22:33 | <shu> | disagree |
22:33 | <shu> | i don't think it's reasonable to consider strings code? |
22:33 | <ljharb> | i also disagree |
22:34 | <littledan> | I mean, they are code in other languages |
22:34 | <shu> | what does that mean? |
22:34 | <shu> | you can jump to a string? |
22:34 | <littledan> | well, just accessing a field by name in C++ is a fragment of code, and the kind of stuff you can do with [] in JS would be "reflection" |
22:35 | <shu> | i am very confused |
22:35 | <littledan> | anyway this is philosophy and not relevant to any decision we have here |
22:35 | <ptomato> | I guess in that there is no way to do this in C++?
|
22:36 | <justinfagnani> | in many languages a utility to replace a method would have to use metaprogramming, in JS you can patch a prototype - same goal, different mechanism. I think it's still metaprogramming. |
22:36 | <shu> | okay, then my apologies for using too imprecise a term |
22:36 | <littledan> |
|
22:37 | <shu> | i am specifically against evolving JS to enable more facilities to reflect code as data in order to manipulate that data, and to evaluate the manipulated new data as code |
22:37 | <shu> | a space that i consider decorators to be in generally, thus the desire to restrict them |
22:37 | <ptomato> | although, now that I think of it, you can do it in C++ with offsetof and/or template parameters |
22:38 | <justinfagnani> |
this isn't part of the proposals though, right? |
22:38 | <apaprocki> | although, now that I think of it, you can do it in C++ with |
22:38 | <bakkot> | justinfagnani: e.g. the proposal in its current form exposes the names of parameters, which thus far are purely code rather than data except in terms of f.p.toString |
22:38 | <shu> |
|
22:38 | <justinfagnani> | if it helps to use "reflection" instead of "metaprogramming", to indicate there are no new facilities for evaluating data as code, then ok |
22:39 | <ljharb> | code as data? |
22:40 | <shu> | justinfagnani: e.g. the proposal in its current form exposes the names of parameters, which thus far are purely code rather than data except in terms of f.p.toString |
22:40 | <shu> | decorators prevents this |
22:40 | <justinfagnani> | I meant "data as code" referring to Shu's objection |
22:40 | <shu> | i think jordan is just saying you reversed the direction |
22:40 | <justinfagnani> | I did? |
22:41 | <justinfagnani> | you oppose reflecting on code as data, then using evaluating that data as new code |
22:41 | <ljharb> | "evaluating code as data" is the Bad Thing |
22:41 | <justinfagnani> | yes? |
22:41 | <shu> | oh sure, yes, there's a round trip |
22:41 | <justinfagnani> | right |
22:42 | <ljharb> | "evaluating data as code" is already eval, and separately we also want to avoid new forms of eval |
22:42 | <shu> | so thanks for pushing on this i guess i don't strictly mean a full round trip |
22:42 | <shu> | reifying code as data, then running code on that code-as-data and causing new behavior, also feels like a smell to me |
22:43 | <shu> | that's how i think of what underlies people not liking "hidden magic" |
22:44 | <bakkot> | yes for DI in particular |
22:44 | <bakkot> | like normally the answer to "how did these values get bound to these parameters" is "the caller passed them in, or they are the default values" |
22:44 | <bakkot> | after parameter decorators, the answer will be "it is literally not knowable' |
22:45 | <justinfagnani> | I don't use DI myself, but... this is also true in DI |
22:45 | <justinfagnani> | the DI container passes in the parameters through a normal ctor call |
22:45 | <ptomato> | I think of hidden magic much more broadly - for me it's anything where execution jumps to an entirely different place and it's not obvious from the code |
22:45 | <ptomato> | like accessor properties, operator overloading, ... |
22:46 | <bakkot> | the DI container is a maximally abstract central location for passing values to things |
22:46 | <bakkot> | "the values are passed by the DI container" doesn't tell you anything about how they got there |
22:47 | <bakkot> | similarly, if you (as I do) transform your whole program into a bespoke implemented-in-JS VM, and then the main loop of the VM does the dispatch for all function calls in the entire program, that's also "the values are passed by the callers" but it's completely impossible for readers to follow |
22:47 | <ptomato> | I don't necessarily want to stamp out hidden magic, I think it's great when used responsibly and in reasonable amounts, and I'd hesitate to pass a value judgement on others' codebases that might have different tradeoffs as to what they consider "reasonable" |
22:47 | <justinfagnani> | it's fine to not like that, but it's pretty analogous to higher-order-functions... those can absolutely be abused in nasty ways. So many of us would prefer code bases that don't do that too much. But is it invalid as a whole? |
22:48 | <ptomato> | haha, I think I'm saying the same thing as justinfagnani here :-) |
22:48 | <bakkot> | I don't know what "invalid" means. |
22:48 | <bakkot> | Like it does... work? It's a legal program you can write in a language which allows it? |
22:48 | <bakkot> | But is it something the language should specifically set out to enable? That is a matter of opinion and my opinion is no, it should not. |
22:48 | <ljharb> | i feel like there was not appetite to add "curry" or "compose", partially for those reasons |
22:53 | <shu> | man if my Schemer professors could see me now |
22:53 | <shu> | "macros are bad, actually" "language tower is dumb, actually" |
22:54 | <Michael Ficarra> | I also reviewed this proposal (aside from the latest grammar changes) |
22:54 | <bakkot> | do you mean numeric tower or does "language tower" mean a different thing? |
22:54 | <shu> | no i mean language tower |
22:55 | <shu> | trying to find some documentation here... |
22:55 | <Michael Ficarra> | in Scheme, in order to solve any problem, you first create the perfect language for solving that problem, and then you write the solution in that language |
22:56 | <shu> | but yes, the basic idea is you build a tower of DSLs that bottoms out at Core Scheme or whatever |
22:56 | <Michael Ficarra> | DSLs on DSLs |
22:56 | <shu> | and hygenic macros pave the way for this wonderful write-only worldview |
22:56 | <shu> | heaven forbid you should want to collaborate with others |
22:57 | <Michael Ficarra> | that's why schemers value PL skills so highly, it's because they see every programmer as a PL designer |
22:57 | <bakkot> | https://softpanorama.org/People/Knuth/index.shtml#Introduction
|
23:00 | <Michael Ficarra> | something we haven't done as well on: D&I initiatives |
23:00 | <shu> | please photoshop me into the photo |
23:06 | <shu> | you can use this picture |
23:06 | <apaprocki> | thought it would be your router with the blinking connection light |
23:09 | <rbuckton> | i don't think it's reasonable to consider strings code? __code__ , if that helps. |
23:13 | <Chris de Almeida> | 🎉 |
23:16 | <waldemar> |
|
23:33 | <ptomato> | For sure. After I posted the message, I thought of `offsetof` |