yield and new : SpiderMonkey and the draft Spec

Dmitry Soshnikov dmitry.soshnikov at gmail.com
Mon Mar 14 01:02:11 PDT 2011


Yep, thanks Brendan,

I filed the bug https://bugzilla.mozilla.org/show_bug.cgi?id=641436

But the thing with `this` is still interesting for me. So in this particular
case `this` should be set to `undefined`. Should it be always set to
`undefined` (strict) / global object and regardless -- calling from `new` or
via simple call? There nothing is said about `this` value of the
[[ExecutionContext]] created for the "newbord" generator. What should it be
set to?

Thanks,
Dmitry.

On Sun, Mar 13, 2011 at 11:39 PM, Brendan Eich <brendan at mozilla.com> wrote:

> Hi Dmitry,
>
> It looks to me like you've just found a bug in SpiderMonkey's generator
> implementation, which pre-dates the strawman:generators proposal by four+
> years. Please file it in the right place: https://bugzilla.mozilla.org/.
> Thanks.
>
> The bug is a regression. Here's what my Firefox 3-era JS shell does:
>
> js> // infinite objects generator
> js> let g = new function () {
>   this.x = 10;
>   while (true) {
>     yield;
>   }
> };
> js>
> js> // generate an array of 3 objects
> js> let objects = [1, 2, 3].map(function(i) g.next());
> js> objects
> ,,
> js> uneval(objects)
> [(void 0), (void 0), (void 0)]
>
> Clearly, yield; should not yield a mysterious object as the return value of
> g.next().
>
> /be
>
> On Mar 13, 2011, at 3:04 PM, Dmitry A. Soshnikov wrote:
>
>  Hello,
>
> I hope you can help with explaining of what is going on with `this` value
> inside the body of a generator?
>
> Consider e.g. the following case:
>
> // infinite objects generator
> let g = new function () {
>   this.x = 10;
>   while (true) {
>     yield;
>   }
> };
>
> // generate an array of 3 objects
> let objects = [1, 2, 3].map(function(i) g.next());
>
> console.dir(objects);
>
> Results:
>
> [
>     [[Class]]: "Array",
>     length: 3,
>     0: {
>         [[Class]]: "Object",
>         x: 10
>     },
>     1: {
>         [[Class]]: "Object"
>     },
>     2: {
>         [[Class]]: "Object"
>     }
> ]
>
> Only first object has `x` property. Also:
>
> console.log(objects[0] == objects[1]); // false
> console.log(objects[1] == objects[2]); // false
>
>
>
> As I understand, [[Construct]] activated by the `new` calls [[Call]] of the
> function, which produces the `g` generator. I look here:
> http://wiki.ecmascript.org/doku.php?id=strawman:generators and see:
>
> 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*
>         [[State]] = “newborn”
>         [[Handler]] = the standard generator handler
>     Return V
>
> So, `g` will be the generator with the needed [[Code]] and empty
> [[ExecutionContext]]. Notice, there nothing is said about `this` value.
>
> In calling `next` (i.e. `send(undefined)`) we get into:
>
> 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
>         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
>  We see that a new context is created but again, nothing is said about its
> `this` value.
>
> When evaluating *Execute*(G.[[Code]]) we with yield get into:
>
> Yielding
>
> The semantics of evaluating an expression of the form yield e is:
>
>     Let V ?= Evaluate(e)
>     Let K = the current execution context
>     Let O = K.currentGenerator
>     O.[[ExecutionContext]] := K
>     O.[[State]] := “suspended”
>     Pop the current execution context
>     Return (*normal*, V, *null*)
>
> Btw, what does "?=" mean?
>
> Here the K is the context created on in the `send` method (still we haven't
> any info about `this` value).
>
> The following call to `next` will again enter `send` method with
> `undefined` but we already get into:
>
> Resuming generators
>
> *Operation* *Resume*(K, completionType, V)
>
>     Push K onto the execution context stack
>     Let G = K.currentGenerator
>     Set the current scope chain to G.[[Scope]]
>     Continue executing K as if its last expression produced
> (completionType, V, *null*)
>  where we proceed with evaluating previously saved continuation. And again,
> nothing about `this` is said.
>
> As I see, during all these steps always the same K is passed around and
> evaluated. `This` value is a property of the context and K has it, but
> which?
>
> As was shown in the example above, `this` is set to the newly created
> object, but it's a current SpiderMonkey's behavior; don't know how it
> correlate with this draft spec.
>
> Consider e.g. the following example (tested in SpiderMonkey):
>
> g = new function() {
>   yield new Boolean((yield) == this)
> };
>
> console.log(''+ g.send(g.next())); // false
>
> g = new function() {
>   yield new Boolean(this == (yield))
> };
>
> console.log(''+ g.send(g.next())); // true
>
> Why in first call `yield` wasn't newly created object and in the second one
> -- it was? What actually _should_ yield without an argument yields?
> `undefined` I guess.
>
> So don't know which behavior is correct and whether it's a strange behavior
> in current SpiderMonkey.
>
> Thanks,
> Dmitry.
>  _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110314/6a45fca2/attachment-0001.html>


More information about the es-discuss mailing list