01:38
<jschoi>
* Property “names” probably would no longer be apt terminology; it could be more like Object.getOwnPropertyKeys.
01:44
<jschoi>
* Property “names” probably would no longer be apt terminology for non-string values; the method name could be like Object.getOwnPropertyKeys.
01:44
<jschoi>
* Property “names” probably would no longer be apt terminology for non-string keys; the method name could be like Object.getOwnPropertyKeys.
04:33
<loganfsmyth>
Anyone know what's going on here? Are we all misunderstanding? https://stackoverflow.com/questions/67855714/eval-declaration-instantiation-when-calling-context-is-evaluating-formal-param
05:42
<bakkot>
loganfsmyth: that note became stale as of https://github.com/tc39/ecma262/pull/1046
05:43
<bakkot>
I suppose I'll open a PR
05:44
<loganfsmyth>
excellent, that makes sense
05:48
<bakkot>
https://github.com/tc39/ecma262/pull/2428
05:48
<bakkot>
loganfsmyth: You want to answer the stackoverflow question or shall I try to dig up my old account?
05:50
<loganfsmyth>
I posted an answer, thanks!
18:39
<bakkot>
jmdyck: re https://github.com/tc39/ecma262/issues/2400, you suggest replacing "Set the code evaluation state of contextA such that when evaluation is resumed with a Completion v [...]." with "Resume contextB passing B-VALUE. Let v be the value returned by the resumed computation."
18:39
<bakkot>
problem: it is not generally the case that contextB is the thing which resumes the thing just suspended.
18:40
<bakkot>
e.g., in Await, it's not contextB which does the resumption, but rather some future Await Fulfilled Function (or Await Rejected Function, of course)
18:40
<bakkot>
I'm trying to think of an alternative phrasing which avoids this, but haven't come up with anything I like yet
18:43
<jmdyck>
"the thing which resumes" present tense? I say that contextB is the execution context that most recently resumed the evaluation of contextA.
18:43
<bakkot>

I'm focusing specifically on the step

Resume contextB passing B-VALUE. Let v be the value returned by the resumed computation.

18:43
<bakkot>
to me, that step implies that contextB is going to be the thing which provides v.
18:44
<bakkot>
and, by extension, is going to be the thing which subsequently resumes contextA.
18:46
<jmdyck>
Ah,okay. Well, it doesn't actually say that contextB will be returning v and resuming contextA, though that's what I would have thought.
18:47
<jmdyck>
I still don't grok Await machinery
18:49
<bakkot>
It's not just Await; the same issue arises for plain generators. contextB is the previous caller of Generator.prototype.next, whereas v is going to be provided by the next caller of Generator.prototype.next.
18:51
<bakkot>

Maybe something like

  1. Resume contextB passing B-VALUE.
  2. Assert: when control reaches here, contextA is once again the running execution context.
  3. Let v be the value with which contextA was resumed.
