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

Improve array destructuring spec compliance #15183

Merged
merged 15 commits into from Nov 25, 2022
27 changes: 19 additions & 8 deletions packages/babel-helpers/src/helpers.ts
Expand Up @@ -779,25 +779,36 @@ helpers.iterableToArrayLimit = helper("7.0.0-beta.0")`
// _e = _iteratorError
// _i = _iterator
// _s = _step
// _x = _next
// _r = _return

var _i = arr == null ? null : (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]);
if (_i == null) return;

var _arr = [];
var _n = true;
var _d = false;
var _s, _e;
var _s, _e, _x, _r;
try {
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
_x = (_i = _i.call(arr)).next;
if (i === 0) {
if (Object(_i) !== _i) return;
_n = false;
} else {
for (; !(_n = (_s = _x.call(_i)).done); _n = true) {
_arr.push(_s.value);
if(_arr.length === i) break;
}
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
if (!_n && _i["return"] != null) {
_r = _i["return"]();
if (Object(_r) !== _r) return;
}
} finally {
if (_d) throw _e;
}
Expand All @@ -812,9 +823,9 @@ helpers.iterableToArrayLimitLoose = helper("7.0.0-beta.0")`
if (_i == null) return;

var _arr = [];
for (_i = _i.call(arr), _step; !(_step = _i.next()).done;) {
_arr.push(_step.value);
if (i && _arr.length === i) break;
var _s;
for (_i = _i.call(arr); arr.length < i && !(_s = _i.next()).done; ) {
_arr.push(_s.value);
}
return _arr;
}
Expand Down
@@ -0,0 +1,41 @@
expect(() => {
var [] = {
[Symbol.iterator]: () => {
return {
return: () => {},
};
},
};
}).toThrow(TypeError);

expect(() => {
var [] = {
[Symbol.iterator]: () => {
return {
return: () => ({}),
};
},
};
}).not.toThrow();

expect(() => {
var [x] = {
[Symbol.iterator]: () => {
return {
next: () => ({ done: false, value: 1 }),
return: () => {},
};
},
};
}).toThrow(TypeError);

expect(() => {
var [x] = {
[Symbol.iterator]: () => {
return {
next: () => ({ done: false, value: 1 }),
return: () => ({}),
};
},
};
}).not.toThrow();
@@ -0,0 +1,33 @@
var [] = {
[Symbol.iterator]: () => {
return {
return: () => {},
};
},
};

var [] = {
[Symbol.iterator]: () => {
return {
return: () => ({}),
};
},
};

var [x] = {
[Symbol.iterator]: () => {
return {
next: () => ({ done: false, value: 1 }),
return: () => {},
};
},
};

var [x] = {
[Symbol.iterator]: () => {
return {
next: () => ({ done: false, value: 1 }),
return: () => ({}),
};
},
};
@@ -0,0 +1,42 @@
var _Symbol$iterator = {
[Symbol.iterator]: () => {
return {
return: () => {}
};
}
},
_Symbol$iterator2 = babelHelpers.slicedToArray(_Symbol$iterator, 0);
var _Symbol$iterator3 = {
[Symbol.iterator]: () => {
return {
return: () => ({})
};
}
},
_Symbol$iterator4 = babelHelpers.slicedToArray(_Symbol$iterator3, 0);
var _Symbol$iterator5 = {
[Symbol.iterator]: () => {
return {
next: () => ({
done: false,
value: 1
}),
return: () => {}
};
}
},
_Symbol$iterator6 = babelHelpers.slicedToArray(_Symbol$iterator5, 1),
x = _Symbol$iterator6[0];
var _Symbol$iterator7 = {
[Symbol.iterator]: () => {
return {
next: () => ({
done: false,
value: 1
}),
return: () => ({})
};
}
},
_Symbol$iterator8 = babelHelpers.slicedToArray(_Symbol$iterator7, 1),
x = _Symbol$iterator8[0];
@@ -0,0 +1,38 @@
expect(() => {
var [] = null;
}).toThrow(TypeError);

expect(() => {
var [] = 42;
}).toThrow(TypeError);

expect(() => {
var [] = {};
}).toThrow(TypeError);

expect(() => {
var [] = { [Symbol.iterator]: () => {} };
}).toThrow(TypeError);

expect(() => {
var [] = [];
var [] = [0, 1, 2];
var [] = "foo";
var [] = (function*() { throw new Error("Should not throw"); })();
var [] = { [Symbol.iterator]: () => ({}) };
var [] = { [Symbol.iterator]: () => () => {} };
var [] = { [Symbol.iterator]: async function*() {} };
}).not.toThrow();

var returnCalled = false;
var [] = {
[Symbol.iterator]: () => {
return {
return: () => {
returnCalled = true;
return {};
},
};
},
};
expect(returnCalled).toStrictEqual(true);
@@ -0,0 +1,24 @@
var [] = null;
var [] = 42;
var [] = {};
var [] = { [Symbol.iterator]: () => {} };

