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

Fix __spreadArray for non-concat-spreadables #45386

Merged
merged 1 commit into from Aug 10, 2021
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
2 changes: 1 addition & 1 deletion src/compiler/factory/emitHelpers.ts
Expand Up @@ -647,7 +647,7 @@ namespace ts {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how crazy we want to get with this one but we could also do

Suggested change
return to.concat(ar || Array.prototype.slice.call(from));
return to.concat(ar || (from instanceof Array ? from : Array.prototype.slice.call(from)));

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered that, including a check for isConcatSpreadable, but it just became long-winded and the performance benefits seemed negligible.

Copy link
Member Author

@rbuckton rbuckton Aug 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was originally thinking of doing this:

var __spreadArray = (this && this.__spreadArray) || (function () {
    var toString = Object.prototype.toString;
    var slice = Array.prototype.slice;
    var isArray = typeof Array.isArray === "function" ? Array.isArray : function (obj) { return toString.call(obj) === "[object Array]"; };
    var isConcatSpreadable = typeof Symbol === "function" && Symbol.isConcatSpreadable;
    function canConcat(obj) { return isArray(obj) || isConcatSpreadable && obj[isConcatSpreadable]; }
    return function (to, from, pack) {
        if (pack || arguments.length === 2) {
            for (var i = 0, l = from.length, ar; i < l; i++) {
                if (ar || !(i in from)) {
                    if (!ar) ar = slice.call(from, 0, i);
                    ar[i] = from[i];
                }
            }
            if (ar) from = ar;
        }
        return to.concat(canConcat(from) ? from : slice.call(from));
    }
})();

};`
};

Expand Down
Expand Up @@ -26,7 +26,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// In a typed function call, argument expressions are contextually typed by their corresponding parameter types.
function foo(_a) {
Expand Down
Expand Up @@ -23,7 +23,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// In a contextually typed array literal expression containing no spread elements, an element expression at index N is contextually typed by
// the type of the property with the numeric name N in the contextual type, if any, or otherwise
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/arrayLiteralSpread.js
Expand Up @@ -31,7 +31,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
function f0() {
var a = [1, 2, 3];
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/arrayLiteralSpreadES5iterable.js
Expand Up @@ -47,7 +47,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
function f0() {
var a = [1, 2, 3];
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/arrayLiterals2ES5.js
Expand Up @@ -69,7 +69,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// SpreadElement:
// ... AssignmentExpression
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/arrayLiterals3.js
Expand Up @@ -47,7 +47,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// The resulting type an array literal expression is determined as follows:
// - If the array literal contains no spread elements and is contextually typed by a tuple-like type,
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/callChain.js
Expand Up @@ -50,7 +50,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
o1 === null || o1 === void 0 ? void 0 : o1();
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/callOverload.js
Expand Up @@ -19,7 +19,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var n;
fn(1); // no error
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/callWithSpread.js
Expand Up @@ -81,7 +81,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var _a, _b, _c, _d, _e, _f, _g;
function foo(x, y) {
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/callWithSpread2.js
Expand Up @@ -45,7 +45,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// good
all.apply(void 0, ns);
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/callWithSpread3.js
Expand Up @@ -44,7 +44,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// error
fs2.apply(void 0, __spreadArray(['a'], s2, false)); // error on ...s2
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/callWithSpread5.js
Expand Up @@ -16,7 +16,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
fn.apply(void 0, __spreadArray(__spreadArray([], nnnu, false), [x], false));
fn.apply(void 0, __spreadArray(__spreadArray([], nntnnnt, false), [x], false));
Expand Up @@ -77,7 +77,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// In a destructuring assignment expression, the type of the expression on the right must be assignable to the assignment target on the left.
// An expression of type S is considered assignable to an assignment target V if one of the following is true
Expand Down
Expand Up @@ -93,7 +93,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// In a destructuring assignment expression, the type of the expression on the right must be assignable to the assignment target on the left.
// An expression of type S is considered assignable to an assignment target V if one of the following is true
Expand Down
Expand Up @@ -42,7 +42,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// V is an array assignment pattern, S is the type Any or an array-like type (section 3.3.2), and, for each assignment element E in V,
// S is the type Any, or
Expand Down
Expand Up @@ -71,7 +71,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
function a1() {
var x = [];
Expand Down
Expand Up @@ -49,7 +49,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// The type T associated with a destructuring variable declaration is determined as follows:
// If the declaration includes a type annotation, T is that type.
Expand Down
Expand Up @@ -65,7 +65,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
// The type T associated with a destructuring variable declaration is determined as follows:
// If the declaration includes a type annotation, T is that type.
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/excessiveStackDepthFlatArray.js
Expand Up @@ -48,7 +48,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
configureStore({
middleware: __spreadArray([], defaultMiddleware, true)
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/excessivelyLargeTupleSpread.js
Expand Up @@ -48,7 +48,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var a0 = [0];
var a1 = __spreadArray(__spreadArray([], a0, true), a0, true);
Expand Down
Expand Up @@ -24,7 +24,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
f1();
f1(1, 2);
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/genericRestParameters1.js
Expand Up @@ -174,7 +174,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
f1 = f2;
f2 = f1;
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/genericRestParameters2.js
Expand Up @@ -88,7 +88,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
f10(42, "hello");
f10(42, "hello", true);
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/genericRestParameters3.js
Expand Up @@ -75,7 +75,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
f1("foo", "abc");
f1("foo", 10, true);
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/keyofAndIndexedAccess.js
Expand Up @@ -681,7 +681,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var Shape = /** @class */ (function () {
function Shape() {
Expand Down
Expand Up @@ -69,7 +69,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
function f1() {
var b = true;
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/newWithSpread.js
Expand Up @@ -104,7 +104,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
function f(x, y) {
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/newWithSpreadES5.js
Expand Up @@ -103,7 +103,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
function f(x, y) {
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/noCrashOnNoLib.js
Expand Up @@ -15,7 +15,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
exports.__esModule = true;
exports.f = void 0;
Expand Down
Expand Up @@ -80,7 +80,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
function fn(a, b, c, d, e, f, g) {
var c_1, c_1_1;
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/readonlyRestParameters.js
Expand Up @@ -36,7 +36,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
function f0(a, b) {
f0(a, b);
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/recursiveReverseMappedType.js
Expand Up @@ -24,7 +24,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
function join(l) {
return __spreadArray(['marker'], l, true);
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/recursiveTypeReferences1.js
Expand Up @@ -139,7 +139,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var a0 = 1;
var a1 = [1, [2, 3], [4, [5, [6, 7]]]];
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/restTuplesFromContextualTypes.js
Expand Up @@ -108,7 +108,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
(function (a, b, c) { }).apply(void 0, t1);
(function () {
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/selfReferencingSpreadInLoop.js
Expand Up @@ -13,7 +13,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var additional = [];
for (var _i = 0, _a = [1, 2, 3]; _i < _a.length; _i++) {
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/spliceTuples.js
Expand Up @@ -32,7 +32,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
var k1;
k1 = __spreadArray([1], sb, true);
Expand Down
Expand Up @@ -15,6 +15,6 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
ar[i] = from[i];
}
}
return to.concat(ar || from);
return to.concat(ar || Array.prototype.slice.call(from));
};
foo1 = __spreadArray([], Array.isArray(foo2) ? foo2 : [foo2], true);