diff --git a/lib/coffee-script/nodes.js b/lib/coffee-script/nodes.js index 86df6927..28b6907e 100644 --- a/lib/coffee-script/nodes.js +++ b/lib/coffee-script/nodes.js @@ -87,7 +87,7 @@ }; Base.prototype.compileClosure = function(o) { - var args, argumentsNode, func, jumpNode, meth, parts; + var args, argumentsNode, func, jumpNode, meth, parts, ref3; if (jumpNode = this.jumps()) { jumpNode.error('cannot use a pure statement in an expression'); } @@ -105,7 +105,7 @@ func = new Value(func, [new Access(new Literal(meth))]); } parts = (new Call(func, args)).compileNode(o); - if (func.isGenerator) { + if (func.isGenerator || ((ref3 = func.base) != null ? ref3.isGenerator : void 0)) { parts.unshift(this.makeCode("(yield* ")); parts.push(this.makeCode(")")); } diff --git a/src/nodes.coffee b/src/nodes.coffee index 3c565894..973f4309 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -90,7 +90,7 @@ exports.Base = class Base meth = 'call' func = new Value func, [new Access new Literal meth] parts = (new Call func, args).compileNode o - if func.isGenerator + if func.isGenerator or func.base?.isGenerator parts.unshift @makeCode "(yield* " parts.push @makeCode ")" parts diff --git a/test/generators.coffee b/test/generators.coffee index 66447fdb..7932b482 100644 --- a/test/generators.coffee +++ b/test/generators.coffee @@ -218,3 +218,50 @@ test "symbolic operators has precedence over the `yield`", -> mapped = CoffeeScript.eval "(arr) -> (#{expression} for i in arr)" arrayEq mapped(values), collect yielded values + +test "yield handles 'this' correctly", -> + x = -> + yield switch + when true then yield => this + yield for item in [1] + yield => this + yield if true then yield => this + yield try throw yield => this + throw yield => this + + y = x.call [1, 2, 3] + + z = y.next() + arrayEq z.value(), [1, 2, 3] + ok z.done is false + + z = y.next 123 + ok z.value is 123 and z.done is false + + z = y.next() + arrayEq z.value(), [1, 2, 3] + ok z.done is false + + z = y.next 42 + arrayEq z.value, [42] + ok z.done is false + + z = y.next() + arrayEq z.value(), [1, 2, 3] + ok z.done is false + + z = y.next 456 + ok z.value is 456 and z.done is false + + z = y.next() + arrayEq z.value(), [1, 2, 3] + ok z.done is false + + z = y.next new Error "ignore me" + ok z.value is undefined and z.done is false + + z = y.next() + arrayEq z.value(), [1, 2, 3] + ok z.done is false + + throws -> y.next new Error "boom"