01:10:48  <cloudshu>caitp: ping
01:11:06  <cloudshu>caitp: could you (or someone) explain to me why this test is correct: https://github.com/tc39/test262/blob/master/test/language/statements/for-await-of/async-func-dstr-var-ary-ptrn-elision-step-err.js
01:12:07  <cloudshu>i'd understand if the loop were |for await (var [,] of iter)| instead of |for await ([,] of [iter])|
01:12:15  <caitp>rick or leo are probably better choices, but give me an hour and ill try
01:12:29  <cloudshu>caitp: no worries -- an easier to check question is does v8 pass that test?
01:12:42  <caitp>no, not iirc
01:12:54  <caitp>if its what i think it is
01:12:56  <cloudshu>caitp: fwiw SM fails as well
01:13:02  <cloudshu>caitp: i'll wait for leo, thanks!
01:29:32  * chicoxyzzyjoined
01:30:03  * chicoxyz_joined
01:33:53  * chicoxyzzyquit (Ping timeout: 246 seconds)
01:59:48  * not-an-aardvarkquit (Quit: Connection closed for inactivity)
02:10:12  <bterlson>https://github.com/rbuckton/ecmascript-ref anyone for a new pseudo-keyword?
02:26:10  <ljharb>eef, that seems way too magic
02:33:22  * bradleymeckjoined
02:39:17  * not-an-aardvarkjoined
03:02:00  <bterlson>ljharb: which part?
03:25:22  * rbucktonjoined
03:27:24  * rbucktonquit (Client Quit)
03:27:42  * rbucktonjoined
03:29:47  <bradleymeck>bterlson: is this just sugar instead of fns
03:30:24  <bradleymeck>i feel like `($ref = ref) => ref = $ref` ~= this
03:32:26  <bradleymeck>might make lifetime tracking a bit harder but don't see anything crazy about it except using a non-reserved word
03:33:57  * jmdyckquit (Quit: Leaving.)
03:39:49  <ljharb>bterlson: the whole concept - having references. it's bad enough that modules create live bindings :-/
04:18:30  * bradleymeckquit (Quit: bradleymeck)
06:19:48  * not-an-aardvarkquit (Quit: Connection closed for inactivity)
09:47:02  * chicoxyzzyjoined
09:50:11  * chicoxyz_quit (Ping timeout: 246 seconds)
09:51:58  * chicoxyzzyquit (Ping timeout: 260 seconds)
10:25:07  * mylesborinsquit (Quit: farewell for now)
10:25:14  * bradleymeckjoined
10:25:37  * mylesborinsjoined
10:34:48  * bradleymeckquit (Quit: bradleymeck)
11:05:28  * jmdyckjoined
11:49:27  * bradleymeckjoined
12:30:27  * bradleymeckquit (Quit: bradleymeck)
13:11:05  * bradleymeckjoined
14:03:08  * bradleymeckquit (Quit: bradleymeck)
14:17:40  * bradleymeckjoined
14:33:26  * caridyquit (Remote host closed the connection)
14:33:57  * caridyjoined
14:35:44  * Fishrock123joined
14:41:32  * bradleymeckquit (Quit: bradleymeck)
14:42:17  * bradleymeckjoined
14:42:49  * bradleymeckquit (Client Quit)
16:37:35  * rbucktonquit (Ping timeout: 240 seconds)
16:46:20  * rwaldronjoined
19:15:44  * rbucktonjoined
20:03:45  * Fishrock123quit (Remote host closed the connection)
20:13:21  * bradleymeckjoined
20:15:19  * Fishrock123joined
20:15:36  * Fishrock123quit (Remote host closed the connection)
20:23:32  * mylesborinsquit (Excess Flood)
20:23:59  * mylesborinsjoined
20:25:40  * bradleymeckquit (Quit: bradleymeck)
20:32:19  * Fishrock123joined
20:35:52  * Fishrock123quit (Remote host closed the connection)
21:06:00  * Fishrock123joined
21:14:38  * Fishrock123quit (Quit: Leaving...)
21:33:43  <cloudshu>bterlson: this is like ocaml ref?
21:34:24  <cloudshu>bterlson: is the actual motivation better engine optimization opportunities if it's new syntax? manual boxing is obviously possible today
21:44:08  <samth>cloudshu: that appears to be much more than ref in ml
21:44:25  <samth>it addressof in C
21:45:13  <samth>bterlson: why have that instead of `() => x`
21:45:42  <cloudshu>samth: okay, then yes, your question
21:46:03  <cloudshu>i can imagine that it'll make some C# codegen easier, but i'm wary adding another possible perf cliff to the language
21:46:07  <cloudshu>our bindings already super weird
21:46:15  <samth>it seems like the issue is TDZ in decorators, which functions fix
21:46:44  <rbuckton>samth, the boilerplate for both reading and writing a reference using callbacks is a bit cumbersome
21:47:23  <rbuckton>samth, yes decorators is one case where this is useful.
21:47:29  <samth>oh, because you can write `ref y = ref x` and then do `y` instead of `x.value`
21:47:39  <rbuckton>That's correct.
21:48:04  <bterlson>I think it's also much easier to optimize ref than just functions
21:48:39  <samth>still seems like `let y = ()=>x; y()` is pretty short
21:49:05  <bterlson>samth: per https://github.com/tc39/ecma262/pull/919#issuecomment-302594742, are you pro-"syntax-based operation" over "syntax-directed operation"?
21:49:10  <samth>bterlson: on the one hand, I agree, on the other hand as soon as you write `ref x` all accesses to x are de-optimized
21:49:30  <samth>bterlson: I wasn't sure if it was syntax-directed or not since I was on my phone
21:49:31  <samth>:)
21:49:43  <rbuckton>samth, to be fully the same you have to do something like `let y = (v) => v === undefined ? x : (x = v)`, but that doesnt work if `undefined` is a valid value
21:50:21  <bterlson>also the behavior of [] access is hard to emulate
21:50:59  <bterlson>adds more code anyway
21:51:11  <rbuckton>so the full function version would be `let y = function (v) { return arguments.length === 0 ? x : (x = v); }` or having two functions: `let y = { get value() { return x; }, set value(v) { x = v; } }`. `ref` expressions create the latter for you.
21:52:11  <samth>when do you need to set through the ref?
21:52:58  <rbuckton>See the `max` example at https://github.com/rbuckton/ecmascript-ref/blob/master/README.md
21:54:11  <rbuckton>Decrement the value of the higher reference: `ref y = max(ref a, ref b); y--;`
21:55:21  <samth>rbuckton: I understand how it works, just wondering why you would want that -- I understand the motivation for reading in decorators, but not for writing
21:56:58  <rbuckton>samth, decorators isn't the use case here. Its just a general language feature.
21:57:35  <bterlson>to be fair, angular's usage of decorators motivates the reading side quite a bit :-P
21:57:40  <rbuckton>Decorators definately benefit from having forward references, but there are many other possibilities for this kind of feature.
21:57:56  <bterlson>and it's fair to say that reading has way more utility than writing I think?
21:58:24  <samth>rbuckton: right, but this is a big change to the model of the language
21:58:41  <samth>And so you want comparably big use cases
21:58:43  <cloudshu>i think a lot more motivation is needed than "just a general feature" if you're talking about adding &
21:59:06  <rbuckton>samth, yes and no. `ref` can be modeled today with object literals, but its fairly verbose.
21:59:29  <cloudshu>it needs closures, no?
21:59:42  <cloudshu>there's nothing else that forces a binding to be observably persisted beyond its frame
22:00:14  <rbuckton>using functions for forward references is a footgun for decorators when capturing a forward reference to a class. Its much more difficult to distinguish between `@Type(MyClass)` and `@Type(() => MyClass)` as the argument in both cases is a function.
22:01:35  <cloudshu>ah i see
22:01:41  <rbuckton>cloudshu, in the general case yes, but engines could optimize some common cases.
22:02:27  <cloudshu>so, am i being cynical here or does this seem like
22:02:44  <cloudshu>TDZ is making some case hard. let's add something that'll let us work around TDZ
22:04:46  <bterlson>no tdz wouldn't help forward refs would it? You get an undefined value rather than a thing you can query for a value later?
22:05:27  <rbuckton>I tend to look at `&` and `ref` as different. `&` often implies addresses and pointers and unmanaged memory. `ref` generally implies a reference to a value that is still susceptible to GC and can be moved around in the heap (e.g. moving out of nursery, compaction, etc.).
22:06:10  * not-an-aardvarkjoined
22:06:26  <cloudshu>bterlson: functions would
22:06:50  <bterlson>right I agree function wrapping is a way to get this behavior
22:07:08  <cloudshu>bterlson: that both the class ctor is typeof "function" and a thunk that returns the class ctor is typeof "function" is unfortunate though
22:07:59  <samth>rbuckton: ref is just addressof in JavaScript, where pointers are objects and everything is safe
22:08:25  <bterlson>and the points don't matter
22:09:09  <rbuckton>samth, yes. Its similar in C#, except in C# you have both `ref` (which points to a managed reference) and `&` (which points to unmanaged memory).
22:12:26  <cloudshu>my mental model for this is still that it'll mainly benefit codegen for compiling other managed languages that have such managed pointers
22:13:35  <rbuckton>`ref` expressions are effectively syntactic sugar over something you can do today with functions or an object literal. They have the added benefit of removing ambiguity between constructors and thunks for decorators, and a much simpler (and well trodden in other languages) syntax.
22:15:31  <cloudshu>rbuckton: adding new syntax has a pretty high bar in my mind; what's the main pain point of using a library for this, more typing?
22:15:42  <cloudshu>rbuckton: or missed optimization opportunities?
22:15:49  <rbuckton>`ref` declarations allow you to simplify local bindings and avoid odd `this` behavior for calls (e.g. `a()` vs. `a.value()`), as well as allow engines to optimize away closures when both the decl and its initalizer are refs
22:18:20  <cloudshu>(actually why does this need a separate declaration type, why not just have ref values?)
22:18:29  <cloudshu>for optimization?
22:18:33  <rbuckton>cloudshu, I agree on the high bar for syntax. Decorators and forward references are a key driver. Another is that it is a powerful feature on its own that is commonly used in many other languages.
22:19:49  <bterlson>rbuckton: I want to see a real example of ref setting
22:20:15  <rbuckton>cloudshu, mostly for optimization. `ref` expressions and `ref` declarations could be two separate proposals, with `ref` declarations building on `ref` expressions, but both are small enough and closely related that keeping them together seemed the better choice for now.
22:20:22  <cloudshu>rbuckton: i find "commonly used in many other languages" too broad and handwavy for me to consider compelling :)
22:21:00  <rbuckton>bterlson, in C#, there are a fairly large number of examples of `ref` (and `out`, which is fairly similar).
22:21:02  <bterlson>also does `ref x = ref foo.x; x; x;` trigger a getter twice?
22:21:35  <bterlson>oh, once I guess
22:21:41  <cloudshu>rbuckton: ref declarations seem odd to me as proposed right now because being a ref seems like it should be composable with scope
22:21:42  <rbuckton>bterlson, yes it would trigger the getter twice.
22:22:38  <rbuckton>bterlson, consider this example instead: `ref x = ref ar[0]; x; x;` or `ref x = ref ar[0]; x; ar[0]++; x;`
22:23:04  <rbuckton>what do you mean by "composable with scope"?
22:23:23  <cloudshu>rbuckton: i might want let refs vs var refs
22:23:55  <Bakkot>Strongly disagree that this is a small feature
22:24:08  <cloudshu>as an implementer that example scares me for the increased attack surface
22:24:11  <cloudshu>the array example
22:24:25  <rbuckton>I did consider that: `let ref x` or `const ref x`. It seemed a bit verbose, and whats the use of `const y = 1; let ref x = ref y;` since `y` is const.
22:24:37  <Bakkot>your ref declarations and expressions are definitely simiar, but neither is at all what I'd call small
22:25:21  <ljharb>i think first-class refs is a really really big feature that changes the language in a significant way.
22:25:22  <rbuckton>Though on the other side: `let y = 1; const ref x = ref y;` does seem worthwhile
22:25:53  <cloudshu>refs are of course semantically just as safe as functions, but that at least part of their motivation is better optimization in the engine would suggest that they will receive different treatment in engines, which i think will significantly increase the surface of... possible security bugs
22:26:07  <cloudshu>don't consider than argument against, that's my general worry
22:26:10  <cloudshu>that*
22:26:23  <rbuckton>ljharb, I agree that it would. That impact alone seems to merit new syntax. If it was just for a corner case for decorators I don't feel it would be worth it.
22:26:31  <cloudshu>i have no right to speak since SABs
22:26:35  <ljharb>lol ^
22:26:36  <Bakkot>lol
22:26:50  <Bakkot>SABs enabled things which were strictly impossible before, to be fair
22:26:53  <ljharb>rbuckton: what's the need in decorators? i probably didn't read your readme thoroughly
22:27:56  <rbuckton>ljharb, forward references: `class A { @Type(B) get b() {} }; class B { @Type(A) get a() {} };` is an error today (regardless of TDZ)
22:28:36  <Bakkot>the advantage vs closures is just optimization?
22:28:39  <rbuckton>But `class A { @Type(ref B) get b() {} }; class B { @Type(ref A) get a() {} };` would not have this issue, and wouldn't be ambiguous between a thunk for a constructor and a constructor
22:29:03  <rbuckton>Bakkot, optimization (in the general case) and disambiguation (in the decorator case)
22:29:16  <Bakkot>optimization and readability in that, I guess, but otoh it kind of destroys the readability of the rest of the language.
22:29:21  <ljharb>rbuckton: right but then i could `export const foo = () => ref A;`, which is very different
22:29:26  <ljharb>i'm very concerned about readability.
22:30:21  <rbuckton>ljharb, compare that to: `export const foo = () => ({ get value() { return A; }, set value(v) { A = v; } });` if you wanted the exact same capability right now.
22:30:47  <cloudshu>Bakkot: that's a good point
22:31:17  <ljharb>i'm personally not interested in enabling circular references/deps
22:31:26  <cloudshu>Bakkot: not like JS has type specifiers. now i just have to wonder if things are refs
22:31:37  <rbuckton>Another use case we found on TypeScript is that it would make refactorings in an editor much easier, for extracting functions, etc. Refactoring out a part of a larger function where locals are mutated becomes a bit messy.
22:31:58  <cloudshu>Bakkot: though is that *much* worse than wondering if things are thunks?
22:32:10  <Bakkot>well, at least with thunks there's an explicit call
22:32:23  <Bakkot>currently "local variable reads/writes" is one of the only things in the entire language which is not side-effecting
22:32:54  <Bakkot>I would mourn that loss deeply
22:32:59  <rbuckton>a `ref` expression is just `typeof === "object"` and has a `value` accessor
22:33:23  <rbuckton>Though I can see your point with respect to `ref` declarations.
22:33:55  <rbuckton>Perhaps it *would* be better to separate the proposals
22:34:00  <Bakkot>yeah, the readability concern is much stronger for declarations than references
22:34:09  <Bakkot>though, uh
22:34:54  <rbuckton>How is that different than import and export bindings though?
22:35:33  <ljharb>import/export bindings aren't first class
22:35:39  <ljharb>but yes, i have the same readability concerns about those.
22:35:51  <ljharb>you can't pass around a binding; passing a binding anywhere reifies the value.
22:36:01  <ljharb>imo that's an important restriction.
22:36:06  <rbuckton>`import * as x from './y'` gives you a first class module object
22:36:23  <ljharb>sure, but mutable objects isn't anything new
22:36:28  <ljharb>in that case there's no bindings at all
22:36:42  <ljharb>it's def weird that it's a frozen object that could also change on you, sure.
22:37:20  <rbuckton>`ref` expressions behave no differently in that respect than a function closure
22:38:15  <ljharb>i agree - but it's expected that an invoked function could return anything
22:39:42  <ljharb>in that case then @Type could take a think for a type, instead of just a type itself, no?
22:39:44  <ljharb>*thunk
22:39:51  <ljharb>like `@Type(() => B)`
22:40:08  <Bakkot>if there's a lot of interest from other committee members I could maybe be pursuaded, but I feel like I should say up front that I would block the proposal as it stands right now; first-class references would be a major new feature which I don't think would be good fit for the language
22:40:09  <ljharb>that's usually how i work around these kinds of circular issues; just always require a thunk
22:40:11  <bterlson>mr. type check, how do you test for whether you have a thunk or the class itself?
22:40:17  <bterlson>assuming you're @Type
22:40:22  <ljharb>bterlson: you take a thunk unconditionally
22:40:26  <Bakkot>+ also I was just rereading https://mail.mozilla.org/pipermail/es-discuss/2015-June/043307.html today
22:40:40  <bterlson>how do you throw if you don't pass a thunk?
22:40:44  <bterlson>or does it just fail mysteriously
22:40:47  <ljharb>bterlson: so you throw if it's not a function, or if that function's length isn't 0
22:40:59  <ljharb>and yeah, there's no way to avoid weird behavior on an empty function.
22:41:06  <bterlson>so, fails mysteriously if you pass a class instead of thunk to class
22:41:26  <ljharb>sure, that is true. you could also throw if its `.name` wasn't the empty string, i suppose
22:41:39  <Bakkot>bterlson: I feel like... there are maybe some tools you're familiar with which could help with this problem...
22:41:42  <ljharb>i agree it's not perfect. but in this new proposal, how would you typecheck a ref?
22:41:53  <ljharb>(also yes, obv type systems solve this too)
22:41:55  <rbuckton>I think angular was doing something like `@Type(forwardRef(() => B))` where `forwardRef` would tag the function, but its really no safer than `@Type(() => B)`
22:42:33  <ljharb>unless we're talking about a Ref.isRef :-p
22:44:37  <rbuckton>Depends on if we add Number.isNumber, String.isString, etc.
22:45:47  <ljharb>those all have prototype methods that brand-check; so regardless if `ref` provides a new first-class kind of value, there'd have to be some way to brand-check it.
22:46:08  <rbuckton>I need to add this to the proposal as well: a `ref` expression creates a site object (similar to the array for a tagged template), so `(ref x) === (ref x)`.
22:47:38  <rbuckton>ljharb, the actual implementation would have some kind of %RefPrototype% that would have the get/set accessors that check the brand via internal slot.
22:47:50  <rbuckton>That's not in the strawman as of yet though.
22:47:58  <bterlson>now let's not get ahead of ourselves. Brand checks are evil, right? ;)
22:49:18  <ljharb>i was promised when toStringTag was left in ES6 that all new types would provide some form of brand checking :-)
23:00:00  <cloudshu>rbuckton: i think you've discovered that many of us have violent gut reactions to this thing. more concrete motivations over "it's a widely used feature elsewhere" would help a lot if you plan to advance this
23:02:12  <rbuckton>Fair enough.
23:31:35  <Bakkot>question: why is `const a = 0; a = 1` not an early error? is the reason just dynamic scope constructs?
23:31:48  <Bakkot>it could've been an early error in strict mode, at least
23:31:52  <Bakkot>... still could, maybe?
23:32:14  <Bakkot>but probably not.
23:49:39  <cloudshu>Bakkot: yeah, i'd guess with?
23:50:59  <cloudshu>that makes me sad that we didn't call unscopables "without"
23:53:34  <ljharb>omg total missed opportunity
23:53:51  <ljharb>i still want `Promise.empty = new Promise(() => {})` to be a thing
23:59:16  <bterlson>cloudshu: sorry haven't gotten to that issue I promised to look at yet. Is next week too late?
23:59:28  <cloudshu>bterlson: nope, next week is fine