diff --git a/lib/6to5/transformers/spread.js b/lib/6to5/transformers/spread.js index 6c6cf6508c..9a90a95f7f 100644 --- a/lib/6to5/transformers/spread.js +++ b/lib/6to5/transformers/spread.js @@ -14,42 +14,68 @@ var getSpreadLiteral = function (spread, file) { }; var hasSpread = function (nodes) { - return nodes.length && _.last(nodes).type === "SpreadElement"; + var has = false; + _.each(nodes, function (node) { + if (node.type === "SpreadElement") { + has = true; + return false; + } + }); + return has; +}; + +var build = function (props, file) { + var nodes = []; + + var _props = []; + + var push = function () { + if (!_props.length) return; + nodes.push(b.arrayExpression(_props)); + _props = []; + }; + + _.each(props, function (prop) { + if (prop.type === "SpreadElement") { + push(); + nodes.push(getSpreadLiteral(prop, file)); + } else { + _props.push(prop); + } + }); + + push(); + + return nodes; }; exports.ArrayExpression = function (node, parent, file) { var elements = node.elements; if (!hasSpread(elements)) return; - var spread = elements.pop(); + var nodes = build(elements, file); + var first = nodes.shift(); - var concat = util.template("array-concat", { - ARGUMENT: getSpreadLiteral(spread, file) - }); + if (!nodes.length) return first; - concat.callee.object.elements = elements; - - return concat; + return b.callExpression(b.memberExpression(first, b.identifier("concat"), false), nodes); }; exports.CallExpression = function (node, parent, file) { var args = node.arguments; if (!hasSpread(args)) return; - var spread = args.pop(); - - var spreadLiteral = getSpreadLiteral(spread, file); var contextLiteral = b.literal(null); node.arguments = []; - if (args.length) { - var concat = util.template("array-concat"); - concat.arguments = [spreadLiteral]; - concat.callee.object.elements = args; - node.arguments.push(concat); + var nodes = build(args, file); + var first = nodes.shift(); + + if (nodes.length) { + node.arguments.push(b.callExpression(b.memberExpression(first, b.identifier("concat"), false), nodes)); } else { - node.arguments.push(spreadLiteral); + node.arguments.push(first); } var callee = node.callee; diff --git a/test/fixtures/syntax/spread/array-literal-first/actual.js b/test/fixtures/syntax/spread/array-literal-first/actual.js new file mode 100644 index 0000000000..3857ab97d4 --- /dev/null +++ b/test/fixtures/syntax/spread/array-literal-first/actual.js @@ -0,0 +1 @@ +var lyrics = [...parts, "head", "and", "toes"]; diff --git a/test/fixtures/syntax/spread/array-literal-first/expected.js b/test/fixtures/syntax/spread/array-literal-first/expected.js new file mode 100644 index 0000000000..ef93019076 --- /dev/null +++ b/test/fixtures/syntax/spread/array-literal-first/expected.js @@ -0,0 +1,3 @@ +"use strict"; +var _slice = Array.prototype.slice; +var lyrics = _slice.call(parts).concat(["head", "and", "toes"]); diff --git a/test/fixtures/syntax/spread/array-literal-middle/actual.js b/test/fixtures/syntax/spread/array-literal-middle/actual.js new file mode 100644 index 0000000000..9b354ad7cf --- /dev/null +++ b/test/fixtures/syntax/spread/array-literal-middle/actual.js @@ -0,0 +1 @@ +var a = [b, ...c, d]; diff --git a/test/fixtures/syntax/spread/array-literal-middle/expected.js b/test/fixtures/syntax/spread/array-literal-middle/expected.js new file mode 100644 index 0000000000..70e1aef3cc --- /dev/null +++ b/test/fixtures/syntax/spread/array-literal-middle/expected.js @@ -0,0 +1,3 @@ +"use strict"; +var _slice = Array.prototype.slice; +var a = [b].concat(_slice.call(c), [d]); diff --git a/test/fixtures/syntax/spread/array-literal-multiple/actual.js b/test/fixtures/syntax/spread/array-literal-multiple/actual.js new file mode 100644 index 0000000000..e65edc597a --- /dev/null +++ b/test/fixtures/syntax/spread/array-literal-multiple/actual.js @@ -0,0 +1 @@ +var a = [b, ...c, d, e, ...f]; diff --git a/test/fixtures/syntax/spread/array-literal-multiple/expected.js b/test/fixtures/syntax/spread/array-literal-multiple/expected.js new file mode 100644 index 0000000000..4e9bc9f415 --- /dev/null +++ b/test/fixtures/syntax/spread/array-literal-multiple/expected.js @@ -0,0 +1,3 @@ +"use strict"; +var _slice = Array.prototype.slice; +var a = [b].concat(_slice.call(c), [d, e], _slice.call(f)); diff --git a/test/fixtures/syntax/spread/method-call-first/actual.js b/test/fixtures/syntax/spread/method-call-first/actual.js new file mode 100644 index 0000000000..0d63c0ea63 --- /dev/null +++ b/test/fixtures/syntax/spread/method-call-first/actual.js @@ -0,0 +1 @@ +add(...numbers, foo, bar); diff --git a/test/fixtures/syntax/spread/method-call-first/expected.js b/test/fixtures/syntax/spread/method-call-first/expected.js new file mode 100644 index 0000000000..82d56c4065 --- /dev/null +++ b/test/fixtures/syntax/spread/method-call-first/expected.js @@ -0,0 +1,3 @@ +"use strict"; +var _slice = Array.prototype.slice; +add.apply(null, _slice.call(numbers).concat([foo, bar])); diff --git a/test/fixtures/syntax/spread/method-call-middle/actual.js b/test/fixtures/syntax/spread/method-call-middle/actual.js new file mode 100644 index 0000000000..b04a3f0223 --- /dev/null +++ b/test/fixtures/syntax/spread/method-call-middle/actual.js @@ -0,0 +1 @@ +add(foo, ...numbers, bar); diff --git a/test/fixtures/syntax/spread/method-call-middle/expected.js b/test/fixtures/syntax/spread/method-call-middle/expected.js new file mode 100644 index 0000000000..16b1508097 --- /dev/null +++ b/test/fixtures/syntax/spread/method-call-middle/expected.js @@ -0,0 +1,3 @@ +"use strict"; +var _slice = Array.prototype.slice; +add.apply(null, [foo].concat(_slice.call(numbers), [bar])); diff --git a/test/fixtures/syntax/spread/method-call-multiple/actual.js b/test/fixtures/syntax/spread/method-call-multiple/actual.js new file mode 100644 index 0000000000..c06ed01cfb --- /dev/null +++ b/test/fixtures/syntax/spread/method-call-multiple/actual.js @@ -0,0 +1 @@ +add(foo, ...numbers, bar, what, ...test); diff --git a/test/fixtures/syntax/spread/method-call-multiple/expected.js b/test/fixtures/syntax/spread/method-call-multiple/expected.js new file mode 100644 index 0000000000..69096bc7bd --- /dev/null +++ b/test/fixtures/syntax/spread/method-call-multiple/expected.js @@ -0,0 +1,3 @@ +"use strict"; +var _slice = Array.prototype.slice; +add.apply(null, [foo].concat(_slice.call(numbers), [bar, what], _slice.call(test)));