On Jan 23, 2014, at 2:14 PM, Bradley Meck wrote:

> I was playing around with generators / looking at await for promises and 
> notices a very difficult thing revolving around generators not having a 
> reference to themselves.
> 
> See: 
> 
> https://gist.github.com/bmeck/72a0f4f448f20cf00f8c
> 
> I have to end up wrapping the generator function to get a reference to the 
> generator for passing to nested functions.
> 
> Is there a reason the execution context is not a generator / there is no 
> reference back to the generator during [[call]]?

The [[Call]] whose execution context is suspended and captured is by the 
generator instance is the actual call to the generator function that created 
that instance.  So, the this value of that context is the this value of that 
original call of the generator function. Creation and initialization of the 
generator instance takes place before executing the generator function body. 
This means there are some interesting ways that the this value manifests depend 
upon the nature of the this call. 

For example,
(this is what the ES6 spec. says should happen, I don't know if any 
implementation has this all correct yet)

Assume:
 
function g* () {"use strict"; yield "this: " + this};  //don't want undefined 
this turning into the global object

g.prototype = function toString() {return "a generator instances made by g"};
var obj = {
     g,
     toString() {return "obj"}
};

//plan function call
console.log(g().next().value);  //"this: undefined" 
//same as 
console.log(g.call(undefined).next().value);  
//Just like calling any function call, undefined is the default this value.

//method call
console.log(obj.g().next().value); //"this: obj"
//same as:
console.log(g.call(obj).next().value);  
//just like any method call

//explicit constructor call
console.log((new g()).next().value): //"this: a generator instances made by g"
//same as:
console.log(g.call(g[Symbol.create]()).next().value);  
//just like newing any constructor function

In other words, if you want this bound to the function instance within the body 
of the constructor function use the generator function as a constructor and new 
it. 

How, does it all work?  It depends upon the generator function being to 
distinguish an uninitialized generator instance from other objects.  This is 
something that all constructors that want to have the same behavior for both 
new and regular calls need to be able to do.

The prolog of a generator function (before capturing and suspending the 
execution context) looks at the this value that was passed to it.  If the this 
value is an uninitialized generator object (such as is returned by the @@create 
method of a generator function) it initializes that generator object, captures 
the execution context, and return the now initialized generator object that was 
passed in as its this. 

If the this value is anything else (undefined, any object that isn't an 
uninitialized generator instance) the prolog allocates a new generator instance 
(using @@create), initializes it, captures the context and returns the newly 
allocated  generator instance. 

In neither case is the original this binding modified.

Allen
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to