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?
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.
Are the environment record and exotic object creation procedures the same?
i.e. creation of a basic object with different internal slots and methods, than that of an ordinary object?
Are both objects constructed with the same %Object% intrinsic method?
P.S. Is it correct to refer to an environment record as a completed execution context?
An Environment Record isn't an object at all. (Or more precisely, there's no requirement that Environment Records be implemented as objects. Thinking of them as objects will probably hinder your understanding.)
Environment Records are "specification values", entities that are defined only as a device to specify semantics. In contrast, objects are "language values", values that your JavaScript code can actually manipulate.
P.S. Is it correct to refer to an environment record as a completed execution context?
Nope. Environment Records and Execution Contexts are distinct kinds of specification values. A typical Execution Context will refer to one or two Environment Records, to resolve identifiers in the code that it evaluates.
I was going through the scoping concept and I found out that it is possible to implement both lexical and dynamic scope. Can any one help me to understand what is the major difference between Lexical and Dynamic scope in accordance of JavaScript?
Also how can we implement it in JavaScript?
In lexical scoping, the variable can be called only from within the block of the code which it is defined. The scope of that variable is defined when the program is compiled. The variable can be accessed by its children's execution contexts. But it doesn't work backward to its parents, meaning that the variable likes cannot be accessed by its parents.
In dynamic scope, the variable declared can be called from outside the code block. In this, the compiler will search for the variable reference in the local function first, then it searches in the function that called the local function, then it searches in the function that called that function, and so on, up the call stack. "Dynamic" refers to change, in that the call stack can be different every time a given function is called, and so the function might hit different variables depending on where it is called from.
http://wiki.c2.com/?DynamicScoping
In his (great) series of books “You don't know JS", Kyle Simpson states that dynamic scope and this mecanism are "near cousin", he also says that :
"the this mechanism is kind of like dynamic scope."
(YDKJS, Scope and Closure, Appendix A)
What is preventing him from saying that this is plain and simple dynamic scoping ?
Also, in the book "this & Object Prototypes", also part of the series YDKJS, as far as I can say, Kyle is not mentioning once dynamic scope while discussing how thisis working, so I am a bit surprised why he decided to not go further in the analogy... Does anyone have an idea why ?
Thanks
The reason I claim this is just "kind of like" a dynamic scope and not actually a dynamic scope is based on these two observations:
The aesthetic of accessing the "scope context" explicitly with an object reference (this.foo = 1) is distinct from implicitly accessing it via lexical variable reference (foo = 1). At best, this makes the two systems of "scope" parallel, not the same. But there's more different than what it seems on the surface!
But more importantly, dynamic scopes are traditionally defined as scope chains that are based on the call-stack. That is, a dynamic scope is one where the decision of what "scope contexts" to consult, in order, is exactly the current stack of function calls. But this isn't based on the call-stack, per se, but rather just the manner in which the most recent call in the stack was made, only.
Consider this scenario: foo() calls bar(), bar() calls baz(), and in baz() a reference is made to an x variable that is not defined in baz().
In lexical scope, the lookup would be baz(), then whatever the outer scope of baz() is, and so on. bar() and foo() wouldn't be consulted at all, unless they happened to be the lexically surrounding scopes of baz().
In dynamic scope, the call stack foo() -> bar() -> baz() is the scope chain, so baz() is consulted, then bar(), then foo(), regardless of where those 3 functions exist lexically in the code base.
Now, consider the same scenario, but this.x is the reference made inside baz(). The call stack foo() -> bar() -> baz() is not particularly relevant in resolving this.x. Rather, the only thing that matters is how baz() was invoked. If the call site is baz(), the "default binding" rule applies. If it's this.baz(), the "implicit binding" rule applies. If it's baz.call(..), the "explicit binding" rule applies. And if it's new baz(), the "new binding" rule applies. That's it.
Actually, it's not the only thing, it's just the first decision that's made. Once it's determined what object (aka scope context object) this points to, now the only thing that matters is the prototype chain of that object, as that's the "scopes" that will be consulted, in order of the prototype chain linkage.
Summary:
In lexical scope, where a function is defined is the only thing that determines what contexts are used, and in what order, to resolve a variable reference.
in dynamic scope, where a function is called from is the only thing that determines what contexts are used, and in what order, to resolve a variable reference.
in this-based context, neither where a function is defined nor where it's called from are relevant. Therefore, this is neither lexical scoping nor dynamic scoping.
The only thing that matters here is how the current function in the call stack (top of the stack) was called. Well, that's the only thing that matters to determine which scope chain to start the lookup on. But once that object is decided, it's now that object's prototype chain that entirely defines the scope resolution.
Because the this "variable" is the only variable that has dynamic scope, all other ("real") variables have lexical scope in JavaScript. In contrast, in "plain and simple dynamic scoping", all variables have dynamic scope and you can't get away from it (which is really ugly). So when we want to have multiple values in our dynamic scope, we store them in an object, and access them as properties of the this object, which is quite different from dynamic scope and also involves object inheritance.
Writing the following will result in the evaluation of the Function constructor function, resulting in the presence of a property on the global object pointing to a function-object instance Foo.
function Foo() {}
Execution contexts are created when functions are invoked, hence has an execution context other than the global one been created even without invocation of Foo?
My thinking is as follows:
Everything is an object in JavaScript (with minor exceptions related to primitives). Objects are created by functions. Foo is an object. A function has been invoked.
Answering my own question, based on the long comment list above.
No execution context is created because execution contexts are only meaningful for user-defined code. For the internal operation of a JavaScript engine, such as the precise mechanism for the creation of the function-object Foo in the code in the question, are left to engine implementers.