Skip to content

Commit 4f30f2f

Browse files
committed
Minor cleanup, ensure multiple emit helpers for outfile tests
1 parent 8acb22e commit 4f30f2f

File tree

15 files changed

+5890
-3551
lines changed

15 files changed

+5890
-3551
lines changed

package-lock.json

Lines changed: 4 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/compiler/factory/emitHelpers.ts

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

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

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
@@ -6991,4 +6991,15 @@ namespace ts {
69916991
return bindParentToChildIgnoringJSDoc(child, parent) || bindJSDoc(child);
69926992
}
69936993
}
6994+
6995+
function isPackedElement(node: Expression) {
6996+
return !isOmittedExpression(node);
6997+
}
6998+
6999+
/**
7000+
* Determines whether the provided node is an ArrayLiteralExpression that contains no missing elements.
7001+
*/
7002+
export function isPackedArrayLiteral(node: Expression) {
7003+
return isArrayLiteralExpression(node) && every(node.elements, isPackedElement);
7004+
}
69947005
}

src/testRunner/unittests/tsbuild/helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,8 @@ const { b, ...rest } = { a: 10, b: 30, yy: 30 };
583583
const content = fs.readFileSync(path, "utf8");
584584
fs.writeFileSync(path, `${content}
585585
function ${project}${file}Spread(...b: number[]) { }
586-
${project}${file}Spread(...[10, 20, 30]);`);
586+
const ${project}${file}_ar = [20, 30];
587+
${project}${file}Spread(10, ...${project}${file}_ar);`);
587588

588589
replaceText(fs, `src/${project}/tsconfig.json`, `"strict": false,`, `"strict": false,
589590
"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)