yield and new : SpiderMonkey and the draft Spec

Dmitry A. Soshnikov dmitry.soshnikov at gmail.com
Mon Mar 14 13:22:27 PDT 2011


On 14.03.2011 23:02, Brendan Eich wrote:
>> I.e. again, what I notice (and asked), is that there's no any info in the draft spec about `this` value of the generator's context. I think it would be good to add this information.
> A generator function is still a function, and |this| binding is orthogonal to yield making the surrounding function a generator:
>
> js>  function gen() { yield [this, 1]; yield [this, 2]; yield [this, 3]; }
> js>  var obj = {foo: gen, toString: function(){return "[obj]"}}
> js>  var a = []
> js>  for (v in obj.foo()) a.push(v)
> 3
> js>  a[0][0] === obj
> true
> js>  a[0][0] === obj
> true
> js>  a[1][0] === obj
> true
> js>  a[2][0] === obj
> true
> js>  a.toString()
> "[obj],1,[obj],2,[obj],3"
>

Oh, I see.

A possible place to store |this| according to the current strawman is:


    Calling

Let |f| be a generator function. The semantics of a function call |f(x1, 
..., xn)| is:

Let E = a new VariableEnvironment record with mappings for |x1| ... |xn|
Let S = the current scope chain extended with E
Let V = a new generator object with
[[Scope]] = S
[[Code]] = f.[[Code]]
[[ExecutionContext]] = *null*

**[[ThisBinding]] = *GetBase(Reference(base, "f"))*

[[State]] = "newborn"
[[Handler]] = the standard generator handler
Return V


I.e. since here we don't create the context, at least can save |this| of 
the reference. For the example of the strawman it will be global, since 
f(...). And for your example with `obj.foo`, it's the `obj` object. OK, 
now it's clear.

And then in:


    Internal method: send

G.[[Send]]

Let State = G.[[State]]
If State = "executing" Throw Error
If State = "closed" Throw Error
Let X be the first argument
If State = "newborn"
If X != *undefined* Throw TypeError
Let K = a new execution context as for a function call

Let K.[[ThisBinding]] = G.[[ThisBinding]]

K.currentGenerator := G
K.scopeChain := G.[[Scope]]
Push K onto the stack
Return /Execute/(G.[[Code]])
G.[[State]] := "executing"
Let Result = /Resume/(G.[[ExecutionContext]], *normal*, X)
Return Result

And now everything's becoming clear.

> We'll clarify this in the strawman.
>

Yep, would be good.

Thanks again Brendan,

Dmitry.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110314/2103c80c/attachment.html>


More information about the es-discuss mailing list