var [] = [];
var [] = [0, 1, 2];
var [] = "foo";
var [] = (function*() { throw new Error("Should not throw"); })();
var [] = { [Symbol.iterator]: () => ({}) };
var [] = { [Symbol.iterator]: () => () => {} };
var [] = { [Symbol.iterator]: async function*() {} };

var returnCalled = false;
var [] = {
[Symbol.iterator]: () => {
return {
return: () => {
returnCalled = true;
return {};
},
};
},
};
@@ -0,0 +1,61 @@
var _ref = null,
_ref2 = babelHelpers.slicedToArray(_ref, 0);
var _ = 42,
_ref3 = babelHelpers.slicedToArray(_, 0);
var _ref4 = {},
_ref5 = babelHelpers.slicedToArray(_ref4, 0);
var _Symbol$iterator = {
[Symbol.iterator]: () => {}
},
_Symbol$iterator2 = babelHelpers.slicedToArray(_Symbol$iterator, 0);
var _ref6 = [0, 1, 2];
var _foo = "foo",
_foo2 = babelHelpers.slicedToArray(_foo, 0);
var _ref7 = /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee() {
return babelHelpers.regeneratorRuntime().wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
throw new Error("Should not throw");
case 1:
case "end":
return _context.stop();
}
}
}, _callee);
})(),
_ref8 = babelHelpers.slicedToArray(_ref7, 0);
var _Symbol$iterator3 = {
[Symbol.iterator]: () => ({})
},
_Symbol$iterator4 = babelHelpers.slicedToArray(_Symbol$iterator3, 0);
var _Symbol$iterator5 = {
[Symbol.iterator]: () => () => {}
},
_Symbol$iterator6 = babelHelpers.slicedToArray(_Symbol$iterator5, 0);
var _Symbol$iterator7 = {
[Symbol.iterator]: /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee2() {
return babelHelpers.regeneratorRuntime().async(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
case "end":
return _context2.stop();
}
}
}, _callee2, null, null, Promise);
})
},
_Symbol$iterator8 = babelHelpers.slicedToArray(_Symbol$iterator7, 0);
var returnCalled = false;
var _Symbol$iterator9 = {
[Symbol.iterator]: () => {
return {
return: () => {
returnCalled = true;
return {};
}
};
}
},
_Symbol$iterator10 = babelHelpers.slicedToArray(_Symbol$iterator9, 0);
Expand Up @@ -45,7 +45,7 @@ try {
expect(thrown).toEqual(true);
try {
thrown = false;
var _ = babelHelpers.toArray(void 0);
var _ = babelHelpers.slicedToArray(void 0, 0);
} catch (e) {
thrown = true;
}
Expand Down
@@ -0,0 +1,22 @@
let gets = 0;
let it = {
[Symbol.iterator]: () => ({
get next() {
gets++;
let i = 0;
return () => ({ done: false, value: i++ });
},
}),
};

let [] = it;
expect(gets).toBe(1);

let [a] = it;
expect(gets).toBe(2);
expect(a).toBe(0);

let [b, c] = it;
expect(gets).toBe(3);
expect(b).toBe(0);
expect(c).toBe(1);
@@ -0,0 +1,3 @@
expect(() => {
var [] = { [Symbol.iterator]: () => [] };
}).not.toThrow();
@@ -0,0 +1 @@
var [] = { [Symbol.iterator]: () => [] };
@@ -0,0 +1,3 @@
{
"plugins": ["transform-destructuring"]
}
@@ -0,0 +1,4 @@
var _Symbol$iterator = {
[Symbol.iterator]: () => []
},
_Symbol$iterator2 = babelHelpers.slicedToArray(_Symbol$iterator, 0);
@@ -0,0 +1,3 @@
expect(() => {
var [] = { [Symbol.iterator]: () => async function* () {} };
}).not.toThrow();
@@ -0,0 +1 @@
var [] = { [Symbol.iterator]: () => async function* () {} };
@@ -0,0 +1,6 @@
{
"plugins": [
"transform-destructuring",
"transform-regenerator"
]
}
@@ -0,0 +1,12 @@
var _Symbol$iterator = {
[Symbol.iterator]: () => /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee() {
return babelHelpers.regeneratorRuntime().async(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
case "end":
return _context.stop();
}
}, _callee, null, null, Promise);
})
},
_Symbol$iterator2 = babelHelpers.slicedToArray(_Symbol$iterator, 0);

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -1,5 +1,5 @@
function f(_ref) {
var _ref2 = babelHelpers.toArray(_ref);
var _ref2 = babelHelpers.slicedToArray(_ref, 0);
return /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee() {
return babelHelpers.regeneratorRuntime().wrap(function _callee$(_context) {
while (1) {
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-traverse/src/scope/index.ts
Expand Up @@ -686,7 +686,7 @@ export default class Scope {
if (i === true) {
// Used in array-spread to create an array.
helperName = "toConsumableArray";
} else if (i) {
} else if (typeof i === "number") {
args.push(numericLiteral(i));

// Used in array-rest to create an array from a subset of an iterable.
Expand Down