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 <[email protected]> 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 > [email protected] > https://mail.mozilla.org/listinfo/es-discuss > > >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

