diff --git a/runtime/dev.js b/runtime/dev.js index 6e354771b..d9bce87c1 100644 --- a/runtime/dev.js +++ b/runtime/dev.js @@ -140,6 +140,9 @@ method = "next"; arg = undefined; } + + } else if (method === "return") { + context.abrupt("return", arg); } state = GenStateExecuting; @@ -182,6 +185,7 @@ generator.next = invoke.bind(generator, "next"); generator.throw = invoke.bind(generator, "throw"); + generator.return = invoke.bind(generator, "return"); return generator; } diff --git a/runtime/min.js b/runtime/min.js index f57e28fcc..a61de46b1 100644 --- a/runtime/min.js +++ b/runtime/min.js @@ -7,4 +7,4 @@ * additional grant of patent rights can be found in the PATENTS file in * the same directory. */ -(function(t,r,e){function n(t,r,e,n){return new o(t,r,e||null,n||[])}function o(t,r,n,o){function i(r,o){if(s===f)throw new Error("Generator is already running");if(s===p)throw new Error("Generator has already finished");for(;;){var i=l.delegate;if(i){try{var a=i.iterator[r](o);r="next",o=e}catch(c){l.delegate=null,r="throw",o=c;continue}if(!a.done)return s=h,a;l[i.resultName]=a.value,l.next=i.nextLoc,l.delegate=null}if("next"===r){if(s===u&&"undefined"!=typeof o)throw new TypeError("attempt to send "+JSON.stringify(o)+" to newborn generator");s===h?l.sent=o:delete l.sent}else if("throw"===r){if(s===u)throw s=p,o;l.dispatchException(o)&&(r="next",o=e)}s=f;try{var d=t.call(n,l);s=l.done?p:h;var a={value:d,done:l.done};if(d!==y)return a;l.delegate&&"next"===r&&(o=e)}catch(v){s=p,"next"===r?l.dispatchException(v):o=v}}}var a=r?Object.create(r.prototype):this,l=new c(o),s=u;return a.next=i.bind(a,"next"),a.throw=i.bind(a,"throw"),a}function i(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2]),this.tryEntries.push(r)}function a(t,r){var e=t.completion||{};e.type=0===r?"normal":"return",delete e.arg,t.completion=e}function c(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(i,this),this.reset()}function l(r){var e=r,n=t.Symbol;if(n&&n.iterator in r)e=r[n.iterator]();else if(!isNaN(r.length)){var o=-1;e=function i(){for(;++or;++r)this[t]=null},stop:function(){this.done=!0;var t=this.tryEntries[0],r=t.completion;if("throw"===r.type)throw r.arg;return this.rval},dispatchException:function(t){function r(r,n){return i.type="throw",i.arg=t,e.next=r,!!n}if(this.done)throw t;for(var e=this,n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n],i=o.completion;if("root"===o.tryLoc)return r("end");if(o.tryLoc<=this.prev){var a=s.call(o,"catchLoc"),c=s.call(o,"finallyLoc");if(a&&c){if(this.prev=0;--r){var e=this.tryEntries[r];if(e.tryLoc<=this.prev&&s.call(e,"finallyLoc")&&(e.finallyLoc===t||this.prev=0;--r){var e=this.tryEntries[r];if(e.tryLoc===t){var n=e.completion;if("throw"===n.type){var o=n.arg;a(e,r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,e){return this.delegate={iterator:l(t),resultName:r,nextLoc:e},y}}}}).apply(this,Function("return [this, function GeneratorFunction(){}]")()); \ No newline at end of file +(function(t,r,e){function n(t,r,e,n){return new o(t,r,e||null,n||[])}function o(t,r,n,o){function i(r,o){if(u===f)throw new Error("Generator is already running");if(u===p)throw new Error("Generator has already finished");for(;;){var i=l.delegate;if(i){try{var a=i.iterator[r](o);r="next",o=e}catch(c){l.delegate=null,r="throw",o=c;continue}if(!a.done)return u=h,a;l[i.resultName]=a.value,l.next=i.nextLoc,l.delegate=null}if("next"===r){if(u===s&&"undefined"!=typeof o)throw new TypeError("attempt to send "+JSON.stringify(o)+" to newborn generator");u===h?l.sent=o:delete l.sent}else if("throw"===r){if(u===s)throw u=p,o;l.dispatchException(o)&&(r="next",o=e)}else"return"===r&&l.abrupt("return",o);u=f;try{var d=t.call(n,l);u=l.done?p:h;var a={value:d,done:l.done};if(d!==y)return a;l.delegate&&"next"===r&&(o=e)}catch(v){u=p,"next"===r?l.dispatchException(v):o=v}}}var a=r?Object.create(r.prototype):this,l=new c(o),u=s;return a.next=i.bind(a,"next"),a.throw=i.bind(a,"throw"),a.return=i.bind(a,"return"),a}function i(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2]),this.tryEntries.push(r)}function a(t,r){var e=t.completion||{};e.type=0===r?"normal":"return",delete e.arg,t.completion=e}function c(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(i,this),this.reset()}function l(r){var e=r,n=t.Symbol;if(n&&n.iterator in r)e=r[n.iterator]();else if(!isNaN(r.length)){var o=-1;e=function i(){for(;++or;++r)this[t]=null},stop:function(){this.done=!0;var t=this.tryEntries[0],r=t.completion;if("throw"===r.type)throw r.arg;return this.rval},dispatchException:function(t){function r(r,n){return i.type="throw",i.arg=t,e.next=r,!!n}if(this.done)throw t;for(var e=this,n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n],i=o.completion;if("root"===o.tryLoc)return r("end");if(o.tryLoc<=this.prev){var a=u.call(o,"catchLoc"),c=u.call(o,"finallyLoc");if(a&&c){if(this.prev=0;--r){var e=this.tryEntries[r];if(e.tryLoc<=this.prev&&u.call(e,"finallyLoc")&&(e.finallyLoc===t||this.prev=0;--r){var e=this.tryEntries[r];if(e.tryLoc===t){var n=e.completion;if("throw"===n.type){var o=n.arg;a(e,r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,e){return this.delegate={iterator:l(t),resultName:r,nextLoc:e},y}}}}).apply(this,Function("return [this, function GeneratorFunction(){}]")()); \ No newline at end of file diff --git a/test/tests.es6.js b/test/tests.es6.js index deeb2dfb6..a5f830095 100644 --- a/test/tests.es6.js +++ b/test/tests.es6.js @@ -1797,3 +1797,51 @@ describe("for-of loops", function() { ], 6); }); }); + +describe("generator return method", function() { + if (!runningInTranslation) { + // The return method has not been specified or implemented natively, + // yet, so these tests need only pass in translation. + return; + } + + it("should work with newborn generators", function() { + function *gen() { + yield 0; + } + + var g = gen(); + + assert.deepEqual(g.return("argument"), { + value: "argument", + done: true + }); + + assertAlreadyFinished(g); + }); + + it("should behave as if generator actually returned", function() { + var executedFinally = false; + + function *gen() { + try { + yield 0; + } catch (err) { + assert.ok(false, "should not have executed the catch handler"); + } finally { + executedFinally = true; + } + } + + var g = gen(); + assert.deepEqual(g.next(), { value: 0, done: false }); + + assert.deepEqual(g.return("argument"), { + value: "argument", + done: true + }); + + assert.strictEqual(executedFinally, true); + assertAlreadyFinished(g); + }); +});