00:00 | <rbuckton> | bakkot: I've run into this when working with non async/await code (i.e., working directly with Promise ). |
00:00 | <snek> | it turned out it was fine |
00:01 | <Justin Ridgewell> | shu: finally found the example that AMP hit: https://github.com/ampproject/amphtml/pull/15107 |
00:01 | <rbuckton> | A better (but maybe harder to answer) question is, how may people incorrectly write Promise.resolve(f()) ? This wouldn't fix those cases, but would give those developers something easier to reach for when they're looking for a solution. |
00:01 | <Justin Ridgewell> | After this, we forced all Promise.resolve(fn()) to use tryResolve(fn) helper |
00:02 | <shu> | is jest bad |
00:02 | <shu> | i feel like i've picked up some subtext somewhere that jest is bad, but unsure |
00:02 | <rbuckton> | jest is a good test framework that unfortunately does some very bad things. |
00:02 | <snek> | i think jest is ok? |
00:02 | <nicolo-ribaudo> | I feel like I'm the only one in the world that still likes Jest |
00:02 | <snek> | i don't use it often |
00:02 | <ryzokuken> | is jest bad |
00:03 | <nicolo-ribaudo> | Jest does Bad Things ^TM just because we haven't shadow realms yet |
00:03 | <hax (HE Shi-Jun)> | Promise.resolve((async () => fn())()) ? |
00:03 | <nicolo-ribaudo> | So Node folks hate it |
00:03 | <littledan> | only some parts of Jest are bad... |
00:03 | <snek> | node folks hate everything, i say this as a node folk |
00:03 | <rbuckton> | (async () => fn())() . |
00:05 | <nicolo-ribaudo> | I think we should start using more the number of dependents as a metric, rather than the number of downloads, since it tells us how many people actually needed to write that code |
00:05 | <nicolo-ribaudo> | A very popular library can still have shitty code |
00:06 | <snek> | i will continue to use whatever number best supports my position |
00:06 | <nicolo-ribaudo> | i will continue to use whatever number best supports my position |
00:06 | <bakkot> | ljharb: npm apparently doesn't let you fetch more than 10 pages of dependents so this is useless but since I've written it now https://gist.github.com/bakkot/61a9bddb1c88155297f4c6f0880189f6 |
00:07 | <shu> | ljharb: Justin Ridgewell shoot i missed your message before i didn't give consensus if it came before |
00:07 | <shu> | that diff is convincing enough for me, stage 2 sgtm, if ljharb wanna come back at end of today |
00:07 | <shu> | but not 2.7 yet because i think it probably needs to pass along ...arguments |
00:09 | <littledan> | shu: finally found the example that AMP hit: https://github.com/ampproject/amphtml/pull/15107 |
00:09 | <shu> | Justin Ridgewell: so wait actually now i'm reading MDN page for play() |
00:09 | <shu> | it says if it can't play(), a rejected Promise is returned |
00:09 | <shu> | was the sync throw a Chrome bug or is MDN wrong? |
00:10 | <Justin Ridgewell> | If I remember correctly, el.play() used to sync return, then it was changed to return a promise, but it can still sync throw. |
00:10 | <ljharb> | that diff is convincing enough for me, stage 2 sgtm, if ljharb wanna come back at end of today |
00:10 | <shu> | https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play says rejected Promise |
00:10 | <shu> | okay if the most compelling argument is "sometimes there are bugs and people do the bad thing", i guess that's fine with me |
00:10 | <shu> | the cost for this is pretty trivial |
00:13 | <Justin Ridgewell> | shu: https://github.com/ampproject/amphtml/pull/6083#discussion_r87054018 |
00:13 | <Justin Ridgewell> | I asked the exact same thing |
00:14 | <bakkot> | so zip is product on iterator (in the type-theory sense). sum doesn't really make sense on sync iterators (you can do zip+flat but there's not much reason) but on async iterators sum totally works, as AsyncIterator.merge or race or something like that. I will probably propose that at some point |
00:16 | <shu> | Justin Ridgewell: cursed that they just changed it, thanks for the knowledge |
00:18 | <ljharb> | shu: https://github.com/tc39/proposal-promise-try/issues/9 btw for the passing arguments thing |
00:19 | <shu> | thanks |
00:20 | <bakkot> | shu: https://github.com/tc39/proposal-promise-try/issues/9 btw for the passing arguments thing (async () => fn())() |
00:20 | <bakkot> | am I missing something about that |
00:20 | <ljharb> | i mean i am not personally ok with using syntax here |
00:20 | <bakkot> | sorry, that was re: your first comment in that thread |
00:21 | <snek> | Promise.try(() => f(a, b, c)) |
00:21 | <shu> | ok wait if you're ok with arrows why not just use |
00:21 | <shu> | but i mean i'm willing to take other people's words for what forms they want to type |
00:21 | <ljharb> | "wrapping in an arrow function" is how i spell "wrapping in a function" for people that can't ship that syntax, like myself :-p |
00:21 | <shu> | no deeper reason than that |
00:21 | <ljharb> | i think the readability/confusion thing still applies for an AIIFE tho, arrow or no |
00:22 | <ljharb> | which tbf is an argument in favor of passing arguments |
00:22 | <littledan> | what if we let prefix ^ be a shorter way to write ()=> ? Could make a lot of these arrows shorter. [but it wouldn't scale to the async case] |
00:22 | <ljharb> | however, this facility of setTimeout (passing args) has proven very confusing for practitioners, so i'm not anxious to repeat it |
00:23 | <snek> | what if we let prefix & &1 in elixir is like (a) => a |
00:23 | <rbuckton> | however, this facility of setTimeout (passing args) has proven very confusing for practitioners, so i'm not anxious to repeat it setTimeout is strange because it injects a timeout between the callback and the arguments. |
00:23 | <nicolo-ribaudo> | however, this facility of setTimeout (passing args) has proven very confusing for practitioners, so i'm not anxious to repeat it setTimeout is confusing because
|
00:24 | <snek> | i think arrow functions and bind are both better solutions than making everything that takes a callback also accept arguments somewhere |
00:24 | <jschoi> | https://github.com/tc39/proposal-pipeline-operator/blob/main/README.md#tacit-unary-function-application-syntax would cover this and have +> % mean x => x .Er, meant to reply to littledan there. |
00:24 | <TabAtkins> | For setTimeout, there's a potentially noticeable difference between setTimeout(f, 1000, a, b, c) and setTimeout(()=>f(a,b,c), 1000) , which is that a/b/c are evaluated eagerly or late. |
00:24 | <shu> | accepting a string is the way PHP and god intended |
00:24 | <TabAtkins> | There's no such difference in Promise.try() |
00:25 | <rbuckton> |
|
00:25 | <shu> | what is going on with matrix |
00:25 | <shu> | i'm seeing like, decoherence |
00:26 | <Justin Ridgewell> | Explici t support |
00:26 | <Justin Ridgewell> | Can’t talk |
00:26 | <snek> | who was i talking to earlier about discord message logs |
00:28 | <rbuckton> | i think arrow functions and bind are both better solutions than making everything that takes a callback also accept arguments somewhere |
00:28 | <snek> | What are your thoughts on https://github.com/tc39/proposal-partial-application? |
00:28 | <snek> | i don't write javascript in a super fp heavy way |
00:30 | <rbuckton> | That's fair. I'm still planning on coming back to that one at some point. I admit it paired far better with F#-style pipelines, but I still think it has value. |
00:35 | <rbuckton> | Feedback, someone needs to turn off a mic |
00:37 | <jschoi> | Did I disappear from the queue? |
00:38 | <Michael Ficarra> | jschoi: refresh |
00:38 | <rbuckton> | Did I disappear from the queue? |
00:39 | <littledan> | isn't it typed differently because it's not representable as an integer? |
00:40 | <snek> | ye |
00:40 | <snek> | the best thing is in v8 there's a parameter you have to pass when converting where you explicitly opt into checking for -0 or not |
00:41 | <snek> | surely no bugs have ever come of this 😄 |
00:41 | <shu> | isn't it typed differently because it's not representable as an integer? |
00:41 | <hax (HE Shi-Jun)> | I understand the issue of -0, but I don't think it should be considered in Math.sum proposal. |
00:42 | <Michael Ficarra> | I'd need a stronger argument to convince me to return +0 when passed an empty input |
00:42 | <shu> | hax (HE Shi-Jun): in which direction? |
00:42 | <shu> | Michael Ficarra: well it's confusing! |
00:42 | <ljharb> | wait why wouldn't empty input produce NaN |
00:42 | <snek> | i'd want to hear from someone who knows how binary64 works on whether its problematic. if it isn't, we should do +0 |
00:42 | <Michael Ficarra> | shu: it toStrings as 0! |
00:43 | <nicolo-ribaudo> | wait why wouldn't empty input produce NaN sum(...arr) and arr[0] + sum(..arr.splice(1)) do the same thing for non-empty arr :) |
00:43 | <ljharb> | they wouldn't anyways because of the current slide, right? |
00:43 | <nicolo-ribaudo> | Oh actually, with Kevin's algorithm this isn't true |
00:43 | <snek> | let getNegativeZero = () => Math.sum([]) please don't break my code |
00:43 | <nicolo-ribaudo> | Yeah good point jordan |
00:44 | <ljharb> | this is IEEE floats, math and real numbers have nothing to do with anything. "the sum of nothing" can be whatever we want |
00:44 | <nicolo-ribaudo> | this is IEEE floats, math and real numbers have nothing to do with anything. "the sum of nothing" can be whatever we want Math.sum([]) === 1 |
00:44 | <snek> | like is there maybe some implication if you do Math.sum(Math.sum(x), y) ? |
00:44 | <shu> | I'd need a stronger argument to convince me to return +0 when passed an empty input |
00:44 | <ljharb> | sumExact |
00:44 | <snek> | or use it in other random places |
00:45 | <hax (HE Shi-Jun)> | hax (HE Shi-Jun): in which direction? |
00:45 | <snek> | python also implicitly has ints in places tho |
00:46 | <Michael Ficarra> | i'm hearing you like exploits |
00:46 | <shu> | hax (HE Shi-Jun): i have already said why it's not irrelevant to v8 |
00:46 | <shu> | this doesn't prevent -0 from flowing to the wrong place intentionally |
00:46 | <Michael Ficarra> | yeah but that's not the surface |
00:46 | <shu> | manual inlines in the JIT for builtins is a surface |
00:47 | <nicolo-ribaudo> | i'm hearing you like exploits I don't find this convincing here because -0 is already in the language, and returing it from a new function just adds more places to be careful by a limited number (in the places where you are inlining this built-in). And now we are explicitly aware about this -0, it could be even be explicitly called out in the spec by saying why we return it so that implementers don't miss it. |
00:47 | <nicolo-ribaudo> | Otoh, Jordan's observation made me less storngly in favor of -0 |
00:47 | <Luca Casonato> | Me too Kevin, me too :P |
00:48 | <shu> |
|
00:48 | <rbuckton> | For additional reference, C#'s Enumerable.Sum also returns positive zero for an empty list. |
00:48 | <Michael Ficarra> | parseInt('-0') oh no exploits |
00:48 | <shu> | i mean can i hear a positive argument for why you want it to be -0 |
00:48 | <snek> | technically you can subtract a list, its just not a thing |
00:48 | <shu> | i said the exploit thing tongue in cheek |
00:49 | <Michael Ficarra> | maybe ask Duncan MacGregor for pointers to the examples from other languages he was referring to? |
00:49 | <nicolo-ribaudo> | i mean can i hear a positive argument for why you want it to be -0 |
00:49 | <shu> | is that property relied on |
00:49 | <shu> | like, for the use cases here |
00:50 | <shu> | if Python returns +0, i know that ecosystem does a lot of numerical stuff and it doesn't bother them, that gives me one signal |
00:50 | <shu> | Duncan MacGregor said ruby experienced the opposite thing, i'd like to learn more about that |
00:50 | <snek> | if Python returns +0, i know that ecosystem does a lot of numerical stuff and it doesn't bother them, that gives me one signal |
00:51 | <shu> | its fsum returns an integer? |
00:51 | <snek> | oh fsum probably does not |
00:51 | <snek> | is fsum a thing |
00:51 | <shu> | i'm specifically talking about fsum because that's what kevin was talking about (i thought) |
00:51 | <shu> | yes |
00:51 | <nicolo-ribaudo> | I've relied ib it for As Jordan pointed out however, that doesn't work here so my main argument is "all the others do this, we should not diverge" |
00:51 | <snek> | ah math.fsum |
00:51 | <shu> |
|
00:52 | <jschoi> | Well, because all the number combinators return their identity when called with 0 args Whether In other words, the question here is which equivalence relation we think is most useful (or least risky) for general code that needs to use Math.sum. |
00:52 | <shu> |
+ over floats |
00:52 | <shu> | how do === and Object.is figure into it? |
00:53 | <rbuckton> | If there should only be one answer, we either need a reference implementation or comprehensive test cases to ensure all implements do arrive at the same answer. |
00:53 | <shu> | oh i see, you mean x+id === x or Object.is(x+id, x) ? |
00:53 | <nicolo-ribaudo> | how do Object.is at some point, since it's not the identity only for the -0 vs +0 case |
00:53 | <shu> | yeah fair enough |
00:53 | <jschoi> | how do -0 and +0 are considered “equivalent” or different is related to whether we consider both -0 and +0 to be identities on the + operation. |
00:54 | <jschoi> | Basically what Nicolo just said. |
00:54 | <shu> | is that an argument for one direction over the other? |
00:54 | <jschoi> | I think it’s reasonable to return +0 and call it an “identity” (loosely, based on === ). |
00:54 | <shu> | sgtm |
00:55 | <Duncan MacGregor> | Duncan MacGregor said ruby experienced the opposite thing, i'd like to learn more about that |
00:56 | <Duncan MacGregor> | Ruby's array summing is a bit of a disaster area in my experience, it has a load of gotchas depending on whether the whole array is floats or not, and other fun things. |
00:58 | <Duncan MacGregor> | On the SQL and null note we couldn't return null because null is not the identity under addition in JS. null + null give 0. :-( |
00:58 | <ljharb> | NaN + NaN is NaN tho :-p |
00:59 | <shu> | Not returning -0.0 has the weird effect that summing two arrays (1 empty) can give a different result from summing the concatenated array. sum([]) + sum([1]) vs sum([].concat([1])) ? |
00:59 | <Rob Palmer> | New topic: How come we don't have a table of Stage 2.7 proposals? Is it that none have landed into that bucket yet? https://github.com/tc39/proposals |
00:59 | <jschoi> | The engines nowadays would optimize Math.sum([0, 1, 2]) such that the intermediate array doesn’t get allocated then GCed, right? |
01:00 | <ljharb> | yes, that's correct. i'll make a table for it once we have one |
01:00 | <Michael Ficarra> | even if we wrote down the full algorithm, we would still need to write somewhere that it was computing full precision summation because that is not immediately obvious from looking at 100 algorithm steps |
01:00 | <Bradford Smith> | ljharb: Would you be satisfied with the spec pointing to documentation for an example known-good algorithm? |
01:00 | <ljharb> | why not put both? (to both the last two comments) |
01:01 | <snek> | as an implementor i don't think writing out an algorithm would be helpful, it would just be noise |
01:01 | <nicolo-ribaudo> | shu: Math.sum([-0]) what would you expect it to return? |
01:01 | <ljharb> | it would be helpful to me ¯\_(ツ)_/¯ |
01:01 | <snek> | i think linking to an example is far better |
01:02 | <jschoi> | yes, that's correct. i'll make a table for it once we have one |
01:02 | <nicolo-ribaudo> | If this returns +0 , I think it's ok to say "we always normalize -0". But if it can return -0, than you already have to be careful about it when implementing |
01:02 | <shu> | shu: |
01:02 | <Duncan MacGregor> | sorry being slow, meaning if you do |
01:02 | <shu> | If this returns |
01:02 | <Duncan MacGregor> | On ruby those actually give the same answer because ruby starts with 0 and adds the elements... |
01:02 | <rbuckton> | even if we wrote down the full algorithm, we would still need to write somewhere that it was computing full precision summation because that is not immediately obvious from looking at 100 algorithm steps |
01:03 | <shu> | So if you have [-0.0].sum + [].sum that would give a different result to ([-0.0] + []).sum. |
01:03 | <nicolo-ribaudo> | Ok so my position is that Math.sum([-0]) and Math.sum([]) must return the same result. I would prefer both to return -0, but as long as they return the same value I'm fine |
01:03 | <ljharb> | Does a prior “Stage 3 conditional on approval by reviewers” status retroactively count as “Stage 2.7”? Regarding proposal-array-from-async. |
01:03 | <shu> | Ok so my position is that |
01:03 | <Duncan MacGregor> | what are the two sums? +0.0 for the former and -0.0 for the latter? |
01:04 | <ljharb> | bakkot: mark me reviewed; altho i think the example should be a link and not "i have to google now" |
01:04 | <shu> | what i'm confused |
01:04 | <Duncan MacGregor> | I did say Ruby's summation was a mess. :-) |
01:07 | <bakkot> | Are there corner cases in arbitrary precision arithmetic that would be useful to point out in the specification? We do that in a number of places in the spec. |
06:26 | <Chris de Almeida> | for the notes, which Justin offered explicit support to advance math.sum ? |
06:26 | <Chris de Almeida> | I think it was JRL... ? |
09:41 | <Justin Ridgewell> | Not me |
09:41 | <Justin Ridgewell> | Too many Justins. |
17:57 | <Luca Casonato> | Can someone in the room find someone from ServiceNow to pick us up from the reception? There is 10 of us stuck at reception here |
18:14 | <Chris de Almeida> | please add your name to the attendees list at the top of the meeting notes |
18:20 | <Michael Ficarra> | I disagree that "the syntax part of it would be the part slowing it down" |
18:20 | <Michael Ficarra> | the data model is just as likely to be problematic as the syntax |
18:21 | <nicolo-ribaudo> | Eemeli mentioned that this data model ends up working also with the other known formats though |
18:22 | <Richard Gibson> | FYI, the data model is at https://github.com/unicode-org/message-format-wg/tree/main/spec/data-model |
18:27 | <Richard Gibson> | a Message is either a PatternMessage (with declarations and a pattern ) or a SelectMessage (with declarations and selectors for indexing into variants , where each Variant is a list of keys to match and a pattern . And Pattern is an array in which each element is either a string or an Expression (representing e.g. a variable) or a Markup (representing something analogous to an HTML/XML start/end tag). |
18:34 | <Justin Ridgewell> | Can we just version the syntax parser? Sorry, haven’t been able to listen to most of the proposal. |
18:37 | <Justin Ridgewell> | If this is already going to be a spec at another standards body. |
18:37 | <Michael Ficarra> | it already is versioned: 2 |
18:38 | <bakkot> | shu: did not hear comments from you on intl.messageFormat; would you be ok with it going for stage 2 with just the data model and not the syntax? |
18:40 | <shu> | yes, that's fine with me |
18:40 | <shu> | my concerns need some systemic approach to address, and wouldn't be productive to ask individual proposals to deal with them |
18:41 | <shu> | to wit, concerns with how we distribute stdlib additions that won't benefit from independent implementations |
18:45 | <littledan> | I wouldn't want to add all identity escapes to Unicode RegExps; that'd limit our evolution possibilities |
18:46 | <bakkot> | agreed but I wouldn't want to use any \ +punctuator escapes for anything other than identity escapes, that would be very confusing |
18:46 | <bakkot> | so I don't think this actually meaningfully limits the language evolution |
18:47 | <littledan> | agreed but I wouldn't want to use any |
18:50 | <Bradford Smith> | ljharb: Didn't you intend to ask for stage 2.7? |
18:50 | <Bradford Smith> | did I miss that? |
18:50 | <ljharb> | only if no changes were to be made |
18:50 | <rbuckton> | agreed but I wouldn't want to use any |
18:51 | <ljharb> | since nearly everyone wanted the change, i'll ask for it at the next meeting instead |
18:51 | <Bradford Smith> | right, ok |
18:51 | <Michael Ficarra> | bakkot: I like Haskell's \& which terminates variable-length escapes that precede it |
18:52 | <ljharb> | oof, white on light blue is a very hard to read contrast :-/ |
18:54 | <bakkot> | this slide needs a bright red drop shadow on the text |
18:54 | <nicolo-ribaudo> | This transcriptionist is getting capitalization right even for terms not on the slides (SharedArrayBuffer) |
18:54 | <bakkot> | for readability :) |
18:54 | <nicolo-ribaudo> | I love them |
18:54 | <jschoi> | Time to audit Shu’s slides for WCAG compliance. |
18:56 | <Michael Ficarra> | yeah this transcriptionist seemed much better than usual |
19:00 | <Justin Ridgewell> | it already is versioned: 2 |
19:00 | <Justin Ridgewell> | Ie, split the parser from the format. |
19:00 | <bakkot> | uhhhh why is the meeting being recorded now |
19:00 | <snek> | did the presentation just say someone is recording |
19:00 | <bakkot> | I am fine with Shu being recorded if he wants that but I would prefer not to be recorded |
19:00 | <nicolo-ribaudo> | This transcriptionist is getting capitalization right even for terms not on the slides (SharedArrayBuffer) |
19:02 | <Michael Ficarra> | noooooooooo |
19:09 | <Chris de Almeida> | to reiterate: I accidentally triggered a kb shortcut that started the recording in zoom and immediately stopped it. I think it was recording for maybe... 1 second? |
19:09 | <Chris de Almeida> | why there is no confirmation for that, I have no idea |
19:09 | <ljharb> | zoom pops up a warning when it starts, but doesn't remove the recording when it stops, so i didn't realize it had stopped |
19:10 | <Chris de Almeida> | zoom would show it's recording near the top of the window IIRC |
19:10 | <Chris de Almeida> | in any case, def not recording, and apologies for the scare! |
19:11 | <rbuckton> | Duncan MacGregor: Based on our conversations in the shared structs proposal, anything that could block would also have an async counterpart that could be used in the main thread (e.g., the "async locking" primitives discussed on one of the slides). |
19:14 | <rbuckton> | Very much want non-blocking, concurrent collections for this case. |
19:15 | <Mathieu Hofman> | Luca Casonato: do you have pointers where the move to remove the wasm handshake was discussed? I'd like to follow the developments, in particular regarding to this agent global syscall table it would likely introduce |
19:18 | <rbuckton> | since danielrosenwasser's question wasn't asked verbally, it may be worthwhile to copy it into the notes for anyone reading afterwards |
19:18 | <Duncan MacGregor> | Duncan MacGregor: Based on our conversations in the shared structs proposal, anything that could block would also have an async counterpart that could be used in the main thread (e.g., the "async locking" primitives discussed on one of the slides). |
19:18 | <nicolo-ribaudo> | Done |
19:19 | <snek> | tokio is a good prior art for async concurrency primitives |
19:19 | <rbuckton> | Thanks, I think an async API for condition varialbe might work, but my experience of writing concurrency libraries and reviewing concurrent code in general is that we should absolutely aim for higher level constructs because building them correctly from lower level ones is really hard and is not something we should generally be steering developers towards doing. |
19:21 | <snek> | i think mark would say we should be building erlang instead of c++ |
19:22 | <danielrosenwasser> | since danielrosenwasser's question wasn't asked verbally, it may be worthwhile to copy it into the notes for anyone reading afterwards |
19:22 | <nicolo-ribaudo> | apologies, didn't want to exhaust the timebox while I scrambled for the mic |
19:24 | <shu> | can i get a timebox check? |
19:26 | <Chris de Almeida> | 10m |
19:26 | <Chris de Almeida> | 9 min |
19:27 | <Chris de Almeida> | 8 min |
19:27 | <Michael Ficarra> | we really need TCQ to display the time remaining |
19:28 | <nicolo-ribaudo> | 6 and three quarters |
19:32 | <Rob Palmer> | 3 mins |
19:34 | <Rob Palmer> | 1 min |
19:34 | <snek> | 55 seconds |
19:34 | <nicolo-ribaudo> | 50 |
19:34 | <bakkot> | what else are we even going to do in the remaining time before lunch though? |
19:34 | <Luca Casonato> | Luca Casonato: do you have pointers where the move to remove the wasm handshake was discussed? I'd like to follow the developments, in particular regarding to this agent global syscall table it would likely introduce |
19:34 | <snek> | i am also curious of this kevin |
19:38 | <rbuckton> | If WASM has shared structs and concurrency primitives, and JS doesn't, it will be almost no time between availability in WASM and the first shared-structs package on NPM that makes it available in JS with a poorer experience than we could provide. |
19:38 | <iain> | Improving the JS/Wasm API seems like a good thing to do independent of our decision here |
19:39 | <Michael Ficarra> | what else are we even going to do in the remaining time before lunch though? |
19:39 | <bakkot> | if we get wasm shared objects I'm immediately going to write a JS library which uses wasm and proxies to implement the shared structs proposal |
19:39 | <bakkot> | I think the JS proposal can be almost completely polyfilled based on the wasm one |
19:39 | <snek> | binaryen about to get a lot of npm downloads |
19:40 | <Rob Palmer> | Is Ben Allen in this room? |
19:40 | <Ben> | Yes |
19:40 | <rbuckton> | I think the JS proposal can be almost completely polyfilled based on the wasm one |
19:40 | <ljharb> | Except syntax and the handshake complexity, and I'd really prefer we have actual syntax for this in JS. |
19:40 | <rbuckton> | I've used the dev trial for shared structs, and syntax is so much better. |
19:41 | <rbuckton> | the current proposal has no syntax, does it? |
19:41 | <rbuckton> | The dev trial does not |
19:41 | <ljharb> | ah :-/ |
19:41 | <bakkot> | Except syntax and the handshake complexity, and I'd really prefer we have actual syntax for this in JS. |
19:41 | <ljharb> | syntax, but the things produced are objects, not primitives? |
19:41 | <rbuckton> | yes, objects |
19:41 | <bakkot> | syntax, but the things produced are objects, not primitives? class declaration |
19:42 | <ljharb> | seems strange to have syntax for that then |
19:42 | <ljharb> | oh ok, for declaration but not usage? |
19:42 | <shu> | yeah it's for declaring the "types" |
19:42 | <rbuckton> | We cannot leverage class as is due to how fixed layout is determined, but the syntax is very close to class syntax. |
19:42 | <snek> | class(shared) |
19:44 | <rbuckton> | The are a number of additional restrictions on shared structs that aren't compatible with class construction semantics, and one of our areas of exploration was how to handle thread-local prototypes and correlating struct definitions between two threads. |
19:47 | <rbuckton> | but essentially the syntax is the same as class . The struct keyword essentially indicates the difference in construction and layout. IIRC, syntax is also helpful for VMs that want to do static analysis and leverage the declaration to determine fixed layout. |
19:50 | <rbuckton> | handshake you can do if the library is run in the worker as well. for sure agreed that syntax would be good. this is mostly pointing out that erights' objection just does not make sense because we'll do it in JS anyway |
19:51 | <bakkot> | and also serialization, presumably |
19:51 | <iain> | There's one possible world where this gets implemented in Wasm and then the syntax / polyfill is (at least initially) provided via build-time tooling. In particular, because Wasm functions don't close over nearly as much state as JS functions, shared behaviour seems strictly easier / cleaner to specify and implement in Wasm. |
19:51 | <rbuckton> | There has been a lot of interest inside of Microsoft around the shared structs proposal. |
19:53 | <rbuckton> | There's one possible world where this gets implemented in Wasm and then the syntax / polyfill is (at least initially) provided via build-time tooling. In particular, because Wasm functions don't close over nearly as much state as JS functions, shared behaviour seems strictly easier / cleaner to specify and implement in Wasm. struct syntax in TypeScript using the dev-trial implementation, even if only to test out the syntax. I'm not sure it is something we would ship if we never shipped syntax in JS. |
19:55 | <shu> | There's one possible world where this gets implemented in Wasm and then the syntax / polyfill is (at least initially) provided via build-time tooling. In particular, because Wasm functions don't close over nearly as much state as JS functions, shared behaviour seems strictly easier / cleaner to specify and implement in Wasm. |
19:55 | <shu> | another way to look at it is, the TLS syscall table is solving the attaching behavior problem |
19:56 | <ljharb> | bakkot: it's much easier to write your own function for it yes, but it's still not as ergonomic and readable as something built-in would be |
19:58 | <Duncan MacGregor> | I think in Java, because it go for structural types but only nomitative ones, you woul chunk things in a stream by using a collector to build the objects that represent the chunks. |
19:59 | <iain> | shu: What do you mean by crossing the boundary? Suppose we improve Wasm-JS interop by (eg) adding a section to wasm that lists the exposed fields/methods, and expose those to JS. My understanding is that in that case, your shared wasm object would have a shared shape that points to shared methods, all of which live in the shared heap, and you don't have to worry about shared->unshared edges in the same way you do with thread-local shapes. |
20:00 | <iain> | The obvious downside is that the shared methods all have to be written in wasm |
20:00 | <shu> | iain: how do you call the shared methods? |
20:00 | <rbuckton> | As a counterpoint to Mark's argument: Worker and SharedArrayBuffer already exist in JS and you can already get into trouble if you try to write multithreaded code and do so poorly, but that trouble often stems by JS not having adequate support for synchronization primitives and shared data, such that everyone needs to roll their own concurrency mechanism, and that's just plain worse. |
20:02 | <rbuckton> | You can implement Mutex and ConditionVariable on top of SAB using Atomics today (and I have). You can implement a very limited shared structs on top of SAB today as well (and I have). What's missing is object references and GC support. |
20:04 | <iain> | shu: Hmm. You access the property, you get some sort of wrapper back that has a local->shared edge, and then you invoke it. Are you saying that the wrapper has the same problem? |
20:04 | <iain> | It seems like we could spec the wrapper as some sort of opaque immutable type where identity is unobservable, and then avoiding repeated allocations of the wrapper is an implementation detail |
20:06 | <iain> | I guess identity is observable via comparison |
20:08 | <iain> | Alternatively, couldn't the wrapper be a shared object itself? |
20:58 | <shu> | shu: Hmm. You access the property, you get some sort of wrapper back that has a local->shared edge, and then you invoke it. Are you saying that the wrapper has the same problem? |
20:58 | <shu> | Alternatively, couldn't the wrapper be a shared object itself? |
21:00 | <iain> | That still seems preferable to the TLS ephemeron scheme |
21:01 | <shu> | i'm confused, how is this connected to the TLS ephemeron scheme? |
21:01 | <snek> | is this the same thing i wanted all those months ago |
21:01 | <littledan> | I liked the idea of avoiding the wrapper using TLS... aren't these wrappers expensive? how would you avoid repeat allocation? |
21:01 | <shu> | i might be misunderstanding this doesn't seem connected to the TLS thing |
21:01 | <shu> | the TLS thing is needed for shared wasm to use unshared JS functions (web APIs) |
21:01 | <shu> | i thought iain was talking about the other direction: JS calling shared wasm function |
21:02 | <littledan> | oh sorry for changing the subject; just catching up |
21:02 | <iain> | shu: I was talking about the local shape thing |
21:02 | <shu> | local shape? |
21:02 | <shu> | there are too many streams, sorry, might need to take it from the top at a later time |
21:02 | <iain> | shu: Thread-local prototypes |
21:03 | <shu> | iain: how do wrappers help there? |
21:05 | <iain> | My understanding of this slide deck is that we want to be able to attach behaviour to shared structs, but JS functions are necessarily not shared, so we need the TLS weakmap to assign thread-local prototypes. If wasm functions can be shared, then instead of thread-local prototypes, we can have shared prototypes, so we don't need the TLS weakmap or the ephemeron tracing. |
21:05 | <shu> | ah i see what you're saying |
21:06 | <littledan> | I like the idea for sharing behavior by having this TLS point to an object which serves as the prototype of an object. This lets you have getters for fields. |
21:06 | <littledan> | so then you need a way to allocate a Wasm GC object with a particular TLS field as a prototype [and presumably also a non-shared version, without using TLS] |
21:06 | <shu> | iain: i think that's morally equivalent to a new exotic callable that's sorta-kinda dynamically scoped. this was written off earlier in the design process because nobody i asked wanted new exotic callables |
21:07 | <shu> | i'm not deathly opposed to it but it's also a can of worms (i think) |
21:07 | <iain> | Not sure I understand where dynamic scoping comes in |
21:08 | <iain> | I was also under the impression that (aside from the question of how we expose it to JS) we got it mostly for free from the Wasm proposal, although I admit that I have been paying more attention to the JS side |
21:09 | <shu> | suppose the wasm function traps and needs to throw an exception. this exception needs to be materialized somehow. currently this is one of the ways in which functions are "deeply unshareable" in that you create Error instances from the realm in which the function was created |
21:09 | <shu> | this is a question that JS wrappers of shared wasm functions still need to answer |
21:09 | <shu> | an easy answer is: the realm of the wrapper, the wrapper is unshared |
21:09 | <shu> | a harder answer is: maybe the caller realm (what i meant by dynamic scope), since it's a special exotic callable |
21:10 | <shu> | but i take the point this may be a promising avenue to explore again, in light of the wasm angle |
21:11 | <iain> | Ah, I see. And the wasm proposal doesn't have to deal with this because the Error instance doesn't exist in wasm |
21:11 | <iain> | It's just trapping and then the world ends? |
21:11 | <shu> | yep |
21:11 | <shu> | and it doesn't have a notion of like "this realm's Array constructor" or whatever either |
21:12 | <shu> | a lot of the "original sin" comes down imo to JS functions being too first class |
21:12 | <rbuckton> | ... I remember using "LiveScript" on the server around the same time it was introduced for the browser and became known as JavaScript ... |
21:13 | <rbuckton> | in Netscape SuiteSpot Server, IIRC |
21:13 | <iain> | Are there implementation issues with a special exotic callable, or is the blocker there just the problem of specifying it? |
21:13 | <shu> | i haven't thought deeply about impl concerns |
21:13 | <shu> | IIRC it was more about language complexity |
21:14 | <iain> | From an implementation perspective I think I would prefer the exotic callable, but maybe there's something I'm missing |
21:14 | <shu> | (like, these special things have a different .apply or something? different .bind ?) |
21:16 | <iain> | Let's go back to the wrapper idea for a second. Regular non-shared JS object, with the Function prototype for .apply and friends. Freeze it so that it's completely immutable. |
21:17 | <shu> | which realm's Function prototype? |
21:18 | <iain> | The current realm? Maybe there's a separate instance per-realm. |
21:18 | <shu> | then isn't that... TLS prototypes |
21:19 | <iain> | What I'm trying to think through is whether we can just keep it in a weak map that doesn't care about other threads, because if there's no local edge to it and you collect it, then you just create it again from scratch |
21:19 | <iain> | You won't have pointer identity, but that's unobservable because we've postulated that we could collect it, so there wasn't another copy of the pointer |
21:19 | <shu> | oh |
21:19 | <shu> | that's a different semantics that Luke Wagner brought up in a different context |
21:20 | <shu> | i didn't have time to get to it during the agenda item |
21:20 | <littledan> | it's just kinda slow to have all these weak maps and wrappers, isn't it? |
21:20 | <shu> | yeah |
21:20 | <shu> | definitely needs to be validated |
21:21 | <danielrosenwasser> | leobalter: can you add your name to the notes document? |
21:21 | <snek> | i feel like there is too much nuance for us to ever come up with a more concrete process than what we currently have |
21:22 | <iain> | shu: SM is working on an architectural review of shared structs. Hoping to have it ready soon, although there's been enough new information today that it will take a little bit to digest it. |
21:22 | <iain> | Are there regular meetings for this proposal? Maybe I should be attending them |
21:23 | <shu> | shu: SM is working on an architectural review of shared structs. Hoping to have it ready soon, although there's been enough new information today that it will take a little bit to digest it. |
21:23 | <shu> | and cool! looking forward to review |
21:24 | <Michael Ficarra> | that was a beautiful point Richard Gibson: "lone" objectors are possibly only alone because the people they represent aren't in the room |
21:25 | <ljharb> | or, are in the room but unwilling to speak up - not everyone has the same comfort level with dissent |
21:26 | <Michael Ficarra> | I'm not as sympathetic to that ljharb |
21:26 | <danielrosenwasser> | Shane (SFC) can you add your name to the notes document? |
21:26 | <snek> | dissenting typically implies responsibility for finding a solution as well, its not something you always want to deal with |
21:26 | <ljharb> | I'm not as sympathetic to that ljharb |
21:26 | <bakkot> | while that's sometimes true, it's also often not true; some delegates work on things that no one else is really doing, or have concerns about language specification purity which are relevant only to consumers of the language specification, rather than to developers |
21:27 | <ljharb> | sometimes yes. but there isn't always a solution to be had, and people often have trouble accepting it when there is none. |
21:27 | <Chris de Almeida> | diffusion of responsibility is often at play |
21:30 | <Kris Kowal> | At the time that unanimity was established was when only VM implementers were present at the table and there was no point in making a standard that any one of them was unwilling to implement. |
21:31 | <Kris Kowal> | I’m in favor of keeping the consensus by unanimity, even though we’re not living in that historical context. |
21:31 | <snek> | i very strongly agree with everything mark is saying right now |
21:31 | <danielrosenwasser> | Is there a list of "known phrases" that the transcription bot knows about? |
21:31 | <bakkot> | danielrosenwasser: we have a human transcriptionist |
21:31 | <bakkot> | oh but for the transcribe bot? yes but it's very very short |
21:32 | <danielrosenwasser> | EMCAScript keeps getting put in the notes |
21:32 | <bakkot> |
|
21:32 | <leobalter> | I truly wonder if a decision regarding the consensus process requires TC consensus or actual member vote. |
21:33 | <Chris de Almeida> | the catch 22 which must not be named |
21:33 | <ljharb> | a member vote would suffice but that'd be a failure of the consensus process that we all currently agree to follow |
21:34 | <leobalter> | Consensus should be ideal, but it seems like a can of worms otherwise. We are using consensus to change what consensus means. It's not a simple process. |
21:35 | <bakkot> | i very strongly agree with everything mark is saying right now |
21:35 | <bakkot> | I realize that is maybe dramatic but it's also true and we ought to care about that cost |
21:35 | <ljharb> | ps if it takes 2 member companies to veto, then that means it only costs $7000 to block anything. |
21:35 | <leobalter> | Too much that can be discussed as formality. We need this to evolve more to discuss the format |
21:36 | <ljharb> | I realize that is maybe dramatic but it's also true and we ought to care about that cost |
21:36 | <shu> | ecma is literally pay to participate though |
21:36 | <Michael Ficarra> | ljharb: that would be bad faith |
21:36 | <Michael Ficarra> | we would just ignore it |
21:36 | <ljharb> | ljharb: that would be bad faith |
21:37 | <ljharb> | i'm not saying it's a reasonable tactic, i'm just reinforcing that it's impossible to prevent weaponization |
21:37 | <snek> | I disagree with the idea that "do nothing" is "fail safe". I particularly disagree with it in light of the previous conversation; I really wish it were better understood that failing to provide a good story for parallelism on the web means the experience of using the web is notably slower than it should be, and that is a cost which is measured in small fractions of billions people's lives every day |
21:37 | <bakkot> | if the objector will not change their mind, then we weigh the cost of overruling them against the cost of doing nothing, and I think in some cases - notably in the case of parallelism - the cost of doing nothing is overwhelmingly higher |
21:37 | <littledan> | ps if it takes 2 member companies to veto, then that means it only costs $7000 to block anything. |
21:37 | <ljharb> | right. so it didn't work despite our current process. so changing our process won't stop it more from working. |
21:38 | <shu> | it didn't work for one main reason, which is that he was part of the outgroup |
21:38 | <shu> | the weaponization msaboff alludes to is by members of the long-standing ingroup |
21:40 | <eemeli> | As we'll likely run out of time here, my thought: We should mitigate the negatives of a lone objector blocking progress. One way to do that would be to automate the re-presentation of decisions with a lone objector at a near-future meeting, allowing and expecting discussion to happen in the interim. So effectively require sustained objection to block a thing with a small minority. |
21:40 | <Michael Ficarra> | 😞 this was nowhere near enough time for this topic |
21:41 | <bakkot> | As we'll likely run out of time here, my thought: We should mitigate the negatives of a lone objector blocking progress. One way to do that would be to automate the re-presentation of decisions with a lone objector at a near-future meeting, allowing and expecting discussion to happen in the interim. So effectively require sustained objection to block a thing with a small minority. |
21:42 | <bakkot> | which is very much not the criteria we ought to use |
21:42 | <Michael Ficarra> | omg I agree so hard with Dan right now |
21:42 | <shu> | you also agreed hard with mark earlier |
21:42 | <shu> | confused |
21:42 | <Michael Ficarra> | not me |
21:42 | <shu> | ah, my bad |
21:42 | <snek> | i agreed with mark |
21:43 | <shu> | but yes i also agree with dan |
21:44 | <littledan> | I should've also said: blocks are really really really discouraging and do stop progress, even if people don't mean it to |
21:44 | <snek> | i'm not against improving things, i just feel like we're playing with a very delicately balanced bomb |
21:44 | <leobalter> | I honestly just hope we end some paths for delegate burnout. This is a very sensitive topic and I'd love to keep the convo when time allows. |
21:44 | <littledan> | Blocks definitely cause delegate burnout, this is unquestionable |
21:45 | <shu> | it has many knock on effects, delegate burnout the worst among them for individual well-being |
21:45 | <littledan> | I also should've said: I'm really confident that everyone here just wants what's best for JS, and we're just trying to figure out the way to collect the data and judgements we're all bringing |
21:45 | <leobalter> | TC39 lost some considerate participations and I totally sympathize with the idea of trying to resolve this. I don't have an answer ready on how we do this. |
21:45 | <shu> | it encourages to shop venues, and in the limit, it encourages erosion of the weight of tc39 itself |
21:50 | <Michael Ficarra> | lol stop putting new things on the queue please, we're trying to drain it |
21:51 | <littledan> | it would be an improvement if voices had the same weight. Right now, we weigh people higher if they have a propensity to veto |
21:52 | <shu> | i don't think voices should have the same weight |
21:52 | <shu> | but giving propensity to veto higher weight is much worse than equal weight |
21:53 | <littledan> | We should understand what different stakeholders represent, and make decisions with that in mind. But I think the committee currently has equality as a goal/mostly shared value, and I hope it stays that way, and that we can reinforce it more. |
21:55 | <bakkot> | I think I would put it this way: The veto process means that we say the risk of doing the wrong thing is always more than the risk of doing nothing. And that's just not true. Some things, sugar especially, doing nothing is relatively costless; some things, like new capabilities and APIs for performance, the cost of doing nothing is actually quite high. Our process should allow seriously weighing the costs of doing nothing, and not privilege the costs of doing the wrong thing as the ultimate determinant. |
21:56 | <leobalter> | msaboff: I highly encourage we continue discussing this. Thank you for bringing it up to TC39! |
21:58 | <ljharb> | does anyone remember which meeting shadowrealms was dropped to stage 2? |
21:58 | <rbuckton> | Per what danielrosenwasser said, it would definitely help if lone dissenters became actively involved in the proposal to help address concerns. Vetoing a proposal and walking away when that proposal has otherwise broad support isn't helpful. |
21:58 | <shu> | does anyone remember which meeting shadowrealms was dropped to stage 2? |
21:58 | <bakkot> | ("relatively costless" is the wrong way of putting it, since in every case blocking certainly has costs on delegates, which are quite real and I don't want to leave those out. but the costs are of a different kind than the costs of the web being slower or otherwise worse for users) |
21:59 | <danielrosenwasser> | To be clear, I am somewhat okay with people saying "this is just a matter of taste", but I am frustrated when the feedback is left as an exercise to the champion. |
21:59 | <shu> | i am not okay with people saying it's a matter of taste when it's not a matter of taste though! |
21:59 | <bakkot> | chairs: queue needs advancing |
21:59 | <snek> |
|
21:59 | <snek> | how do you come to agreement on it |
22:00 | <Kris Kowal> | bakkot: That would seem to suggest that we would need different rules for consensus for different kinds of changes. Perhaps we can use consensus to weaken consensus selectively. |
22:00 | <snek> | but a person "abusing the process" could just... not agree to weaken it |
22:01 | <littledan> | bakkot: That would seem to suggest that we would need different rules for consensus for different kinds of changes. Perhaps we can use consensus to weaken consensus selectively. |
22:03 | <ljharb> | i agree - ad hoc consensus to allow a lower bar to agreement is a wonderful way to preserve the safety of complete consensus while reducing friction where it's not necessary |
22:04 | <ljharb> | if we can come up with a way to do that in general, as opposed to ad hoc, that would be great (for scenarios where it applies) |
22:04 | <nicolo-ribaudo> | I think we need to solve this in abstract, since once somebody wants to block something concrete there is no reason for them to give consensus to ignore their non-consensus |
22:04 | <ljharb> | i agree with snek tho that it'll be difficult to come up with an objective rubric for that |
22:05 | <littledan> | These sorts of consensual processes can definitely help us, but we still need some way of handling situations of contentious vetoes. |
22:05 | <ljharb> | I think we need to solve this in abstract, since once somebody wants to block something concrete there is no reason for them to give consensus to ignore their non-consensus |
22:05 | <leobalter> | does anyone remember which meeting shadowrealms was dropped to stage 2? |
22:05 | <Chris de Almeida> | well, in some way we've already been cautiously starting to do this, with non-binding polls for choices that we all agree are aesthetic/unimportant. I think this is really positive and should continue! |
22:06 | <Chris de Almeida> |
|
22:07 | <littledan> | yes.. voting on advancing a proposal is a very different kettle of fish compared to voting for bikeshedding-type decisions |
22:07 | <Chris de Almeida> | it is probably a very small number of times it would come up but if there are decisions that need to be made in a timely manner, that could mean the need to vote. this is what the CSS WG does.. but again, ONLY if a decision must be made |
22:07 | <Chris de Almeida> | one issue is, there isn't always a shared understanding about what's bikeshedding and what's very significant. I often find myself thinking that something is bikeshedding that others thing is very significant. |
22:07 | <Michael Ficarra> | TIL |
22:07 | <ljharb> | i think that's exactly the problem - if we all agree it's bikeshedding the contention doesn't manifest |
22:08 | <Michael Ficarra> | makes you wonder where these phrases come from |
22:08 | <Chris de Almeida> |
|
22:08 | <ljharb> | but when one person thinks something is critical and another thinks it's trivial, it often gets tense |
22:08 | <Chris de Almeida> |
|
22:09 | <littledan> | maybe! I find that a lot of these cases are the ones where we make decisions by being held hostage, which can be suboptimal. |
22:10 | <snek> | what is timely progress |
22:10 | <Michael Ficarra> | chair discretion |
22:11 | <Michael Ficarra> | the chair is a very powerful role and I think we kind of take that for granted in this group |
22:11 | <Michael Ficarra> | they don't need to be this generous |
22:11 | <ljharb> | historically the chair has had zero power |
22:11 | <shu> | i think historically the TC39 chair is one of the weaker positions as far as standards body chairs go |
22:11 | <ljharb> | that power has been slowly increasing, in a good way |
22:11 | <snek> | our chairs are also delegates, we can't escalate decisions to them without conflict of interest |
22:12 | <Michael Ficarra> | our chairs reliably recuse themselves when there is a conflict |
22:12 | <ljharb> | historically also, the chair had no interest in the specifics of language changes. |
22:13 | <Michael Ficarra> | don't ever elect me as chair because I wouldn't hesitate to wield its power (thoughtfully) |
22:13 | <Rob Palmer> | Thank you for noticing Michael. Each meeting the chairs maintain a list of topics in advance that we have an interest in to ensure that we do not chair those topics. But we don't really shout about this. |
22:14 | <Chris de Almeida> | I can tell you unequivocally that the chairs, as chairs, feel strongly about making absolutely no decisions for the committee, as much as possible, beyond purely administrative things and similar things where burdensome to committee |
22:14 | <Michael Ficarra> | I would also be fine with the chairs being a little more authoritative, especially during plenary |
22:15 | <ryzokuken> | honestly, if we did strongly decide to do something like this, I'd recommend this be done by the secretaries |
22:15 | <Chris de Almeida> | the less noticeable we are, the better |
22:16 | <littledan> | honestly, if we did strongly decide to do something like this, I'd recommend this be done by the secretaries |
22:16 | <ryzokuken> | do you mean by Samina, the TC39 secretary? |
22:16 | <ljharb> | if we're worried about a conflict of interest, ecma receives more money from ordinary members than associates, so there may be a potential conflict there (obv,. hopefully not) |
22:16 | <ryzokuken> | as pointed out above, chairing the meeting is an administrative role that allows us to facilitate topics we are neutral about while being delegates |
22:16 | <littledan> | as pointed out above, chairing the meeting is an administrative role that allows us to facilitate topics we are neutral about while being delegates |
22:17 | <Michael Ficarra> | the less noticeable we are, the better |
22:18 | <Chris de Almeida> | I mean, there's nuance, but I think you get what I mean 🙂 |
22:18 | <ljharb> | doesn't mean we want to overcorrect tho :-) |
22:19 | <ryzokuken> | yeah it just sounds like too much work to do this and also mediate all conflicts... |
22:19 | <nicolo-ribaudo> | I like the charis giving chocolate and hats to bribe delegates |
22:19 | <Chris de Almeida> | to put it simply, we don't want to be making decisions that are committee decisions |
22:21 | <littledan> | right so I think we need a procedure for delegates to contest vetoes (after the meeting, since during the same meeting would be too fast/chaotic/unconsidered) |
22:21 | <littledan> | rather than asking the chairs to constantly adjudicate by themselves on everything |
22:23 | <ljharb> | and we now have a Stage 2.7 section https://github.com/tc39/proposals?tab=readme-ov-file#stage-27 |
22:24 | <shu> | anyway more dispassionately i also think the lone veto thing actually is great for small groups (the older, smaller, closer-knit TC39) but doesn't scale |
22:25 | <shu> | like you don't want a family of 4 to vote on all decisions, that will be bad |
22:26 | <Kris Kowal> | Spec invariants and subgroups would go a long way to making TC39 scale. I am eager to write a blank check to Intl. |
22:27 | <bakkot> | I am somewhat less eager to write a blank check to Intl |
22:27 | <Kris Kowal> | Yeah, I don’t mean everyone. I mean me. |
22:27 | <bakkot> | I am fine leaving the decisions which are just internationalization to subgroups, but not overall questions of API design |
22:27 | <snek> | bakkot you'll need to sustain your objection to writing a blank check to intl |
22:28 | <Kris Kowal> | A “I hereby waive my interest in a veto on Intl provided it maintains these here invariants.” |
22:28 | <rbuckton> | I am fine leaving the decisions which are just internationalization to subgroups, but not overall questions of API design |
22:28 | <bakkot> | rbuckton: sorry, I was referring only to Intl specifically |
22:29 | <bakkot> | I am fine with subgroups in general but not taking the output of any subgroup wholesale into the language |
22:29 | <bakkot> | there are some questions best left to subgroups but most proposals involve some questions which are not of that kind |
22:30 | <Kris Kowal> | The DOM as an API subgroup. |
22:30 | <shu> | my brother i'm pretty sure we are the subgroup |
22:31 | <ljharb> | i definitely think that establishing a thorough list of invariants will drastically reduce lone objections |
22:32 | <Richard Gibson> | seems pretty obvious to me |
22:33 | <bakkot> | thinking about the lone objections I can remember I am not sure I can think of any which could have been handled by a list of invariants? except invariants like "no new unreachable intrinsics" or "no shared-state parallelism", neither of which would have gotten consensus to be on such a list |
22:34 | <ptomato> | I would like to see a thorough list of invariants be a high-priority goal regardless, but I agree with Kevin here |
22:35 | <littledan> | the invariants project will need to contend with the fact that a lot of the invariants that people care about the most will be absent from the list of invariants which has committee consensus. For this reason, I think the first step should be to document all the concerns that some people are thinking about (as has already begun in how-we-work), rather than get consensus on it. |
22:36 | <shu> | i don't like the idea of consensus seeking on invariants |
22:36 | <shu> | invariants i think are particular reflections of goals |
22:36 | <shu> | i want some semblance of understanding of goals |
22:36 | <ljharb> | (re kevin and dan) that's a fair point. having a list of invariants, some of which have consensus and many of which won't, would still be helpful |
22:37 | <shu> | goals as scoped as possible, of course |
22:37 | <ljharb> | (re shu) also a good point |
22:37 | <shu> | i don't think "more better js" is a valid goal |
22:43 | <leobalter> | shu: would you mind taking a quick look at the conclusion/resolution for ShadowRealm? I want to make sure I'm not missing anything.e |
22:45 | <rbuckton> | I kind of like the idea of markdown fences as an alternative to escaping ` and ${ and end-of-string \ , but I don't have a strong preference. |
22:46 | <ljharb> | it might be nice to allow N backticks, paired, to change what needs to be escaped? |
22:47 | <bakkot> |
is already legal, alas |
22:47 | <ljharb> | like with a single backtick, you have to escape backticks; but if you put, say, three, you'd only have to escape a set of triple backticks |
22:47 | <rbuckton> | I thought that was in the proposal when I reviewed it last week. |
22:47 | <ljharb> | ah true |
22:47 | <shu> | shu: would you mind taking a quick look at the conclusion/resolution for ShadowRealm? I want to make sure I'm not missing anything.e |
22:47 | <bakkot> |
|
22:47 | <bakkot> | that said, it might still be web-compat |
22:48 | <bakkot> | but changing existing parses is scary |
22:48 | <rbuckton> | When I looked at it before, it was @``` , with a n+3 backticks that must be matched, as long as its one more backtick than the number of contiguous backticks in the body. |
22:49 | <jschoi> |
|
22:49 | <Justin Ridgewell> | Syntax isn't a Stage 1 concern… |
22:49 | <Justin Ridgewell> | Do we want to explore this? If so, we'll define syntax when we explore it. |
22:50 | <rbuckton> | but markdown fences are tricky in that `` ` `` ignores the leading and trailing whitespace to avoid it being treated as a contiguous run of backticks |
22:50 | <bakkot> | …Wait, what does this parse as, again?
|
22:50 | <Richard Gibson> | …Wait, what does this parse as, again?
is the same as
|
22:51 | <snek> | should've added an early error on that |
22:51 | <snek> | or a lookahead |
22:51 | <bakkot> | yeah I tend to agree |
22:51 | <bakkot> | oh well |
22:52 | <Michael Ficarra> | where's the fun in that snek ? |
22:52 | <snek> | lol |
22:52 | <bakkot> | doubled punctuators being special is well-precedented |
22:52 | <Michael Ficarra> | it's JavaScript, you're supposed to be able to construct horrors |
22:52 | <snek> | lets use r#""# like rust |
22:53 | <bakkot> | it's JavaScript, you're supposed to be able to construct horrors
is not... less horrible |
22:53 | <danielrosenwasser> | Meta: do people find it valuable to get constraints for later stages, even at earlier proposal advancement meetings? I would think it is helpful. |
22:53 | <bakkot> | lets use r"" "" , I don't think you need the # s? |
22:54 | <leobalter> | I really like the problem we are trying to resolve having used this feature within different languages ie Perl. Even thou, I don't know if I'd have the energy to pursue this string proposal considering it needs us to elect a token |
22:54 | <Justin Ridgewell> | Sure, I think "desire for minimal syntax" is a good thing to bring up, but "I don't like `#" isn't |
22:55 | <rkirsling> | yeah Mark's reaction was basically my reaction too |
22:55 | <bakkot> | I want a better String.raw and would consider that in scope for this proposal... |
22:55 | <bakkot> | https://github.com/tc39/proposal-string-cooked/issues/13 |
22:56 | <ptomato> | Meta: do people find it valuable to get constraints for later stages, even at earlier proposal advancement meetings? I would think it is helpful. |
22:57 | <rbuckton> | I want a better String.raw with it? Why would that be in scope? |
22:57 | <nicolo-ribaudo> | Meta: do people find it valuable to get constraints for later stages, even at earlier proposal advancement meetings? I would think it is helpful. |
22:58 | <bakkot> | Isn't the point of this that you don't need String.raw doesn't work |
22:58 | <Bradford Smith> | Maybe "here documents for JS" |
22:58 | <bakkot> | hence if we could have a version of String.raw which had fewer sharp edges, that would be in the direction of solving the problem |
22:58 | <rbuckton> | Isn't that just a side-effect of special \ escapes? |
22:58 | <ljharb> | what's the exact title? |
22:59 | <littledan> | bakkot: Did you agree with my problem statement? Please feel free to edit it |
22:59 | <littledan> | what's the exact title? |
22:59 | <rbuckton> | A better String.raw doesn't solve \` , \${ , and end-of-string \ |
22:59 | <bakkot> | bakkot: Did you agree with my problem statement? Please feel free to edit it |
23:00 | <rbuckton> | That is 100% a syntax issue, no amount of API support can fix it. |
23:01 | <rbuckton> | Maybe there are improvements that could be made for String.raw , but that won't address the main concerns this proposal seeks to address. |
23:02 | <hax (HE Shi-Jun)> | https://github.com/tc39/proposal-string-cooked/issues/13 String.rare does not really solve the problem, u still need to do many escaping, and it also make the escaping rule much complex. |
23:04 | <Chris de Almeida> | NB: topics have shuffled a bit on the schedule |
23:06 | <hax (HE Shi-Jun)> | When I looked at it before, it was |
23:06 | <rbuckton> | As a syntax, you don't need to limit yourself to @ and # as there are other infix tokens that could be made into a prefix token. For example, you could use \``` ... ``` to mean "I've done all the escaping I need to do at the start and end of the string" |
23:07 | <hax (HE Shi-Jun)> | Yeah, I understand there are many possibilities, I just use the syntax which already have precedents in other languages as example. |
23:07 | <rbuckton> | Infix tokens do cause problems for tagged templates, though \``` doesn't |
23:08 | <hax (HE Shi-Jun)> | Maybe "here documents for JS" |
23:16 | <Justin Ridgewell> | Maybe there are improvements that could be made for raw string |
23:17 | <Justin Ridgewell> | The same way dedent is (fully) cooking the dedented raw string |
23:17 | <Justin Ridgewell> | You'll still need to escape the 3 cases, but those escape sequences won't appear in the rare output (all other escapes would) |
23:20 | <Bradford Smith> | But if "improved template literal" it very unlikely we could have "here doc" style solution.
|
23:20 | <rbuckton> | I think the interesting thing about the proposal is that you don't need to escape anything, with the exception being ${ , but that could also be tied to the opening of the fenced string literal. The Explainer used n+1 @ tokens, but could just as easily use n+1 \ tokens, etc. |
23:23 | <hax (HE Shi-Jun)> |
|
23:23 | <nicolo-ribaudo> | Maybe there are improvements that could be made for String.raw but it replaces \<backtick> with <backtick> and removes backslashes at the end of template parts |
23:24 | <rbuckton> | That still requires escaping in the literal |
23:25 | <Bradford Smith> | Not sure how it look like template string (except it use backticks :P ), a problem of here doc style is normally it only support defining end delimiter but we also need to deal with interpolation delimiter. const myEmbeddedString = String.dedent( Normal template content ${<<hereDocEndText>> Whatever I want to have here as long as this ends with <<hereDocEndText>>} ); |
23:25 | <hax (HE Shi-Jun)> | yeah, my goal is to avoid escaping. which means, whatever text you have, u could just paste it to js source code , wrap it in a raw literal, without modifcations. |
23:26 | <Justin Ridgewell> | I think the interesting thing about the proposal is that you don't need to escape anything, with the exception being \ at the end of the template, so some escaping will be needed regardless. There was a thread in Google's internal TypeScript chat group about why this case wasn't working with String.raw |
23:28 | <hax (HE Shi-Jun)> | It still doesn't address \ should have no effect on parsing raw literal. |
23:28 | <rbuckton> | If a raw literal syntax does no escaping, then a trailing \ is just a \ . the only thing it looks for is a balanced set of ` characters |
23:29 | <hax (HE Shi-Jun)> | Yeah, we just need some mechanism to define the ending token and the interpolation token. |
23:29 | <rbuckton> |
would be the string |
23:30 | <rbuckton> | element or matrix did not like that... |
23:30 | <Justin Ridgewell> | Even \x20 isn't transformed? I need to pay better attention. |
23:30 | <hax (HE Shi-Jun)> | This is why I use swift-style in the slide, because swift style only use number of # to define both token, which IMO the simplest solution. But I don't know how others think about "simple"... |
23:31 | <hax (HE Shi-Jun)> | Even \#x20 |
23:31 | <nicolo-ribaudo> | This is why I use swift-style in the slide, because swift style only use number of # , you could consider using @ since I don't think anybody would ever want to use it for anything other than decorators anyway |
23:32 | <rbuckton> | Even |
23:32 | <Justin Ridgewell> | if Swift style, it allow u to reenable escaping by |
23:32 | <hax (HE Shi-Jun)> | How do you represent that inside a string, then? |
23:32 | <Justin Ridgewell> | More # ? |
23:33 | <Justin Ridgewell> | Yah |
23:33 | <Justin Ridgewell> | Ok |
23:34 | <hax (HE Shi-Jun)> | On the other side, C# raw strings use two symbols: the number of " for end token, the number of $ for interpolation token. |
23:34 | <hax (HE Shi-Jun)> | The draft in the repo use C# style. |
23:34 | <hax (HE Shi-Jun)> | Personally I feel Swift style is much "simple" :P |
23:42 | <hax (HE Shi-Jun)> | One point is, if only use repeated ` (or any repeated single char) as end token, it significantly has more conflict probability than combinations like `# . |
23:52 | <Rob Palmer> | The removal of the curly brackets dramatically helps me absorb the syntax here. |
23:53 | <nicolo-ribaudo> | As a syntax, you don't need to limit yourself to |
23:53 | <nicolo-ribaudo> | ^ Is this problem solvable in any way? |
23:54 | <bakkot> | nicolo-ribaudo: require that triple-backtick strings have a leading and trailing newline, and strip those from the output |