Skip to content

Commit 163ed30

Browse files
committed
Minor cleanup, ensure multiple emit helpers for outfile tests
1 parent f9a05eb commit 163ed30

File tree

14 files changed

+5886
-3539
lines changed

14 files changed

+5886
-3539
lines changed

src/compiler/factory/emitHelpers.ts

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -617,34 +617,6 @@ namespace ts {
617617
};`
618618
};
619619

620-
/** @deprecated To be removed in TS >= 4.3, as it may be referenced in a tsbuildinfo */
621-
export const spreadHelper: UnscopedEmitHelper = {
622-
name: "typescript:spread",
623-
importName: "__spread",
624-
scoped: false,
625-
dependencies: [readHelper],
626-
text: `
627-
var __spread = (this && this.__spread) || function () {
628-
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
629-
return ar;
630-
};`
631-
};
632-
633-
/** @deprecated To be removed in TS >= 4.3, as it may be referenced in a tsbuildinfo */
634-
export const spreadArraysHelper: UnscopedEmitHelper = {
635-
name: "typescript:spreadArrays",
636-
importName: "__spreadArrays",
637-
scoped: false,
638-
text: `
639-
var __spreadArrays = (this && this.__spreadArrays) || function () {
640-
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
641-
for (var r = Array(s), k = 0, i = 0; i < il; i++)
642-
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
643-
r[k] = a[j];
644-
return r;
645-
};`
646-
};
647-
648620
export const spreadArrayHelper: UnscopedEmitHelper = {
649621
name: "typescript:spreadArray",
650622
importName: "__spreadArray",
@@ -888,8 +860,6 @@ namespace ts {
888860
awaiterHelper,
889861
extendsHelper,
890862
templateObjectHelper,
891-
spreadHelper,
892-
spreadArraysHelper,
893863
spreadArrayHelper,
894864
valuesHelper,
895865
readHelper,
@@ -920,4 +890,11 @@ namespace ts {
920890
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
921891
})(name => super[name], (name, value) => super[name] = value);`
922892
};
893+
894+
export function isCallToHelper(firstSegment: Expression, helperName: __String) {
895+
return isCallExpression(firstSegment)
896+
&& isIdentifier(firstSegment.expression)
897+
&& (getEmitFlags(firstSegment.expression) & EmitFlags.HelperName)
898+
&& firstSegment.expression.escapedText === helperName;
899+
}
923900
}

