Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throw better errors for non-iterables when Symbol doesn't exist. #11264

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 18 additions & 9 deletions packages/babel-helpers/src/helpers.js
Expand Up @@ -936,7 +936,7 @@ helpers.iterableToArray = helper("7.0.0-beta.0")`
if (
typeof iter === 'string'
|| Object.prototype.toString.call(iter) === "[object Arguments]"
|| Symbol.iterator in Object(iter)
|| (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter))
) return Array.from(iter);
}
`;
Expand All @@ -952,9 +952,12 @@ helpers.iterableToArrayLimit = helper("7.0.0-beta.0")`
// _e = _iteratorError
// _i = _iterator
// _s = _step
if (!(
Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]"
)) { return }

if (
(typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) &&
Object.prototype.toString.call(arr) !== "[object Arguments]"
) return;

var _arr = [];
var _n = true;
var _d = false;
Expand All @@ -980,9 +983,11 @@ helpers.iterableToArrayLimit = helper("7.0.0-beta.0")`

helpers.iterableToArrayLimitLoose = helper("7.0.0-beta.0")`
export default function _iterableToArrayLimitLoose(arr, i) {
if (!(
Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]"
)) { return }
if (
(typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) &&
Object.prototype.toString.call(arr) !== "[object Arguments]"
) return;

var _arr = [];
for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
_arr.push(_step.value);
Expand All @@ -994,13 +999,17 @@ helpers.iterableToArrayLimitLoose = helper("7.0.0-beta.0")`

helpers.nonIterableSpread = helper("7.0.0-beta.0")`
export default function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance");
throw new TypeError(
"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
);
}
`;

helpers.nonIterableRest = helper("7.0.0-beta.0")`
export default function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
throw new TypeError(
"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
);
}
`;

Expand Down
@@ -0,0 +1,13 @@
var a = (() => [1, 2, 3])();

// Simulate old environment
let _Symbol = Symbol;
Symbol = void 0;
try {
var [first, ...rest] = a;

expect(first).toBe(1);
expect(rest).toEqual([2, 3]);
} finally {
Symbol = _Symbol;
}
@@ -0,0 +1,6 @@
var a = (() => [1, 2, 3])();

// !!! In order to run this test, this shouldn't be optimized using type inference
// If it's optimized and doesn't call toArray, please modify this test
// and exec.js
var [first, ...rest] = a;
@@ -0,0 +1,8 @@
var a = (() => [1, 2, 3])(); // !!! In order to run this test, this shouldn't be optimized using type inference
// If it's optimized and doesn't call toArray, please modify this test
// and exec.js


var _a = babelHelpers.toArray(a),
first = _a[0],
rest = _a.slice(1);
@@ -1,9 +1,22 @@
var foo, bar;

expect(
() => {
var [foo, bar] = undefined;
}).toThrow("Invalid attempt to destructure non-iterable instance");
() => [foo, bar] = undefined
).toThrow(/destructure non-iterable/);

expect(
() => {
var foo = [ ...undefined ];
}).toThrow("Invalid attempt to spread non-iterable instance");
() => [foo, bar] = {}
).toThrow(/destructure non-iterable/);

// Simulate old browser
let _Symbol = Symbol;
Symbol = void 0;
try {

expect(
() => [foo, bar] = {}
).toThrow(/destructure non-iterable/);

} finally {
Symbol = _Symbol;
}
@@ -0,0 +1,5 @@
{
"plugins": [
"transform-destructuring"
]
}
Expand Up @@ -6,9 +6,9 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "d

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _iterableToArrayLimit(arr, i) { if ((typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) && Object.prototype.toString.call(arr) !== "[object Arguments]") return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

Expand Down
@@ -0,0 +1,10 @@
var a = (() => [2, 3])();

// Simulate old environment
let _Symbol = Symbol;
Symbol = void 0;
try {
expect([1, ...a]).toEqual([1, 2, 3]);
} finally {
Symbol = _Symbol;
}
@@ -0,0 +1,6 @@
var a = (() => [2, 3])();

// !!! In order to run this test, this shouldn't be optimized using type inference
// If it's optimized and doesn't call toConsumableArray, please modify this test
// and exec.js
[1, ...a];
@@ -0,0 +1,6 @@
var a = (() => [2, 3])(); // !!! In order to run this test, this shouldn't be optimized using type inference
// If it's optimized and doesn't call toConsumableArray, please modify this test
// and exec.js


[1].concat(babelHelpers.toConsumableArray(a));
@@ -0,0 +1,10 @@
var o = {};

expect(() => [...undefined]).toThrow(/spread non-iterable/);

expect(() => [...o]).toThrow(/spread non-iterable/);

// Simulate old browser
Symbol = void 0;

expect(() => [...o]).toThrow(/spread non-iterable/);
Expand Up @@ -2,9 +2,9 @@

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _iterableToArrayLimit(arr, i) { if ((typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) && Object.prototype.toString.call(arr) !== "[object Arguments]") return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

Expand Down
@@ -1,8 +1,8 @@
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _iterableToArrayLimit(arr, i) { if ((typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) && Object.prototype.toString.call(arr) !== "[object Arguments]") return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

Expand Down
@@ -1,5 +1,6 @@
import _Array$from from "../../core-js/array/from";
import _isIterable from "../../core-js/is-iterable";
import _Symbol from "../../core-js/symbol";
export default function _iterableToArray(iter) {
if (typeof iter === 'string' || Object.prototype.toString.call(iter) === "[object Arguments]" || _isIterable(Object(iter))) return _Array$from(iter);
if (typeof iter === 'string' || Object.prototype.toString.call(iter) === "[object Arguments]" || typeof _Symbol !== "undefined" && _isIterable(Object(iter))) return _Array$from(iter);
}
4 changes: 3 additions & 1 deletion packages/babel-runtime-corejs2/helpers/iterableToArray.js
Expand Up @@ -2,8 +2,10 @@ var _Array$from = require("../core-js/array/from");

var _isIterable = require("../core-js/is-iterable");

var _Symbol = require("../core-js/symbol");

function _iterableToArray(iter) {
if (typeof iter === 'string' || Object.prototype.toString.call(iter) === "[object Arguments]" || _isIterable(Object(iter))) return _Array$from(iter);
if (typeof iter === 'string' || Object.prototype.toString.call(iter) === "[object Arguments]" || typeof _Symbol !== "undefined" && _isIterable(Object(iter))) return _Array$from(iter);
}

module.exports = _iterableToArray;
2 changes: 1 addition & 1 deletion packages/babel-runtime/helpers/esm/iterableToArray.js
@@ -1,3 +1,3 @@
export default function _iterableToArray(iter) {
if (typeof iter === 'string' || Object.prototype.toString.call(iter) === "[object Arguments]" || Symbol.iterator in Object(iter)) return Array.from(iter);
if (typeof iter === 'string' || Object.prototype.toString.call(iter) === "[object Arguments]" || typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}
2 changes: 1 addition & 1 deletion packages/babel-runtime/helpers/iterableToArray.js
@@ -1,5 +1,5 @@
function _iterableToArray(iter) {
if (typeof iter === 'string' || Object.prototype.toString.call(iter) === "[object Arguments]" || Symbol.iterator in Object(iter)) return Array.from(iter);
if (typeof iter === 'string' || Object.prototype.toString.call(iter) === "[object Arguments]" || typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}

module.exports = _iterableToArray;