0

I wanted to understand the internal mechanisms of a JavaScript engine for asynchronous functions, so I checked the Spec. For the rest of this question, I will refer to the linked version of the specification.

Section 6.2.3.1 describes this. Basically, a promise is created which is resolved to the expression that is awaited. The promise is then added resolving handlers via .then; The fulfillment handler is a function object created from an abstract closure which captures asyncContext which is the execution context associated to the asynchronous function. This abstract closure suspends the running execution context and restores asyncContext as the running execution context.

The thing I don't understand is: when this abstract closure gets called, isn't the execution context associated with itself the running execution context? Wouldn't this abstract closure suspend itself then? I believe so because .then [27.2.5.4.1 PerformPromiseThen] creates jobs via 27.2.2.1 NewPromiseReactionJob which creates an abstract closure that uses 9.5.3 HostCallJobCallback to call the handler which in turn must perform 7.3.14 Call on it, leading to an invocation of the [[Call]] internal method of the function object (10.2.1). This pushes a new execution context on the stack.

What am I misunderstanding? What does prevContext actually refer to in 6.2.3.1?

Stefan Octavian
  • 593
  • 6
  • 17
  • "*I will refer to the linked version of the specification.*" - the "version" you linked is the working draft, it changes daily. You might want to consider linking a specific stable version instead, especially when referring to sections by number. – Bergi Jul 26 '22 at 03:51
  • "*Wouldn't this abstract closure suspend itself then?*" - yes it does! Have a look at [this answer](https://stackoverflow.com/a/70663026/1048572) maybe. I do however agree that the language on suspending and resuming execution [could be improved](https://github.com/tc39/ecma262/issues/2618). – Bergi Jul 26 '22 at 04:01
  • @Bergi, oops. Thanks for that. I edit that link to lead to the stable June 2022 edition and made sure that (fortunately) all sections have the numbers written in the question. – Stefan Octavian Jul 26 '22 at 13:52

1 Answers1

1

Your problem might be the idea that there's an execution context "associated with" the abstract closure. The spec is a bit cagey on this point, but I think it's easier to understand examples like yours if you imagine spec algorithms (including abstract closures) as running "outside" any execution context. This then allows spec algorithms to suspend/resume/push/pop execution contexts without any effect on the running of those algorithms.

Michael Dyck
  • 2,153
  • 1
  • 14
  • 18
  • Running spec algorithms outside of "execution contexts" is important, yes, especially when it comes to suspending/resuming. However, abstract closures actually *do* have an execution context, they follow the rules of normal function calls. – Bergi Jul 26 '22 at 03:59
  • Oh, okay. This makes more sense now. I'm still trying to get a grip of how this works exactly, but I think I'll get there now that I understand this. – Stefan Octavian Jul 26 '22 at 13:57