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

This commit is contained in:
Nicolò Ribaudo 2020-03-16 16:34:33 +01:00 committed by GitHub
parent 10058901d0
commit 1ba41f2084
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 115 additions and 26 deletions

View File

@ -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);
}
`;
@ -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;
@ -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);
@ -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."
);
}
`;

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -1,9 +1,22 @@
expect(
() => {
var [foo, bar] = undefined;
}).toThrow("Invalid attempt to destructure non-iterable instance");
var foo, bar;
expect(
() => {
var foo = [ ...undefined ];
}).toThrow("Invalid attempt to spread non-iterable instance");
() => [foo, bar] = undefined
).toThrow(/destructure non-iterable/);
expect(
() => [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;
}

View File

@ -0,0 +1,5 @@
{
"plugins": [
"transform-destructuring"
]
}

View File

@ -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; }

View File

@ -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;
}

View File

@ -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];

View File

@ -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));

View File

@ -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/);

View File

@ -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; }

View File

@ -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; }

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;