src/compiler/transformers/es2015.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3892,6 +3892,8 @@ namespace ts {
38923892
*
38933893
* @param elements The array of Expression nodes.
38943894
* @param needsUniqueCopy A value indicating whether to ensure that the result is a fresh array.
3895+
* This should be `true` when spreading into an `ArrayLiteral`, and `false` when spreading into an
3896+
* argument list.
38953897
* @param multiLine A value indicating whether the result should be emitted on multiple lines.
38963898
*/
38973899
function transformAndSpreadElements(elements: NodeArray<Expression>, needsUniqueCopy: boolean, multiLine: boolean, hasTrailingComma: boolean): Expression {
@@ -3916,6 +3918,15 @@ namespace ts {
39163918
//
39173919
// [output]
39183920
// __spreadArray(__spreadArray([], a), [b])
3921+
//
3922+
// NOTE: We use `isPackedArrayLiteral` below rather than just `isArrayLiteral`
3923+
// because ES2015 spread will replace _missing_ array elements with `undefined`,
3924+
// so we cannot just use an array as is. For example:
3925+
//
3926+
// `[1, ...[2, , 3]]` becomes `[1, 2, undefined, 3]`
3927+
//
3928+
// However, for packed array literals (i.e., an array literal with no OmittedExpression
3929+
// elements), we can use the array as-is.
39193930

39203931
// Map spans of spread expressions into their expressions and spans of other
39213932
// expressions into an array literal.
@@ -3926,46 +3937,35 @@ namespace ts {
39263937
)
39273938
);
39283939

3929-
const helpers = emitHelpers();
39303940
if (segments.length === 1) {
39313941
const firstSegment = segments[0];
3932-
if (!needsUniqueCopy
3933-
|| isPackedArrayLiteral(firstSegment)
3942+
// If we don't need a unique copy, then we are spreading into an argument list for
3943+
// a CallExpression or NewExpression. When using `--downlevelIteration`, we need
3944+
// to coerce this into an array for use with `apply`, so we will use the code path
3945+
// that follows instead.
3946+
if (!needsUniqueCopy && !compilerOptions.downlevelIteration
3947+
|| isPackedArrayLiteral(firstSegment) // see NOTE (above)
39343948
|| isCallToHelper(firstSegment, "___spreadArray" as __String)) {
39353949
return segments[0];
39363950
}
39373951
}
39383952

3953+
const helpers = emitHelpers();
39393954
const startsWithSpread = isSpreadElement(elements[0]);
39403955
let expression: Expression =
39413956
startsWithSpread ? factory.createArrayLiteralExpression() :
39423957
segments[0];
39433958
for (let i = startsWithSpread ? 0 : 1; i < segments.length; i++) {
39443959
expression = helpers.createSpreadArrayHelper(
39453960
expression,
3946-
compilerOptions.downlevelIteration && !isArrayLiteralExpression(segments[i]) ?
3961+
compilerOptions.downlevelIteration && !isPackedArrayLiteral(segments[i]) ? // see NOTE (above)
39473962
helpers.createReadHelper(segments[i], /*count*/ undefined) :
39483963
segments[i]);
39493964
}
39503965

39513966
return expression;
39523967
}
39533968

3954-
function isPackedElement(node: Expression) {
3955-
return !isOmittedExpression(node);
3956-
}
3957-
3958-
function isPackedArrayLiteral(node: Expression) {
3959-
return isArrayLiteralExpression(node) && every(node.elements, isPackedElement);
3960-
}
3961-
3962-
function isCallToHelper(firstSegment: Expression, helperName: __String) {
3963-
return isCallExpression(firstSegment)
3964-
&& isIdentifier(firstSegment.expression)
3965-
&& (getEmitFlags(firstSegment.expression) & EmitFlags.HelperName)
3966-
&& firstSegment.expression.escapedText === helperName;
3967-
}
3968-
39693969
function partitionSpread(node: Expression) {
39703970
return isSpreadElement(node)
39713971
? visitSpanOfSpreads

src/compiler/utilities.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7033,6 +7033,17 @@ namespace ts {
70337033
}
70347034
}
70357035

7036+
function isPackedElement(node: Expression) {
7037+
return !isOmittedExpression(node);
7038+
}
7039+
7040+
/**
7041+
* Determines whether the provided node is an ArrayLiteralExpression that contains no missing elements.
7042+
*/
7043+
export function isPackedArrayLiteral(node: Expression) {
7044+
return isArrayLiteralExpression(node) && every(node.elements, isPackedElement);
7045+
}
7046+
70367047
/**
70377048
* Indicates whether the result of an `Expression` will be unused.
70387049
*

src/testRunner/unittests/tsbuild/helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,8 @@ const { b, ...rest } = { a: 10, b: 30, yy: 30 };
615615
const content = fs.readFileSync(path, "utf8");
616616
fs.writeFileSync(path, `${content}
617617
function ${project}${file}Spread(...b: number[]) { }
618-
${project}${file}Spread(...[10, 20, 30]);`);
618+
const ${project}${file}_ar = [20, 30];
619+
${project}${file}Spread(10, ...${project}${file}_ar);`);
619620

620621
replaceText(fs, `src/${project}/tsconfig.json`, `"strict": false,`, `"strict": false,
621622
"downlevelIteration": true,`);

tests/baselines/reference/destructuringParameterDeclaration3ES5iterable.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ function a11(_a) {
111111
var array = [1, 2, 3];
112112
var array2 = [true, false, "hello"];
113113
a2(__spreadArray([], __read(array)));
114-
a1.apply(void 0, array);
114+
a1.apply(void 0, __spreadArray([], __read(array)));
115115
a9([1, 2, [["string"]], false, true]); // Parameter type is [any, any, [[any]]]
116116
a10([1, 2, [["string"]], false, true]); // Parameter type is any[]
117117
a10([1, 2, 3, false, true]); // Parameter type is any[]

0 commit comments

Comments
 (0)