2020-07-01 [17:50:44.0000] in PR 2045, the built-in generator functions are inaccessible to userland, right? [17:53:53.0000] jmdyck I haven't read that PR's spec text yet, but that was the plan discussed in https://github.com/tc39/proposal-iterator-helpers/issues/97#issuecomment-637833039, yes [17:58:24.0000] okay, well, I'm going to have to read some stuff then, but is there a quick reason for why the built-in generator functions are functions and not abstract operations? [17:59:26.0000] seems like it complicates the spec for no benefit [18:07:31.0000] that I couldn't tell you; the conclusion fo the last discussion I was involved in was "Each iterator helper object will have an internal slot that contains a generator-like algorithm (an abstract closure) with "Yield" steps, something like the %SyncMap% sketch @devsnek posted in #86." [18:08:17.0000] jmdyck: the iterator proposal will make use of built in generators [18:08:41.0000] they're not very useful for the existing iterators imo but people want everything to be the same [18:10:29.0000] will the iterator proposal define new built-in generator functions? [18:10:36.0000] devsnek that doesn't answer the question of why they're being spec'd as actual functions though [18:11:01.0000] i mean i think they should be actual functions [18:11:30.0000] ... why? [18:11:59.0000] because if i was writing them in js i would use functions [18:12:34.0000] ... so? [18:12:40.0000] if you were writing *anything* in js you'd use functions. [18:12:41.0000] I sincerely do not understand the relevance ofo that [18:13:54.0000] i mean if you want to write out 22 iterator prototypes [18:14:01.0000] or spec the existence of suspendable abstract ops [18:14:05.0000] more power to you [18:14:38.0000] the spec already has suspendable abstract ops, doesn't it? [18:14:41.0000] no [18:14:45.0000] the correlation to actual functions is simple because we already have them [18:14:46.0000] I don't think you need to spec the existence of suspend-able abstract ops explicitly [18:15:14.0000] the mechanism that `yield` uses should work just the same in AOs [18:15:27.0000] yield in an AO suspends the function [18:15:28.0000] not the AO [18:16:00.0000] like the boundary is the function [18:16:06.0000] you'd have to set up code execution state for AOs [18:16:17.0000] anyhow, shifting from built-in generator functions to AOs doesn't require suspenable AOs [18:16:53.0000] i'm open to new ideas [18:20:43.0000] the BIGF doesn't do any suspending, it basically just creates the generator object, and calls GeneratorStart on it. [18:20:57.0000] what's BIGF [18:21:06.0000] oh built in generator function [18:21:12.0000] yup [18:21:25.0000] yeah i mean its a generator [18:21:33.0000] then returns the generator object [18:21:36.0000] except the body is spec steps instead of js code [18:22:36.0000] a BIGF isn't a generator, it's a function that returns a generator. [18:23:21.0000] the BIGFs that i'm talking about are actual reified functions [18:24:01.0000] the BIGFs I'm talking about are the ones in PR 2045 [18:25:22.0000] 2045 doesn't make sense to me [18:25:29.0000] like adding slots to the return value implicitly and stuff [18:25:35.0000] ah, well. [18:25:47.0000] now we agree. [18:26:22.0000] what we came up with for iterator helpers is currently (i think) [18:26:34.0000] - BIGF is real actual function [18:27:02.0000] - it's not exposed directly to js (cc ljharb?) [18:27:29.0000] - it has next() invoked immediately to get proper access to the first yield from userland [18:28:11.0000] https://gc.gy/58205433.png [18:28:38.0000] StartIteratorMethod(F, ...) is basically `it = F(...); it.next(); return it` [18:29:23.0000] as I understand it, if it has a `next()`, then it's a generator, not a generator function [18:30:05.0000] whatever you call `function* x() {}` [18:30:12.0000] it's the builtin version of that [18:30:54.0000] That's a generator function, and x() is a generator, I think. [18:31:32.0000] might help to say "generator function" and "generator instance" [18:31:41.0000] a lot of people use "generator" to mean the function [18:32:07.0000] that could lead to confusion all right [18:33:22.0000] "star-syntax generator function" and "generator-backed iterator instance" [18:37:04.0000] Looks like the spec uses "generator object", "generator instance", and "generator" more-or-less interchangeably. [18:37:18.0000] vs "generator function" or "generator function object" [18:37:35.0000] That could stand some clean-up. [19:06:23.0000] devsnek: without that IteratorKind slot, built-in generators cannot be used in String@@iterator or Map@@iterator. For iterator helper proposal, you can omit that slot and everything works fine [19:08:47.0000] I use "generator" to refer "function*" and "iterator" to its return value 🤔 [21:18:15.0000] is "Contains await" in the tla spec defined anywhere [21:21:39.0000] devsnek: https://tc39.es/ecma262/#sec-static-semantic-rules [21:21:49.0000] "Unless otherwise specified every grammar production alternative in this specification implicitly has a definition for a static semantic rule named Contains which takes an argument named symbol whose value is a terminal or nonterminal of the grammar that includes the associated production." [21:22:38.0000] does that break through function boundaries [21:22:48.0000] it looks like it does [21:23:09.0000] no, the functions all have an override which stops it from going through them [21:23:29.0000] e.g. https://tc39.es/ecma262/#sec-function-definitions-static-semantics-contains [21:23:40.0000] oh interesting, ok [21:27:30.0000] someday I will make that Contains link [21:27:55.0000] we need an AI to just automatically link everything that makes sense to be linked [06:56:28.0000] bradleymeck: why do compartments have a module map [06:56:59.0000] that's a much stronger requirement on caching than the spec has [06:57:33.0000] devsnek: essentially because they are where people wanted to put all the host hooks, so moving the map so that compartments can resolve on their own scope rather than the realm [06:57:58.0000] the host hook can still be scoped to the compartment [06:58:07.0000] devsnek: the spec is very loose in its requirements yea, but for things like cyclic linkage you need some way to coordinate [06:58:22.0000] devsnek: maybe i don't understand the question [06:58:44.0000] devsnek: what is the concern with compartments having a map [06:58:54.0000] well not just maps [06:59:13.0000] the import/importNow/module apis are weird to me [06:59:25.0000] we all agree on that [06:59:42.0000] if you desire to store your modules by something more than (referrer, specifier) i would say you should bring your own map [06:59:50.0000] like how we bring our own module map in nodejs's loader [07:00:16.0000] moduleMap is a way to initialize things, not a true store [07:00:42.0000] initialize what [07:01:01.0000] some default hostresolveimportedmodule hook that uses moduleMap? [07:01:06.0000] referrer / callsite is how the spec mandates stuff idk what you mean. you must have some referrer/callsite storage [07:01:35.0000] like literally the api that v8 has [07:01:49.0000] modulo the complexity of ScriptOrModule classes [07:01:52.0000] why is it not that [07:02:14.0000] i don't understand your question, this about making sure we have hooks enforce spec not the v8 API [07:02:28.0000] right the v8 api doesn't put additional behaviour in [07:02:30.0000] its just the spec [07:02:35.0000] but "moduleMap" is new [07:02:37.0000] moduleMap is helpful to initialize without creating new module instances [07:02:46.0000] i don't understand what it initializes [07:02:56.0000] you *could* wire it up yourself [07:03:11.0000] it is just initializing what the default resolve will preempt [07:03:16.0000] if it is empty, it always calls the hook [07:03:23.0000] that seems weird [07:03:28.0000] if it isn't empty it preempts to those values [07:03:30.0000] library territory i guess [07:03:45.0000] see moddable's impl that has a similar API [07:03:52.0000] the use case isn't weird but it being in js is weird [07:03:57.0000] if that makes sense [07:04:10.0000] at this point JS is just JS to me and I have few questions [07:04:54.0000] well i can open a more in depth issue i guess [07:04:58.0000] sure [07:05:14.0000] i haven't found enough time for compartments with all the other meetings i've been drowning in [07:05:27.0000] is there a better person to ping on questions like this [07:28:04.0000] devsnek: kris kowal likely, though hes been touching that repo more than I [07:28:22.0000] realms stuff about push back there is a bit more front and center currently for me 2020-07-02 [00:51:00.0000] ecmarkup question [00:51:24.0000] if I have imported foo and bar into my root spec.html [00:51:56.0000] how can I emu-xref an emu-clause that's in foo from bar? [00:57:23.0000] ah wait, nvm [06:40:54.0000] how does everyone check for truthiness in the spec? 🙈 [06:45:09.0000] call ToBoolean ? [06:45:28.0000] jmdyck: ah, yes. Thanks. 2020-07-04 [20:39:30.0000] devsnek: ping [21:16:15.0000] jmdyck: hi [21:17:52.0000] I wanted to talk to you about generators etc [21:18:53.0000] aight [21:20:47.0000] the other day, you saus that the spec doesn't have suspendable abstract ops, but I'm looking at https://tc39.es/ecma262/#sec-generatorresume step 9 [21:21:15.0000] what about it [21:22:17.0000] that suspends the execution of the GeneratorResume op, and resumes the execution of some other suspended op [21:22:30.0000] it suspends the execution of the entire context [21:22:45.0000] yes [21:23:00.0000] what i meant was, we don't have the ability to suspend just the op [21:23:05.0000] without the surrounding context [21:23:18.0000] ah, ok. [21:25:02.0000] so you think of the context as 'surrounding' the execution of the op? [21:28:24.0000] jmdyck: that seems to be how we've specified it [21:31:26.0000] I ask because there are definitely ops that execute before there are any contexts, and ops that create contexts, and ops that manipulate contexts, which suggests that ops run 'off to the side'. But then there's other stuff that suggests they run 'inside' contexts. [21:32:29.0000] But the spec doesn't really demarcate that shift in perspective. [21:35:06.0000] Anyway, that's a tangent. [21:35:51.0000] The other thing I was looking at was https://tc39.es/ecma262/#sec-generatoryield [21:36:28.0000] this was also interesting https://github.com/tc39/ecma262/pull/1748 [21:41:29.0000] So GeneratorYield (as written) is basically just bookkeeping: it sets some things, pops the context stack, and returns. But the thing is, according to the note in step 10, it doesn't return to the operation that called it. This is very odd. [21:42:50.0000] I mean, I understand that there has to be a transfer of control, but to accomplish it via a Note that just says the return goes where you don't expect it, just seems so weird. [21:43:48.0000] the note is for clarity, its not normative [21:44:25.0000] right, but if you deleted it, what would tell you that the return isn't to the op's caller, like every other op? [21:45:18.0000] i'm guessing some prose somewhere? [21:47:25.0000] Well, there's no prose that talks about GeneratorYield's return semantics. [21:47:45.0000] The only references to GeneratorYield are invocations. [21:48:02.0000] (no prose other than that Note) [21:48:15.0000] hopefully something somewhere describes how suspending an execution context works [21:48:45.0000] Yeah, I don't think there is. [21:50:10.0000] (Another tangent: when the spec says to Suspend a context, it auto-links to https://tc39.es/ecma262/#sec-suspend which is an Atomics op.) [21:50:41.0000] yeah that confused me a lot [21:50:53.0000] back when i was first setting up generators [21:52:24.0000] Well, the clause on execution contexts does talk a little about suspending [21:54:09.0000] but not enough to infer anything about GeneratorYield. [21:58:30.0000] It seems to me that GY should have an explicit transfer of control (suspend itself), and then wait to be resumed (with a value). And then return (as usual) to the op that called GY. [21:58:47.0000] Pretty much like GeneratorResume does. [22:00:13.0000] i wouldn't be against refactorings of how suspension works [22:02:01.0000] One thing though, AsyncGeneratorYield has a similar weirdness. [22:03:00.0000] And I think it could be unweirded in a similar way, but I'm not clear on what happens in AsyncGeneratorResolve. [22:04:23.0000] AsyncGeneratorResolve calls AsyncGeneratorResumeNext, which *has* an explicit xfer of control, except it seems to be going in the other direction, so I'm confused. [22:05:27.0000] does engine262 implement async generators? [22:06:09.0000] yes [22:06:39.0000] Hm, getting late here. I'm heading off, but I'll check the log for any further thoughts you might have. [22:06:45.0000] thanks [08:33:35.0000] ah Why deref() for WeakRef, not a getter `ref`? [08:46:27.0000] I have a small nitpick - In array.map (https://tc39.es/ecma262/#sec-array.prototype.map), the note says that new elements in array are not considered after map starts. But a similar note in array.foreach doesn't have that part of the note (ignores new elements) - even though that is how it operates. [08:46:27.0000] Is this a miss? [08:48:51.0000] Like what is the general guideline about notes? [08:48:51.0000] Some sections have good understandable notes, others are very sparse. Is it mostly dependent on the proposal writer? [09:38:55.0000] bendtherules: it does seem like it should be there -- as it turns out, it WAS there in ES5 but was removed as of ES6: see https://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18 followed by http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.foreach [09:39:44.0000] not sure if there would be notes of such a change but you could submit an editorial PR if you wanted [09:40:10.0000] (chances are it'd get merged; at worst you'd find out why :) ) [09:43:07.0000] Haha. Ok, I'll raise one [10:51:32.0000] Done. PR - https://github.com/tc39/ecma262/pull/2076, issue - https://github.com/tc39/ecma262/issues/2075. 2020-07-05 [20:23:47.0000] is github deleting PRs created by spam accounts? [20:23:52.0000] https://github.com/tc39/ecma262/pull/1609 vanished [20:24:14.0000] it was a automated-looking dupe of a real PR, but unfortunately it had some real discussion which also got nuked [22:15:47.0000] bakkot_: yes, when an account gets effectively klined, its PRs and issues vanish [22:16:54.0000] looks like PR 1609 was the same sha as PR 1507 [22:17:33.0000] https://github.com/tc39/ecma262/pull/1228 was the root [22:18:26.0000] aha [08:18:59.0000] this kflash fellow has made like 5 ecmascript parsers [08:20:19.0000] eacaya, meriyah, seafox, buntis [09:59:38.0000] second one's a lot easier than the first 2020-07-06 [12:15:19.0000] how do people feel about trying to work on mitigating prototype pollution vulnerabilities in user land libraries that the JS ecosystem is seeing a lot of [12:15:55.0000] we can't patch overwrite mistake, but maybe we could make own properties more developer friendly to deal with? [12:18:38.0000] basically the problem is libraries are doing `object[key]` on arbitrary input and by default some builtin prototypes allow for crawling to codegen etc. [12:21:10.0000] on a glance no builtin types allow for codegen based purely off own property traversal unless you have access to the root intrinsic. E.G. to get to Function.prototype.constructor via own property traversal you have to get to Function or Function.prototype, which most userland libraries are not generally called with [12:23:37.0000] bradleymeck: how has --disable-proto been going in node [12:32:14.0000] npm audit still as noisey as ever [12:32:32.0000] same with --frozen-intrinsics [12:33:05.0000] optional chaining does remove the need for some helper libs like lodash so may see a long tail decrease [13:03:22.0000] i still don't think most of them are actual vulnerabilities [13:46:15.0000] bendtherules: heads up on one final change on https://github.com/tc39/ecma262/pull/2076 before i land it :-) [14:32:25.0000] ljharb: regardless of personal feeling there appears to be a need to fix whatever category of issue is causing the distress [14:33:17.0000] I personally do agree it is a vulnerability if you are unable to verify consumers [14:33:18.0000] there's been just as many CVEs caused by catastrophic regex backtracking; why doesn't that need fixing? [14:33:36.0000] I never said it doesn't [14:34:28.0000] I just am asking about addressing a noisy issue of the ecosystem, redos has owasp coverage and mitigation pretty well documented [14:34:29.0000] sorry, not trying to throw some whataboutism on it :-) i'm just confused why this one is worth trying to "fix" in the language and the other one hasn't been [14:35:48.0000] Redos affects other languages and a large variety of tools work to handle it. To my knowledge only ocap styles like SES try to deal with prototype mutation [14:36:46.0000] SES doesn't cover entirely the claimed vulnerability since it doesn't seek to prevent codegen entirely [14:37:21.0000] Prototype pollution is more JS specific than redos basically [14:37:37.0000] that is a fair point [14:40:41.0000] you could also argue that redos doesn't have the same severity, halting execution isn't something JS seeks to prevent generally [14:40:59.0000] prototype pollution is about potential codegen/misinterpretation [14:41:38.0000] one could prevent progress, but the other can potentially lead towards malicious execution 2020-07-07 [19:54:20.0000] @ljharb: Thanks for the heads up. Github app notifications are flaky at times. [20:02:09.0000] bradleymeck: Trying to understand the conversation. So what is the potential problem with object[key] with user-provided key? [20:02:34.0000] Accessing __proto__ in the key? [20:03:09.0000] Even then you can only set proto, not change properties within it. [20:15:06.0000] littledan: what is finalizationRegistry.[[Realm]] for [05:22:30.0000] ljharb: Done [05:23:03.0000] npm watch script seems broken? https://github.com/tc39/ecma262/issues/2083 [08:04:10.0000] v8's test262 runner goes past 100% coverage [08:04:14.0000] i don't like this [09:25:23.0000] bendtherules: thanks [10:17:47.0000] bendtherules: see https://twitter.com/bradleymeck/status/1280209566907670530 , basically you have this whole security firm audit noise from people accessing things on prototypes with dynamic access [10:18:25.0000] and it is a lot of noise if you use `npm audit` or github vulnerability checks [10:32:24.0000] (both of which are on by default) [10:33:20.0000] bradleymeck: is it `constructor-constructor`, and the code? [10:33:41.0000] yes in that case [10:33:47.0000] fun [10:34:03.0000] but other fun and more esoteric stuff like that does come up while i audit stuff [10:52:17.0000] So, if libraries do Get/hasOwnProperty instead of general accessors - doesn't that fix it? [10:52:32.0000] (if that's what they want Ofcourse) [10:53:16.0000] given these are data manipulation libraries usually, that's a fair limitation [10:59:54.0000] bendtherules: the problem is that people write the code [10:59:57.0000] there are of course solutions [11:00:08.0000] but the solutions are only useful if people use them [11:03:33.0000] Hmm, got it. So, there's no easy syntax for that [11:03:37.0000] bendtherules: yes it is largely a DX problem [11:03:45.0000] a variety of things can make this easier [11:03:55.0000] you can use null prototype objects is my main approach [11:04:13.0000] there are actually very few reasons to want to have an instance of Object [11:04:39.0000] so in the example tweet above adding __proto__:null to the literal fixes it [11:04:43.0000] but no one does that [11:05:19.0000] and security noise comes from the libraries doing dynamic access, so even if it is fixed you still get alerts [12:13:24.0000] gotta fix `extends null` [12:13:28.0000] should revisit that [12:13:43.0000] one hairbrained idea I had for it was to make `Function.prototype` new-able [12:13:54.0000] though I don't remember enough details to know why I thought that would fix the problem [12:31:32.0000] bradleymeck: does proto null solve it though? You are going to want to call the inherited method, at some point - after all. [12:31:32.0000] Also what about array literals? That will also finally lead to object in proto chain, right? [12:32:16.0000] it seems fine to me to make `super()` a no-op when super is null, why is that not workable? [12:35:14.0000] ljharb: just thinking out loud, so should `super.xyz`still throw some error? [12:41:10.0000] bendtherules: yes, i'd expect so [12:41:26.0000] but i might expect `super?.xyz` to work [12:41:55.0000] bendtherules: thats fine, the problem is the inherited constructors, calling the method isn't a problem [12:42:22.0000] so yes, a null prototype on dynamic property access usually fixes the issue [12:42:48.0000] bakkot_: to my recollection most of the complaints are about minor edge cases [12:43:18.0000] bendtherules: you can access ([])['constructor'] just fine so idk what the question about them is [12:43:27.0000] bradleymeck yeah mostly [12:44:17.0000] bradleymeck: I meant, if i do `a={__proto__:null}`, then this solves security issue, but now i can't expect `a.toString` to work. What if i want that? [12:44:35.0000] stop wanting that, presumably? [12:44:47.0000] when would you want that to work? [12:44:55.0000] that is, to work how it does by default [12:45:40.0000] ljharb is "when super is null" a at-definition-time property or an at-evaluation-time property? remember that you can dynamically change a class's heritage [12:45:51.0000] bakkot_: evaluation time, for that reason [12:46:06.0000] bakkot_: definition-time is "it's a derived class, so super is allowed" [12:46:37.0000] ok, so is super _required_ in your extends-null class? [12:46:56.0000] I was thinking - with the same object, sometimes i want "safe mode" (i.e. i am dealing with user-generated value in this line) - so i'll write something like`obj[? prop1][? prop1]` [12:47:05.0000] bakkot_: yes, if i want to access `this` [12:47:12.0000] ljharb that seems... very strange [12:47:14.0000] why? [12:47:21.0000] but in next line, when i am calling toString, i can call `obj.toString()` directly [12:47:24.0000] `this` is only ever available in a derived class after calling super() [12:47:25.0000] lj because there is no super class to call? [12:47:29.0000] ljharb * [12:47:36.0000] there's whatever i put in `extends X` [12:47:42.0000] in this case, `null` [12:47:43.0000] sure [12:47:59.0000] ljharb right, well, the contention is that a class which extends null is not a derived class [12:48:11.0000] i'm basing my model on the syntax [12:48:15.0000] if it has "extends" it's a derived class [12:48:28.0000] (not that "derived class" is a good name for it, that's just the spec name) [12:48:35.0000] that is a view one could hold, but not one I share or expect to be common [12:49:10.0000] i mean, i don't think "common" needs to apply with anything that changes the [[Prototyoe]] later [12:49:22.0000] what's common is never monkeying with the prototype at all [12:49:30.0000] I am talking mainly about the mainline case, where you don't do that [12:49:39.0000] ok, so like `class extends null` or the equivalent [12:49:44.0000] yup [12:49:58.0000] `new class extends null { constructor(){ console.log(this); } } // works?` [12:50:02.0000] per your above, no [12:50:05.0000] i'd assume it throws, right [12:50:06.0000] that would surprise me [12:50:18.0000] it would throw with any other value in place of `null` there [12:50:24.0000] ljharb: what would you expect super() to do in that case? [12:50:26.0000] and since it's an expression, `null` is the same as `x` [12:50:29.0000] shu: nothing [12:50:34.0000] shu: just bind the `this` and install fields [12:50:48.0000] why is that less surprising to you than throwing, because the super class is clearly null? [12:50:50.0000] shu: iow super does two things right now, "invoke the superclass constructor" and "bind the receiver and install fields" [12:50:58.0000] ljharb well, yes, because the other things you could put there would be expected to be _actual superclasses_, whereas null is, clearly, not [12:51:04.0000] because in my `extends null` class what i *want* is to install the fields [12:51:11.0000] and i want to control when that happens [12:51:18.0000] ... well [12:51:20.0000] stop wanting that? [12:51:25.0000] lol [12:51:26.0000] sorry sorry [12:51:46.0000] i see, that's a different line of argument that folks have a model that all expressions in heritage positions are somehow semantically interchangeable [12:51:47.0000] I mean to say, I don't find "I want to control when fields are installed on my extends-null class" to be a compelling use case [12:51:49.0000] surprise in an edge case seems less important to avoid than giving people what they want :-p [12:52:03.0000] bakkot_: that part's fair [12:52:09.0000] ljharb right, well, the thing that I want is to not have to call `super` in my extends-null class [12:52:16.0000] because, not being a subclass, I don't expect to have to [12:52:30.0000] there is no superclass to call [12:52:33.0000] i see the difference in our thinking here: to me, if it has `extends`, it *is* a subclass [12:52:41.0000] ... of... what? [12:52:49.0000] of whatever's on the RHS of `extends` [12:52:54.0000] ... null? [12:52:56.0000] null is not a class [12:53:02.0000] this I believe [12:53:04.0000] sure [12:53:37.0000] `new class extends {} { constructor() { this; } }` throws too tho [12:53:45.0000] iow, "the RHS is a class" is already not a guarantee [12:53:55.0000] and the subclass rules still apply to everything simply because `extends` is present [12:53:56.0000] wait, I don't understand this example [12:54:00.0000] why is null the one deviation? [12:54:06.0000] it extends an empty object [12:54:06.0000] ljharb `{}` is not a class, which is why `super()` would throw [12:54:09.0000] sure [12:54:14.0000] but i didn't use super there [12:54:15.0000] i used `this` [12:54:17.0000] sure, but [12:54:18.0000] and it threw because i never called super [12:54:24.0000] because it's a subclass, *because `extends` is there* [12:54:28.0000] ok but it would also throw if you did call `super()` [12:54:31.0000] sure [12:54:38.0000] I don't understand the relevance of this example [12:54:45.0000] so the part that i'm suggesting would be special for null is "what happens when you call super()" [12:54:54.0000] there is no scenario where `extends` is present and you'd not have to call super to access `this` [12:55:05.0000] right, yes, I get that this is what you are proposing [12:55:07.0000] and i don't think it makes any sense to make `null` special for the latter case [12:55:15.0000] our difference is, I don't think `null` is a class [12:55:25.0000] meaning, I don't think one can have a subclass of `null` [12:55:30.0000] neither is most of the other things i can put on the RHS of `extends` [12:55:39.0000] right, you can't have subclasses of those eitherr [12:55:42.0000] because "the thing it extends is a class" is currently irrelevant to whether `super` is required. [12:55:43.0000] ljharb: i also do not understand why your opinion is that "there is no scenario where `extends` is present and you'd not have to call super to access `this`" is such a desirable property to preserve [12:55:58.0000] shu: because the syntax is what developers see [12:56:07.0000] shu: they see extends, they know they need to call super [12:56:11.0000] shu: that's my argument anyways [12:56:18.0000] that is not my intuition [12:56:19.0000] i simply disagree with that intuition [12:56:36.0000] I see `extends null`, I do not expect to have to call `super`, because I do not think I am writing a derived class [12:56:43.0000] right but you might not see null there [12:56:53.0000] ...how? [12:56:54.0000] this is technically true but I think not super relevant [12:57:00.0000] you might have a function that takes a superclass and returns a new class, and the user could pass null or a constructor [12:57:07.0000] I expect the overwhelming majority of cases to put `null` there explicitly [12:57:14.0000] that's fair, i also expect that [12:57:20.0000] ah, i see, that would be a strange kind of class factory [12:57:26.0000] that sometimes generates a subclass and sometimes not? [12:57:37.0000] shu: i maintain it's a subclass if it has `extends` :-) [12:57:47.0000] ljharb I still want to know what you think it is a subclass _of_ [12:57:54.0000] nothing, if it's null [12:57:59.0000] what... does that mean [12:57:59.0000] its subclass-ness is not contingent on what it's subclassing [12:58:18.0000] you and I do not share an understanding of the word "subclass", I see [12:58:21.0000] right [12:58:37.0000] ljharb: when you are writing new classes, do you think about the class hierarchy? [12:58:38.0000] another way to put it, is that to me a subclass is only a class body in which `super` can be used [12:58:43.0000] or do you only think about a stream of tokens? [12:58:43.0000] shu: sure [12:58:58.0000] i don't think about tokens at all, but i do think about what i'm typing, which includes the syntax [12:59:16.0000] okay, when is the point in time when you switch from thinking about your syntactic notion of "subclass" to the other one, where a subclass is a class in a hierarchy with a superclass? [12:59:20.0000] i either typed a base class, or a subclass, by virtue of whether i chose `extends` or not [12:59:28.0000] when i `new` it, i suppose? [12:59:44.0000] you're describing a runtime characteristic, not a definition time one [12:59:52.0000] is there any linkage between your two notions? [12:59:59.0000] this is just all very bizarre to me [13:00:31.0000] so what would be an alternative to "making extends null work" besides "super() where super is null is a runtime noop"? [13:00:55.0000] the constructor checks the Prototype before it evaluates, and if it's null it binds it like a base class? [13:01:04.0000] i'd rather lean towards the presence of `extends` at all makes it an explicit subclass of some kind [13:01:12.0000] it doesn't make sense to call `extends null` subclassing; what you'd be saying is that there is _implicit_ subclassing when `extends` is omitted such that you'd like to be able to explicitly cancel it out [13:01:27.0000] rkirsling: not sure what that means [13:01:46.0000] ljharb: what is the difference in your mental model between `class C extends Object` and `class C` [13:02:17.0000] shu: to me, it is that you have used a different construct [13:02:26.0000] shu: the former is an explicit subclass and the latter isn't? [13:02:30.0000] i don't understand the idea that they are equivalent [13:02:35.0000] shu: i don't actually care that they both inherit from Object.prototype [13:02:39.0000] one requires super() [13:02:41.0000] ^ [13:03:18.0000] you made a choice by using 1 of the 2 constructs, and it causes a variation in how they need to be used [13:03:29.0000] oof. it sucks that those are the same insofar as the word "subclass" is concerned and yet we have a thing about them that isn't the same :( [13:04:13.0000] rkirsling: they aren't the same is exactly the point of why i don't think they should be equated [13:04:28.0000] they do result in the same prototype chain. but they're not the same. [13:04:36.0000] to put it a different way, a non-subclass can simply be thought of as something that cannot call super() during coonstruction [13:04:45.0000] i see, interesting [13:05:00.0000] so you really have a purely syntactic notion of "subclass" [13:05:04.0000] yep [13:05:07.0000] ouch [13:05:11.0000] shu: i wouldn't say syntactic [13:05:14.0000] that's the expectation the ES6 syntax sets up imo [13:05:24.0000] bradleymeck: no? [13:05:32.0000] but the equality of output doesn't tie me to the syntax being equal in intent [13:05:59.0000] bradleymeck: if the difference is not a ontological one in terms of hierarchical relationships but in whether super() throws or not [13:06:03.0000] bradleymeck: that seems purely syntactic to me [13:06:25.0000] it's really unfortunate that we made `extends Object` require `super` :( [13:06:39.0000] if we hadn't, then we'd already know what to do with null [13:06:47.0000] and with `extends {}` or `extends false` [13:07:00.0000] shu: I'd agree that it is related to what the programmer wrote, but not necessarily that it is purely syntactic [13:07:30.0000] /me has to dig up a spec sadness [13:07:56.0000] ljharb: so by this logic, you would not be opposed (syntax budget concerns aside) to another syntax that isn't "extends null" [13:08:16.0000] presumably because there is no extant property about super throwing or not tied to any new syntax [13:08:18.0000] shu: absolutely correvt [13:08:30.0000] `null class` or something [13:08:47.0000] in general i feel like that's a dangerous constraint on design [13:08:49.0000] shu: i'd probably be in the same camp as being fine with other syntax but I would prefer `null` to be in the syntax [13:09:06.0000] shu: how so? [13:09:06.0000] i don't really care enough about this particular use case [13:10:09.0000] shu: I think trying to state that the current programmer divergence must preserve the behavior of being purely syntactical is odd is my main complaint about the argument [13:10:21.0000] ljharb: because to me, i would almost always prefer to make tradeoffs that favor ontological symmetry (what is or isn't a subclass in the class hierarchy sense, in this case) over syntactic symmetry, unless doing so prohibits performant implementations, say [13:10:21.0000] extends is just a signal that the class is different from a non-subclass [13:10:50.0000] ljharb: see our repeated semi-serious attempts to reclaim 'with' to be useful [13:10:51.0000] is there a real issue with not throwing for null as a class heritage? [13:10:58.0000] shu: i think i agree with you in principle, but class syntax failed that rubric at inception, because `extends false` eg is permitted [13:11:26.0000] shu: and similarly, `super` isn't permitted in a class without `extends`, even if that class changes its Prototype later [13:11:31.0000] bradleymeck: no, i think the issue is not requiring typing super() [13:12:08.0000] shu: i don't think there is a problem requiring super() when extending null personally [13:12:35.0000] there's no way that shouldn't throw though :-/ [13:12:39.0000] i'd be kind of terrified if it wasn't required for null, since it is required for everything else [13:12:40.0000] tbh it's annoying to me to require `super()` in *every* case to me where i'm not changing the argument signature [13:12:44.0000] rkirsling: why [13:12:46.0000] rkirsling: yes, why [13:12:55.0000] rkirsling: "super" just means "make sure my instance is set up, somehow" [13:13:27.0000] that it invokes a constructor is an implementation detail [13:13:27.0000] i don't think that's how most people think of it... [13:13:27.0000] it's a function call [13:13:27.0000] it is called "super" [13:13:27.0000] not "init" [13:13:28.0000] rkirsling: it's function-like, like import(). you can't pass it anywhere else. [13:13:34.0000] rkirsling: a function call to what? directly to the class heritage? it doesn't do a normal behavior when you call it [13:13:44.0000] I'd agree it has to be a call to *something* [13:13:50.0000] but not to the class heritage itself [13:13:58.0000] yeah I mean I know it's a keyword but the idea is that you're calling a function, namely the constructor of the superclass [13:14:06.0000] auto call super if you don't call super seems too magical to me [13:14:10.0000] rkirsling: but it doesn't do that exactly [13:14:11.0000] devsnek: i agree [13:14:17.0000] it would need to throw just as `x = null; x.y()` does [13:14:20.0000] and that's not just [13:14:22.0000] you don't call super [13:14:30.0000] rkirsling: sure. and in `extends null` the implied constructor is `function () { return { __proto__: null } }` [13:14:31.0000] it has to be, super isn't used [13:14:40.0000] or smth `if (false) { super() }` [13:14:57.0000] extends null has no useful behavior atm [13:15:06.0000] rkirsling: I don't understand the last comment [13:15:27.0000] you aren't calling a method of the heritage nor the heritage directly [13:15:35.0000] rkirsling: i'd be very surprised if people found that `class C extends null { constructor() { super(); this.a = 1; } } new C()` produces an instance of C, with an own `a` property set to 1, with a [[Prototype]] set to null, was confusing [13:15:52.0000] clearly what we need is [13:16:04.0000] a global `NullProtoObject` constructor [13:16:30.0000] ljharb: it's not the produced thing that's confusing, it's the fact that `super()` doesn't throw [13:16:49.0000] I find that wildly objectionable [13:16:51.0000] rkirsling: I still don't understand the claim it should throw [13:17:03.0000] cause super() clearly doesn't just do a function call [13:17:15.0000] you can't call a method on null, I don't know what else to say [13:17:28.0000] rkirsling: that's not what you're doing [13:17:45.0000] rkirsling: `super()` isn't calling a method on null, it's not calling a method on anything - it's asking the engine to set up the class hierarchy [13:17:49.0000] rkirsling: you don't call methods on class heritage though, see `extends Object.setPrototype(function () {}, null)` [13:17:55.0000] that *may* involve invoking a constructor [13:18:16.0000] ljharb I don't really agree with the claim that `extends false` is permitted [13:18:27.0000] bakkot_: it's syntactically permitted. obv `super()` would throw there [13:18:30.0000] and therefore do not want to reason from that claim [13:18:39.0000] ljharb sure but why does that... matter? [13:18:40.0000] bakkot_: if i don't use `this`, i can still return an object from the constructor and everything works fine [13:18:46.0000] because that's how classes work? [13:19:02.0000] i don't see how it makes sense to just pretend to ignore a bunch of existing semantics until it matches the mental model you want [13:19:48.0000] my mental model is that JS is not typechecked, which means a lot of nonsense is allowed statically and throws only at runtime [13:20:15.0000] you brought up this example in response to Shu's "i would almost always prefer to make tradeoffs that favor ontological symmetry over syntactic symmetry" [13:20:24.0000] in particular, you claimed JS has failed at this because the syntax is allowed [13:20:34.0000] hm [13:20:35.0000] I dispute this; I claim it also matters what is allowed _at runtime_ [13:20:42.0000] i'm just not clear that there is an ontological symmetry [13:20:45.0000] and `extends false` is not [13:20:58.0000] (unless you do weird things JS programmers are unlikely to need to think about) [13:21:00.0000] i just think of every feature in terms of abstracting all operands to variables [13:21:00.0000] super() does *something* and not a direct call of some kind to the class heritage [13:21:03.0000] bakkot_: ok, so then you'd prefer `this` to Just Work whenever the superclass either doesn't exist, or it's a base class, or is null? [13:21:42.0000] ljharb concretely, I think `this` should work without calling `super()` first when you have `class {}` or `class extends null {}` [13:21:43.0000] bakkot_: meaning that the impl would have to check the prototype chain the first time `this` is referenced in any class, instead of only when super is called in a derived/never in a base? [13:21:50.0000] right [13:21:57.0000] i wouldn't mind `extends null` meaning you don't call super [13:21:57.0000] ljharb I am not making claims about what should happen outside of those two cases [13:21:59.0000] but others would [13:22:10.0000] bakkot_: should or must? [13:22:12.0000] bakkot_: ok, seems like we'd need to figure that out tho [13:22:23.0000] ljharb of course, yes [13:22:32.0000] I just want agreement on the core, happy-path semantics first [13:22:38.0000] before we worry about the edge cases [13:22:46.0000] i don't think the one can come without the other [13:22:56.0000] uh [13:22:59.0000] why? [13:23:01.0000] so with changing the proto later, even in `class {}`, what happens the first time `this` is referenced? [13:23:22.0000] people will argue about `function factory(S) { return class extends S { constructor() { super(); } } }` [13:23:29.0000] hang on, before I respond to that, I want to know why we need to talk about the edge cases before agreeing on the core semantics [13:23:56.0000] bakkot_: because in classes, i don't think they're separable [13:24:02.0000] the edge cases are part of the core semantics to me [13:24:05.0000] ljharb well [13:24:08.0000] I do not agree with that [13:24:21.0000] that's... pretty much a contradiction in terms [13:24:41.0000] for classes specifically, i think everything's so entangled and intertwined that it can't really be separated [13:24:48.0000] to me, class fields discussions bore that out as well [13:24:52.0000] bakkot_: i think the presence of extends forcing super() is really brutal to try and claim is decoupled [13:25:12.0000] bradleymeck I'm not claiming it's decoupled? [13:25:16.0000] that's the case I'm talking about [13:25:30.0000] i'm losing something via reading this [13:26:25.0000] bradleymeck my core claims are "`this` should work without calling `super()` first when you have `class {}` or `class extends null {}`" and "I want to get agreement on these cases before trying to reason about what happens when you change the prototype dynamically" [13:27:51.0000] bakkot_: there were people who objected to a super call not aligning exactly with the existence of `extends` regardless of what the value actually is [13:28:02.0000] devsnek yes, ljharb has expressed that opinion [13:28:07.0000] (and while i'm one of them i don't think i ever said as much in plenary) [13:28:09.0000] which is why I'm here contesting it [13:28:14.0000] so there's a number of folks who think that way [13:29:16.0000] ljharb anyway, would you be willing to talk about my claims without trying to get into what happens in edge cases? [13:29:42.0000] bakkot_: can you explain why it must not require calling super, while extends Object must? [13:29:48.0000] because if you agree those are good goals but don't think there's a good way to achieve them, that's different from disagreeing with the goals [13:30:05.0000] bakkot_: i'm not sure what more we'd talk about :-) i hear your suggestion, and altho it conflicts with my intuition about extends+super, to me the only way i'd be able to consider ignoring that conflict is if i understand the edge cases too [13:30:19.0000] bradleymeck I don't think anyone writes `extends Object` and I don't actually care if that particular case requires calling `super` or not [13:30:21.0000] i do disagree with the goal, but not in a forever-intractable kind of way [13:30:32.0000] i think "avoiding writing super()" is a non-goal [13:30:52.0000] (if that were a goal, then most of my "actual" subclasses wouldn't have required it either, including every react component) [13:31:11.0000] i'd agree that avoiding verbosity isn't a real goal, as long as usability isn't too impacted, you already are doing additional burden by requiring `extends null` [13:32:14.0000] yes, my objection is not "this is a burden", it's "this requirement breaks my ontology by suggesting that an extends-null class is a subclass when it is not" [13:32:33.0000] bakkot_: why is it not i guess is the follow up [13:32:38.0000] to paraphrase a smart person, "stop wanting that ontology?" [13:32:43.0000] bradleymeck of what? [13:32:43.0000] :-p [13:32:56.0000] bakkot_: why is extending null not a subclass if it has a heritage [13:32:56.0000] ljharb I am willing to give it up if there is reason to believe it is unusual! [13:33:23.0000] ljharb but fwiw I cannot find any definition of "subclass" anywhere for which "it is a subclass, but not of anything" would make sense [13:33:26.0000] i would be very surprised if muggle devs thought about the definition of subclass at all [13:33:33.0000] lack of heritage does affect things like replacements of heritage causing errors [13:33:37.0000] strong disagree [13:33:51.0000] everyday practitioners for sure think about class hierarchy? [13:33:55.0000] i believe they think their class either extends something or doesn't, and if it does, it requires super [13:34:04.0000] shu: yes but not in a strict "this is a subclass" sense [13:34:08.0000] I don't think devs think that [13:34:26.0000] i'm fine with the idea that people think about some hierarchy but i don't understand that having a heritage is seen as not being a subclass [13:34:32.0000] if anything they forget that it's not simple OOP [13:34:43.0000] bradleymeck having a heritage _specifically from null_ is not being a subclass [13:34:51.0000] you cannot be a subclass without having a superclass [13:34:54.0000] rkirsling: sure but those people also aren't going to be extending null [13:34:57.0000] `null` is not a superclass [13:35:04.0000] true [13:35:04.0000] ok so then maybe "subclass" is the wrong term [13:35:11.0000] if it has `extends`, the spec calls it a derived class [13:35:14.0000] ljharb: this past hour of argumentation has kinda hinged on your using a spec author's understanding of "subclass" and say that people don't understand it that way [13:35:15.0000] derived classes require use of super [13:35:19.0000] bakkot_: can you explain why it isn't something that can be derived from? [13:35:24.0000] shu: hm, let me think about that one [13:35:50.0000] shu: to be clear I do think there is variation on the presence of a heritage that is attempting to be ignored, ljharb isn't purely alone [13:36:03.0000] bradleymeck I didn't say "cannot be derived from", I said "is not a class" [13:36:12.0000] *is not a superclass [13:36:17.0000] the reason there being, it is not a class [13:36:31.0000] the reason for that being that it... isn't... a class? I don't know how to justify that onoe [13:36:40.0000] ljharb: all i'm saying is almost all practitioners, by my observation and experience, certainly think about subclassing. what they don't think about is what you defined "subclass" to mean, so yes i agree we should stop using "subclass" in this argument at least. [13:37:24.0000] bakkot_: if a class is derived from something it isn't a subclass? [13:37:30.0000] maybe like "explicit extension" [13:37:56.0000] in particular i think the claim that `extends` is purely syntactic is false [13:37:59.0000] `class X { constructor() { this.x = 'x'; } }; X.__proto__ = function Y() {this.y = 'y';}; new X();` [13:38:01.0000] vs [13:38:09.0000] `class X extends Object { constructor() { super(); this.x = 'x'; } }; X.__proto__ = function Y() {this.y = 'y';}; new X();` [13:39:00.0000] that feels like a pretty compelling example to me [13:39:07.0000] bradleymeck: what is that trying to show [13:39:51.0000] shu: one of those does add this.y, one does not [13:40:03.0000] both have a class heritage value of Object [13:40:18.0000] bradleymeck: in the spirit of avoiding the term "subclass", I would regard a class which `extends null` as sitting at the top of its class hierarchy, the same way that a class which does not `extend` anything does [13:40:33.0000] since it sits at the top of its class hierarchy, I would be surprised if I had to call `super()` [13:41:04.0000] bakkot_: i am unclear on *why* it is at the top [13:41:27.0000] bradleymeck uh [13:41:34.0000] there is no possible thing which could be above it? [13:41:36.0000] null seems to be at the top [13:41:40.0000] null is not a class [13:41:45.0000] null cannot be in a class heirarchy [13:42:01.0000] i mean, the hierarchy is between [[Prototype]] values, which are all objects or null [13:42:04.0000] LSV cannot hold for `null` and any `class` under almost any circumstances [13:42:09.0000] so null is part of a prototype hierarchy - at the top [13:42:10.0000] *LSP [13:42:32.0000] i mean, we can argue it isn't a class but that class does have a heritage [13:42:40.0000] a "class hierarchy" is just a combination of the constructor's prototype hierarchy, and its prototype object (and its prototype hierarchy) [13:42:48.0000] no! that's the core confusion i think [13:42:54.0000] ljharb strong disagree [13:43:17.0000] do ES5 constructors have a class hierarchy? [13:43:19.0000] class hierarchy is a concept which exists independent of language [13:43:28.0000] it is a concept prior to concrete programming languages [13:43:31.0000] ^ [13:43:32.0000] there's a programmer's "theory" of a class hierarchy, it's the mental map of building blocks of a program and how things are divided up [13:43:49.0000] ljharb and bradleymeck instead are arguing from purely mechanical grounds of what JS happens to do and how that is inconsistent [13:44:04.0000] because JS is a dynamic language, inconsistencies and weirdness will invariably be possible [13:44:08.0000] shu: i don't care what you call it, it can be a base class but it has a heritage [13:44:12.0000] ... [13:44:31.0000] bakkot_: then "extends null" as a concept just doesn't fit into your concept of class hierarchy imo [13:44:39.0000] shu: to be clear i don't care if null is considered outside the heirarchy [13:44:47.0000] ljharb yes, that is my claim [13:44:49.0000] even the existence of a null [[Prototype]] doesn't seem like it's part of this class hierarchy concept [13:44:57.0000] which would mean it's not an appropriate concept to apply to JS [13:45:02.0000] ljharb disagree [13:45:20.0000] i simply don't understand this logic that heritage must match a class hierarchy and be a direct call of some kind to it [13:45:35.0000] I don't think every feature in a language needs to be represented perfectly by some concept for that concept to be useful [13:45:40.0000] both of those seem to be invalidated both at runtime and to some extent at parse time [13:45:44.0000] bradleymeck: i don't think that's the logic [13:45:51.0000] bakkot_: nor does a useful concept need to constrain every aspect of the language's design [13:45:59.0000] ljharb right [13:45:59.0000] but [13:46:02.0000] shu: what is the logic? avoid using subclass [13:46:04.0000] that does not mean you are free to ignore it [13:46:34.0000] bradleymeck I don't know what you mean by "heritage", I am realizing [13:46:39.0000] bradleymeck: the logic is that *unless* you do edge casey things like runtime __proto__ mutation, not requiring super() in `extends null` classes matches up with the general OOP model of class hierarchies [13:46:56.0000] bradleymeck: and that is a valuable property [13:47:01.0000] bakkot_: “not constrain” definitely means “free to ignore” :-p [13:47:09.0000] shu: can you explain what we get for that property? [13:47:10.0000] ljharb: that is also just not true! [13:47:25.0000] bradleymeck: we get a happy path for common usage? the normal 80-20 thing [13:47:26.0000] it doesn’t mean it’s wise to ignore it ofc [13:47:33.0000] shu: can you explain that more [13:47:46.0000] why is not using super() the explicit happy path [13:47:58.0000] like, what does that mean [13:48:03.0000] bradleymeck the happy class is not that you are avoiding `super` [13:48:09.0000] its that your usage of the language matches the concepts in your head [13:48:24.0000] in particular, that a class which extends `null` is at the top of its class heirarchy [13:48:32.0000] bradleymeck: like, when i'm programming in an OO way, i think about classes and how i organize my code, right? [13:48:46.0000] bradleymeck: i don't start by first saying "let me think of the full semantics of JS's classes" [13:48:49.0000] i think about organization [13:48:57.0000] bakkot_: i don't understand that claim, i don't have a concrete mental model i try to force all my programming into [13:49:05.0000] this isn't concrete [13:49:10.0000] I will let shu say the thing I would say [13:49:11.0000] it's like a rough organizational idea? [13:49:30.0000] shu: ok, and having super() would break it, and in a way that isn't easily learned/debugged? [13:49:46.0000] what about it breaks the model [13:49:50.0000] bradleymeck: oh i don't know about the ease claim, it seems easy enough to fix [13:50:18.0000] bradleymeck: it's not a binary break-or-not-break [13:50:22.0000] it makes the mapping more difficult [13:50:24.0000] what would it mean if a base class is calling super() [13:50:29.0000] from your model [13:50:40.0000] i don't know what it would mean [13:50:47.0000] bradleymeck it would not mean anything [13:50:55.0000] `super()` is a thing for subclasses to do [13:51:03.0000] bakkot_: it would be non-sensical or something else? [13:51:04.0000] in particular, for them to invoke their superclass [13:51:12.0000] bakkot_: and if they don't have superclass? [13:51:26.0000] bradleymeck this question is like "what would it mean if orange was a sound" [13:51:27.0000] to my recollection abstract superclasses etc might be ellided in ye olden days [13:51:34.0000] bakkot_: i'd disagree [13:51:45.0000] bradleymeck: hold on, the "if they don't have a superclass" is the turning point where we diverge, i think [13:52:07.0000] bradleymeck: *you*, as a JS expert, know that the congruence i want for `super` in my hypothetical is _already not true_ [13:52:29.0000] bradleymeck: the contention is that the cases where it is already not true are, i think, rare, like runtime prototype mutation [13:52:38.0000] shu: i'm thinking of me in 11th grade learning Java [13:52:38.0000] bakkot_: ok what about this: what if `super()` always throws when the superclassish is null, but `super?.()` doesn't throw when it's null (but does set up the `this`) [13:52:46.0000] bakkot_: would that break you and shu's mental model? [13:53:06.0000] shu: a lot of what you are stating is really confusing, just like polymorphism is confusing, let alone things like multiple inheritance [13:53:14.0000] but we are familiar with topics here [13:53:44.0000] wait `super?.()` doesn't (and shouldn't) exist since it's a keyword though [13:53:46.0000] ljharb again, my core claim is that a class which extends `null` should not need to call `super`; I am somewhat less worried about what happens in other cases [13:53:55.0000] i was not ready for `super?.()` [13:54:01.0000] but i don't hate it [13:54:01.0000] rkirsling: it could certainly be permitted [13:54:20.0000] bradleymeck: single inheritance is confusing? [13:54:28.0000] shu: for me it was [13:54:35.0000] to some extent... is? [13:54:37.0000] bradleymeck in 11th grade Java, you would not call `super()` in a class which does not have a superclass [13:54:52.0000] `super()` is a thing for subclasses to do, and a subclass cannot not-have a superclass [13:55:02.0000] bakkot_: that was learned and still seems to be completely fine if i had been forced to call it [13:55:21.0000] why would it be completely fine though? [13:55:23.0000] it wasn't inherent in the fact that a class inherited [13:55:27.0000] it refers to something nonexistent [13:55:35.0000] couldn't you argue if you don't specify `extends` it defaults to Objcet [13:55:37.0000] rkirsling: why does super() have to do something? [13:55:49.0000] thats really a crux of the argument [13:56:04.0000] if super() doesn't need to do anything... why do you have to avoid calling it [13:56:17.0000] bradleymeck here we are arguing about whether `super` should be required; if it is required. it definitely does do something [13:56:25.0000] devsnek: yeah that's my view but I guess it's messy since extends syntactically requires super [13:56:26.0000] bakkot_: why [13:56:46.0000] what might be better a question [13:56:54.0000] bradleymeck: a no-op is still a something [13:56:56.0000] bradleymeck um. how can it be required and also not do something? at the very least "make the class work"? that is a thing that it has done. [13:58:06.0000] i think i am going to do some reviews [13:58:27.0000] I understand that super is _more_ than just a function call but I don't buy that it's ever not one, just because the function is an implicit no-op [13:58:36.0000] bakkot_: to clarify a bit, i don't see a no-op as being a claim that it does something and equating lack of extends and extends Object to be very consistent [13:59:04.0000] bradleymeck I am not dead-set against it being a no-op. what I am against is it being required. [13:59:27.0000] also, like I said, I don't really care about the `extends Object` case and am happy to explore whatever semantics there would make people happy [13:59:46.0000] are there use counters for `extends null` [13:59:50.0000] bakkot_: I'm very unclear on why it must not be required [14:00:14.0000] devsnek: there was at one point, but it is so error ridden it was terribly low when aklein did it [14:00:25.0000] devsnek `extends null` currently results in a thing which is impossible to instantiate, which is almost certainly not the thing anyone wants [14:00:43.0000] bradleymeck well, I don't know if I can say it any more clearly than it was said above, but I'll give it one more shot. [14:00:57.0000] i'm thinking we might just throw if its null [14:01:05.0000] remove the special case for null rather [14:01:33.0000] devsnek: it's not really a special case right now tho, is it? [14:01:39.0000] it is [14:01:42.0000] bakkot_: thanks, I'm just very confused on what this class heir-achy idea in some circle i've not participated in is being broken by :( [14:02:11.0000] ljharb: ClassDefinitionEvaluation 5.e [14:02:55.0000] i never had this mandate in my college that base classes must never do some sort of super, just that they don't [14:03:07.0000] they must not inherit [14:03:10.0000] the easy way out here would be to specify that Function.prototype returns Object.create(null) when [[Construct]]ed [14:03:57.0000] definitely cannot do that [14:04:04.0000] why not [14:04:22.0000] i've certainly seen code that uses new Function [14:04:32.0000] oh you mean the proto itself [14:04:34.0000] yes [14:04:35.0000] mmm [14:04:38.0000] odd [14:04:43.0000] when you do `class extends null` [14:04:49.0000] the parent is `Function.prototype` [14:04:56.0000] which is why it can't be instantiated [14:06:04.0000] if you did that "easy way out", wouldn't one expect `instanceof Function.prototype` to be true? [14:06:16.0000] not inherently? [14:06:27.0000] the result of `new X` doesn't have to fulfill `instanceof X` [14:07:08.0000] ljharb: i mean builtin protos are weird already, some are instances of their function, some are regular objects, some have the brand of their function [14:07:33.0000] i feel like that's still an expectation people would hold in the common case [14:07:47.0000] if we're going with "null isn't part of the class hierarchy" as an expectation [14:08:57.0000] i think all the reasonable alternatives are listed in the pr somewhere [15:26:34.0000] bradleymeck sorry, I had a meeting before I could finish writing this up [15:27:47.0000] anywhere here: https://gist.github.com/bakkot/d931e4d67a4d44ff79261d3699621cc8 [15:28:49.0000] these are all things that I think, but also concretely I think they correctly describe the intuitions of most people who use `class` in languages like JS, Java, python, C++, etc [15:37:31.0000] bakkot_: 💯 2020-07-08 [09:21:25.0000] Why does Math.pow not handle bigint type? [09:28:58.0000] bendtherules: a general concern about overloading; see https://github.com/tc39/proposal-bigint/issues/197#issuecomment-467941106 [09:40:34.0000] bakkot_: got it. [11:14:54.0000] it would be nice if super could be used in normal function expressions [11:15:03.0000] like when you're trying to override a method in a hacky way [11:17:07.0000] I think that would make more sense if we didn't have the whole [[HomeObject]] thing [11:17:23.0000] (a thing for which I've never entirely understood the motivation, tbh) [11:17:31.0000] more magic is always good right? [11:17:38.0000] :( [11:17:54.0000] I have a slide in an internal talk I've been writing which contains only the words "Magic Is Bad" [11:18:04.0000] lol [11:18:08.0000] maybe its time to overhaul classes [11:18:13.0000] *in a web compatible way* [11:18:24.0000] super also works in object literals [11:18:28.0000] well, super property access, anyway [11:18:33.0000] huh [11:18:55.0000] this would be vastly more useful if `__proto__` weren't considered a bad pattern [11:19:03.0000] maybe that's a problem with what is considered a bad pattern, though [11:19:26.0000] you can use super in method definitions [11:19:29.0000] in object literals [11:20:55.0000] right, it's just that the super is going to be Object.prototype unless you've mutated the proto after the fact or have used `__proto__` in the initial literal [11:21:12.0000] and both of the "unless" things are usually frowned upon [11:21:43.0000] so having syntax which is only useful if you do frowned-upon things or for some reason want to access properties of Object.prototype is... weird [11:23:07.0000] i don't think people generally frown on __proto__ in literals [11:24:50.0000] hm, maybe. I don't see it used much, certainly [11:25:07.0000] we shouldn't've put it in annex b if we were expecting it to continue to be good practice [11:34:56.0000] `{ a: 1 } with null` [12:44:19.0000] bakkot_: thanks for the write up. I'm not sure I understand/agree with it still but it seems to give a clear idea. I do have some replies to each point though. [12:44:44.0000] per 1: Mainly it seems that the idea of "is-a" simply cannot be applied to classes that have null prototypes is a claim. So that would mean they are not describable in general? If they are not describable as being a thing that seems odd in its own. [12:46:16.0000] per 2: it starts with the claim extends `null` is the same as no heritage, which is partially the debate (missing heritage doesn't dynamic delegate / uses Object not `null`) so I'm unclear on why that is being treated as given. [12:46:44.0000] per 3: this explanation doesn't seem to be rooted in anything? [12:47:54.0000] 4 is derived from 2 and 3 which seems ok, but it doesn't seem to follow through. it relies on the model of 2 and 3 as being intuitive and given which both of them seem confusing to me at least on first few reads [12:49:14.0000] I think a key framing is "think of instances of this class as also being instances of any other, broader class." as being the pre-requisite for *allowing* the idea super to be considered [12:49:53.0000] to me, super() doesn't actual tie to a specific class / concrete thing to call and does some really magical stuff if taken in isolation [12:50:43.0000] it seems, to you super() is being tied to some concrete thing to call and that a class must exist but I'm not clear on why it is concrete nor why it must directly exist [12:51:42.0000] i think we can reason about what is sensical/non-sensical to frame our side whichever way in retrospective we want on a personal level [12:51:59.0000] but to me I'm unclear on why super() is being stated as inherently non-sensical [12:52:42.0000] i'd agree super.foo() is non-sensical, it is requesting a specific thing to be delegated, but it is unclear why super() is [12:58:45.0000] bradleymeck: will write up responses so I can post them all at once, one sec [13:00:27.0000] bakkot_: i will state that to me this is seeming very much towards trying to make things fit with a mental model and not about learnability/debuggability/refactorability/consistency which the more i think on those the more i think even if it doesn't 100% a mental model it would be preferable to require it [13:01:17.0000] i'm just unclear on what the downside of requiring it is concretely besides the extra characters [13:01:40.0000] and that falls down to i'm unclear on why a "baseclass calling super() [13:01:45.0000] "baseclass" [13:01:55.0000] must mean errors [13:09:36.0000] i do see things like having a constructor body be usable for both a base and subclass as a boon, syntax does hint on if something is requires, matching every other heritage (including Object) requires calling super() even if it errors, etc. [13:09:59.0000] required* [13:10:29.0000] but the explanation is kind of heady so far [13:10:57.0000] oof, that was a long one [13:11:09.0000] bakkot_: how does “super installs calls fields” play into your gist? [13:11:22.0000] *class fields [13:14:32.0000] ljharb: ? what does that mean when there is no heritage? [13:17:13.0000] bradleymeck: `super()` first invokes the superclass, and then installs the *current class*’s public and private fields [13:17:36.0000] bradleymeck: https://gist.github.com/bakkot/8ca6db3b995d55f3b6886a5be87d0f38 [13:17:46.0000] ljharb I haven't said anything about fields? I'm not sure what you're asking. [13:17:47.0000] bradleymeck: so on a `class extends null`, either 1) `super()` would install that class’s fields, or 2) `this` would be automatically available and the fields would be installed prior to the constructor running [13:17:50.0000] bakkot_: right [13:17:56.0000] bakkot_: your gist says “this is what super *does*" [13:18:01.0000] bakkot_: but it doesn’t mention class fields [13:18:14.0000] bakkot_: so i’m asking you how your mental model adjusts to the other thing super does. [13:18:30.0000] ie, the thing that has nothing to do with a class hierarchy [13:19:12.0000] I would not say that `super()` installs fields; I would say that the class constructor does this itself as soon as `super()` has provided the object onto which the fields should be installed [13:19:29.0000] ^ [13:21:15.0000] i mean, i type `super()` and if i don’t, the class fields don’t get installed [13:21:37.0000] surely the class mechanics might be doing it, but that’s not the constructor. but thanks, i think that answers my mental model question [13:21:47.0000] bakkot_: I'd state c.) that your conclusions doesn't mesh with the terminology not that I reject either the terminology or conclusion itself. in particular i don't understand the terminology of super/sub class since not having a class above in the hierarchy seems to be confounded by things ` class X {} ` being treated as a base class but it does inherit from Object and that super() is tied to a concrete thing [13:22:34.0000] > Specifically, to me, super is a reification of the relationship between classes discussed above - hence the name - and does not make sense in the absence of such a relationship. [13:22:37.0000] this is interesting to me since it doubles down again on a concrete/direct relationship rather than what to me appears to be an indirect relationship [13:23:32.0000] > [Breaking this OOP mental] is a very significant cost. [13:23:36.0000] can you clarify this [13:24:20.0000] i think the mental model simply doesn't mesh with reality and thats causing me troubles [13:24:37.0000] since things with a superclass are being treated as non-subclasses in discussions [13:26:03.0000] and things with a heritage (or lack of in the case of null) are being asserted that the heritage cannot be considered an is-a relationship indirectly in the same way that `extends Foo` can while `extends Foo` doesn't actually assert things being a `Foo` [13:26:13.0000] re: "`class X {} ` being treated as a base class but it does inherit from Object": the point is that I am talking only about how I mentally organize my code. It happens to be the case that every instance of `class {}` inherits from Object, in Javascript's mechanics (and Java's for that matter), but this is a mechanical fact about the implementation of `class` in the language rather than a reflection of a relationship I am [13:26:13.0000] specifically intending or thinking about wrt the structure of my program. [13:26:18.0000] i think if we had used a different token than `class` this discussion would be less interesting [13:26:40.0000] bakkot_: right, and that is confusing to me [13:27:05.0000] because these claims are not matching reality nor claiming to enhance actual programs themselves [13:27:20.0000] so i'm not sure what is being argued for and why [13:27:30.0000] um. [13:27:54.0000] i see the terms, but the terms are being given as if they are truths somehow and parts of those are confusing me [13:28:05.0000] I guess I have not thus far explicitly made the claim that the ability to think about the structure of my programs and have that be reflected by the programs themselves is valuable, so let me explicitly say that now. [13:28:29.0000] bakkot_: sure, but now thats much more subjective [13:28:37.0000] This is all subjective, yes. [13:28:46.0000] yes, but in degrees [13:29:02.0000] I don't think this is very subjective, as these things go. [13:29:06.0000] subjective except that the write-up above has gone to lengths to ensure that it reflects the most basic concepts of OOP [13:29:28.0000] the ones from which it would be disingenuous to diverge and still use a keyword like `class` [13:29:32.0000] rkirsling: in my OOP courses in college/high school we didn't have these rigid models [13:30:03.0000] somewhat objectively, the default for `extends` is `Object` [13:30:05.0000] i did understand that a subclass inherits [13:30:31.0000] but the definition of a base class in these recent talks is all over the place [13:31:53.0000] i think there is a desire for omission to be treated like a base class and acknowledgement that it is not reality, but to treat an explicit value (null) as a base class even if it has a heritage [13:32:07.0000] i don't understand the actual benefit of the desire [13:32:11.0000] I don't know what "that is not reality" means there [13:32:14.0000] it is a base class [13:32:19.0000] bakkot_: it inherits [13:32:23.0000] you get .toString etc [13:32:24.0000] that is not the definition I am using! [13:32:29.0000] I was very careful with my definitions! [13:33:12.0000] bakkot_: i think your definitions are confusing to me as I've stated [13:33:32.0000] hm [13:33:35.0000] I don't know how to get past that [13:33:38.0000] i also think that if you’re arguing a more broad concept of class heritage, “a subclass inherits from a base class” is a part of it [13:33:51.0000] there’s no class hierarchy without inheritance [13:33:52.0000] these are things which are, to me, extremely bedrock foundational principles of OOP [13:34:05.0000] and JS isn’t merely an OOP language, it’s multi-paradigm [13:34:25.0000] which is why there’s a number of language semantics that don’t mesh with those principles [13:34:46.0000] and obv it’s totally fine to pick and choose the semantics you care about for your own mental model [13:34:48.0000] bakkot_: i was explained OOP and we did state that base/sub/super classes as terms, but in languages where everything is a delegation (recursive object root type) you can't have a base class for example [13:35:43.0000] it seems there is a sub/super relationship mental model difference as part of the issue [13:36:12.0000] and the sub/super are the same for those? it simply doesn't make sense to try and force those terms there [13:37:45.0000] `super` is the term the language already uses [13:37:57.0000] we are debating the semantics of a token literally spelled `super()` [13:38:21.0000] bakkot_: sure, seems fine to call the language to perform super() steps even if there isn't a super to me? [13:38:47.0000] super() steps to me are indirect not a concrete/direct thing [13:38:48.0000] if we’re talking about literal spelling, then we can’t really ignore the presence of `extends` [13:39:08.0000] iow either the concrete syntax is important, or else it would be the same discussion of super was spelled `init()` [13:39:13.0000] *if [13:39:22.0000] super() is extremely confusing in general and I can't easily think of it as a generic function call [13:39:27.0000] ljharb I read "extends null" as "extends nothing", i.e. "does not extend anything", i.e. "is a base class" [13:39:39.0000] none of that seems inconsistent with anything I've said [13:39:45.0000] that is clear, which suggests that `class {}` is not a base class [13:39:47.0000] bakkot_: is the same true for extends undefined? [13:39:49.0000] because it doesn’t extend nothing [13:40:09.0000] ljharb `class {}` also does not extend anything [13:40:17.0000] so... no? [13:40:18.0000] and yet, it inherits from Object, which is the same thing [13:40:20.0000] bakkot_: I'd very strongly it does [13:40:25.0000] argue* [13:40:34.0000] “x extends y” to me is a statement both about the syntax and about the runtime behavior [13:40:53.0000] java/ruby classes extend object by default even if you omit the clause [13:40:56.0000] i suppose the weird part is that `class { }` doesn’t already have a null proto [13:41:41.0000] ljharb as I said above, several times, it is an interesting mechanical fact that the resulting objects have `Object.prototype` in their prototype chain, but this has very little to do with the relationships between structures I am thinking about when organizing my program, which is the thing I actually care about [13:41:41.0000] perhaps the oddity here is that `class`, `extends`, and `super` are all familiar from class inheritance but "null proto" is inherently prototypal [13:42:10.0000] bakkot_: i find it strange that you’d think about how your program is organized when defining classes but not when using them [13:42:23.0000] ... what? [13:42:33.0000] rkirsling: yes, i 1000% agree that all the spellings in `class` are terrible because they evoke a classical inheritance mindset :-) but that ship has sailed [13:42:46.0000] well I didn't mean that so much as like [13:42:46.0000] ljharb I have no idea how you got that from anything I said [13:42:49.0000] bakkot_: “has Object.prototype in their prototype chain” is part of how your class instances are organized [13:43:04.0000] bakkot_: it’s not just a mechanical fact, it’s a core part of the organization of your instances. [13:43:04.0000] we're having a hard time because the goal isn't to instantiate a non-Object [13:44:17.0000] ljharb "is represented by electricity moving through silicons" is a part of how my classes are implemented, but that is still not an organizing principle which I keep in mind most of the the time when designing the implementation of a class [13:44:27.0000] lol ok fair [13:44:27.0000] so like, `extends Object` might be default but even with null proto we're not trying to instantiate something that can't hold properties [13:44:41.0000] but i'd think the runtime behavior of your instances *is* something you keep in mind when designing the implementation of a class [13:44:49.0000] like “is this a prototype method or a static method" [13:44:58.0000] or “what instance methods will this have from its prototype chain" [13:45:09.0000] hence maybe `extends null` could be called dangerous if that phrasing inherently mixes worlds [13:45:18.0000] the fact that an object has Object.prototype in its prototype chain is virtually never relevant to the organization of my code [13:45:34.0000] other prototypes which I have explicitly put in the proto chain are [13:46:14.0000] bakkot_: but that doesn't match reflection utilities in other languages either [13:46:15.0000] there’s a bunch of coding styles where that’s true, sure [13:46:16.0000] ruby // class A; end # A.superclass => Object [13:46:29.0000] but if you’re using your instance as a dictionary, or using `instanceof Object` anywhere, it matters [13:46:48.0000] pythong: class Foo: \n pass \n issubclass(object, Foo) => true [13:47:02.0000] same for java/etc. [13:47:02.0000] ljharb I am not using my `class {}` instances as dictionaries [13:47:23.0000] bakkot_: i understand that, but that isn’t something universally true [13:47:35.0000] i’ve seen lots of (bad) code that does `Object.assign(this, opts)` or similar [13:47:59.0000] and you can still use super.toString even if you don't have an extends clause right? [13:48:03.0000] i don’t do it in my own code either, but i’m not *unaware* of the existing of Object.prototype; if i were, i wouldn’t want extends null in the first place [13:48:07.0000] *existence [13:48:28.0000] ljharb: i feel called out [13:48:34.0000] yes, this is a claim about how people tend to reason about their code. it is about abstractions. obviously all abstractions can break down in some cases: `+ 1` does not actually "add one" in the mathematical sense, because of integer overflow, but I still claim that is how one typically thinks about what that code doeos [13:48:53.0000] bradleymeck: yes, `(new class { x() { return super.toString(); } }).toString()` works as expected [13:49:41.0000] bradleymeck: `(new class { constructor() { return Object.create(null); } x() { return super.toString(); } }).x()` throws tho [13:49:52.0000] (oops, s/.toString/.x` in my first example, same result) [13:49:59.0000] well yes because you replaced the result ;-p [13:50:14.0000] i'm pretty sure it'd work if i also installed the `x` method onto the null object [14:02:39.0000] ljharb: thats because super is tied to its scope not the the call though I thought [14:10:02.0000] bradleymeck: i believe that’s right [15:03:01.0000] ljharb: am i a member of the editors team on GH? every time you request a review from it I get a notification saying you requested a review from me [15:03:51.0000] um, not that i'm aware [15:03:57.0000] let me check [15:04:26.0000] https://usercontent.irccloud-cdn.com/file/Z5AMMh92/Screenshot_20200708-170413.jpg [15:04:57.0000] devsnek: you aren't; it might be a weird github bug since you've commented on the pr [15:05:05.0000] perhaps [15:05:05.0000] i request the editors team to review a *lot* of PRs [15:05:29.0000] I've noticed :D 2020-07-09 [18:49:48.0000] Is it okay to add additional internal slots after the object created? [18:58:46.0000] no, don't do that [18:59:33.0000] unless you really can't express it any other way, then maybe we can see if an exception makes sense, but per https://tc39.es/ecma262/#sec-object-internal-methods-and-internal-slots: [18:59:40.0000] Unless explicitly specified otherwise, internal slots are allocated as part of the process of creating an object and may not be dynamically added to an object. [10:18:13.0000] shu: isn't this jobcallback stuff all happening inside of the steps for running a job [10:18:31.0000] why can't this be part of a host's implementation defined preparation/cleanup steps [10:19:57.0000] devsnek: it probably should be happening in the steps for running a job, per my last comment, but there still needs to be an extra hook to capture the incumbent to pass back [10:20:37.0000] ah i didn't see that, glad we came up with similar conclusions :D [10:20:40.0000] devsnek: i was trying to mirror the webidl semantics, but i don't think webidl conflates job and a callback function [10:20:49.0000] err, i do think, rather [10:21:49.0000] so webidl always associates the incumbent per function object, which is what my current PR does. but that seems to be extra expressivity that's not needed [10:22:29.0000] since we don't have any API that for example takes multiple callbacks at different points in time, possibly with different incumbents, then posts a single job that calls them [10:23:02.0000] makes sense [10:23:07.0000] this reminds me that i need to review your other job pr [11:52:40.0000] devsnek: interestingly, domenic's batching case suggests a per-function approach is perhaps desirable [11:52:57.0000] what uses batching [11:53:12.0000] devsnek: since you were thinking per-job, do you have concerns with the extra expressivity? [11:53:17.0000] i don't think anything does currently [11:54:23.0000] though, if the extra machinery isn't too much complexity, i don't see why we wouldn't want the extra expressivity [11:54:36.0000] this whole thing feels weird [11:54:42.0000] sort of like an implementation detail leak about the job [11:55:54.0000] i don't share that view, JS is embedded [11:55:59.0000] i guess the generalization is "whenever a job calls a function"? [11:56:00.0000] stuff in jobs already cross that boundary [11:56:02.0000] yes [11:56:09.0000] the generalization is "job callbacks" [11:56:34.0000] those need additional state in some embedders [11:57:01.0000] `HostCall(job record, f, thisvalue, args)` [11:57:10.0000] and put some HostDefined on job records [11:57:30.0000] yes, something like that [11:57:36.0000] though not sure if it needs the job record passed back in [11:57:50.0000] sure, jobrecord.[[HostDefined]] or whatever [12:22:58.0000] ljharb: if you have better names than emplace I really have no strong desires as a base except that the name shouldn't reflect an operation it might not do [12:23:51.0000] i'll definitely think about an alternative [12:24:09.0000] i realize it's not quite as reasonable to object to a name without providing at least one alternative :-) [12:24:42.0000] bradleymeck: was "one callback, but with arguments that tells you if it's an update or an insert" also blocked? [12:24:52.0000] yes [12:24:57.0000] what was the reasoning? [12:25:06.0000] it devolves to just being a ternary with and update and insert function generally [12:25:18.0000] no real reason to force it to be a single function at that point [12:25:43.0000] i'd say the reason is "because some folks objected to passing two callbacks" [12:26:18.0000] function handler(isUpdate, existingIfIsAnUpdate) { return isUpdate ? update(existingIfIsAnUpdate) : defaultValue() } [12:26:41.0000] ljharb: i don't see any major problem with an options bag [12:27:07.0000] in a comment we even had someone show an example of a reciever storing data [12:27:16.0000] handler receiver [12:27:36.0000] oof [12:27:56.0000] i can understand the complaint about not including naming in the function params, and that double purposing the handler is weird [12:27:57.0000] fwiw, the mess that is "a proxy handler" would make me fight pretty hard to eagerly extract the functions from the object [12:28:14.0000] ljharb: implementations strongly disagree XD [12:28:23.0000] on which part [12:28:37.0000] (also i don't think the callbacks should be called with a receiver at all) [12:28:46.0000] ljharb: collection normalization wanted to do that, but impl feedback was that it *must* match proxy handler behavior to ease impl and be more consistent [12:28:48.0000] it's conceptually an options bag, not a handler object [12:28:54.0000] um [12:29:10.0000] ljharb: regardless impls do not agree and I had to change a previous proposal because of it [12:29:13.0000] that would be inconsistent with the way options bags are used everywhere else in the ecosystem [12:29:20.0000] can you remind me who had that objection? [12:29:29.0000] /me digs about [12:29:30.0000] because the way proxy handlers work is bizarre and confusing and unique [12:29:57.0000] you could dig through the notes too :P [12:30:02.0000] https://github.com/tc39/proposal-collection-normalization/issues/15#issuecomment-515337415 is in there [12:30:15.0000] notes would be around that timeframe [12:30:33.0000] totally fair, if it's in the notes i'll look [12:31:59.0000] if it's just that one github comment tho i'd want to explore it more. in the case of collection normalization, that involves the internal hooks of maps and sets; for upsert i just don't buy a perf argument [12:32:08.0000] also, the precedent we now have is that `resolve` is looked up on `Promise` eagerly [12:32:47.0000] ljharb: it was in committee don't remember if it was in the presentation or hallway [12:32:59.0000] ljharb: upsert is not just perf [12:33:10.0000] yeah i'm not finding anything in the notes [12:33:21.0000] upsert is mostly about fixing the (now fixed) bugs we had to deal with when making a complex multi-level cache for work [12:33:32.0000] it took years to completely find them all [12:33:51.0000] and most had to deal w/ all the variation of .has/.get/.set workflows to try to insert or update a value [12:33:52.0000] what i mean is, i don't understand how the "similarity to proxy handlers" argument applies when that's the only place in the language we dynamically look up values on an object later, and when in all the Promise combinators, we look up the functions eagerly, on purpose [12:34:05.0000] and that Promise change was made *because* of implementor perf arguments [12:34:10.0000] ljharb: talk to implementors? [12:34:19.0000] happy to but it's not in the notes, so that one github comment's all i've got [12:35:00.0000] (or rather i can't find it in the notes) [12:35:31.0000] ljharb: just ping rbuckton and maya directly? [12:35:53.0000] they would know the source of the underlying reasoning perhaps more than I [12:36:00.0000] i'm just reacting [12:36:27.0000] ping rbuckton :-) any context here? i'll ping maya later [13:02:44.0000] ljharb: since these are not persistent and are always looked up since the handler is immediately called does it even have meaning to eagerly read the values? [13:03:02.0000] we don't keep a ref to the options bag after the return value [13:03:45.0000] it determines observability [13:04:05.0000] ie if it’s a getter, then i could determine if the map’s `has` had been checked first or not [13:04:22.0000] oh also that raises another question; are these looking up `.has` and `.get` and `.set`, or are they using the internal operations? [13:16:55.0000] ljharb: no .has delegation [13:16:58.0000] absolutely not [13:17:04.0000] great [13:17:15.0000] no get or set either, i hope? [13:17:18.0000] correct [13:17:24.0000] reentrancy concern nailed that [13:17:24.0000] yay ty [13:17:38.0000] otherwise we did have subclassing concerns if we didn't delegate [13:17:50.0000] but with reentrancy delegating would be really awkward [13:17:58.0000] also other langs don't do that [13:18:25.0000] right; i’m personally already convinced that the normalization approach is the only viable path for JS to making subclassing easier without polluting methods with reentrancy and observable lookups [13:33:27.0000] how long until we define that ~empty~ can coerce into a list [13:34:42.0000] never 😠 [13:36:54.0000] it should coerce into a singleton list with `"Empty"` [13:47:57.0000] shu: which is == 0 I presume [13:48:15.0000] i like that, yes [13:49:22.0000] 😂 [13:49:29.0000] presumably also, ~empty~ is neither truthy nor falsy [13:49:48.0000] `!~empty~` produces `document.all` [13:50:06.0000] and `+~empty~` ofc produces `NaN` [13:50:25.0000] no, those are terrible ideas [13:51:46.0000] maybe we need a new... `void` value to represent a reified empty [13:53:39.0000] and `anything in void` would ofc be false [14:20:58.0000] void in void [14:26:05.0000] touché [14:32:25.0000] v8 has exactly what we need "the hole" 2020-07-10 [07:16:19.0000] i'm going to need an editorial and spec review of https://tc39.es/proposal-upsert/ , added to agenda as requesting stage 3, but unclear a bit on what that means when you need the review. [07:16:37.0000] seems like going towards stage 3 made sense, but we cannot advance it this meeting realistically [07:16:57.0000] slides also cover the recent changes https://docs.google.com/presentation/d/16PtTpuvkTFycaaqkk5XGZRPLNwzUrzBuN9y7VSrGX9k/edit#slide=id.p [07:23:24.0000] devsnek: I made https://github.com/bmeck/proposal-arbitrary-module-namespace-identifiers for `import {"" as foo} from "";` gonna do the spec today [07:23:31.0000] i remember you were asking about it [07:37:44.0000] bradleymeck: nice [07:38:12.0000] the only hard bit is going to be figuring out how to phrase it needs to be representable as valid utf8 [07:40:10.0000] we have infra for valid utf8 thanks to {en,de}codeURI{component} [07:42:10.0000] oh thank god [07:43:14.0000] well in a prose-y way anyway [07:43:52.0000] internal slot X + getter x(), or configurable-readonly property x. Which one is better in the API design? [07:44:42.0000] jackworks: check out AggregateError errors property [07:46:21.0000] devsnek: nah, under the hood i see [[IsUnpairedSurrogate]] which is all i needed really [07:46:58.0000] mathiasbynens: you might know better, is there anything besides surrogates that is a concern when checking if a string in JS is valid utf8? [07:47:23.0000] oh I got the link https://github.com/tc39/proposal-promise-any/issues/38 [07:47:30.0000] thanks I'll read it [07:48:11.0000] bradleymeck: for valid UTF-8, it's just surrogates [07:48:32.0000] mathiasbynens: so a static check that all the code points in a string literal are paired would be fine? [07:50:11.0000] bradleymeck: there are cases where you want to check for the larger set of non-characters but that shouldn't be security-sensitive unless you're doing something weird [07:50:43.0000] mathiasbynens: this is trying to ensure w/e string is valid utf-8 due to wasm integration https://github.com/bmeck/proposal-arbitrary-module-namespace-identifiers#concerns [07:50:55.0000] > Getters are for querying internal state; if there's nothing "internal" about it, a data property seeems more idiomatic to me. [07:50:56.0000] non-characters? [07:51:29.0000] this make sense to me, if the data is designed to be immutable, it might be better to use readonly property instead of slot+getter [07:51:33.0000] bradleymeck: U+FDD0 et al http://www.unicode.org/faq/private_use.html#nonchar4 [07:53:04.0000] mathiasbynens: interesting, Name in WASM allows for those it looks like https://webassembly.github.io/spec/core/binary/values.html#binary-utf8 [07:53:27.0000] bradleymeck: imho everything should allow those, since they can perfectly be represented in utf8 [07:53:31.0000] name is not the same as exports [07:53:46.0000] bradleymeck: but e.g. Chrome's JSON parser/writer didn't until I recently fixed it [07:53:48.0000] so ymmv [07:54:04.0000] mathiasbynens: seems reasonable, this is a spec change just ensuring it is valid utf-8 not that it is sensible [07:54:04.0000] oh i see [07:54:14.0000] bradley you linked to the text format spec in your proposal repo [07:54:23.0000] doh [07:54:33.0000] should be binary format [07:55:01.0000] done [07:55:15.0000] 👍🏻 [07:55:32.0000] mathiasbynens: so only need to iterate and check [[IsUnpairedSurrogate]] it seems, thanks [07:55:57.0000] i still need to fix my utf8 functions in engine262 [07:56:03.0000] i think something is broken in decoding [08:27:01.0000] i figured out why i don't like reading the prose in the spec [08:27:04.0000] its too wide [08:29:15.0000] adding `max-width: 50em` to `p` helps a lot [10:26:18.0000] why is `export {package as import}` valid when 100% you can't have a local binding named package? [10:26:46.0000] i get that it will blow up later, but it seems like left hand side should be an Identifier not IdentifierName? [10:29:17.0000] there's an early error for it [10:29:41.0000] but it is kind of odd that there's an explicit early error rather than just using `Identifier`, not sure what's up with that [10:30:09.0000] from the perspective of a parser that's how you'd parse it [10:30:15.0000] maybe that was the thinking [10:30:40.0000] is it? I feel like you'd want to parse it using `Identifier`, which is a thing you already know about [10:31:02.0000] oh nvm I'm thinking of import not export [10:31:40.0000] import was probably written first and the export mirrored it [10:31:51.0000] yea import goes down to Identifier via BindingIdentifier [10:32:02.0000] so they don't match, which is equally odd [10:32:50.0000] like there's even a note about "The above rule means that each ReferencedBindings of NamedExports is treated as an IdentifierReference." [10:33:56.0000] I guess IdentifierReference is different from Identifier in that it includes `yield` and `await`? but you can't have a local binding named yield or await in a module anyway [10:34:45.0000] when is safari gonna ship #! [10:36:14.0000] unrelated: igalia published a post about Temporal: https://blogs.igalia.com/compilers/2020/06/23/dates-and-times-in-javascript/ [10:38:58.0000] I'm counting the seconds until I can use temporal [10:39:12.0000] but I'm not sure the seconds are correct because I don't have temporal [10:39:23.0000] they won't be after temporal either :( [10:39:34.0000] why not [10:40:09.0000] https://github.com/tc39/proposal-temporal/issues/54#issuecomment-546723710 [10:40:41.0000] 👀 [10:53:32.0000] rkirsling: I'm wondering here, that is the grammar notation for 08.1 in the specs [10:56:03.0000] it sounds like `08.1` is not conforming to the specs [11:01:01.0000] mathiasbynens: if you find time, can you glance to check the algo of https://bmeck.github.io/proposal-arbitrary-module-namespace-identifiers/#sec-module-semantics [11:09:26.0000] bradleymeck: looks good [11:10:32.0000] nice [11:11:25.0000] it goes well with the specs, my bad. I've just found it [11:31:58.0000] rkirsling: https://github.com/tc39/ecma262/issues/2090 [12:16:08.0000] is "async" not an actual keyword? [12:16:17.0000] like of/as/from/etc [12:17:12.0000] devsnek: it is a "contextual keyword" [12:17:20.0000] but no not specy [12:17:58.0000] ecmascript has the most evil grammar [12:19:36.0000] /me stares at bash [12:21:34.0000] bradleymeck: _C_ defined at step 4.b is unused [12:22:35.0000] ok now i just need to disambiguate `async()` and `async () =>` [12:23:08.0000] jmdyck: thanks [12:24:55.0000] devsnek: I remember having to fix that one in JSC [12:25:25.0000] it was painful in the sense that I addressed all of the relevant failures but IIRC it still didn't feel globally perfect [12:26:30.0000] ah no I'm mistaken, it was await as a param name [12:27:03.0000] https://trac.webkit.org/changeset/249925/webkit [12:28:51.0000] (also I guess I'm mistaken in that it seems it wasn't so bad in the end; I think it was just difficult to pull apart the intertwining issues at first) [12:38:08.0000] leobalter: thanks for officially bringing up the discussion [12:38:55.0000] my feelings are sort of like the eval thing -- either option seems okay as long as we've chosen it consciously [12:39:22.0000] rkirsling: no problem, I believe it deserves at least that visibility, even more if I wanted this to be a follow up to the proposal [12:40:15.0000] I'm slightly on the same page for the eval problem, but I tend to prefer it being indirect [12:40:30.0000] as long TC39 makes an opinion, I'd be fine with any outcome [12:40:41.0000] s/opinion/decision [13:00:34.0000] (in the eval case in particular, I'm strongly opposed to King Solomon-ing it into an error, but happy to have either spec or impl be made correct) [14:06:52.0000] likewise [16:48:13.0000] ljharb: if you have a blanket review comment like "reformat" i personally would appreciate not using GH's suggest feature [16:48:20.0000] it makes the threads extremely long and hard to scroll through [16:48:25.0000] is there a way to collapse all of them at once [16:54:17.0000] yeah that's fair feedback; i'll delete most of them [16:55:49.0000] shu: do you know how common it is for finalization groups to use unregister tokens [16:55:51.0000] the intention was to try to do the work myself rather than imposing a burden [16:56:17.0000] shu: k, i left two; one as an example and the other that also fixes a typo [16:56:43.0000] ljharb: yeah, i think suggestions is a well intentioned feature, i just find it so hard to read [16:56:56.0000] understandable [16:56:58.0000] especially since what people end up using them for are typos and other small fixes [16:57:09.0000] the ability to select multiple lines at once helps a ton [16:57:40.0000] devsnek: i don't know [16:58:06.0000] i found an interesting optimization for register() in v8 where it doesn't have to do a runtime call if there's no unregister token [16:58:16.0000] not sure how useful it will be though [16:58:33.0000] is there an example of an overwhelming case? I love suggestions, I just hate the bug where you can't accept them in 262 [16:58:57.0000] (I don't think I've personally had an overwhelming case though) [16:59:20.0000] devsnek: right, the runtime calls have to do with the unregister token map. to flip it around, i'd imagine it's at least also common to *not* have unregister tokens [16:59:23.0000] rkirsling: in the weakrefs PR, every prose paragraph was hard-wrapped, so if i'd done them all there'd have been like a hundred or more [16:59:27.0000] rkirsling: i stopped at like 10 [16:59:56.0000] devsnek: so in that scenario a fast path is probably worth it, but without real world use cases we're always just guessing 2020-07-11 [17:00:08.0000] ljharb: ohhh I see [17:00:20.0000] shu: almost done with the CL [17:00:27.0000] just working on a weird assertion failure [17:01:29.0000] if it doesn't complicate the method significantly, probably fine [18:43:08.0000] jmdyck: does your type analysis currently distinguish between Number values and mathematical values? [18:43:30.0000] urg, that's such a mess [18:43:38.0000] currently, yes [18:43:39.0000] I am reviewing https://github.com/tc39/ecma262/pull/2007 and having the assistance of automated tooling would go a long way [18:43:54.0000] we mix them up in a bunch of places and this PR fixes some but not all of them [18:44:06.0000] it tries to, but has to give up a lot of the time [18:46:17.0000] i suppose i could make a branch that tries to be strict and only targets 2007 for now [18:47:19.0000] What sort of timeline are you looking at? [18:48:40.0000] Eh, there's not exactly any hard deadlines, but this is our highest priority other than the stage 4 stuff and normative PRs, since it touches a bunch of things and keeping it rebased will be a pain [18:48:56.0000] I ask because I am currently doing the review; I'm not going to finish it today or anything, I'm just catching a bunch of things by doing manual type checking [18:49:13.0000] and it occurred to me that a computer would be better at this [18:50:43.0000] wup [18:50:45.0000] yup [21:08:04.0000] I was looking at Array species and it talks about realm records. Is realm related to iframes in browser? Like 2 objects from 2 diff iframe means diff realm? [21:19:47.0000] bendtherules: basically yeah, an iframe is a different realm [21:21:41.0000] Ok. And is it also possible in other common environments, like node? [21:22:08.0000] yep [21:22:14.0000] node has "contexts" [21:22:25.0000] https://nodejs.org/api/vm.html [12:49:06.0000] being able to use declaration in torque reminds me how much i miss it in js [12:49:12.0000] we should definitely add it [12:52:59.0000] devsnek did you... miss a word there? [12:53:09.0000] redeclaration* [12:53:27.0000] as in like `var a; var a;`? [12:53:46.0000] yeah but with lexical declarations too [12:53:56.0000] would the second `a` shadow the old one? [12:54:20.0000] or just reset the ref, so that it can be GC'ed? [12:55:07.0000] basically just modifies the existing binding [12:55:20.0000] there are some nice things you can do with that though [12:56:07.0000] for example `let { a, b } = c()` vs `({ a, b } = c())`` [12:56:43.0000] ts could use it for type rebinding `let a: T = foo(); let a: U = bar(a);` [13:03:39.0000] I see [13:04:49.0000] rust has this too [13:04:52.0000] its very nice 2020-07-13 [17:26:15.0000] :w [17:26:21.0000] oops [11:40:32.0000] devsnek: new variable declarator kind? [11:40:45.0000] bradleymeck: hmm? [11:41:14.0000] def {x,y} = pt; pt.translate(1,1); def {x,y} = pt; [11:41:28.0000] though questions of shadowing get confusing due to JS having hoisting [11:42:01.0000] is that just a re-declareable var? [11:42:04.0000] *let, sorry [11:42:09.0000] yes [11:42:13.0000] that's what i originally suggested [11:42:19.0000] i feel like there's a stage 1 proposal here [11:45:34.0000] agree with bradleymeck on hoisting [11:45:48.0000] seems very confusing given hoisting. which one gets closed over? [11:45:55.0000] shu: i mean, thats the only real complaint left with the repl goal [11:46:31.0000] in other languages it is via source location, which honestly would be fine, but diff problem than repl has [11:48:49.0000] the rule i'm imagining is [11:48:59.0000] if the code would cause a redeclaration error [11:49:04.0000] make it valid [11:49:11.0000] leave everything else untouched [11:49:21.0000] so they point to the same storage? [11:49:37.0000] thats what v8 did for making their repl design doc [11:50:12.0000] i think either they're the same variable or you invalidate the old ones [11:50:19.0000] invalidating seems needlessly annoying [11:50:33.0000] `sudo let x` [11:51:36.0000] ljharb: 👏 [11:52:58.0000] could also reassign consts that way [11:53:22.0000] `sudo eval = undefined` [11:53:26.0000] proposal: make const less constant [11:53:39.0000] free me of linter errors! [11:53:43.0000] proposal: `let const` [11:53:50.0000] also `const mut` [11:54:01.0000] `let let let = 1` gasp a new tier [11:54:20.0000] why is redeclaring important in js exactly? [11:54:34.0000] i think it is just convenient in other langs [11:54:38.0000] that was the point [11:54:50.0000] do these other langs have types and benefit from being able to shadow a same-named declaration with a differently typed one? [11:54:56.0000] I think this is just a repl impl issue [11:55:02.0000] ah, for repls that makes sense [11:55:04.0000] redecl in a static file is bad news [11:55:28.0000] (I'm not representing the discussion here though, that's just my view) [11:56:03.0000] shu: i just hate putting destructuring reassignments in parens [11:56:16.0000] ts users could benefit from the type thing you mentioned though [11:56:27.0000] rust allows that too and its very nice [11:56:30.0000] ohhh that was your motivation [11:56:40.0000] the destructuring thing doesn't seem that compelling to me [11:56:45.0000] the TS one i have to think about [11:57:06.0000] yeah this is like [11:57:11.0000] a nit of a feature [11:57:16.0000] I'm kind of unclear on why type-shadowing wouldn't be dangerous though [11:57:20.0000] which is why i didn't think it warranted new syntax [11:57:47.0000] it might be dangerous in ts due to the laxness of its type system [11:58:01.0000] or maybe taken in stride [11:58:03.0000] rkirsling: the *only* case where it's kind of legit, and probably the one devsnek ran into in Torque, V8's DSL, is where you cast an argument [11:58:20.0000] ah yeah that's the same as rust [11:58:33.0000] oh from something void*-esque to what it really is? [11:58:35.0000] e.g., in pseudo-ish code `function f(xArg: Any) { let x = Cast(xArg); }` [11:58:38.0000] yes exactly [11:58:40.0000] yeah [11:58:51.0000] i don't know of other places where shadowing with different type is a good idea [11:58:53.0000] except you can do `x: Any` and `let x = Cast(x)` [11:59:11.0000] that is far from sufficient motivation for allowing redecls in general imo [11:59:20.0000] yeah its not like the most revolutionary deature [11:59:21.0000] that's kind of surprising even without the redecl though [11:59:23.0000] feature* [11:59:39.0000] that `{ let x = ... x ...;} ` is allowed [11:59:58.0000] yeah actually with JS's parameter scope rules that isn't a redeclaration [12:00:38.0000] its not valid due to tdz though [12:00:46.0000] actually in strict mode its also invalid to declare the name [12:01:16.0000] or maybe all modes [12:01:26.0000] yeah all modes [12:01:30.0000] at top-level function scope sure, but you could block it [12:01:50.0000] can't get around the TDZ though [12:01:57.0000] anyway yeah this is one of those features that's too small to feel justified [12:02:02.0000] yup [12:02:31.0000] we could add it in variables v3 [12:02:49.0000] lol [12:02:54.0000] (`val` and `val mut`, eta 2030) [12:02:59.0000] if this wasn't about redecl and was simply about destructuring assignment to existing bindings then maybe there's something there [12:03:14.0000] but only if it didn't add to the syntax budget [12:03:20.0000] which seems unlikely to achieve [12:03:28.0000] right if you want to separate those two item [12:03:29.0000] items [12:11:31.0000] devsnek if you don't like parens for destructuring you can use `0,` instead [12:11:45.0000] `let x; 0,{ x } = { x: 1 }; [12:11:48.0000] that's almost worse [12:11:58.0000] it's better 'cause it's local! [12:12:01.0000] though it makes me wonder [12:12:03.0000] `void`? [12:12:06.0000] i.e. you don't have to put parens at the end [12:12:16.0000] omg are you kidding me [12:12:34.0000] I am not entirely serious, no [12:12:34.0000] that really binds as `(void { a }) = 1`? [12:12:37.0000] yeah [12:12:46.0000] sad times [12:12:47.0000] assignment expressions are very low precedence [12:12:57.0000] oh god the comma [12:13:32.0000] what a truly horrific invention [12:14:08.0000] you know I was pretty much joking but looking at it it's kind of growing on me [12:14:14.0000] that "horrific invention" is the basis of minifiers, have some RESPECT [12:14:25.0000] lolol [12:15:35.0000] ok new proposal idea [12:16:08.0000] somehow allow `void AssignmentExpression` [12:18:53.0000] you could allow it in statement position easily enough, I think [12:19:04.0000] tricker in expression position [12:19:19.0000] or, well, it might be easy I'm just less sure if the obvious thing would work [12:19:36.0000] and can more readily convince myself it works in statement position [12:19:45.0000] Bakkot: lol I shared that with a colleague and he was like "if only it worked for `() => 0,{ bar: 42 }`" [12:19:52.0000] rkirsling ha [12:20:16.0000] that one I am happy to write the parens [12:20:29.0000] and also happy that comma doesn't work [12:20:48.0000] agreed, just made me laugh [12:21:55.0000] that comma works perfectly don't @ me [13:47:55.0000] shu: are you worried about people setting really high maximum values on resizable buffers in order to get around the resize limit [13:48:11.0000] s/resize limit/maximum size limit/ [13:49:22.0000] This is not slack but I basically need some @channel for the broad message: [13:49:28.0000] i feel like the primary use case for resizing is that you don't know what the maximum will be [13:49:29.0000] if you consume Test262, please read this: https://github.com/tc39/test262/issues/2699 [13:49:40.0000] devsnek: not really, why? [13:50:03.0000] like i said above [13:50:21.0000] i don't think wasm requires a maximum limit either [13:50:52.0000] it does for shared [13:51:13.0000] but that doesn't answer why i might be worried about people setting really high maximum values? [13:51:37.0000] cuz that's how you would get around the problem [13:52:00.0000] and browsers might not want people falling into that pattern [13:52:03.0000] idk [13:52:38.0000] i don't understand the full concern, that because applications do not know ahead of time what their max buffer size is, they will reserve something huge? [13:53:06.0000] and that reserving something huge is bad because... they cause their own application to run out of address space? [13:53:12.0000] right, that seems like a bad pattern [13:53:41.0000] that seems no worse than if someone wants to do that today, they would either commit to a huge buffer today [13:53:48.0000] or they keep making new buffers and copying [13:53:54.0000] well the point of resizing is that you don't commit to huge [13:53:57.0000] i don't get this [13:54:12.0000] you commit to the address range, but you do not commit to the actual memory [13:54:30.0000] what do you not get? did you read the motivation? [13:54:40.0000] yeah [13:54:54.0000] is there a part of the motivation that you don't understand, or you disagree with the motivation? [13:54:55.0000] ok so for example [13:55:01.0000] i have this package called earl [13:55:11.0000] that converts js values into erlang term format buffers [13:55:32.0000] ideally you start smallish and only grow if needed [13:55:55.0000] the main performance hit rn is growing, i have to allocate a new buffer and copy everything over [13:56:02.0000] resizing sounds great [13:56:14.0000] for that use case, is it important that you keep the identify of the ArrayBuffer the same? [13:56:21.0000] no [13:56:29.0000] then you should be using transfer() which i am reviving as part of this proposal [13:56:36.0000] Resizable buffers are for in-place grwoth [13:56:52.0000] if your issue is you need zero-copy growth, realloc semantics are sufficient, and that should be used instead [13:57:19.0000] so realloc is possible? [13:57:29.0000] what do you mean by "possible"? [13:58:19.0000] your explainer says that realloc is bad because xyz and so you want to avoid it [13:58:27.0000] which is fine [13:59:10.0000] but if transfer doesn't avoid it [13:59:16.0000] then why are you avoiding it with resize [14:00:07.0000] because there are two use cases [14:01:08.0000] 1) an in-place growable buffer like wasm has, so that an underlying buffer can grow without requiring buffers and TA views be remade. that use case requires the identities of the buffers and TAs to stay the same. related is the webgpu re-pointing use case [14:01:50.0000] 2) realloc for arbitrary growing and shrinking, avoiding copying where possible. this use case doesn't care about the identity of the buffers and TAs and can make new JS objects if needed [14:02:27.0000] i don't get why these are exclusive [14:02:52.0000] semantically, they are not. implementation and security experience says otherwise [14:02:59.0000] is there some inherent thing about security and the identity of the object i'm missing [14:03:25.0000] the implementation and security thing boils down to what i said in the explainer, that you want to be able to implement the first use case as not moving the underlying data pointer [14:03:39.0000] but if they *can* move [14:03:42.0000] if the underlying data pointer can move, you have perf cliffs, extra security risk to make sure you don't have stale data pointers, etc [14:04:10.0000] ah ok [14:04:22.0000] detaching was a huge security bug farm [14:04:45.0000] so its specifically, moving with the same object identity [14:04:51.0000] if you allow general data pointer moves, which is a much larger surface than "data pointer or null", it puts security folks on edge [14:04:53.0000] yep [14:05:00.0000] got it [14:05:16.0000] ok one other question [14:05:26.0000] shoot [14:05:38.0000] you mention the wasm detach problem in the motivation section [14:05:47.0000] about how you have to check every time you read if the buffer was detached [14:06:09.0000] is that solved with this? i didn't see anything but maybe i missed it [14:06:50.0000] good question, i didn't outline the solution in the explainer since. it's solved with the JS integration exposing a new API that uses growable buffers [14:07:06.0000] so its still on wasm to provide some sort of hook, ok [14:07:12.0000] no hook [14:07:30.0000] but right now, when you ask for a wasm memory, you get an AB back. i doubt that can be changed to return a ResizableAB and be web compat [14:07:45.0000] it couldn't be a resizableAB anyway [14:07:51.0000] wasm memories don't have to have an upper limit [14:08:05.0000] there can be a new API where the wasm JS api gives you a ResizableAB, which emscripten would use [14:08:12.0000] in practice there is, surely, set it at that [14:08:35.0000] i doubt most compilers emit an upper limit [14:08:41.0000] the emscripten team has told me this would solve their issue, at least [14:09:29.0000] i imagine not having a limit can be reported as like, 3gb when exposed to JS [14:09:45.0000] that can a contract for emscripten output, i imagine [14:09:49.0000] but then 3gb of your heap is reserved [14:10:06.0000] if you did that more than once in node you'd get an OOM [14:10:09.0000] that is not observable? and it also is in practice [14:11:41.0000] where possible wasm memory bounds checks are implemented with guard pages + segfault handler, and doing so reserves the virtual memory range [14:12:17.0000] perhaps you are confusing virtual memory reservation and getting them backed by physical memory [14:12:47.0000] if you make two reservations [14:12:56.0000] each 3gb or so [14:13:16.0000] if you are running the engine in 32bit, you've exhausted your vm range and are shit out of luck [14:13:24.0000] if you are running the engine in 64bit, you're probably fine [14:13:43.0000] but the v8 heap is only so large [14:13:52.0000] what do you mean by the v8 heap? [14:13:59.0000] the GC heap is not the process heap [14:13:59.0000] the place where all the stuff is stored [14:14:07.0000] there are several places :) [14:14:19.0000] the place where all the heap objects are stored [14:14:19.0000] buffer backing stores are not allocated on the GC heap [14:14:30.0000] oh [14:14:33.0000] interesting [14:14:37.0000] i don't think any engine does that? [14:15:12.0000] so they're just out in process memory? [14:15:33.0000] it's hookable by the embedder depending on where they need the buffer to be, but yes they're externally managed [14:15:37.0000] could be mmap'd directly [14:15:43.0000] interesting [14:15:54.0000] it's hard to get a contiguous address range otherwise [14:16:10.0000] i just figured most arraybuffers were usually small [14:16:16.0000] the GC heap can't be reserve contiguous gig+ ranges just in case an app needs it, for instance [14:16:18.0000] nope [14:16:29.0000] i think there's probably a bimodal distribution of buffer sizes [14:16:34.0000] given asmjs and wasm [14:16:58.0000] well wasm in itself is probably bimodal [14:17:13.0000] its either tiny canvas app or firefox running inside firefox [14:17:31.0000] anyway this is starting to make more sense [14:17:38.0000] thumbs up [14:17:57.0000] gotta run, bbl [14:18:00.0000] 👋🏻 [14:22:15.0000] leobalter: I consume test262 in ~half a dozen projects and they will all need to be updated to point to main instead of master unless github supports redirecting branches, but I don't expect that to be all that much work [14:22:56.0000] Thanks Bakkot! Idk how to name it in that list so I'll have your name :) [14:22:59.0000] Bakkot: leobalter: iirc one thing you can do is point to "HEAD" and it'll always point to the default branch [14:23:17.0000] that's not the same as github supporting redirection for web URLs (which is still critically important) but it should suffice for tooling [14:23:34.0000] ljharb: too many thinks directly pointing to master [14:23:39.0000] in the import process [14:23:45.0000] or linking (which is worse) [14:27:28.0000] leobalter: what i mean is, the tools can all update from master to HEAD and they'll work moving forward, regardless of the default branch name (or the availability of an alternate name) [14:30:45.0000] FWIW is to set a plan to completely delete the master branch, so I need people to know we are doing this change [14:43:13.0000] I think it might be better to lean harder on GitHub for updates on how soon they plan to deploy redirection [14:45:52.0000] i agree [16:48:20.0000] so here's a question [16:48:38.0000] if we're inclined to discouraging direct eval [16:48:59.0000] how come we let it apply to lexical scopes too? [16:50:17.0000] seems like some bud-nipping could've been done when introducing let/const [16:50:50.0000] making direct eval do something more complicated than evaluate the code it's passed in the context it's in seems like it would be worse [16:50:56.0000] at least the current state is possible to explain [16:51:40.0000] hmm it's possible I haven't thought it through enough but [16:51:55.0000] I was just thinking in terms of like [16:52:54.0000] if vars hoist through blocks then it would seem like direct eval's visibility could be similarly scoped to the containing function [16:56:20.0000] I mean I guess that would amount to creating a more awful thing just for the sake of discouraging its use though 2020-07-14 [17:24:58.0000] yeah [17:25:10.0000] currently it is very clean, it's just that the thing it does very cleanly is bad [17:25:18.0000] (at least in most contexts) [17:25:36.0000] it is not clear that making it less clean purely for the sake of discouraging it would be an improvement [17:27:45.0000] mhm [17:40:38.0000] Bakkot: I'm working on 2007, but it's slow going. [17:46:15.0000] jmdyck sweet [17:46:27.0000] let me know if there's anything which would help on my end [17:46:49.0000] e.g. if you find there's a particular batch of errors which is impeding further progress I'd be very happy to fix those [17:47:00.0000] I should probably just go ahead and fix the ones I've already identified [17:47:26.0000] it needs a rebase to master, and there are merge conflicts [17:47:49.0000] mostly steps-with-ids [17:59:17.0000] (i had to rebase my copy of 2007, because my pipeline only targets the latest master. So that isn't impeding my progress, but when I'm done, I'm probably going to submit a PR against 2007, so that should be easier of it's up-to-date.) [19:00:10.0000] And there are some choices that strike me as odd. E.g., look at SplitMatch's _q_ parameter. The preamble declares it as an integral Number, and the two call-points add some stuff to ensure that it is indeed a Number. But the SplitMatch only ever uses ℝ(_q_). So why not just say it's a mathematical param, and eliminate the conversions to and from Number? [20:21:15.0000] Bakkot, you've got me one of the trickiest reading of the grammar today. https://github.com/tc39/test262/issues/427#issuecomment-657937019 [20:21:24.0000] so please, HALP [20:23:47.0000] leobalter oh man that's an old issue [20:23:56.0000] I will take a look [20:27:39.0000] leobalter: you say in that issue "here comes a trick: IsUnresovableReference returns true becase the base value component of V is still the Global Env Record." [20:27:46.0000] should that "true" be "false"? [20:34:38.0000] That's a part I'm not fully sure. I formulate this question better at the last comment in the issue. [20:34:52.0000] my reading of the spec is that it is false [20:34:55.0000] I am writing up a comment [20:34:58.0000] I believe IsUnresovableReference returns false, because the Reference is set [20:35:14.0000] but the short version is, your reading of the spec is correct and this is a bug in ecma-262 which never got fixed [20:35:56.0000] I'm so glad I decided to review that old issue [20:41:57.0000] commented and opened https://github.com/tc39/ecma262/issues/2093 [20:42:11.0000] leobalter yeah, thanks for catching this [20:42:18.0000] there's still a bunch of spec bugs :( [20:42:31.0000] but we're making some progress I think! [20:42:40.0000] I'll add this case to the Test262 report for the fun parts. [20:43:12.0000] this is not simple to fix, basically we need to catch several Runtime Evaluations and add a HasBinding check before performing PutValue [20:47:35.0000] leobalter the fix proposed in the esdiscuss thread is to add an additional check for the existence of the property in SetMutableBinding [20:47:45.0000] for both object and global environment records, I guess [20:48:27.0000] actually just for object I guess, since the global one defers to the object one for non-lexical bindings [20:49:47.0000] I believe for the Object we'd need to carry on some flag to tell this binding should be there [20:50:04.0000] at least something before PutValue for sure [20:50:47.0000] there's no way to get the reference to exist in the first place without it being there [20:51:06.0000] that is to say, I don't think there's a "this binding should not be there" case to distinguish from the "this binding should be there" [21:02:02.0000] Bakkot: perhaps this: https://github.com/tc39/ecma262/compare/master...leobalter:2093/putvalue-strict-check?expand=1 [21:02:10.0000] But I need to verify what else is calling PutValue [21:06:18.0000] I opened a draft PR for now https://github.com/tc39/ecma262/pull/2094 [21:07:00.0000] This might be wrong, but so far it seems ok'ish. I need to continue checking everything that goes through PutValue tomorrow [21:08:15.0000] that probably works [21:08:22.0000] though, ugh, this is observable because of proxies [21:14:05.0000] and the proxy can have side effects [21:14:10.0000] proxies are the worst [21:21:04.0000] Indeed [11:26:21.0000] that feel when U+2028 is allowed in strings [11:58:53.0000] why doesn't Map.prototype.delete remove `p` from `entries` [12:04:23.0000] huh? [12:07:49.0000] "The value empty is used as a specification device to indicate that an entry has been deleted. Actual implementations may take other actions such as physically removing the entry from internal data structures." [12:09:17.0000] Map.prototype.clear says: "The existing [[MapData]] List is preserved because there may be existing Map Iterator objects that are suspended midway through iterating over that List." [12:09:28.0000] maybe the same reason applies to Map.p.delete [12:10:01.0000] i think the clear one is about the actual identity of the list [12:10:03.0000] not the items within [12:14:35.0000] Hm, %MapIteratorPrototype%.next extracts _m_.[[MapData]] every time it's called, so it seems like neither the identity of the List nor the 'persistence' of its entries are important [12:16:23.0000] no, changed my mind. [12:17:39.0000] persistence of entries means that if you 'delete' while iterating, [[MapNextIndex]] will still point to the 'next' entry [12:18:54.0000] if 'delete' removed an entry from the List, then [[MapNextIndex]] would 'skip' if you delete while iterating. [13:43:34.0000] Bakkot: my analysis is uncovering some other (2007-independent) problems [13:44:15.0000] jmdyck I am not surprised [13:44:19.0000] with numbers, or more generally? [13:47:01.0000] E.g. ToInteger can return +/- infinity, but it seems to me that most callers aren't dealing with that possibility. [13:49:37.0000] at a quick glance it looks like most callers immediately clamp the result with min or max, which is fine [13:49:49.0000] (min and max explicitly include +/- infinity in their domain) [13:50:05.0000] but I could definitely believe some don't, and it certainly should not claim to return an integral number [13:51:20.0000] also, that doesn't work when you try to shift things over to mathematical values [13:52:06.0000] what is 2007 [13:52:20.0000] PR #2007, mathematical values [13:52:28.0000] ah [13:52:54.0000] hm, well, it works fine if we say that our mathematical values are augmented with +/- infinity, but there's is some subtlety there [13:54:20.0000] "Note that the mathematical value of non-finite values is not defined", so "the mathematical value of ? ToInteger(_x_)" is typically not defined [13:58:36.0000] Yeah; I'll bring that up with the other editors. Personally, given this evidence, I am inclined to say that you are allowed to take the mathematical value of infinities (but not NaN), though that may cause trouble elsewhere [13:59:05.0000] i would be inclined the same, pending the trouble it will probably cause elsewhere [14:33:13.0000] maybe we want to introduce extended mathematical values [14:33:22.0000] which is the reals and also +/- infinity [14:33:30.0000] but keep this distinct from regular mathematical values [14:33:50.0000] and only ever do comparisons on things in this class [14:34:02.0000] (I know we do actual arithmetic in some cases and we'd probably change those.) 2020-07-15 [11:15:55.0000] could we remove the year from https://tc39.es/ecma262/ builds [11:18:47.0000] i'm tired of people asking what's new in es2021 [11:27:18.0000] devsnek: like specifically es2021? or es20XX in general? [11:27:34.0000] rkirsling: well ES20XX in general [11:27:56.0000] lol you think they'll stop asking it because that changes? [11:28:13.0000] but yeah sure, that seems fine to me - it could also say "ECMAScript® 2021 Draft" or something better [11:28:14.0000] i mean it's always the same [11:28:16.0000] er I guess what I meant to ask is, are you wanting to abolish year-based naming or just the draft label? [11:28:21.0000] they link to the living spec [11:28:30.0000] and ask "what's new in es2021" [11:28:40.0000] can we put some sort of template variable there [11:28:40.0000] yeah the location of the word Draft seems like it might invite confusion [11:28:50.0000] set it to "Living" for gh pages builds [11:28:59.0000] and whatever the relevant year is for archival builds [11:29:10.0000] but we do have ratified yearly releases so it seems appropriate to say that it's moving toward the next snapshot... [11:29:34.0000] yeah nothing is *incorrect* [11:29:55.0000] it just confuses people [11:30:15.0000] I suppose Living seems okay too I suppose if it weren't confusing for editors [11:30:23.0000] oops proofreading [11:30:36.0000] but ljharb is right, those blog posts aren't going anywhere :P [11:30:51.0000] what does html label it? [11:31:21.0000] how does html label itself or ecma262? [11:36:04.0000] how does html's living standard label itself [11:36:35.0000] HTML - Living Standard [11:36:47.0000] Last Updated XYZ [11:37:08.0000] although I suppose they also don't have HTML2021 [11:37:43.0000] does w3 still republish it as a recommendation every year [11:47:24.0000] "Living Standard" sounds fine to me [11:51:59.0000] honestly it seems fine to ask what's in es2021 [11:52:24.0000] the yearly editions are a reasonable time for people who are not super involved to catch up with what's happened lately [11:52:32.0000] rather than it being a constant thing [11:53:18.0000] yup [11:56:06.0000] Bakkot: it's out of sync [11:56:19.0000] its not annoying when people ask what's in es2020 [11:56:28.0000] you can just point them to the paragraph in the introduction [11:56:28.0000] ah [11:56:41.0000] its that they think es2021 exists [11:56:51.0000] YEAR+! [11:56:53.0000] 1* [11:57:12.0000] hmmmmmm [11:58:10.0000] I still feel like the biggest problem is that the Draft bit is currently rather overlookable [11:59:11.0000] if Draft came immediately after 2021 it'd already be clearer, like ljharb suggested [11:59:34.0000] whatever works [11:59:45.0000] imo it should say "living" but i'm not an editor [12:01:52.0000] i like living [12:02:13.0000] i think it should still have 2021 somewhere but maybe not in big letters [12:02:30.0000] maybe at the bottom :P [12:03:33.0000] "i like living" is a good quote [12:03:43.0000] @horsejs [12:07:40.0000] once years ago, while walking around union square in SF, a homeless man said to me "dying must be easy because living sure is hard" [12:07:52.0000] i thought that was extremely profound at the time [12:08:16.0000] years later i think i found out it was 50cent lyrics or something [12:08:25.0000] lol [12:10:10.0000] still could be profound :-) [12:10:21.0000] Death's gotta be easy 'cause life is harder, yeah, yeah [12:10:21.0000] Death's gotta be easy 'cause life is hard [12:10:21.0000] Death's gotta be easy 'cause life is harder, yeah [12:10:37.0000] https://www.youtube.com/watch?v=WbPvDBGN3HM [12:12:24.0000] ljharb: very true, though at the time i thought the man was philosophizing himself 2020-07-16 [19:34:40.0000] I wonder if there's any point to implementing atomics and sab in engine262 [19:34:56.0000] could maybe validate some of the logic [19:38:17.0000] you aren't currently using generators in engine262, right? [19:41:01.0000] if so, it is probably not that much work to add multithreading; you just add a babel transform which turns every AO into a generator, wraps every call to an AO so that it invokes and consumes the whole generator and gives you the return value, and wraps every expression with `yield` [19:52:52.0000] Bakkot: I use generators to implement generators [19:53:45.0000] it doesn't bubble through AOs though [19:53:50.0000] kind of a mess [19:56:40.0000] hmm [19:56:47.0000] step one implement generators from scratch [19:56:51.0000] lol [19:56:57.0000] step two implement multithreading by making everything a generator [19:57:44.0000] well I was thinking, I might not be able to test actual multithreading but I could at least test that the spec steps generally make sense [19:58:29.0000] I am also working on a bytecode evaluator (called "boost"), I could do more in depth validation with that if I ever finish it [19:58:55.0000] designing a bytecode for JS is a fun exercise [19:59:19.0000] mostly the try/finally bits [19:59:29.0000] took me a good while to realize new expressions can be two opcodes [20:00:36.0000] I do try/catch by pushing an instruction pointer and current stack depth into an array [20:01:17.0000] instruction pointer of the catch block anyway [20:01:26.0000] doesn't support finally blocks yet [20:01:30.0000] catch is pretty easy, finally is somewhat trickier [20:01:43.0000] getting finally right was like 25% of the entire effort of building the VM when I tried this [20:01:48.0000] I guess it's a desugaring problem [20:01:54.0000] yup [20:01:58.0000] try finally = catch that throws at the end [20:02:15.0000] try catch finally = try catch that catches and then catch that throws [20:02:16.0000] maybe [20:02:48.0000] `try { } catch (e) {} finally {}` is 100% equivalent to `try { try {} catch (e) {} } finally {}` [20:03:02.0000] that's fun [20:03:31.0000] actually wait it has to deal with return instructions too [20:03:41.0000] yeah return and break are the part that make this hard [20:03:50.0000] I guess you have to push a fake return location [20:04:00.0000] let me see if I can get permission to open source the fuzzer I wrote for this [20:04:06.0000] ooo [20:04:22.0000] (it's the obvious thing you'd do if you set out to write a fuzzer for this problem, nothing special) [20:04:39.0000] (just I have already written it) [20:05:04.0000] I tell myself I'll start fuzzing after I pass all of test262 [20:05:09.0000] haven't gotten that far yet [20:05:25.0000] the fun cases are stuff like `x: try { return 0; } finally { if (Math.random() < 5) break x; }` [20:05:54.0000] `< .5`, not 5 [20:06:12.0000] I haven't done labels yet either [20:06:22.0000] I guess that won't be too hard to add [10:17:33.0000] rkirsling: still failing like 10k tests but looking pretty good in terms of test262 coverage https://gc.gy/62624842.png [10:17:47.0000] er [10:17:49.0000] rwaldron: ^ [13:06:01.0000] I feel like this might've been brought up before but it's weird that return is sometimes an await and sometimes not [13:06:16.0000] in async vs async generator [13:07:20.0000] hm, i would assume it never needs the await [13:08:31.0000] it's better for it to include the await [13:08:34.0000] cuz of try/catch [13:10:14.0000] in the spec? [13:11:54.0000] I mean so you don't need to write `return await` [13:13:34.0000] right but you might not want the await [13:14:31.0000] the way it works in async function imo is the right way; i think there was discussion about this for async generators late in the process, but i don't remember the outcome [13:33:15.0000] I know we discussed it for `yield`, see https://github.com/tc39/proposal-async-iteration/issues/93 [13:34:55.0000] I would guess that `return` implicitly unwraps in async generators so that it matches `yield` [13:34:58.0000] it is a bit odd though [13:36:35.0000] oh, wait, that happens because the value from `return` isn't going to get wrapped in a promise [13:38:18.0000] if `return` didn't implicit await you could end up with `{ done: true, value: [a promise] }`, which would be weird [13:38:30.0000] (at least, I assume this is the reason) [13:39:01.0000] ah right, yes, that was the reason [13:39:17.0000] that doesn't have to be an await [13:39:21.0000] iirc, i'd have preferred syntactically requiring `return await`, but instead we went with implicit await [13:39:31.0000] it could be a `.then(fulfill)` [13:39:40.0000] pushing the error to the caller instead of the returner [13:40:12.0000] that would be weirder still [13:40:29.0000] it makes more sense to me than the await [13:42:14.0000] actually wait maybe I don't understand the proposal [13:42:46.0000] what would `(async function*(){ return Promise.reject(0); })` return? [13:42:56.0000] (and the first couple of `.next`s) [13:43:07.0000] idk off the top of my head [13:43:12.0000] i could plug my idea into engine262 in a bit [16:56:21.0000] bradleymeck: did you have a repo for the arbitrary-module-specifiers proposal? [16:56:30.0000] could find it on tc39/proposals 2020-07-17 [17:01:35.0000] Bakkot: https://github.com/bmeck/proposal-arbitrary-module-namespace-identifiers [17:01:35.0000] it never made it to stage 1, but https://github.com/bmeck/proposal-arbitrary-module-namespace-identifiers has it and spec text [17:01:48.0000] it gets merged on stage 1 from my previous exp [17:02:00.0000] oh i thought it had stage 1 [17:02:24.0000] missed deadline last time [17:02:41.0000] ah [17:02:52.0000] really the only confusing bit is the utf8 verification [17:03:05.0000] that's like a stage 3 concern though [17:03:09.0000] can wait until 2025 to figure that out [17:03:15.0000] rest is kind of odd syntax but seems fine [17:03:51.0000] devsnek: it was already checked by mathiasbynens and it looks like we only need to be sure it doesn't have unpaired surrogates [17:04:03.0000] makes sense [17:04:33.0000] in entirely unrelated news, i added numeric separators to engine262 [17:08:10.0000] fun fun! [17:08:49.0000] i'm just putting off the stuff i actually need to fix like assignment patterns [17:17:06.0000] i can feel ya, i was using an AST and noticed I couldn't differentiate MemberExpression as Reference vs Value in it and just took a break from porting some stuff [17:23:45.0000] that is a distinction Shift makes! [17:23:57.0000] and yeah, forbidding unpaired surrogates is the only necessary thing there [17:24:14.0000] which we should do, I feel strongly [17:26:09.0000] bradleymeck actually, on that note, do we maybe want to constrain Abstract Module Record to require valid unicode for specifier names? [17:26:22.0000] doesn't affect ES currently, afaict [17:26:42.0000] Bakkot: shift does not differentiate that to my knowledge? cause that is what i was dealing with [17:27:02.0000] and I doubt anyone is using wasm modules with unpaired surrogates in their specifier names [17:27:08.0000] Bakkot: I think it would be fine to limit those names [17:27:17.0000] Bakkot: unpaired are invalid in wasm [17:27:31.0000] thats the only real reason i care [17:27:44.0000] but non-characters are supported so 🤷 [17:27:57.0000] bradleymeck: shift distinguishes MemberAssignmentTarget and MemberExpression [17:28:01.0000] is that not what you are looking for? [17:28:17.0000] `delete THIS.SHOULD.BE.A.REF` [17:28:17.0000] re: wasm, sweet [17:28:22.0000] ahhh [17:28:37.0000] delete is weird, yes. I could see an argument for changing that, actually [17:28:38.0000] also for calls [17:28:46.0000] not so much for calls though [17:28:47.0000] since you want to know which base gets the `this` [17:29:11.0000] hm, hm [17:29:19.0000] x.y() => call { callee : member expression : {x, y} } [17:29:27.0000] I guess I would prefer to fix that via an explicit membercall node type, if we wanted that [17:29:40.0000] so you have to convert member expressions to always be refs and then unwind it depending on exterior position [17:29:54.0000] 🤷 every AST has its compromises [17:30:07.0000] not like there is a univerally perfect solution [17:30:37.0000] Bakkot: re: banning non-UTF names, probably just a normative PR? [17:30:40.0000] yup [17:31:17.0000] in advance of the proposal, probably [17:31:19.0000] some of the syntax productions used in these areas are a big questionable too but i'm in no rush to fix that [17:31:29.0000] Bakkot: I'd welcome an abstract op [17:31:55.0000] honestly just a fn that complains about if a string is not fully unicode would be great [17:32:45.0000] if you open a normative PR using such an AO and leave its definition as a TODO I or someone else will fill it out if it gets consensus [17:40:17.0000] also would back a `String.prototype.isValidUnicode` proposal, which I seem to recall discussing at some point [17:40:20.0000] maybe with mathiasbynens [17:40:33.0000] maybe we just need a new string type [17:40:37.0000] (would also accept `String.isValidUnicode(foo)`) [17:40:43.0000] we're adding new numbers, new time stuff, etc [17:40:50.0000] time for new strings [17:42:37.0000] Bakkot: i vaguely prefer string.isValidUnicode since it coercing seems fine [17:42:49.0000] /me stares angrily at Buffer in node [17:43:12.0000] wfm I guess [17:44:26.0000] we should put the text encoding api in ecma262 [17:45:26.0000] weren't people objecting to that [17:45:42.0000] i'm sure someone somewhere would object to that [17:56:50.0000] I think people objected to that yes [17:56:53.0000] it has been raised [22:34:04.0000] Bakkot: re: `String.prototype.isValidUnicode`, I remember that! annevk was involved too. I think the name we had in mind back then was `.isWellFormed` or some such [23:50:28.0000] Thanks for the ping, yeah, that's something I'm interested in [23:51:21.0000] It would let me close https://github.com/whatwg/encoding/issues/174 [05:51:00.0000] mathiasbynens: i can make a proposal if none exits? [05:51:08.0000] its a tiny op [05:54:26.0000] bradleymeck: i can't find the relevant github thread anymore (not sure which repo it was on), but iirc the general sentiment was that this is easy enough to polyfill [05:55:23.0000] mathiasbynens: with arbitrary module namespace names the op would be in the spec anyway [05:55:28.0000] and the polyfill is a pain to explain [05:57:31.0000] bradleymeck: https://github.com/whatwg/encoding/issues/174#issuecomment-480735701 [05:58:22.0000] bradleymeck: to be clear, I'm not opposed! this was just the pushback I anticipated. it certainly keeps coming up regularly, so maybe we should just do it now [05:59:35.0000] mathiasbynens: if we are limiting names and we have the op, I want it just because I can point to tests in node that do fail to actually test this [05:59:54.0000] streams of various kinds often just do body = ""; on('data', _ => body += _) [06:00:00.0000] and that is... not bueno [07:14:21.0000] Bakkot: i'm leaving it at https://bmeck.github.io/proposal-arbitrary-module-namespace-identifiers/#sec-isvalidunicode but it is extracted [07:14:38.0000] we just don't use it anywhere right now so no ECMA262 PR [07:15:58.0000] feel free to steal and make a PR about abstract module namespace names [07:50:42.0000] Bakkot: so basically the async generator behaves the same way *except* you have to explicitly `await` yields and returns to catch the exceptions [07:50:48.0000] so probably not web compatible [09:41:07.0000] Bakkot you're one of my best references for syntax grammar, can you help me and caiolima on this one, please? https://github.com/tc39/proposal-class-fields/pull/313#issuecomment-660078419 [09:50:57.0000] leobalter I agree with your interpretation, though not your proposed fix [09:50:58.0000] will comment [09:51:48.0000] I don't like how long my proposed fix is, and I'd love to make it _smarter_ [09:54:26.0000] "It is an early error if you try to delete a private field" ez [09:59:32.0000] leobalter commented [10:30:50.0000] bradleymeck mathiasbynens: fwiw, while I think "is easy to polyfill" can be a reasonable argument against a proposal, my position is that it's usually not a good argument when the thing being proposed is a single primitive operation [10:31:01.0000] and I think "is this string valid unicode" is a single primitive operation [10:31:15.0000] I think it's worth bringing to committee on that basis [10:35:51.0000] also i think "easy" needs to not just mean "easy for an expert"; i'd bet most people can't easily polyfill "is this valid unicode" [10:44:44.0000] yeah that's also a fair point [10:44:56.0000] ljharb: that's actually pretty easy to do [10:45:06.0000] michaelficarra it's easy if you know what surrogate pairs are [10:45:13.0000] which most don't [10:45:14.0000] how many JS programmers know what surrogate pairs are? [10:45:19.0000] he didn't say UTF-16, he said Unicode [10:45:38.0000] the way that JS strings fail to be valid unicode is by having unpaired surrogates [10:45:45.0000] don't roll your own unicode [10:46:12.0000] i've also bet most users don't have any idea that the length of 💩 is 2 [10:46:15.0000] *i'd [10:46:24.0000] no one ever takes the length of a poop emoji [10:46:27.0000] so it doesn't matter [10:46:35.0000] devsnek: you can't be serious [10:47:00.0000] emoji usage is very high, and code that splits strings might end up with half poos [10:47:02.0000] ok unless you're twitter [10:47:20.0000] or 3/4ths of a flag [10:47:21.0000] twitter's definition of 'the length of string' is pretty interesting [10:47:32.0000] "Later in 2017, Twitter increased the maximum Tweet length from 140 to 280 Unicode code points... except that code points U+1100 HANGUL CHOSEONG KIYEOK upwards now counted double. This effectively divided Unicode into "light" code points and "heavy" code points." [10:48:24.0000] though I vaguely recall for a while they were only making that distinction client-side, and server-side they were using the "number of unicode code points" definition [10:48:29.0000] is that the point at which you flip between letters and glyphs [10:48:35.0000] i mean, there's definitely some tweets that are heavy and some that are light [10:48:48.0000] what is this "letter" vs "glyph" distinction you allude to [10:48:56.0000] probably the wrong words but like [10:49:08.0000] lol devsnek you are like little baby [10:49:13.0000] you need more letters in english to make a word than you do in japanese [10:49:53.0000] ideographs is the word you're looking for [10:50:07.0000] aha [10:50:22.0000] i remember (before the 280 char bump, at least), you could tweet a lot more words in chinese/japanese than you could in english for that reason [10:50:23.0000] there is not a point where unicode switches from being phonetic letters to being ideographs [10:50:28.0000] they are mixed, alongside other symbols [10:50:40.0000] ^ [10:50:55.0000] well there goes my theory [10:51:48.0000] i mean ideographs are also kinda phonetic [10:52:07.0000] yeah also there is not a clean distinction between "ideographs" and "phonetic letters" [10:52:09.0000] japanese is straight up mixed with syllabaries [10:52:16.0000] but even in chinese, we use some radicals only for their sound [10:52:19.0000] devsnek: here's a good reference: https://en.wikipedia.org/wiki/Plane_(Unicode)#/media/File:Roadmap_to_Unicode_BMP.svg [10:53:56.0000] that's just the BMP [10:55:14.0000] i think its time we assign each english letter its own meaning [10:55:28.0000] F and I are already done [10:55:29.0000] "English" letter...? [10:55:37.0000] letter used in english [10:55:41.0000] wherever they came from [10:56:33.0000] is ö an english letter? [10:56:39.0000] I guess that depends on whether you work for the New Yorker [10:56:44.0000] lol [10:57:46.0000] if `&` is a letter it has a meaning [10:57:49.0000] oh you mean like þ [10:58:27.0000] (well, "&" has meaning either way I guess, just it only counts towards this project if it is a letter) [10:58:50.0000] Bakkot: unfortunately, Unicode doesn't consider & a letter [10:58:57.0000] unfortunate [10:59:04.0000] yeah that one's really questionable [10:59:46.0000] if æ is a letter, & should be, too [11:00:38.0000] "&" is funny because sometimes it is its own word and sometimes it is part of one, like "&c" [11:00:51.0000] though I guess that is a lot of letters work... [11:01:11.0000] what is &c [11:01:47.0000] oh an abbreviation of et cetera [11:01:50.0000] never seen that before [11:02:53.0000] iirc that's the origin of "et cetera" [11:03:01.0000] or maybe it's the other way around, i dunno [11:04:36.0000] et was "merged" to & over time, you can see a lot of cool examples of the progression [11:04:38.0000] "et" is the origin of "&" [11:04:42.0000] ahhh k [11:05:19.0000] which is why I say that æ being a letter implies & should be too [11:05:41.0000] its a codepoint [11:05:49.0000] good enough right [11:06:53.0000] devsnek: you make me sad [11:07:03.0000] :( [11:07:42.0000] what is a letter but a miserable pile of secrets [11:09:48.0000] I don't think I understand the question [11:10:17.0000] is "墸" an ideogram [11:10:55.0000] what a deep and philosophical question [11:11:04.0000] Bakkot: yes [11:11:18.0000] michaelficarra what idea or concept does it represent [11:11:40.0000] Bakkot: that's not up to Unicode to determine [11:12:09.0000] except for emojis, in which case that's the whole point [11:12:17.0000] let me put it another way: when they put it in, no human associated an idea or concept with that specific symbol [11:12:56.0000] true, but it was explicitly declared to be an ideograph, so it is [11:13:34.0000] is that how that works? [11:14:19.0000] "an ideograph is that which the unicode consortium calls an ideograph" is not a very satisfying definition [11:14:52.0000] let's say Unicode encoded ☢ 100 years ago [11:15:01.0000] satisfyingly simple [11:15:03.0000] it is an ideograph, but nobody would have any idea what it meant [11:15:13.0000] later, we would assign meaning to it [11:15:31.0000] possibly, many years from now, it may come to mean something else to the majority of us [11:16:20.0000] in a sense they're all ideographs [11:16:22.0000] similar to 🍆 [11:16:37.0000] I don't think that whether or not a particular symbol is an ideograph must necessarily be time-invariant [11:16:40.0000] devnsek: that's not correct, letters just aren't ideographs because they have to be composed into a word [11:16:51.0000] if i send a single F [11:17:07.0000] f [11:17:09.0000] i think most people understand that to have a meaning [11:17:16.0000] there are words composed of single letters, but those are different things [11:17:20.0000] well most people who speak english at least [11:17:36.0000] it's different from "I" [11:17:45.0000] how? [11:17:53.0000] it's not a word [11:18:03.0000] I guarantee "most" english speakers would not understand what you meant by the single letter "f" [11:18:23.0000] well, a good amount, probably not more than half [11:18:32.0000] devsnek: why is it not a word? [11:18:39.0000] because it's not in the dictionary? [11:19:08.0000] lol let's not get into prescriptivism vs descriptivism [11:19:11.0000] language is ever-changing, words come and go and change meaning all the time [11:19:18.0000] the same way ☢ isn't a word [11:19:20.0000] even though it has a meaning [11:19:39.0000] it's not a word because it's not composed of letters lol [11:19:48.0000] this discussion pains me [11:19:51.0000] lmao [11:20:18.0000] we can all attend some intro to linguistics and philosophy of language courses then come back and debate this [11:20:21.0000] aren't words in ideographical languages not composed of letters [11:20:31.0000] i actually took intro to linguistics [11:20:49.0000] i don't remember most of it [11:22:20.0000] shu I am basically shitposting my way through this conversation on the assumption that everyone here is aware that these questions do not and cannot have objectively correct answers [11:22:42.0000] ^ [11:22:45.0000] Bakkot: they have prescribed answers from Unicode [11:22:53.0000] well, a lot of them do [11:23:04.0000] michaelficarra yeah but we do not have agreement that Unicode is the single source of truth [11:23:23.0000] ahem, [11:23:26.0000] otherwise "was the consortium correct to say & is not a letter" would not be a meaningful question [11:23:53.0000] looking forward to SARCASTIC_RESPECTFUL_F [11:25:36.0000] 𝔉 [11:25:45.0000] ⸮ [11:26:09.0000] 🪦 [11:26:28.0000] TIL there's a headstone emoji [11:26:55.0000] michaelficarra: that's a box for me [11:27:23.0000] ljharb: Apple's emoji support is terrible [11:28:30.0000] ljharb: can you see ㋿? [11:29:34.0000] michaelficarra: i see box then a character [11:30:14.0000] "SQUARE ERA NAME REIWA" [11:30:17.0000] wow weird [11:30:33.0000] michaelficarra: yep, i see ㋿ [11:30:48.0000] 12.1 is less than 13 [11:31:05.0000] by 0.9 [11:31:10.0000] Bakkot: I'm trying to see how out of date his support is [11:31:37.0000] make a website with a character from each version [11:31:38.0000] ljharb: by "see" do you mean it's rendered correctly? [11:31:51.0000] devsnek by about 300 days [11:32:04.0000] devsnek: I already have lol [11:32:06.0000] wow not even a year [11:32:36.0000] michaelficarra: i mean, i could share a screenshot, but i see a character and not a box [11:32:38.0000] devsnek: yeah there's a pretty funny story behind the Unicode 12.1 release [11:32:57.0000] sounds like es4 [11:33:22.0000] > Unicode 12.1 adds exactly one character [11:33:36.0000] michaelficarra: https://emojipedia.org/headstone/ says "second half of 2020", so it doesn't seem that out of date [11:33:37.0000] oh i'm caught up now [11:33:46.0000] cuz of the new japanese era announcement [11:33:59.0000] reiwa was over a year ago [11:35:16.0000] not sure i'd classify "this year's new emoji" not being supported as "terrible" ¯\_(ツ)_/¯ [11:35:24.0000] i see ㋿ as rei then wa real squished? [11:35:41.0000] ya same [11:35:43.0000] I wonder if the Japanese emperor is the sole person who has unilateral authority to cause a character to be added to unicode [11:36:08.0000] visually i see three vertical pieces squished into one, the first is a trianglish one on top of a P-ish one; the second looks like a tree, and the third looks like one of those medieval hanging flags with a forked bottom [11:36:13.0000] (but just one character) [11:36:37.0000] just need to get the president to add a new letter to english [11:36:43.0000] that's how that works right [11:37:16.0000] I prefer not to think about that question [11:37:53.0000] devnsek: languages and scripts are different things [11:39:19.0000] ljharb: hasn't been updated for 14 months, in the world of software, is pretty bad [11:39:40.0000] michaelficarra it's still 2020 [11:39:53.0000] believe it or not [11:40:16.0000] it's not that it hasn't been updated in 14 months, it's that it hasn't been updated since march 10th when unicode 13 came out [11:40:22.0000] michaelficarra: so, 4 months [11:40:26.0000] which is not bad [11:46:35.0000] fair, let's see when they get Unicode 13 support [11:47:27.0000] i'm assuming it'll be by september, since that's when new MacOS's and safari's tend to come out [11:49:07.0000] hopefully it coincides with an important security update since that's apparently the only thing that causes people to update [11:51:15.0000] imo people update for shiny features far more often than for any security updates [11:56:20.0000] holy shit how did I miss this whole conversation [11:56:28.0000] it's so long to catch up on too [11:56:45.0000] don't feel pressured to catch up [11:57:58.0000] the sole actual content is 'yeah, String.isValidUnicode (or whatever name) is probably a good idea' [11:58:19.0000] devsnek: oh no I wouldn't be whining if it weren't relevant to my interests lol [12:02:51.0000] Bakkot: fair enough lol [12:03:13.0000] I liked that 墸 came up [12:03:39.0000] and ljharb's visual description of ㋿ 😂 [12:07:23.0000] :-p [12:53:50.0000] Since people are in shitposting mood, let me ask something I have wondered about for some time - [12:53:50.0000] How does the spec explain closure thingy? [12:53:50.0000] Is it more of a yeah, any function can access outer variables (with no Implementation details) or something more specific (tells which variables to capture) ? [12:55:02.0000] every function has an environment, variables are stored in environments and looked up by name when used [12:55:34.0000] the whole "which variables to capture" thing isn't decidable in general because of `with` and direct `eval` [12:55:50.0000] blocks have environments too [12:55:50.0000] I guess I should rather say that every function has an environment _chain_ [12:55:53.0000] and switches [12:56:14.0000] and functions store which environment they are in [12:56:31.0000] in a manner of speaking [12:56:57.0000] https://tc39.es/ecma262/#sec-newfunctionenvironment [12:57:16.0000] So, inner function looks up own env, then outer env - but it doesn't say how long a env should exist if the function execution is completed? [12:57:46.0000] the spec doesn't say how long anything should exist [12:58:05.0000] well i guess it gives minimums [13:02:41.0000] devsnek: hmm. [13:02:41.0000] Related question - environment seems to contain env record. Is there any operation where this env record is removed from from one env and moved to another? Or is Environment to Env record practically a 1:1 mapping? [13:03:08.0000] which spec are you reading [13:03:29.0000] we got rid of the "environment" vs "environment record" thing [13:04:57.0000] Well, we got rid of LexicalEnvironment as a thing [13:05:13.0000] sorry, "Lexical Environment". [13:05:25.0000] bendtherules: if you aren't already, you should reference tc39.es/ecma262 [13:05:50.0000] ("LexicalEnvironment" is still the name of a component of execution context) [13:06:57.0000] that refactoring is the one time i have wanted to use typescript [13:07:23.0000] I think the spec still uses "environment" somewhat casually to mean the same thing a Environment Record. [13:08:01.0000] (and also in other phrases, e.g. "the host environment") [13:09:35.0000] there its use is not the same as environment record [13:09:58.0000] "host environment" will have a formal definition as of https://github.com/tc39/ecma262/pull/1951 [13:10:07.0000] yeah, that's what i meant. [13:10:44.0000] "also" as in "also, with another meaning" [13:11:08.0000] so bendtherules, I don't think it's ever been true that "an environment contains an environment record" [13:11:37.0000] it contains an outer environment [13:12:00.0000] that's not a containment relaionship. [13:12:20.0000] Right. I read once more and only found env records. [13:12:31.0000] or, you could say it contains a reference to an outer env. [13:12:40.0000] Maybe that's the mental mapping i had for some reason [13:13:13.0000] jmdyck: well that argument starts to get into the memory layout of records [13:13:58.0000] which is why i wouldn't make that argument [13:15:40.0000] my point was just that saying "contains" is a bit silly since it's the same relationship either way [13:20:20.0000] So, LexicalEnvironment and VariableEnvironment (parts of the execution context) - are they used to "skip" a lookup when you want to declare a var? [13:20:56.0000] Mental model for me is var looks up the closest function, but spec just uses current VariableEnvironment [13:21:36.0000] there's basically two lists of environments [13:21:46.0000] one for lexical declarations and one for variable declarations [13:21:55.0000] And also, is VariableEnvironment always a parent or same as LexicalEnvironment? [13:22:03.0000] its less about "skipping" and more about them not lining up [13:22:37.0000] Devsnek - but sometimes they do refer to the same thing, no? [13:22:42.0000] yes [13:23:52.0000] So, function always adds a entry for both. [13:23:52.0000] But i would have thought that functions without a block statement doesn't need a LexicalEnvironment? [13:24:16.0000] Like `() => 123` [13:25:03.0000] Although this doesn't have a visible impact anyway [13:25:38.0000] generally a new lexical environment isn't added [13:26:04.0000] the spec doesn't really go out of its way to avoid creating spec objects [13:26:11.0000] that too [13:26:15.0000] it doesn't at all [13:26:19.0000] well sometimes it does [13:27:02.0000] i think the only time it does is to make sure references are the same? do we do it elsewhere? [13:28:18.0000] hm i guess for "out of its way" yeah it doesn't [13:28:25.0000] FunctionDeclarationInstantiation does this, but it shouldn't [13:28:44.0000] wasn't there a bunch of discussion about that [13:29:38.0000] yup [13:40:24.0000] Different question - Why do some statements return NormalCompletion with a explicit value? Where is this used? I understand the need in expressions [13:41:03.0000] eval [13:41:17.0000] let x = eval('if(Math.random()<.5)0; else 1;'); console.log(x) [13:41:56.0000] oh, never thought of that [13:42:22.0000] And these values have legit usage? [13:44:01.0000] I don't know what "legit" means here [13:44:12.0000] certainly making that line of code not work would break a bunch of websites, yes [13:45:35.0000] I meant like people actually use this? Not suggesting that it should be modified or anything. [13:45:48.0000] I understand, so more of a compatibility thing [13:48:58.0000] I would not recommend using this, to be clear [13:49:19.0000] but there is a lot of JS in the world, and a lot of people writing more of it all the time [13:50:17.0000] also I should mention that these will maybe start getting use if do expressions go forward: https://github.com/tc39/proposal-do-expressions/ [13:50:32.0000] I hoped to work on that in time for this meeting, but have had too much other stuff [13:50:46.0000] Ahh, I was just looking at that 😀 [16:01:33.0000] devsnek: i'm out of time today to re-review your CL, and with TC39 i might not get to it again until next next week, is that okay? [16:01:39.0000] np [16:01:47.0000] thanks 2020-07-18 [22:12:19.0000] Did something change recently about the spec html? In ecmarkup or something? [22:12:19.0000] On mobile, navigating the doc and specially the sidebar search has become sooo much slower. No debounce, etc? [22:12:19.0000] Might be something that chrome (on android) has changed though. [22:15:38.0000] I don't believe so, no [22:15:50.0000] it's always been slow in chrome; it's much, much better in firefox [22:17:13.0000] Firefox mobile? [22:18:22.0000] yeah [22:18:31.0000] also large diffs on github [22:18:39.0000] freeze chrome but do fine on firefox [22:27:39.0000] Yeah, firefox is working better. The view is little zoomed out compared to chrome, but definitely manageable. [08:38:35.0000] Question - In try..finally, why does finally's (non-normal) completion record take precedence, even when try is throwing? [08:39:39.0000] Finally can effectively then act as a catch sometimes. Where can i find the discussion logs for finally in try? [08:53:47.0000] this is an ancient decision, almost certainly copied from Java, which probably copied it from something else before it [08:54:00.0000] you'd have to go back to some mailing lists from the 80s, I expect [08:54:05.0000] if it's captured anywhere [08:54:26.0000] haha, got it :) [08:59:09.0000] that said, I think it's pretty natural: if I write `function f(){ try { return x; } finally { doSomething() } }`, and `doSomething()` throws, I don't want that function to just return without throwing [09:00:55.0000] What about `function f(){ try { throw x; } finally { return y; } }`? I would expect finally to not act suppress the error - that behaviour is somewhat implicit here [09:01:09.0000] I do not have that expectation I guess [09:01:10.0000] *not suppress [09:01:18.0000] ok, fair enough [09:01:23.0000] and also do not expect that code to come up nearly as often [09:06:57.0000] shu: https://docs.google.com/presentation/d/19S97ZqhibJABqzeP5ZU6Flk6TVgWzXuvJWFbNTTfpWs/edit#slide=id.g8d8a4d4a81_0_377 also affects node you might note [11:04:18.0000] bradleymeck: will try to remember by monday but if it slips my mind please call it out during my preso? 2020-07-19 [07:18:53.0000] k [15:33:08.0000] The merge of PR 1951 introduces a lot of "sec-" ids that aren't on emu-clause elements, which is unusual. Is it desired? [16:09:38.0000] hm, yeah, I didn't notice that the definition ids were prefixed with `sec-`. shu ^ ? [16:23:30.0000] oldid ftw 2020-07-20 [19:36:02.0000] jmdyck: Bakkot: copypasta, let me change now [19:37:59.0000] hm, there is some precedent for this, like `thisStringValue` having `` [19:38:07.0000] that's kinda unfortunate [19:38:27.0000] Bakkot: do ``s take oldids=? [19:38:49.0000] not sure, let me check [19:39:30.0000] shu: should, based on impl [19:39:41.0000] i'm not adding oldids to the ones i just introduced but for the older ones, we should keep the oldids [19:39:43.0000] okay great [19:41:05.0000] yeah, tested experimentally [19:41:52.0000] it's kind of funny actually; the oldids will link directly to the definition, rather than (as is normal for dnfs) the containing section [19:44:57.0000] https://github.com/tc39/ecma262/pull/2103 [19:45:00.0000] /me off [04:32:33.0000] everybody ready for today? [04:32:37.0000] https://youtu.be/jxi0ETwDvws?t=116 [06:10:08.0000] i suppose i did know this already, but i'm very surprised that optional chains aren't valid assignment targets [07:56:24.0000] ljharb: hi - looking at https://github.com/tc39/ecma262/pull/2045, it seems very likely to land. Is that right? [08:18:12.0000] devsnek: i think there was some back and forth and it was dropped in ancient times due to back and forth [08:18:35.0000] ya [08:19:00.0000] ystartsev: that channel has a lot of programming related music videos [08:19:02.0000] i asked people at godaddy about if they wanted it and the overwelming majority wanted if (z) x.y = z rather than that [08:19:10.0000] i am knowledgeable of that, but in the moment of writing code i just naturally did `a?.b = c` and then was sad when it failed [08:19:30.0000] isn't that `??=` [08:19:34.0000] or just `||=` [08:19:45.0000] jorendorff: there're still some work not done, including old ids and some review ExEBoss rises I'll handle them tomorrow [08:19:50.0000] oh no i guess that's the inverse [08:20:15.0000] jackworks: yep -- it all looks good [08:20:46.0000] i just wanted to make sure i'm not missing anything [09:21:12.0000] jorendorff: afaik all the editors are on board with the concept; it may need some more tweaks, and it’ll need review (but that will likely be after plenary) [09:21:42.0000] ljharb: ok, thanks. that makes sense. [09:22:07.0000] yeah I haven't gotten a chance to review the PR itself and so can't say if the current form works, but I still agree with the plan we talked about during last meeting [09:22:31.0000] jorendorff: the hope is to find some balance between “converting none of the existing iterator-producers” and “converting all of them” that both convinces us it’s viable and also doesn’t make jackworks do too much work :-) [09:24:44.0000] ljharb: Ah, I see. Thanks for the extra context. Does this imply trying to change the prototype chains of the existing iterator-producers? [09:26:52.0000] I don't think so; I am pretty sure when we discussed this at the last meeting we said that the point of this effort was strictly editorial improvement for specifying iterators [09:27:24.0000] and I am in general not in favor of making normative decisions for editorial reasons [09:57:03.0000] jorendorff: no, it very much implies not doing that, since that'd be observable :-) [09:57:12.0000] OK, good [10:10:14.0000] bterlson: I love your social isolation hair style [10:14:54.0000] leobalter: lol thanks [11:57:30.0000] how would people people want to spec export/import wildcards regarding arbitrary binding name strings, currently we use a special string: "*default*" , but that would be valid in https://github.com/bmeck/proposal-arbitrary-module-namespace-identifiers , so need to alter on a type somehow so it isn't a string [11:58:38.0000] same for "*" [11:59:28.0000] we could spec it using symbols as special well known values? [11:59:59.0000] or use tilde-values? [12:02:22.0000] jmdyck: i guess we could, seems a bit odd to mix string and tilde values in a list [12:02:46.0000] can we refactor this https://gc.gy/62976763.png [12:02:59.0000] bradleymeck: sounds like a question for #tc39-editor-group [12:03:06.0000] I think we could use a spec enum value for it [12:03:29.0000] devsnek: refactor how? [12:03:35.0000] can move it there [12:03:37.0000] don't need nested if statements i don't think [12:04:00.0000] jmdyck: might push this up in a minute https://gc.gy/62976833.png [12:04:34.0000] bradleymeck: a spec enum makes sense to me [12:05:46.0000] shu: [12:05:53.0000] I don't have a motivation for disallowing [12:06:22.0000] I'm just addressing a point that came out from the proposal issues, and my preference is to not disallow [12:06:58.0000] it's too specific and disallowing might involve some tricky change in the grammar to also extend DecimalLiteral in Annex B [12:07:17.0000] so if you don't see enough motivation, I'm totally onboard with you [12:07:27.0000] leobalter: yeah it just seems like more work to me [12:07:45.0000] leobalter: since as you said exponential parts have been allowed forever, and that's the same kind of weirdness [12:08:20.0000] so if we can't disallow all weirdness, it seems worse to me to bless some subset of weirdness and say "okay these weird things are allowed, but new weird things aren't allowed", if we don't expect people to use the feature anyhow [12:08:29.0000] all other things being equal, that is, like implementation and spec burden [12:08:34.0000] in this case it seems like they are? [12:09:27.0000] the flip side is maybe if we allow it it's likely to be implemented wrong? [12:10:14.0000] like, in the parser when you start parsing a legacy nonoctal you'll pass some flag that says "separators not allowed" which might get accidentally propagated to the part after `.` or `e`, but that's a pretty weak argument [12:10:52.0000] but given that it's all implemented already... [12:11:34.0000] we also have "*namespace*" [12:12:02.0000] devsnek: I checked the history: that elseless-if-within-if goes back to a late draft of ES6. It seems like there's never been a reason for it. [12:12:26.0000] shu I created a new slide I'll show during the continuation: https://docs.google.com/presentation/d/1J-oYbstZX2W0LCIVtKG4XbTxWe3cH8JoWNGnoL2F-94/edit#slide=id.g8c6affb1a1_0_50 [12:12:44.0000] ljharb: https://travis-ci.org/github/tc39/ecma262/jobs/710124061 [12:12:49.0000] it's weird that I'm presenting a proposal that my goal is to reject it :) [12:12:58.0000] jmdyck: thx, made pr https://github.com/tc39/ecma262/pull/2105 [12:13:04.0000] leobalter: :highfive: more or less [12:13:05.0000] lol [12:14:03.0000] devsnek: that happens when the PR has too many commits, but i deployed a service fix for it an hour ago. rerunning. [12:14:27.0000] i mean its only got 1 commit [12:14:32.0000] (once I can come up with a rationale for how things are then I feel less strongly about changing them, I suppose) [12:16:01.0000] devsnek: I made a suggestion on 2105, and gh gives me an option to "Commit suggestion", which I don't think I've seen before. [12:16:06.0000] devsnek: hm, if it fails again i'll reach out to my contact at Begin [12:16:14.0000] jmdyck: if it works go for it [12:16:19.0000] jmdyck: it's supposed to always be there [12:16:22.0000] https://gc.gy/62977581.png [12:16:28.0000] when i try to use it [12:16:47.0000] there's a bug on github; if the suggestion is from someone with write access, you can't accept it [12:17:01.0000] incredible [12:17:23.0000] Oh, I see it when people make suggs on *my* PRs, but this is my sugg on someone else's PR. [12:17:37.0000] what happens if you click it [12:17:49.0000] let's see.... [12:17:51.0000] and try to commit it [12:17:58.0000] that bug has been plaguing us forever 😭 [12:18:13.0000] jmdyck: iirc you have write access on 262, so you *should* have write access on all PR branches too [12:18:51.0000] do i have write access to 262? [12:19:17.0000] Got the same old "This diff has recently been updated. Refresh and try again." [12:19:40.0000] devsnek: afaik no [12:53:15.0000] devsnek: build issue is fixed, job passed on rerun [12:53:50.0000] 👍🏻 [13:22:47.0000] rkirsling: we've had consensus for this one, right? https://github.com/tc39/test262/issues/2653 [13:23:12.0000] leobalter: yep! :D [15:55:32.0000] if we have do expressions do we need static constructors [15:58:33.0000] devsnek: yes, for anything in the block that's not setting up a field [15:58:51.0000] like if it wants to put a data property on the prototype, or to defineProperty something [15:59:32.0000] ljharb: why can't you do that in a do expression [16:01:30.0000] because the do expression would still have to be assigned to a class field, and you may not want one? [16:01:46.0000] huh [16:01:57.0000] where else would you put a do expression except in the RHS of a class field [16:02:12.0000] ljharb: const X = do { create class here } [16:02:26.0000] or let X I guess [16:02:34.0000] why are class declarations mutable anyway [16:59:21.0000] devsnek: that wouldn't provide access to private fields outside the class body. [16:59:42.0000] though private declarations would! [16:59:46.0000] which we should do anyway 2020-07-21 [17:00:40.0000] what bakkot said is what I was about to say [17:00:42.0000] right, private declarations + do expressions would certainly cover it [17:01:00.0000] it feels unclean tho to modify a class outside the class body [17:01:08.0000] so i'd still want static blocks, even with those two features [19:16:14.0000] "Content Encoding Error: An error occurred during a connection to ci.tc39.es. " [19:17:39.0000] (when trying to see the Begin.com rendering of PR #2105) [19:23:27.0000] jmdyck: there’s been an issue that was fixed today; let me rerun the render [06:48:20.0000] "Let nestedAssignmentPattern be the AssignmentPattern that is covered by DestructuringAssignmentTarget." [06:48:22.0000] why is this needed [06:48:31.0000] oh nvm i'm dumb [10:36:12.0000] I've gotta confess, most of the issues I bring to TC39 are because I find issues at Test262, some are spec some are how things are implemented. [10:36:49.0000] i think so far all my changes to ecma262 are bugs [10:36:52.0000] The word "champion" fits well on where I'm just the messenger, like a bug from yesterday that I just suggested expressed rejection [10:37:11.0000] leobalter that is one of the best reasons to bring things to tc39 [10:37:53.0000] ^ [10:38:17.0000] mine both were via test262 as well [10:38:32.0000] this time [10:38:51.0000] it is but it feels but I'd like to be more clear in the next issues that I'm just the messenger. My personal goal is interoperability, most of the times just limited to it [10:40:36.0000] It's not a bad thing, I really appreciate people working along to find a solution. I really meant it saying I'm thankful to Bakkot showing more context to the issue. [10:41:31.0000] and I'm happy that now I have a better justification to work on the respective tests. "Why? To make the JS ecosystem better" [10:41:43.0000] just a _public reflection_ [10:50:22.0000] bendtherules: I believe REPLs use the NormalCompletion values [10:51:55.0000] I don't remember the secret irc incantation to get the attention of bterlson akirose and co... I think I have a scheduling issue with my topic today. I have meeting from 2-3 (ET) and my Numeric Sep topic falls in that time [10:54:50.0000] `/notice #tc39-chairs your message here` [10:54:54.0000] <3 [10:55:14.0000] akirose can you pop that in the channel topic? [10:55:31.0000] in the delegates channel topic would be great [10:55:42.0000] Oh, word [10:55:47.0000] What ljharb said [11:16:42.0000] wrt Tests for WeakRefs, I believe any further coverage for WeakRefs should be for specific implementations to match what each want wants for their GC and how deterministic each one can be. I don't see value in more coverage with shared tests (Test262). [11:17:01.0000] littledan: ^^ (after your presentation, for sure) [11:20:42.0000] 👀 https://gc.gy/63060637.png [11:31:38.0000] my preferred options, in order: 1. Engines should just filter out cleanupsome tests by the matching feature tag. 2. remove the tests from tests. [11:31:47.0000] I'm not a fan of adding a "stage 2" flag. [11:32:31.0000] and I would prefer not creating precedent [11:33:57.0000] so you'd prefer that they...clean up some, eh [11:35:05.0000] leobalter: I'm fine with that, I was just trying to nod to rwaldron 's announcement that there would be more tests (maybe I misunderstood him) [11:35:20.0000] rkirsling: haha yes [11:35:59.0000] littledan: that's something I haven't synced with rwaldron so he might have seen something I'm not up to date [11:36:37.0000] yeah his presentation was the first I heard of it too [11:36:48.0000] leobalter, that's the thing I wanted to sync on last week, [11:37:02.0000] ok, back to my _other_ meeting. [11:37:32.0000] jridgewell: we can see your IRC notifications [11:37:50.0000] haha [11:38:23.0000] stage &&= 4 [11:39:18.0000] woo [11:40:11.0000] keith_mi_ shu wrt to my preferred options above. A [11:40:34.0000] Would you be fine with option 1? [11:40:59.0000] adding a new feature flag for cleanupSome? [11:41:06.0000] that wfm [11:42:11.0000] Yeah, new flag is fine, we currently filter by directory [11:42:24.0000] at this point yes, we should add a flag for cleanupSome because we only have one for FinalizationRegistry but also this folder https://github.com/tc39/test262/tree/main/test/built-ins/FinalizationRegistry/prototype/cleanupSome [11:42:50.0000] keith_mi_ keith_miller [11:43:06.0000] witch one is not the evil one ? :) [11:43:14.0000] neither [11:43:19.0000] Both are evil [11:53:12.0000] `git grep --name-only -e 'async-gc\.js' --or -e 'cleanupSome'` might find every file we should add the flag [12:05:37.0000] https://github.com/tc39/test262/pull/2713 [12:05:52.0000] littledan ystartsev keith_mi_ shu ^^ [12:06:10.0000] nice, thanks [16:38:20.0000] does anyone recall why we never added regexp.escape? [16:38:47.0000] i.e. a thing which takes a string and gives you a regexp which matches exactly that string (as a substring) [16:40:23.0000] ah: https://github.com/benjamingr/RegExp.escape/issues/37#issue-98309281 [16:40:29.0000] Bakkot: the so-called "even-odd" problem [16:40:43.0000] yep [16:41:05.0000] sigh [16:45:04.0000] I tried to revive it at https://esdiscuss.org/topic/regexp-escape#content-54 , but that never went anywhere (and in particular did not go in front of committee) [16:48:32.0000] I do not find markm's argument compelling [16:49:41.0000] having a tag which lets you assemble a regex out of parts seems fine as well, but I would still get utility out of a thing which made it your responsibility to not precede it by a backslash or left bracket or whatever [16:50:26.0000] I wonder if he might be persuaded to change his stance, now that five years have passed with no progress on this frotn [16:50:48.0000] +1 [16:54:23.0000] that’d be great 2020-07-22 [20:04:14.0000] engine262 rewrite now failing fewer than 10,000 tests 🎉 [20:04:30.0000] Nice one! [20:04:46.0000] its mostly early errors at this point :( [20:04:56.0000] still don't have a great way to do early errors [20:05:45.0000] might rip out all the early error stuff i currently have and make it a second pass [20:07:22.0000] traditionally early errors are part of the parser [20:08:10.0000] yeah still part of the parser api [20:08:29.0000] i mean like, `parseScriptBody` wouldn't be what checks for duplicate lexical bindings [20:08:45.0000] I mean it could be [20:08:51.0000] everything is a mess [20:08:56.0000] `a.await` is a parse error rn [20:09:16.0000] i'm liking the idea of shift's reduce thing [20:46:53.0000] i wonder if it would be web compatible to make evaluators able to throw AggregateErrors instead of SyntaxError [21:17:20.0000] /me 10,000 tests! wow! [06:26:11.0000] the link for Decorators slides at https://github.com/tc39/agendas/blob/master/2020/07.md and in the notes doc doesn't work, can someone involved with the proposal fix it? [08:11:17.0000] what if function parameters had elisions [08:12:51.0000] `Object.defineProperty(new Proxy({}, {getOwnProperty(o, k) {return {value:1}}}), 'why', {value:2})` is... strange [08:14:36.0000] `{ let o = new Proxy({}, {getOwnPropertyDescriptor(o, k) {return {value:1}}}); Object.defineProperty(o, 'why', {value:2}).why; }` => 2 [08:14:56.0000] `{ let o = new Proxy({}, {getOwnPropertyDescriptor(o, k) {return {value:1}}}); o.why; Object.defineProperty(o, 'why', {value:2}).why; }` => 2 [08:15:17.0000] { let o = new Proxy({}, {getOwnPropertyDescriptor(o, k) {return {value:1}}}); Object.getOwnPropertyDescriptor(o, 'why'); Object.defineProperty(o, 'why', {value:2}); } => error [08:15:46.0000] you can read the non-configurable value [08:16:01.0000] and you can replace it, as long as you don't check if it is configurable [08:16:29.0000] the `get` trap being distinct from the `getOwnPropertyDescriptor` trap is a bit weird, yeah [08:17:41.0000] bradleymeck in your last example it's the `Object.getOwnPropertyDescriptor` which throws, not the `Object.defineProperty` [08:18:53.0000] also confusing [08:19:28.0000] you can read it, but not see its descriptor? [08:19:37.0000] what is this hell [08:22:17.0000] > the `get` trap being distinct from the `getOwnPropertyDescriptor` trap is a bit weird, yeah [08:22:41.0000] i'm learning yea [08:27:35.0000] proxies are strange [08:29:42.0000] reflection always gets strange eventually [11:22:11.0000] what is a JS builtin that takes an options bag ? [11:22:57.0000] bradleymeck: 262 doesn't really have any, unless you count a Proxy handler, or Object.defineProperties/Object.create's second argument [11:23:09.0000] no, per the discussion we just had [11:23:30.0000] handler is thing which gets "this" value apparently [11:23:37.0000] options bag, doesn't [11:23:46.0000] defineProperties kind of? [11:23:53.0000] there's nothing in 262 that takes a function off an object and calls it directly [11:23:59.0000] in 402, there's tons of examples tho [11:24:03.0000] it doesn't really configure the algorithm [11:24:14.0000] should we cross ref 402 in the how-we-work term list? [11:35:21.0000] how about requisition() instead of upsert()/emplace() [11:36:11.0000] this proposal would be great if we had Decorators [11:36:44.0000] ensure()? [11:36:51.0000] what if we made a new kind of function declaration [11:36:58.0000] that wasn't hoisted [11:37:04.0000] then we could just do normal style generators [11:37:07.0000] decorators* [11:41:54.0000] `await @all x` [11:42:26.0000] for me this looks better than `await.all x`, not going through stacking trace issues [11:43:01.0000] I'd be pretty satisfied with `await * x`, only giving sugar for Promise.all [11:43:07.0000] what about [11:43:12.0000] `for await concurrent (const x of y) {}` [11:43:38.0000] ~= `await Promise.all(y.map((x) => {}))` [11:44:51.0000] devsnek: probably a separate discussion but I'd be up to discuss it as well [11:44:54.0000] devsnek that interacts weirdly with abrupt completions [11:45:43.0000] it seems like it would lead to a lot more concurrency bugs than the current patterns [11:46:16.0000] i guess the hard part would be deciding what `break` does [11:46:21.0000] everything else seems well defined [11:47:57.0000] presumably `return` exits the function as soon as any iteration hits it, and it's just a race? [11:48:07.0000] that is the "a lot more concurrency bugs" thing [11:48:37.0000] oh yeah return [11:48:45.0000] rkirsling: kind of, but idk how that implies potential update [11:49:03.0000] Bakkot: the map is more about mapping to async functions, not the result of those async functions [11:49:42.0000] devsnek I am not sure what that means [11:49:45.0000] or, like, why it matters [11:49:57.0000] I know how Promise.all works I just don't know why you are mentioning this [11:50:06.0000] bradleymeck: true. was all I could think of at that moment though [11:54:37.0000] this is interesting https://es.discourse.group/t/nan-trapping-operators/402 [11:55:02.0000] rkirsling: .summon()? [11:55:07.0000] jackworks: the proposal I was referring to was https://es.discourse.group/t/array-prototype-uniqby/138 [11:55:09.0000] nice [11:55:48.0000] .claim is pretty good [12:01:35.0000] do we have any knowledge of static JS tools that assume after a map.has(k) === true that map.get(k) should get a value that does exist [12:01:49.0000] also how do people feel about .get(k) firing a user code trap? [12:15:15.0000] devsnek: I think this is at the wrong poit [12:15:19.0000] point** [12:15:29.0000] You'd want to throw when you generate the NaN, not when you compare with it. [12:15:55.0000] bradleymeck: Typescript doesn't, last I checked [12:15:58.0000] jridgewell: `nonanscope {}` [12:15:58.0000] devsnek: "`for await concurrent (const x of y) {}`" yeah, I always want to have some kind of concurrent control over `for await` loops. maybe even further, with args `for await concurrent 4` means max 4 running or `for await concurrent _identifier_` to refer a custom task dispatcher [12:17:43.0000] Bakkot: yeah, maybe we ban the "break" or "return" only leave "continue" in `for await concurrent` like the do expression did [12:21:01.0000] jackworks yeah, though I would still worry about closed-over values [12:21:19.0000] I remember there was a "use strong" in v8 that will throw immediately when a math operation yielding NaN, I like that idea, not in the language, but as a debugger tool. [12:21:21.0000] for loops it is very common to have, like, `let x; for (...) { if (test) x = whatever }` [12:21:31.0000] which, if the loop is concurrent, is probably a bug [12:21:56.0000] you can have the same thing with Promise.all, of course, but it is much harder to run into [12:21:56.0000] Oh maybe we can suggest v8 to add a "Pause on NaN calculation" [12:23:46.0000] "if the loop is concurrent, is probably a bug" yeah but since it is opt-in, developer should learn about what is race condition [12:24:01.0000] ehhhhhhhhhhhhhhhh [12:24:14.0000] concurrency bugs are notoriously one of the Hard Problems [12:24:26.0000] I would be very, very reluctant to introduce an affordance which makes them easier to run into [12:25:13.0000] I do not find "developers should be careful" a compelling argument in this case, especially given how hard concurrency bugs are to avoid in codebases that don't have Rust-style ownership or similar guarantees [12:25:26.0000] "Promise.all, of course, but it is much harder to run into" agree, but the problem is today, async concurrent calculation is pain to write `await Promise.all(arr.map(async x=> ...))` too tedious [12:29:35.0000] "very reluctant to introduce an affordance which makes them easier to run into" reasonable... so we just let async concurrent pain to write, to let devs write serial async code? at least for me, sometimes it's really safe to do the async concurrent calculation but I don't want to write `await Promise.all(arr.map(async x=> ...)) ` these bunch of code so I let it run in serial [12:31:36.0000] I am happy to explore affordances which make it easier to write concurrent code; I don't think `await.all` would have the same problem as `for await concurrent`, for example [12:31:39.0000] I think WeakRef and FinalizationRegistry are applicable to the same argument. they're easy to misuse but they're still added to the 262 and mdn.io gives warnings on it "Avoid where possible" [12:32:03.0000] We would never have added WeakRefs if they hadn't been necessitated by wasm [12:32:30.0000] lol [12:32:36.0000] but they're a fundamental capability, whereas `for await concurrent` is not a fundamental capability [12:34:05.0000] my friend was working on the membrane, he also needs WeakRef; my RPC library provides iterating on remote async generators so I need WeakRef too [12:34:05.0000] `for await concurrent` is about making certain kinds of code easier to write, which means we need to think hard about whether we in fact want those kinds of code to be easier to write, and my answer is no because that _particular_ syntax makes it much easier to have concurrency bugs, more than other possible affordances for writing concurrent code [12:34:29.0000] yeah they're useful in other cases, it's just that they have way too many problems to justify for those cases alone [12:37:17.0000] hmm, so people will re-inventing it again and again and it's more easily to have bugs in their own impl [12:37:51.0000] is it possible to design a syntax to make it easy to write, meanwhile reduce the possible race condition bugs? [12:38:08.0000] Phew, I haven't had to write it yet myself, but `await Promise.all(arr.map(async x=>...))` is *awful* to write. [12:38:24.0000] `for await.all(const x of arr){...}` plz [12:38:39.0000] (WebCrypto API on mdn even gives a big strong red warning box writes "If you're not sure you know what you are doing, you probably shouldn't be using this API.") [12:40:40.0000] maybe the `for await.all` sugar is too sweet and people will start to abuse it everywhere leads tons of race conditions, then the eslint decides it's a super foot gun and ban it 🤣 [12:43:20.0000] oh I recall a joke, when `async await` steps into our life, I saw an article says `await` is easy to get abused and new comer to JS will try to write `await` before any expression. [12:43:45.0000] tbf people do that! [12:43:48.0000] it just doesn't lead to bugs [12:43:58.0000] so it's not a big problem [13:42:06.0000] name for a .get that defaults a value if no such key is present but does not insert it? (getDefault was seen as having either semantics) [13:42:52.0000] why not `.get(key[, default])` [13:43:02.0000] matches the current default of undefined [13:43:23.0000] getOrDefault [13:43:40.0000] or jordan's thing [13:44:05.0000] `default` would need to be a function, there [13:44:37.0000] ah, true. can default to `() => {}` [13:45:08.0000] getOrCompute [13:45:18.0000] getpute [13:45:22.0000] jridgewell why "need"? [13:45:22.0000] winner [13:45:28.0000] I see the use for it, just not the necessity [13:46:47.0000] Because the default value can be very expensive to create [13:47:14.0000] can be, but is that frequent enough that it is necessarily something which has to be met by this method? [13:47:41.0000] for those cases, you can still do `if (!x.has()) x.put()` or whatever [13:47:44.0000] yes, in my experience [13:48:11.0000] it's often constructing an object or transforming data [13:48:25.0000] To counter, you could just do `x.has(key) ? x.get(key) : default` for your case [13:48:35.0000] right, of course [13:48:40.0000] this is a question about frequency [13:48:48.0000] in my experience, the cheap key is much more common [13:48:53.0000] I am curious if your experience differs [13:49:01.0000] cheap key? [13:49:02.0000] *cheap default [13:49:07.0000] Ah, [13:49:20.0000] My use is templateing libraries [13:50:04.0000] Particularly lit-html, which creates a whole `