10:04
<Luca Casonato>
what are people's opinons on changing the Map and Set constructor to not call Symbol.iterator on the passed value if the passed value brand checks as a Map/Set? So new Map(new Map()) would not call Map.prototype[Symbol.iterator] anymore
10:44
<Ashley Claymore>
We didn't do this for `Set.prototype.union` and co
10:51
<Ashley Claymore>
Do any engines have a faster path for this already, the value is a real Map and the iterator hasn't been modified 
10:54
<Ashley Claymore>
I am interested how much benefit there would be if we can modify array destructuring to avoid the iterator when destructuring an array
12:45
<yulia>
Is the draft schedule up yet?
13:48
<Chris de Almeida>
nearly
14:13
<Chris de Almeida>
draft schedule now available via reflector issue: https://github.com/tc39/Reflector/issues/558
15:20
<Luca Casonato>
I am interested how much benefit there would be if we can modify array destructuring to avoid the iterator when destructuring an array
Yes this was the next thing I was going to ask
15:22
<ljharb>
engines can already do that unobservably when they know the map/set isn't modified
15:38
<snek>
I don't think any engine does it for these, it's very annoying to track
15:38
<snek>
having the spec change would definitely help
15:41
<mgaudet>
Agreed with snek; while heroics are possible and sometimes happen, any place we can specify that no heroics are needed is appreciated
16:12
<iain>
We actually already optimize this path
16:13
<iain>
Although it would be nice if we didn't have to do all the careful plumbing to make sure it's a valid transformation
16:14
<ljharb>
(tbc i'm fully on board with having explicit fast paths for things that pass brand-checks)
16:25
<bakkot>
at least the map iterator isn't side-effecting
16:25
<bakkot>
array iteration is probably the most common case and the iterator has side effects all over the place
16:36
<Ashley Claymore>
Array iterator side-effecting in that it triggers MOP methods?
16:40
<bakkot>
sure and also getters
16:42
<bakkot>
also this is a good place for me to beat my drum of "iterating built ins does not need allocations" https://docs.google.com/document/d/1M5S-u3N3vQkVBGFCoaYt_ABPGl0EW16QQrvDBaY2FiE/edit
19:11
<shu>
Rob Palmer Chris de Almeida please accommodate https://github.com/tc39/agendas/pull/1889 if possible. i know that AsyncContext is held up on web integration stuff, and Scott represents the web side of it for Chrome, so i think it's important to get his input during plenary
19:13
<shu>
could a chair please ping me if the constraint could (or not) be accommodated?
19:13
<shu>
(in case of not, would try to find a secondary)
21:33
<James M Snell>

Hey all... had some feedback come up with regards to Explicit Resource Management today that I wanted to surface and get some input on. The question specifically is, "I think explicit resource management is missing a really important feature: The ability to transfer ownership. I need a way to "release" a variable I declared with using, especially to return it." ... essentially treating the ERM/using as similar to an RAII that can be moved away.

function foo() {
  using foo = new Foo();
  using bar = new Bar();
  // I only want foo or bar disposed if they are not returned
  if (someCondition()) return bar; 
  else return foo;
}
21:35
<James M Snell>
Unfortunately, since both are declared with using, both are going to be disposed when the function returns. The ask from the feedback is whether it would make sense to have some generalized "release" or "move" capability.. like return move bar, etc
21:37
<James M Snell>
obviously we can follow a pattern similar to DisposableStack and have the disposable object itself declare a move() method but that means allocating a new object or having to keep track of the moved state manually
21:37
<Duncan MacGregor>
So I think one of the good things about explicit resource management is its simplicity, there isn't much of an ownership or lifetime model to think about or to get wrong.
21:38
<James M Snell>
we can also null/undefined out the original decl and assign it to a regular scoped variable but that's also a bit wonky .... actually, nevermind, I don't think this works
21:38
<James M Snell>
100% agree
21:38
<Duncan MacGregor>
I think I'd prefer seeing people declaring move() themselves rather than trying to design something in the language.
21:39
<Duncan MacGregor>
But now I'm curious if typescript could layer a full borrow checker on top and do this automatically. :-)
21:52
<James M Snell>
Making every disposable object declare a move() is a bit ... difficult. From the conversation I'm having in another channel on this, "It has to allocate a new instance of itself and move all the contents over to it. This is a lot of work to write for every type. And if anything else in the world holds a (presumably non-owning) reference to the object, those references are now invalid, so it might not even be possible to implement move() correctly, at least without adding a layer of indirection."
22:16
<Duncan MacGregor>
I think I need to sleep on it. I've started writing an reply about 5 times, and deleted them 5 times. My essential concern is that both the 'other non-owning references becoming invalid' and the return of the resource suggest that it is leaking in ways that probably aren't good for an explicit allocated and released resource (the former because we seem to have lost ownership during the method's lifetime, and the latter because we can't require the result is allocated to a variable declared with using).
22:19
<James M Snell>
yeah, it's a tricky one
22:21
<James M Snell>
I prefer the simplicity of ERM as it is but compared to the typical RAII pattern in c++, etc it's a bit over simplified... and that's there the questions here are coming from. We have a code base that is quite heavy in RAII mechanisms and the c++ level with no equivalent at the JS level
22:22
<nicolo-ribaudo>
If we get Symbol.enter/exit, then you'd be able to declare a function `movable` that you'd use as `using x = movable(foo)`
22:23
<James M Snell>

Another example to stew on...

function foo() {
  using bar = new MyDisposable();
  if (someCondition()) throw new Error('boom'); // I want bar disposed in this case
  return bar;  // I don't want it disposed in this case
}
22:23
<James M Snell>
Is there an open proposal for this?
22:23
<James M Snell>
and is it functions only?
22:25
<nicolo-ribaudo>
Actually maybe you don't need .enter? (Sorry my element client is refusing to format markdown) Instead of ``` using foo = getObj() ``` you can do ``` const foo = getObj(); using move = movable(foo) ... move() ``` Where movable returns a function move that returns foo and has its own dispose method forwarded to foo, deactivated by move.
22:26
<James M Snell>
ah, ok, so it's essentially like declaring a disposable boxed type similar to DisposableStack
22:26
<nicolo-ribaudo>
Is there an open proposal for this?
We have https://github.com/tc39/proposal-explicit-resource-management/issues/195
22:26
<nicolo-ribaudo>
It was also discussed in the context of async context, maybe @legendecas:matrix.org knows if we actually have a proposal
22:27
<James M Snell>
Interesting ok
22:45
<Chengzhong Wu>
https://github.com/tc39/proposal-using-enforcement for Symbol.enter
23:32
<bakkot>
function movable(foo) {
  let dispose = foo[Symbol.dispose];
  if (typeof dispose !== 'function') throw new Error('not disposable');
  return {
    resource: foo,
    moved: false,
    [Symbol.dispose]() {
      if (this.moved) return;
      dispose.call(foo);
    },
    move() {
      this.moved = true;
      return foo;
    },
  }
}
23:33
<bakkot>
// usage:
function makeDisposable() {
  return {
    [Symbol.dispose]() {
      console.log('disposed');
    },
  };
}
{
  using movableFoo = movable(makeDisposable());
  const { resource: foo } = movableFoo;
  console.log('normal exit');
  // disposed
}
{
  using movableFoo = movable(makeDisposable());
  const { resource: foo } = movableFoo;
  movableFoo.move();
  console.log('moved before exit');
  // not disposed
}
23:33
<bakkot>
this seems like it's fine to leave to userland
23:33
<bakkot>
it's a little boilerplate I guess
23:49
<Ashley Claymore>
Could make .move return a new movable in the same way DisposableStack.p.move returns a new Stack
23:50
<Ashley Claymore>
or maybe just return the resource after nulling it out 
23:52
<Ashley Claymore>
though need to be careful moving in a _tearable_ hand over 
23:55
<bakkot>
I think just returning the resource is better for the cases described above; presumably the caller is not expecting this wrapped thing and a priori there is no reason to expect them to want to move it again
23:56
<Ashley Claymore>
```
return {
  p: moveable.move(),
  q: mightThrow()
}
```

23:56
<bakkot>
but good idea, returning the resource is a nice convenience, updated
23:56
<bakkot>
yeah it's easy to hold this wrong
23:56
<bakkot>
although this is also true of disposableStack.move()
23:56
<bakkot>
boundaries are always tricky
23:56
<bakkot>
not much to be done about that though without linear types
23:57
<Ashley Claymore>
Yeah, the point of stack.move is that it should be the very last expression 
23:57
<Ashley Claymore>
to ensure the time to move has truly arrived 
23:58
<shu>
if you return the resource and not a new movable, isn't that more like release()
23:58
<bakkot>
I guess but I liked the symmetry with disposableStack.move()
23:58
<shu>
but DS does return a new movable DS
23:59
<Ashley Claymore>
one difference is that the resource is itself a disposable, so it can be _used_ by the caller