diff --git a/packages/babel-plugin-transform-spread/src/index.js b/packages/babel-plugin-transform-spread/src/index.js index f6559cfccd..78e741eddf 100644 --- a/packages/babel-plugin-transform-spread/src/index.js +++ b/packages/babel-plugin-transform-spread/src/index.js @@ -20,6 +20,10 @@ export default declare((api, options) => { } } + function hasHole(spread) { + return spread.elements.some(el => el === null); + } + function hasSpread(nodes) { for (let i = 0; i < nodes.length; i++) { if (t.isSpreadElement(nodes[i])) { @@ -35,14 +39,27 @@ export default declare((api, options) => { return []; } - function build(props: Array, scope) { + function build(props: Array, scope, file) { const nodes = []; let _props = []; for (const prop of props) { if (t.isSpreadElement(prop)) { _props = push(_props, nodes); - nodes.push(getSpreadLiteral(prop, scope)); + let spreadLiteral = getSpreadLiteral(prop, scope); + + if (t.isArrayExpression(spreadLiteral) && hasHole(spreadLiteral)) { + spreadLiteral = t.callExpression( + file.addHelper( + process.env.BABEL_8_BREAKING + ? "arrayLikeToArray" + : "arrayWithoutHoles", + ), + [spreadLiteral], + ); + } + + nodes.push(spreadLiteral); } else { _props.push(prop); } @@ -62,7 +79,7 @@ export default declare((api, options) => { const elements = node.elements; if (!hasSpread(elements)) return; - const nodes = build(elements, scope); + const nodes = build(elements, scope, this); let first = nodes[0]; // If there is only one element in the ArrayExpression and diff --git a/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/exec.js b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/exec.js new file mode 100644 index 0000000000..5e7bb42418 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/exec.js @@ -0,0 +1,2 @@ +let arr = ['a', ...['b',,'c']]; +expect(2 in arr).toBe(true); diff --git a/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/input.js b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/input.js new file mode 100644 index 0000000000..c24ce7d3ed --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/input.js @@ -0,0 +1,2 @@ +var a = [...['a',, 'b']]; +var b = ['a', ...['b',, 'c']]; diff --git a/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/options.json b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/options.json new file mode 100644 index 0000000000..29a3f0e841 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/options.json @@ -0,0 +1,3 @@ +{ + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/output.js b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/output.js new file mode 100644 index 0000000000..bc2f49f74d --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole-babel-7/output.js @@ -0,0 +1,2 @@ +var a = babelHelpers.arrayWithoutHoles(['a',, 'b']); +var b = ['a'].concat(babelHelpers.arrayWithoutHoles(['b',, 'c'])); diff --git a/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/exec.js b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/exec.js new file mode 100644 index 0000000000..5e7bb42418 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/exec.js @@ -0,0 +1,2 @@ +let arr = ['a', ...['b',,'c']]; +expect(2 in arr).toBe(true); diff --git a/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/input.js b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/input.js new file mode 100644 index 0000000000..c24ce7d3ed --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/input.js @@ -0,0 +1,2 @@ +var a = [...['a',, 'b']]; +var b = ['a', ...['b',, 'c']]; diff --git a/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/options.json b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/options.json new file mode 100644 index 0000000000..cbf6d15954 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/options.json @@ -0,0 +1,3 @@ +{ + "BABEL_8_BREAKING": true +} diff --git a/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/output.js b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/output.js new file mode 100644 index 0000000000..b48ee388cb --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/spread/nested-array-with-hole/output.js @@ -0,0 +1,2 @@ +var a = babelHelpers.arrayLikeToArray(['a',, 'b']); +var b = ['a'].concat(babelHelpers.arrayLikeToArray(['b',, 'c']));