Comment #1 on issue 4163 by [email protected]: Construct on generator functions
https://code.google.com/p/v8/issues/detail?id=4163

I think it's correct. Declarations like:

    function* g() {}

Are created like this:

14.4.14 Runtime Semantics: Evaluation

GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }

[...]
3. Let closure be GeneratorFunctionCreate(Normal, FormalParameters,
    GeneratorBody, scope, strict).
[...]

GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }

[...]
7. Let closure be GeneratorFunctionCreate(Normal, FormalParameters,
    GeneratorBody, funcEnv, strict).
[...]

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generator-function-definitions-runtime-semantics-evaluation

9.2.6 GeneratorFunctionCreate (kind, ParameterList, Body, Scope, Strict)

1. Let functionPrototype be the intrinsic object %Generator%.
2. Let F be FunctionAllocate(functionPrototype, Strict, "generator").
[...]

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorfunctioncreate

9.2.3 FunctionAllocate (functionPrototype, strict [,functionKind] )

[...]
4. If functionKind is "non-constructor", then
    a. Let functionKind be "normal".
    b. Let needsConstruct be false.
5. Else let needsConstruct be true.
[...]
9. If needsConstruct is true, then
    a. Set F’s [[Construct]] internal method to the definition specified in
       9.2.2.
    b. If functionKind is "generator", set the [[ConstructorKind]] internal
       slot of F to "derived".
    c. Else, set the [[ConstructorKind]] internal slot of F to "base".
    d. NOTE Generator functions are tagged as "derived" constructors to
       prevent [[Construct]] from preallocating a generator instance.
Generator instance objects are allocated when EvaluateBody is applied
       to the GeneratorBody of a generator function.
[...]

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-functionallocate

The [[ConstructorKind]] interal attribute of all generator functions is
therefore "derived". This matters when "instantiating" an iterable by invoking
a generator function via `new`:

9.2.2 [[Construct]] ( argumentsList, newTarget)

[...]
4. Let kind be F’s [[ConstructorKind]] internal slot.
[...]
6. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
[...]
8. If kind is "base", perform OrdinaryCallBindThis(F, calleeContext,
    thisArgument).
[...]

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-function-objects-construct-argumentslist-newtarget

Step 6 unconditionally sets [[thisBindingStatus]] to "uninitialized" via
NewFunctionEnvironment (see
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-newfunctionenvironment).

Step 8 is *not* taken in this case. That's critical because it is what
ultimately allows the `this` keyword to operate in normal functions:

9.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument )

[...]
9. Return envRec.BindThisValue(thisValue).

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinarycallbindthis

8.1.1.3.1 BindThisValue(V)

1. Let envRec be the function Environment Record for which the method was invoked.
2. Assert: envRec.[[thisBindingStatus]] is not "lexical".
3. If envRec.[[thisBindingStatus]] is "initialized", throw a ReferenceError exception.
4. Set envRec.[[thisValue]] to V.
5. Set envRec.[[thisBindingStatus]] to "initialized".
6. Return V.

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-bindthisvalue

So advancing an iterable created in this way:

    iter.next();

begins execution of the function body. A `this` reference looks like:

12.2.1.1 Runtime Semantics: Evaluation

PrimaryExpression : this

1. Return ResolveThisBinding( ) .

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-this-keyword

8.3.3 ResolveThisBinding ( )

1. Let envRec be GetThisEnvironment( ).
2. Return envRec.GetThisBinding().

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-resolvethisbinding

8.1.1.3.4 GetThisBinding ()

1. Let envRec be the function Environment Record for which the method was invoked.
2. Assert: envRec.[[thisBindingStatus]] is not "lexical".
3. If envRec.[[thisBindingStatus]] is "uninitialized", throw a ReferenceError exception.
4. Return envRec.[[thisValue]].

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-function-environment-records-getthisbinding

...and there's your ReferenceError!

--
You received this message because this project is configured to send all issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to