From 5ba2e6254b43be5a0b14e797c3e2b311c87dd557 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 21 Feb 2015 18:00:43 +1100 Subject: [PATCH] check if iterator has a return method before calling it when breaking in a for...of - #838 --- lib/babel/transformation/transformers/es6/for-of.js | 13 +++++++++++-- .../es6-for-of-loose/break/expected.js | 6 +++--- .../transformation/es6-for-of/break/expected.js | 8 +++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/babel/transformation/transformers/es6/for-of.js b/lib/babel/transformation/transformers/es6/for-of.js index 2343a57e09..935d1dcc19 100644 --- a/lib/babel/transformation/transformers/es6/for-of.js +++ b/lib/babel/transformation/transformers/es6/for-of.js @@ -53,7 +53,7 @@ var breakVisitor = { var ret = t.expressionStatement( t.callExpression(t.memberExpression(state.iteratorKey, t.identifier("return")), []) ); - if (state.wrapReturn) ret = state.wrapReturn(ret); + ret = state.wrapReturn(ret); this.skip(); return [ret, node]; @@ -100,7 +100,13 @@ var loose = function (node, parent, scope, file) { scope.traverse(node, breakVisitor, { iteratorKey: iteratorKey, wrapReturn: function (node) { - return t.ifStatement(t.unaryExpression("!", isArrayKey, true), node); + return t.ifStatement( + t.logicalExpression( + "&&", + t.unaryExpression("!", isArrayKey, true), + t.memberExpression(iteratorKey, t.identifier("return") + ) + ), node); }, label: t.isLabeledStatement(parent) && parent.label.name }); @@ -146,6 +152,9 @@ var spec = function (node, parent, scope, file) { scope.traverse(node, breakVisitor, { iteratorKey: iteratorKey, + wrapReturn: function (node) { + return t.ifStatement(t.memberExpression(iteratorKey, t.identifier("return")), node); + }, label: t.isLabeledStatement(parent) && parent.label.name }); diff --git a/test/fixtures/transformation/es6-for-of-loose/break/expected.js b/test/fixtures/transformation/es6-for-of-loose/break/expected.js index 8a0183d098..c83887fadf 100644 --- a/test/fixtures/transformation/es6-for-of-loose/break/expected.js +++ b/test/fixtures/transformation/es6-for-of-loose/break/expected.js @@ -17,7 +17,7 @@ foo: for (var _iterator = foo(), _isArray = Array.isArray(_iterator), _i = 0, _i var x = _ref; while (true) { - if (!_isArray) _iterator["return"](); + if (!_isArray && _iterator["return"]) _iterator["return"](); break foo; } @@ -55,7 +55,7 @@ foo: for (var _iterator3 = foo(), _isArray3 = Array.isArray(_iterator3), _i3 = 0 } var x = _ref3; - if (!_isArray3) _iterator3["return"](); + if (!_isArray3 && _iterator3["return"]) _iterator3["return"](); break foo; } @@ -75,7 +75,7 @@ for (var _iterator4 = foo(), _isArray4 = Array.isArray(_iterator4), _i4 = 0, _it } var x = _ref4; - if (!_isArray4) _iterator4["return"](); + if (!_isArray4 && _iterator4["return"]) _iterator4["return"](); break; } diff --git a/test/fixtures/transformation/es6-for-of/break/expected.js b/test/fixtures/transformation/es6-for-of/break/expected.js index 20a7d2f79f..fe7b0f9d20 100644 --- a/test/fixtures/transformation/es6-for-of/break/expected.js +++ b/test/fixtures/transformation/es6-for-of/break/expected.js @@ -6,7 +6,7 @@ foo: for (var _iterator = foo()[Symbol.iterator](), _step; !(_step = _iterator.n var x = _step.value; while (true) { - _iterator["return"](); + if (_iterator["return"]) _iterator["return"](); break foo; } @@ -22,8 +22,7 @@ foo: for (var _iterator2 = foo()[Symbol.iterator](), _step2; !(_step2 = _iterato foo: for (var _iterator3 = foo()[Symbol.iterator](), _step3; !(_step3 = _iterator3.next()).done;) { var x = _step3.value; - - _iterator3["return"](); + if (_iterator3["return"]) _iterator3["return"](); break foo; } @@ -32,8 +31,7 @@ foo: for (var _iterator3 = foo()[Symbol.iterator](), _step3; !(_step3 = _iterato for (var _iterator4 = foo()[Symbol.iterator](), _step4; !(_step4 = _iterator4.next()).done;) { var x = _step4.value; - - _iterator4["return"](); + if (_iterator4["return"]) _iterator4["return"](); break; }