18:51
<jmdyck>
and those can be 'in' different contexts (w plain generators)?
18:52
<bakkot>
they are necessarily going to be in different contexts, since each call to .next (as with all function calls) creates and pushes a new context
18:53
<bakkot>
I guess I ought to have said "contextB is the execution context of the previous call of Generator.prototype.next", not "is the caller of"
18:53
<jmdyck>
sorry, i need to page this in
18:53
<jmdyck>
haven't thought about it for a while
18:58
<bakkot>
Not to worry, lots to page in
18:58
<bakkot>
I'll have a PR up in a bit
19:02
<jmdyck>
okay, i think i'm more or less up to speed
19:03
<jmdyck>
And yeah, the wording could be improved, but I'm not sure about your suggestion.
19:09
<jmdyck>
I think it needs to be clearer that the thread of control that performs the 'Resume' step has to then (suspend and) wait until it is Resumed (if ever), at which time a value (v) will be supplied.
19:10
<jmdyck>
Maybe it would suffice if we just defined 'Resume' somewhere.
19:12
<bakkot>
There's always an explicit suspension before the Resume, which maybe makes it clearer?
19:13
<bakkot>
Usually, but not quite always, immediately before the Resume
19:15
<bakkot>
Actually that's maybe false?
19:16
<jmdyck>
Note that GeneratorResume, GeneratorResumeAbrupt , and AsyncGeneratorResumeNext use the "Resume ... Let" step format, although those are all going "the other way", right?
19:16
<bakkot>
There's always an explicit "remove the current context from the stack", though
19:16
<bakkot>
Yeah. For those it makes sense because it really is the execution which is Resumed which is providing the value.
19:19
<jmdyck>
Having the "Resume" and "Let" in the same step helps (to some extent) convey that the 'lifetime' of the step includes a resume-to-suspend chunk of execution of another thread of control.
19:20
<bakkot>
now have a draft at https://github.com/tc39/ecma262/pull/2429
19:21
<bakkot>
I can see the case for having it be a single step, yeah. Hmm.
19:34
<jmdyck>
I have notes about suggesting an AO to have one place to clarify the semantics of transferring flow of control (suspend and resume).
19:36
<jmdyck>
Rather than having to convey it "inline" at each point where it occurs.
19:37
<jmdyck>
But I didn't want to pull that into 2400.
19:43
<jmdyck>
To the original point you raised, I could change "Let v be the value returned by the resumed computation." to something like "If contextA is ever resumed again, let v be the value supplied by the context that resumes it."
19:45
<jmdyck>
or maybe "... the value supplied at the time of resumption"
19:47
<bakkot>
I am pretty indifferent between that and the wording I used in the PR, which is "the value with which it was resumed"
19:47
<jmdyck>
that's fine too.
19:47
<bakkot>
I also changed all the places which do such a resumption to "Resume ... with v"
19:50
<bakkot>
PrepareForTailCall is going to just remain incoherent, I guess
19:53
<jmdyck>
I've updated that comment in 2400.
20:10
<jmdyck>
I forget, where do you discuss PrepareForTailCall?
20:14
<bakkot>
I don't
20:14
<bakkot>
I've been ignoring it because it's obnoxious, basically
20:18
<bakkot>
what it wants to say is, replace the current execution context with that of the new function, such that when you ultimately reach the Return algorithm step which would take you back to the Let result be Call(...). Return result. steps following this PrepareForTailCall, instead move control back to the most recent Let result be OrdinaryCallEvaluateBody(...) step, which is where the aforementioned Return result. step would have returned to
20:19
<bakkot>
but the problem is that "that of the new function" isn't really coherent, and in fact not all function invocations push a new context as their first step - revoked proxies, in particular, do not
20:22
<bakkot>
so, what PrepareForTailCall does instead is just pops the current execution context without transferring control back to the underlying context, and continues execution into Call. When Call returns, you are supposed to understand that this transfers control back to the step which did OrdinaryCallEvaluateBody.
20:22
<jmdyck>
"the new function" = the function passed to Call immediately after the invocation of PFTC?
20:23
<bakkot>
right
20:47
<jmdyck>
This involves EvaluateCall's Assert "... the above call will not return here ..."?
20:52
<jmdyck>
So it's similar to what I complain about in 2400, where manipulating the context stack is supposed to change where an operation will return to.
21:07
<jmdyck>
Is tail-call optimization observable in the spec?
21:10
<jmdyck>
(I.e., did the addition of TailCall stuff to the spec change the behavior required of implementations?)
21:34
<bakkot>
Theoretically, yes, although more as a matter of social consensus than as a question of what's actually clear from the written specification: the TailCall stuff is supposed to require that implementations implement proper tail calls.
21:35
<bakkot>
i.e., to allow you to write code which depends on very deep recursion as long as each recursive call is in tail position
21:36
<bakkot>
but since the spec as currently written does not have a notion of "running out of stack space", and since execution contexts are strictly a spec fiction, it's not entirely clear to me how the PrepareForTailCall stuff is supposed to require this
21:38
<bakkot>
however, as a stupid and I think unintentional side effect, it also has an effect on the realm used for the TypeError produced when invoking a revoked proxy
21:38
<bakkot>
when invoking such a proxy in tail position, that is
21:39
<bakkot>
previously it had a similar effect on the realm of the TypeError produced when invoking a class as a function, but that changed with the merge of https://github.com/tc39/ecma262/pull/2216.
21:39
<bakkot>
(there's still incorrect test262 tests about this which I haven't been able to work up the willpower to fix, given how inane this corner of the spec is: https://github.com/tc39/test262/issues/2978 )
21:45
<jmdyck>

the spec as currently written does not have a notion of "running out of stack space", and ... execution contexts are strictly a spec fiction

So the observable behavior exhibited by the spec model will be the same with or without the TailCall stuff, right?

21:48
<bakkot>
Other than the bit about the realm for the TypeError when invoking a revoked proxy, yes.
21:49
<jmdyck>
right, sorry, that.
21:51
<bakkot>
The idea is that, although we mostly pretend the spec is describing an abstract (and hence unbounded) machine, you are supposed to remember when looking at this part that in fact you are going to be running it on a real (and hence bounded) device, which means that execution contexts will correspond to some finite resource, and hence the requirement in PrepareForTailCall that you discard the old execution context before doing the tail call is supposed to be understood as a requirement that you do not consume more of said finite resource
21:52
<bakkot>
But again this is a "social consensus" thing, not something which is actually present in the spec-as-written
21:56
<jmdyck>
It seems like it should have been possible to express the idea/requirement without making the spec incoherent.
21:57
<bakkot>
I think it's possible that it's coherent if you have the right mental model of how execution contexts and "Return" work, I just don't know what that model is, and the spec does not lay it out
21:59
<jmdyck>
yeah, I tried to grasp something of that mental model in 2400.
21:59
<jmdyck>
But I suspect there are parts of the spec that have a conflicting mental model.