Add __spreadArrays helper (#31166)

This commit is contained in:
Ron Buckton
2019-06-11 14:15:57 -07:00
committed by GitHub
parent ad322a561a
commit 375487ec60
33 changed files with 465 additions and 240 deletions
+3 -2
View File
@@ -19080,8 +19080,8 @@ namespace ts {
}
function checkSpreadExpression(node: SpreadElement, checkMode?: CheckMode): Type {
if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
checkExternalEmitHelpers(node, ExternalEmitHelpers.SpreadIncludes);
if (languageVersion < ScriptTarget.ES2015) {
checkExternalEmitHelpers(node, compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes : ExternalEmitHelpers.SpreadArrays);
}
const arrayOrIterableType = checkExpression(node.expression, checkMode);
@@ -31104,6 +31104,7 @@ namespace ts {
case ExternalEmitHelpers.Values: return "__values";
case ExternalEmitHelpers.Read: return "__read";
case ExternalEmitHelpers.Spread: return "__spread";
case ExternalEmitHelpers.SpreadArrays: return "__spreadArrays";
case ExternalEmitHelpers.Await: return "__await";
case ExternalEmitHelpers.AsyncGenerator: return "__asyncGenerator";
case ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator";
+26
View File
@@ -2657,6 +2657,7 @@ namespace ts {
valuesHelper,
readHelper,
spreadHelper,
spreadArraysHelper,
restHelper,
decorateHelper,
metadataHelper,
@@ -3693,6 +3694,31 @@ namespace ts {
);
}
export const spreadArraysHelper: UnscopedEmitHelper = {
name: "typescript:spreadArrays",
scoped: false,
text: `
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};`
};
export function createSpreadArraysHelper(context: TransformationContext, argumentList: ReadonlyArray<Expression>, location?: TextRange) {
context.requestEmitHelper(spreadArraysHelper);
return setTextRange(
createCall(
getHelperName("__spreadArrays"),
/*typeArguments*/ undefined,
argumentList
),
location
);
}
// Utilities
export function createForOfBindingStatement(node: ForInitializer, boundValue: Expression): Statement {
+27 -11
View File
@@ -3819,8 +3819,11 @@ namespace ts {
// [source]
// [a, ...b, c]
//
// [output (downlevelIteration)]
// __spread([a], b, [c])
//
// [output]
// [a].concat(b, [c])
// __spreadArrays([a], b, [c])
// Map spans of spread expressions into their expressions and spans of other
// expressions into an array literal.
@@ -3834,10 +3837,7 @@ namespace ts {
if (compilerOptions.downlevelIteration) {
if (segments.length === 1) {
const firstSegment = segments[0];
if (isCallExpression(firstSegment)
&& isIdentifier(firstSegment.expression)
&& (getEmitFlags(firstSegment.expression) & EmitFlags.HelperName)
&& firstSegment.expression.escapedText === "___spread") {
if (isCallToHelper(firstSegment, "___spread" as __String)) {
return segments[0];
}
}
@@ -3846,17 +3846,33 @@ namespace ts {
}
else {
if (segments.length === 1) {
const firstElement = elements[0];
return needsUniqueCopy && isSpreadElement(firstElement) && firstElement.expression.kind !== SyntaxKind.ArrayLiteralExpression
? createArraySlice(segments[0])
: segments[0];
const firstSegment = segments[0];
if (!needsUniqueCopy
|| isPackedArrayLiteral(firstSegment)
|| isCallToHelper(firstSegment, "___spreadArrays" as __String)) {
return segments[0];
}
}
// Rewrite using the pattern <segment0>.concat(<segment1>, <segment2>, ...)
return createArrayConcat(segments.shift()!, segments);
return createSpreadArraysHelper(context, segments);
}
}
function isPackedElement(node: Expression) {
return !isOmittedExpression(node);
}
function isPackedArrayLiteral(node: Expression) {
return isArrayLiteralExpression(node) && every(node.elements, isPackedElement);
}
function isCallToHelper(firstSegment: Expression, helperName: __String) {
return isCallExpression(firstSegment)
&& isIdentifier(firstSegment.expression)
&& (getEmitFlags(firstSegment.expression) & EmitFlags.HelperName)
&& firstSegment.expression.escapedText === helperName;
}
function partitionSpread(node: Expression) {
return isSpreadElement(node)
? visitSpanOfSpreads
+7 -6
View File
@@ -5339,12 +5339,13 @@ namespace ts {
Values = 1 << 8, // __values (used by ES2015 for..of and yield* transformations)
Read = 1 << 9, // __read (used by ES2015 iterator destructuring transformation)
Spread = 1 << 10, // __spread (used by ES2015 array spread and argument list spread transformations)
Await = 1 << 11, // __await (used by ES2017 async generator transformation)
AsyncGenerator = 1 << 12, // __asyncGenerator (used by ES2017 async generator transformation)
AsyncDelegator = 1 << 13, // __asyncDelegator (used by ES2017 async generator yield* transformation)
AsyncValues = 1 << 14, // __asyncValues (used by ES2017 for..await..of transformation)
ExportStar = 1 << 15, // __exportStar (used by CommonJS/AMD/UMD module transformation)
MakeTemplateObject = 1 << 16, // __makeTemplateObject (used for constructing template string array objects)
SpreadArrays = 1 << 11, // __spreadArrays (used by ES2015 array spread and argument list spread transformations)
Await = 1 << 12, // __await (used by ES2017 async generator transformation)
AsyncGenerator = 1 << 13, // __asyncGenerator (used by ES2017 async generator transformation)
AsyncDelegator = 1 << 14, // __asyncDelegator (used by ES2017 async generator yield* transformation)
AsyncValues = 1 << 15, // __asyncValues (used by ES2017 for..await..of transformation)
ExportStar = 1 << 16, // __exportStar (used by CommonJS/AMD/UMD module transformation)
MakeTemplateObject = 1 << 17, // __makeTemplateObject (used for constructing template string array objects)
FirstEmitHelper = Extends,
LastEmitHelper = MakeTemplateObject,