Skip to content

Commit

Permalink
Correctly transform spreads to use proper concat method
Browse files Browse the repository at this point in the history
  • Loading branch information
danez committed Dec 1, 2018
1 parent 806e133 commit 5304442
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 11 deletions.
Expand Up @@ -21,7 +21,7 @@ var _ref4 = [a[1], a[0]];
a[0] = _ref4[0];
a[1] = _ref4[1];

var _ref5 = babelHelpers.toConsumableArray(foo).concat([bar]),
var _ref5 = Array.prototype.concat(babelHelpers.toConsumableArray(foo), [bar]),
a = _ref5[0],
b = _ref5[1];

Expand Down
41 changes: 33 additions & 8 deletions packages/babel-plugin-transform-spread/src/index.js
Expand Up @@ -57,19 +57,44 @@ export default declare((api, options) => {
if (!hasSpread(elements)) return;

const nodes = build(elements, scope);
const first = nodes.shift();
const first = nodes[0];

if (nodes.length === 0 && first !== elements[0].argument) {
// If there is only one element in the ArrayExpression and
// the element was transformed (Array.prototype.slice.call or toConsumableArray)
// we know that the transformed code already takes care of cloning the array.
// So we can simply return that element.
if (nodes.length === 1 && first !== elements[0].argument) {
path.replaceWith(first);
return;
}

path.replaceWith(
t.callExpression(
t.memberExpression(first, t.identifier("concat")),
nodes,
),
);
// If the first element is a ArrayExpression we can directly call
// concat on it.
// [..].concat(..)
// If not then we have to use Array.prototype.concat() and not identifier.concat
// because identifier could be extended/modified (e.g. Immutable) and we do not know exactly
// what concat would produce.
if (t.isArrayExpression(first)) {
path.replaceWith(
t.callExpression(
t.memberExpression(nodes.shift(), t.identifier("concat")),
nodes,
),
);
} else {
path.replaceWith(
t.callExpression(
t.memberExpression(
t.memberExpression(
t.identifier("Array"),
t.identifier("prototype"),
),
t.identifier("concat"),
),
nodes,
),
);
}
},

CallExpression(path) {
Expand Down
@@ -0,0 +1,9 @@
const arr = [];

arr.concat = () => {
throw new Error('Should not be called');
};

expect(() => {
const x = [...arr];
}).not.toThrow();
@@ -0,0 +1,7 @@
const arr = [];

arr.concat = () => {
throw new Error('Should not be called');
};

const x = [...arr];
@@ -0,0 +1,7 @@
const arr = [];

arr.concat = () => {
throw new Error('Should not be called');
};

const x = Array.prototype.concat(arr);
@@ -1 +1 @@
var lyrics = babelHelpers.toConsumableArray(parts).concat(["head", "and", "toes"]);
var lyrics = Array.prototype.concat(babelHelpers.toConsumableArray(parts), ["head", "and", "toes"]);
Expand Up @@ -3,5 +3,5 @@ function foo() {
bar[_key] = arguments[_key];
}

return bar.concat();
return Array.prototype.concat(bar);
}

0 comments on commit 5304442

Please sign in to comment.