Is the "initial global execution context" ever popped off the call stack in JavaScript? I am talking about the execution context that is at the bottom of the stack at all times.
Yes, it is. An empty execution context stack is the requirement for any jobs to run.
However, there is no such thing like an "initial global execution context", and since the stack can be empty there is no single context that is at the bottom of the stack all the time.
"Global execution contexts" are created in ScriptEvaluations. Every script does have its own scriptCxt
, yet all of them in a shared realm carry the same global environment records. These scriptCtx
s are not at the bottom at the stack, though.
An "initial execution context" that sits at the bottom of the stack is created in the ECMAScript Initialisation process. It is pretty meaningless, for it does not hold anything but the new realm and only serves as the context for the initialisation of the realm and global object, but it is also used to start off the job queues.
If so, I presume this means it is pushed onto the stack first before a callback is picked up off the Job Queue?
Yes indeed. We can see this from the instructions for the NextJob algorithm steps. These are performed at the end of the ECMAScript initialisation and end of every job, and basically read as follows:
- Suspend the current execution context and pop it from the stack so that the stack is empty.
- Get the next job from any queue. If there are no more, proceed as you want (i.e. typically shuts down the process).
- Create a new, empty (except for the realm of the job) context
newContext
and put it at the bottom of the stack
- Execute the selected job in this context (which starts over NextJob in the end)
These contexts serve as the base for every job, containing all execution that ever happens. In PromiseJobs, they are used rather directly, while in module- and script evaluation jobs other contexts will be pushed on the stack that serve to hold the respective environment records with whom the code should be executed.
Alternatively, is it the [[Scope]].outer chain that provides access to the global environment whenever a callback is pushed onto the stack?
Yes indeed. The scope chain (that is not to be confused with the execution context stack) does provide access from everywhere to the global environment, which sits at the end of every scope chain.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…