From 458e3d48f64f9d70884bc1a32bb0aa76d02f5617 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 12 Nov 2014 18:38:30 +1100 Subject: [PATCH] use Array.from instead of Array.prototype.slice in spread transformer and support NewExpression spreads - fixes #148 --- lib/6to5/templates/values.js | 5 ---- .../transformation/transformers/spread.js | 24 +++++++++++++++---- lib/6to5/types/builder-keys.json | 1 + .../classes/accessing-super-class/expected.js | 17 +++++++------ .../arrow-functions/expected.js | 2 +- .../rest-parameters/multiple/expected.js | 2 +- .../rest-parameters/single/expected.js | 2 +- .../spread/arguments/expected.js | 5 ++-- .../spread/array-literal-first/expected.js | 3 +-- .../spread/array-literal-middle/expected.js | 3 +-- .../spread/array-literal-multiple/expected.js | 3 +-- .../spread/array-literals/expected.js | 3 +-- .../expected.js | 3 +-- .../expected.js | 3 +-- .../expected.js | 5 ++-- .../expected.js | 5 ++-- .../spread/method-call-first/expected.js | 3 +-- .../spread/method-call-middle/expected.js | 3 +-- .../method-call-multiple-args/expected.js | 3 +-- .../spread/method-call-multiple/expected.js | 3 +-- .../spread/method-call-single-arg/expected.js | 3 +-- .../spread/new-expression/actual.js | 2 ++ .../spread/new-expression/expected.js | 12 ++++++++++ 23 files changed, 63 insertions(+), 52 deletions(-) delete mode 100644 lib/6to5/templates/values.js create mode 100644 test/fixtures/transformation/spread/new-expression/actual.js create mode 100644 test/fixtures/transformation/spread/new-expression/expected.js diff --git a/lib/6to5/templates/values.js b/lib/6to5/templates/values.js deleted file mode 100644 index 306193c7ef..0000000000 --- a/lib/6to5/templates/values.js +++ /dev/null @@ -1,5 +0,0 @@ -(function (obj) { - var arr = []; - for (var val of obj) arr.push(val); - return arr; -}); diff --git a/lib/6to5/transformation/transformers/spread.js b/lib/6to5/transformation/transformers/spread.js index a3f11826b5..f5b4023b87 100644 --- a/lib/6to5/transformation/transformers/spread.js +++ b/lib/6to5/transformation/transformers/spread.js @@ -5,10 +5,10 @@ var _ = require("lodash"); var getSpreadLiteral = function (spread, file) { var literal = spread.argument; if (!t.isArrayExpression(literal)) { - literal = util.template("call", { - OBJECT: file.addDeclaration("slice"), - CONTEXT: literal - }); + literal = t.callExpression( + t.memberExpression(t.identifier("Array"), t.identifier("from")), + [literal] + ); } return literal; }; @@ -96,3 +96,19 @@ exports.CallExpression = function (node, parent, file) { node.arguments.unshift(contextLiteral); }; + +exports.NewExpression = function (node, parent, file) { + var args = node.arguments; + if (!hasSpread(args)) return; + + var nodes = build(args, file); + var first = nodes.shift(); + + if (nodes.length) { + args = t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes); + } else { + args = first; + } + + return t.callExpression(file.addDeclaration("apply-constructor"), [node.callee, args]); +}; diff --git a/lib/6to5/types/builder-keys.json b/lib/6to5/types/builder-keys.json index 9d0bb05526..cf85a639df 100644 --- a/lib/6to5/types/builder-keys.json +++ b/lib/6to5/types/builder-keys.json @@ -12,6 +12,7 @@ "IfStatement": ["test", "consequent", "alternate"], "Literal": ["value"], "MemberExpression": ["object", "property", "computed"], + "NewExpression": ["callee", "arguments"], "ObjectExpression": ["properties"], "ParenthesizedExpression": ["expression"], "Program": ["body"], diff --git a/test/fixtures/transformation/classes/accessing-super-class/expected.js b/test/fixtures/transformation/classes/accessing-super-class/expected.js index afe1765d12..c9c28b5fee 100644 --- a/test/fixtures/transformation/classes/accessing-super-class/expected.js +++ b/test/fixtures/transformation/classes/accessing-super-class/expected.js @@ -1,6 +1,5 @@ "use strict"; -var _slice = Array.prototype.slice; var _classProps = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); @@ -26,11 +25,11 @@ var Test = (function (Foo) { Foo.prototype.test.call(this); foob(Foo); - Foo.call.apply(Foo, [this].concat(_slice.call(arguments))); - Foo.call.apply(Foo, [this, "test"].concat(_slice.call(arguments))); + Foo.call.apply(Foo, [this].concat(Array.from(arguments))); + Foo.call.apply(Foo, [this, "test"].concat(Array.from(arguments))); - Foo.prototype.test.call.apply(Foo.prototype, [this].concat(_slice.call(arguments))); - Foo.prototype.test.call.apply(Foo.prototype, [this, "test"].concat(_slice.call(arguments))); + Foo.prototype.test.call.apply(Foo.prototype, [this].concat(Array.from(arguments))); + Foo.prototype.test.call.apply(Foo.prototype, [this, "test"].concat(Array.from(arguments))); }; _extends(Test, Foo); @@ -40,8 +39,8 @@ var Test = (function (Foo) { writable: true, value: function () { Foo.foo.call(this); - Foo.foo.call.apply(Foo.foo, [this].concat(_slice.call(arguments))); - Foo.foo.call.apply(Foo.foo, [this, "test"].concat(_slice.call(arguments))); + Foo.foo.call.apply(Foo.foo, [this].concat(Array.from(arguments))); + Foo.foo.call.apply(Foo.foo, [this, "test"].concat(Array.from(arguments))); } } }, { @@ -49,8 +48,8 @@ var Test = (function (Foo) { writable: true, value: function () { Foo.prototype.test.call(this); - Foo.prototype.test.call.apply(Foo.prototype.test, [this].concat(_slice.call(arguments))); - Foo.prototype.test.call.apply(Foo.prototype.test, [this, "test"].concat(_slice.call(arguments))); + Foo.prototype.test.call.apply(Foo.prototype.test, [this].concat(Array.from(arguments))); + Foo.prototype.test.call.apply(Foo.prototype.test, [this, "test"].concat(Array.from(arguments))); } } }); diff --git a/test/fixtures/transformation/rest-parameters/arrow-functions/expected.js b/test/fixtures/transformation/rest-parameters/arrow-functions/expected.js index 641879f5cf..49c1d11e53 100644 --- a/test/fixtures/transformation/rest-parameters/arrow-functions/expected.js +++ b/test/fixtures/transformation/rest-parameters/arrow-functions/expected.js @@ -3,4 +3,4 @@ var _slice = Array.prototype.slice; var concat = function () { var arrs = _slice.call(arguments); -}; \ No newline at end of file +}; diff --git a/test/fixtures/transformation/rest-parameters/multiple/expected.js b/test/fixtures/transformation/rest-parameters/multiple/expected.js index 70f87316c0..f2f9ea4fe4 100644 --- a/test/fixtures/transformation/rest-parameters/multiple/expected.js +++ b/test/fixtures/transformation/rest-parameters/multiple/expected.js @@ -7,4 +7,4 @@ var t = function (f) { function t(f) { var items = _slice.call(arguments, 1); -} \ No newline at end of file +} diff --git a/test/fixtures/transformation/rest-parameters/single/expected.js b/test/fixtures/transformation/rest-parameters/single/expected.js index ef6466c8b0..306e5f6f68 100644 --- a/test/fixtures/transformation/rest-parameters/single/expected.js +++ b/test/fixtures/transformation/rest-parameters/single/expected.js @@ -7,4 +7,4 @@ var t = function () { function t() { var items = _slice.call(arguments); -} \ No newline at end of file +} diff --git a/test/fixtures/transformation/spread/arguments/expected.js b/test/fixtures/transformation/spread/arguments/expected.js index 7b910095cf..0eccf1909a 100644 --- a/test/fixtures/transformation/spread/arguments/expected.js +++ b/test/fixtures/transformation/spread/arguments/expected.js @@ -1,12 +1,11 @@ "use strict"; -var _slice = Array.prototype.slice; function foo() { - return bar.apply(null, ["test"].concat(_slice.call(arguments))); + return bar.apply(null, ["test"].concat(Array.from(arguments))); } function bar(one, two, three) { return [one, two, three]; } -foo("foo", "bar"); \ No newline at end of file +foo("foo", "bar"); diff --git a/test/fixtures/transformation/spread/array-literal-first/expected.js b/test/fixtures/transformation/spread/array-literal-first/expected.js index 92ba7217fa..ecd8112f3f 100644 --- a/test/fixtures/transformation/spread/array-literal-first/expected.js +++ b/test/fixtures/transformation/spread/array-literal-first/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -var lyrics = _slice.call(parts).concat(["head", "and", "toes"]); \ No newline at end of file +var lyrics = Array.from(parts).concat(["head", "and", "toes"]); diff --git a/test/fixtures/transformation/spread/array-literal-middle/expected.js b/test/fixtures/transformation/spread/array-literal-middle/expected.js index a7085e299e..2a970405c9 100644 --- a/test/fixtures/transformation/spread/array-literal-middle/expected.js +++ b/test/fixtures/transformation/spread/array-literal-middle/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -var a = [b].concat(_slice.call(c), [d]); \ No newline at end of file +var a = [b].concat(Array.from(c), [d]); diff --git a/test/fixtures/transformation/spread/array-literal-multiple/expected.js b/test/fixtures/transformation/spread/array-literal-multiple/expected.js index 281faa0a0b..96880747be 100644 --- a/test/fixtures/transformation/spread/array-literal-multiple/expected.js +++ b/test/fixtures/transformation/spread/array-literal-multiple/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -var a = [b].concat(_slice.call(c), [d, e], _slice.call(f)); \ No newline at end of file +var a = [b].concat(Array.from(c), [d, e], Array.from(f)); diff --git a/test/fixtures/transformation/spread/array-literals/expected.js b/test/fixtures/transformation/spread/array-literals/expected.js index 306c74e11e..b1a162d7e7 100644 --- a/test/fixtures/transformation/spread/array-literals/expected.js +++ b/test/fixtures/transformation/spread/array-literals/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -var lyrics = ["head", "and", "toes"].concat(_slice.call(parts)); \ No newline at end of file +var lyrics = ["head", "and", "toes"].concat(Array.from(parts)); diff --git a/test/fixtures/transformation/spread/contexted-computed-method-call-multiple-args/expected.js b/test/fixtures/transformation/spread/contexted-computed-method-call-multiple-args/expected.js index b169ad461e..0fd897d01f 100644 --- a/test/fixtures/transformation/spread/contexted-computed-method-call-multiple-args/expected.js +++ b/test/fixtures/transformation/spread/contexted-computed-method-call-multiple-args/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -obj[method].apply(obj, [foo, bar].concat(_slice.call(args))); \ No newline at end of file +obj[method].apply(obj, [foo, bar].concat(Array.from(args))); diff --git a/test/fixtures/transformation/spread/contexted-computed-method-call-single-arg/expected.js b/test/fixtures/transformation/spread/contexted-computed-method-call-single-arg/expected.js index 1baae55982..8af9ebcc52 100644 --- a/test/fixtures/transformation/spread/contexted-computed-method-call-single-arg/expected.js +++ b/test/fixtures/transformation/spread/contexted-computed-method-call-single-arg/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -obj[method].apply(obj, _slice.call(args)); \ No newline at end of file +obj[method].apply(obj, Array.from(args)); diff --git a/test/fixtures/transformation/spread/contexted-method-call-multiple-args/expected.js b/test/fixtures/transformation/spread/contexted-method-call-multiple-args/expected.js index cda8769889..49c38c3c2a 100644 --- a/test/fixtures/transformation/spread/contexted-method-call-multiple-args/expected.js +++ b/test/fixtures/transformation/spread/contexted-method-call-multiple-args/expected.js @@ -1,5 +1,4 @@ "use strict"; -var _slice = Array.prototype.slice; -foob.add.apply(foob, [foo, bar].concat(_slice.call(numbers))); -foob.test.add.apply(foob.test, [foo, bar].concat(_slice.call(numbers))); \ No newline at end of file +foob.add.apply(foob, [foo, bar].concat(Array.from(numbers))); +foob.test.add.apply(foob.test, [foo, bar].concat(Array.from(numbers))); diff --git a/test/fixtures/transformation/spread/contexted-method-call-single-arg/expected.js b/test/fixtures/transformation/spread/contexted-method-call-single-arg/expected.js index 9d0c650a61..f28d9430f5 100644 --- a/test/fixtures/transformation/spread/contexted-method-call-single-arg/expected.js +++ b/test/fixtures/transformation/spread/contexted-method-call-single-arg/expected.js @@ -1,5 +1,4 @@ "use strict"; -var _slice = Array.prototype.slice; -foob.add.apply(foob, _slice.call(numbers)); -foob.test.add.apply(foob.test, _slice.call(numbers)); \ No newline at end of file +foob.add.apply(foob, Array.from(numbers)); +foob.test.add.apply(foob.test, Array.from(numbers)); diff --git a/test/fixtures/transformation/spread/method-call-first/expected.js b/test/fixtures/transformation/spread/method-call-first/expected.js index 45b93b3cc8..296def7b48 100644 --- a/test/fixtures/transformation/spread/method-call-first/expected.js +++ b/test/fixtures/transformation/spread/method-call-first/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -add.apply(null, _slice.call(numbers).concat([foo, bar])); \ No newline at end of file +add.apply(null, Array.from(numbers).concat([foo, bar])); diff --git a/test/fixtures/transformation/spread/method-call-middle/expected.js b/test/fixtures/transformation/spread/method-call-middle/expected.js index 9df2185466..73fd6f679c 100644 --- a/test/fixtures/transformation/spread/method-call-middle/expected.js +++ b/test/fixtures/transformation/spread/method-call-middle/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -add.apply(null, [foo].concat(_slice.call(numbers), [bar])); \ No newline at end of file +add.apply(null, [foo].concat(Array.from(numbers), [bar])); diff --git a/test/fixtures/transformation/spread/method-call-multiple-args/expected.js b/test/fixtures/transformation/spread/method-call-multiple-args/expected.js index 7f0b028cd9..9b3257fd06 100644 --- a/test/fixtures/transformation/spread/method-call-multiple-args/expected.js +++ b/test/fixtures/transformation/spread/method-call-multiple-args/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -add.apply(null, [foo, bar].concat(_slice.call(numbers))); \ No newline at end of file +add.apply(null, [foo, bar].concat(Array.from(numbers))); diff --git a/test/fixtures/transformation/spread/method-call-multiple/expected.js b/test/fixtures/transformation/spread/method-call-multiple/expected.js index a340d3c2f6..9c0ff6d20e 100644 --- a/test/fixtures/transformation/spread/method-call-multiple/expected.js +++ b/test/fixtures/transformation/spread/method-call-multiple/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -add.apply(null, [foo].concat(_slice.call(numbers), [bar, what], _slice.call(test))); \ No newline at end of file +add.apply(null, [foo].concat(Array.from(numbers), [bar, what], Array.from(test))); diff --git a/test/fixtures/transformation/spread/method-call-single-arg/expected.js b/test/fixtures/transformation/spread/method-call-single-arg/expected.js index d0c52b6d23..98ed514a41 100644 --- a/test/fixtures/transformation/spread/method-call-single-arg/expected.js +++ b/test/fixtures/transformation/spread/method-call-single-arg/expected.js @@ -1,4 +1,3 @@ "use strict"; -var _slice = Array.prototype.slice; -add.apply(null, _slice.call(numbers)); \ No newline at end of file +add.apply(null, Array.from(numbers)); diff --git a/test/fixtures/transformation/spread/new-expression/actual.js b/test/fixtures/transformation/spread/new-expression/actual.js new file mode 100644 index 0000000000..72800dd42b --- /dev/null +++ b/test/fixtures/transformation/spread/new-expression/actual.js @@ -0,0 +1,2 @@ +new Numbers(...nums); +new Numbers(1, ...nums); diff --git a/test/fixtures/transformation/spread/new-expression/expected.js b/test/fixtures/transformation/spread/new-expression/expected.js new file mode 100644 index 0000000000..49f0e64e87 --- /dev/null +++ b/test/fixtures/transformation/spread/new-expression/expected.js @@ -0,0 +1,12 @@ +"use strict"; + +var _applyConstructor = function (Constructor, args) { + var bindArgs = [null].concat(args); + + var Factory = Constructor.bind.apply(Constructor, bindArgs); + + return new Factory(); +}; + +_applyConstructor(Numbers, Array.from(nums)); +_applyConstructor(Numbers, [1].concat(Array.from(nums)));