diff --git a/CHANGELOG.md b/CHANGELOG.md index 16839b2aa0..4bd19e8f17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ Gaps between patch versions are faulty/broken releases. +## 2.0.4 + + * Avoid being greedy when destructuring array iterables. + ## 2.0.3 * Hoist function declarations in system module formatter for circular references. diff --git a/lib/6to5/file.js b/lib/6to5/file.js index a74d1daa4b..370bdf1826 100644 --- a/lib/6to5/file.js +++ b/lib/6to5/file.js @@ -22,6 +22,7 @@ File.declarations = [ "tagged-template-literal", "interop-require", "to-array", + "sliced-to-array", "object-without-properties", "has-own", "slice" @@ -82,13 +83,19 @@ File.normaliseOptions = function (opts) { return opts; }; -File.prototype.toArray = function (node) { +File.prototype.toArray = function (node, i) { if (t.isArrayExpression(node)) { return node; } else if (t.isIdentifier(node) && node.name === "arguments") { return t.callExpression(t.memberExpression(this.addDeclaration("slice"), t.identifier("call")), [node]); } else { - return t.callExpression(this.addDeclaration("to-array"), [node]); + var declarationName = "to-array"; + var args = [node]; + if (i) { + args.push(t.literal(i)); + declarationName = "sliced-to-array"; + } + return t.callExpression(this.addDeclaration(declarationName), args); } }; diff --git a/lib/6to5/templates/sliced-to-array.js b/lib/6to5/templates/sliced-to-array.js new file mode 100644 index 0000000000..92a6db3aa8 --- /dev/null +++ b/lib/6to5/templates/sliced-to-array.js @@ -0,0 +1,12 @@ +(function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + if (i && _arr.length === i) break; + } + return _arr; + } +}); diff --git a/lib/6to5/transformation/transformers/es6-destructuring.js b/lib/6to5/transformation/transformers/es6-destructuring.js index bb563bcb34..b8c25e23ff 100644 --- a/lib/6to5/transformation/transformers/es6-destructuring.js +++ b/lib/6to5/transformation/transformers/es6-destructuring.js @@ -1,6 +1,7 @@ // TODO: Clean up var t = require("../../types"); +var _ = require("lodash"); var buildVariableAssign = function (opts, id, init) { var op = opts.operator; @@ -61,9 +62,21 @@ var pushObjectPattern = function (opts, nodes, pattern, parentId) { }; var pushArrayPattern = function (opts, nodes, pattern, parentId) { + if (!pattern.elements) return; + + var hasSpreadElement = false; + for (var i in pattern.elements) { + if (t.isSpreadElement(pattern.elements[i])) { + hasSpreadElement = true; + break; + } + } + + var toArray = opts.file.toArray(parentId, !hasSpreadElement && pattern.elements.length); + var _parentId = opts.file.generateUidIdentifier("ref", opts.scope); nodes.push(t.variableDeclaration("var", [ - t.variableDeclarator(_parentId, opts.file.toArray(parentId)) + t.variableDeclarator(_parentId, toArray) ])); parentId = _parentId; diff --git a/test/fixtures/transformation/es6-constants/destructuring/expected.js b/test/fixtures/transformation/es6-constants/destructuring/expected.js index ed8c636697..e95cc916ac 100644 --- a/test/fixtures/transformation/es6-constants/destructuring/expected.js +++ b/test/fixtures/transformation/es6-constants/destructuring/expected.js @@ -1,18 +1,29 @@ "use strict"; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; var _ref = [1, 2]; -var _ref2 = _toArray(_ref); +var _ref2 = _slicedToArray(_ref, 2); var a = _ref2[0]; var b = _ref2[1]; var _ref3 = [3, 4]; -var _ref4 = _toArray(_ref3); +var _ref4 = _slicedToArray(_ref3, 2); var c = _ref4[0]; var d = _ref4[1]; diff --git a/test/fixtures/transformation/es6-destructuring/array/expected.js b/test/fixtures/transformation/es6-destructuring/array/expected.js index 0aadc101ca..9ed0154226 100644 --- a/test/fixtures/transformation/es6-destructuring/array/expected.js +++ b/test/fixtures/transformation/es6-destructuring/array/expected.js @@ -1,18 +1,29 @@ "use strict"; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; var _ref = ["hello", [", ", "junk"], ["world"]]; -var _ref2 = _toArray(_ref); +var _ref2 = _slicedToArray(_ref, 4); var a = _ref2[0]; -var _ref3 = _toArray(_ref2[1]); +var _ref3 = _slicedToArray(_ref2[1], 1); var b = _ref3[0]; -var _ref4 = _toArray(_ref2[2]); +var _ref4 = _slicedToArray(_ref2[2], 1); var c = _ref4[0]; var d = _ref2[3]; diff --git a/test/fixtures/transformation/es6-destructuring/assignment-expression/expected.js b/test/fixtures/transformation/es6-destructuring/assignment-expression/expected.js index ff82bc596a..1e12ecf071 100644 --- a/test/fixtures/transformation/es6-destructuring/assignment-expression/expected.js +++ b/test/fixtures/transformation/es6-destructuring/assignment-expression/expected.js @@ -1,8 +1,19 @@ "use strict"; var _temp, _ref; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; -console.log((_temp = [123], _ref = _toArray(_temp), x = _ref[0], _temp)); +console.log((_temp = [123], _ref = _slicedToArray(_temp, 1), x = _ref[0], _temp)); diff --git a/test/fixtures/transformation/es6-destructuring/assignment-statement/expected.js b/test/fixtures/transformation/es6-destructuring/assignment-statement/expected.js index 7e6b97872e..607c84dd53 100644 --- a/test/fixtures/transformation/es6-destructuring/assignment-statement/expected.js +++ b/test/fixtures/transformation/es6-destructuring/assignment-statement/expected.js @@ -1,12 +1,23 @@ "use strict"; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; var _ref = f(); -var _ref2 = _toArray(_ref); +var _ref2 = _slicedToArray(_ref, 2); a = _ref2[0]; b = _ref2[1]; diff --git a/test/fixtures/transformation/es6-destructuring/empty/expected.js b/test/fixtures/transformation/es6-destructuring/empty/expected.js index a240dd6f32..dbf20c485f 100644 --- a/test/fixtures/transformation/es6-destructuring/empty/expected.js +++ b/test/fixtures/transformation/es6-destructuring/empty/expected.js @@ -1,18 +1,29 @@ "use strict"; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; var _ref = ["foo", "hello", [", ", "junk"], ["world"]]; -var _ref2 = _toArray(_ref); +var _ref2 = _slicedToArray(_ref, 5); var a = _ref2[1]; -var _ref3 = _toArray(_ref2[2]); +var _ref3 = _slicedToArray(_ref2[2], 1); var b = _ref3[0]; -var _ref4 = _toArray(_ref2[3]); +var _ref4 = _slicedToArray(_ref2[3], 1); var c = _ref4[0]; var d = _ref2[4]; diff --git a/test/fixtures/transformation/es6-destructuring/for-in/expected.js b/test/fixtures/transformation/es6-destructuring/for-in/expected.js index d4ac8ee3e3..05780f099f 100644 --- a/test/fixtures/transformation/es6-destructuring/for-in/expected.js +++ b/test/fixtures/transformation/es6-destructuring/for-in/expected.js @@ -1,11 +1,22 @@ "use strict"; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; for (var _ref in obj) { - var _ref2 = _toArray(_ref); + var _ref2 = _slicedToArray(_ref, 2); var name = _ref2[0]; var value = _ref2[1]; diff --git a/test/fixtures/transformation/es6-destructuring/for-of/expected.js b/test/fixtures/transformation/es6-destructuring/for-of/expected.js index bac70afd43..567f5c48f1 100644 --- a/test/fixtures/transformation/es6-destructuring/for-of/expected.js +++ b/test/fixtures/transformation/es6-destructuring/for-of/expected.js @@ -1,12 +1,23 @@ "use strict"; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; for (var _iterator = this.test.expectation.registers[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { var _ref = _step.value; - var _ref2 = _toArray(_ref); + var _ref2 = _slicedToArray(_ref, 3); var name = _ref2[0]; var before = _ref2[1]; diff --git a/test/fixtures/transformation/es6-destructuring/member-expression/expected.js b/test/fixtures/transformation/es6-destructuring/member-expression/expected.js index 6d7052f982..3c54acdb95 100644 --- a/test/fixtures/transformation/es6-destructuring/member-expression/expected.js +++ b/test/fixtures/transformation/es6-destructuring/member-expression/expected.js @@ -1,12 +1,23 @@ "use strict"; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; var _ref = [1, 2]; -var _ref2 = _toArray(_ref); +var _ref2 = _slicedToArray(_ref, 2); this.foo = _ref2[0]; this.bar = _ref2[1]; diff --git a/test/fixtures/transformation/es6-destructuring/mixed/expected.js b/test/fixtures/transformation/es6-destructuring/mixed/expected.js index 843cf59408..d06f6220f7 100644 --- a/test/fixtures/transformation/es6-destructuring/mixed/expected.js +++ b/test/fixtures/transformation/es6-destructuring/mixed/expected.js @@ -1,14 +1,25 @@ "use strict"; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; -var _ref = _toArray(rect.topLeft); +var _ref = _slicedToArray(rect.topLeft, 2); var x1 = _ref[0]; var y1 = _ref[1]; -var _ref2 = _toArray(rect.bottomRight); +var _ref2 = _slicedToArray(rect.bottomRight, 2); var x2 = _ref2[0]; var y2 = _ref2[1]; diff --git a/test/fixtures/transformation/es6-destructuring/parameters/expected.js b/test/fixtures/transformation/es6-destructuring/parameters/expected.js index 79d996786a..3eeb1c713b 100644 --- a/test/fixtures/transformation/es6-destructuring/parameters/expected.js +++ b/test/fixtures/transformation/es6-destructuring/parameters/expected.js @@ -1,7 +1,18 @@ "use strict"; -var _toArray = function (arr) { - return Array.isArray(arr) ? arr : Array.from(arr); +var _slicedToArray = function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else { + var _arr = []; + for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; + } }; function somethingAdvanced(_ref) { @@ -20,12 +31,12 @@ function unpackObject(_ref2) { console.log(unpackObject({ title: "title", author: "author" })); var unpackArray = function (_ref3, _ref5) { - var _ref4 = _toArray(_ref3); + var _ref4 = _slicedToArray(_ref3, 3); var a = _ref4[0]; var b = _ref4[1]; var c = _ref4[2]; - var _ref6 = _toArray(_ref5); + var _ref6 = _slicedToArray(_ref5, 3); var x = _ref6[0]; var y = _ref6[1];