mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Added tests and fixed related emit issues.
This commit is contained in:
@@ -2547,7 +2547,7 @@ namespace ts {
|
||||
transformFlags = TransformFlags.AssertTypeScript;
|
||||
}
|
||||
else {
|
||||
transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclaration;
|
||||
transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion;
|
||||
|
||||
// If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax.
|
||||
if (modifierFlags & ModifierFlags.Export) {
|
||||
@@ -2726,7 +2726,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function computeVariableDeclarationList(node: VariableDeclarationList, subtreeFlags: TransformFlags) {
|
||||
let transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclaration;
|
||||
let transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion;
|
||||
|
||||
if (subtreeFlags & TransformFlags.ContainsBindingPattern) {
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
@@ -2794,6 +2794,7 @@ namespace ts {
|
||||
// These nodes are ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
break;
|
||||
|
||||
case SyntaxKind.YieldExpression:
|
||||
// This node is ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsYield;
|
||||
@@ -2920,6 +2921,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ReturnStatement:
|
||||
case SyntaxKind.ContinueStatement:
|
||||
case SyntaxKind.BreakStatement:
|
||||
transformFlags |= TransformFlags.ContainsHoistedDeclarationOrCompletion;
|
||||
break;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
|
||||
@@ -18069,10 +18069,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean {
|
||||
if (languageVersion < ScriptTarget.ES6) {
|
||||
return grammarErrorOnNode(asyncModifier, Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_6_and_higher);
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
|
||||
@@ -831,10 +831,6 @@
|
||||
"category": "Error",
|
||||
"code": 1308
|
||||
},
|
||||
"Async functions are only available when targeting ECMAScript 6 and higher.": {
|
||||
"category": "Error",
|
||||
"code": 1311
|
||||
},
|
||||
"'=' can only be used in an object literal property inside a destructuring assignment.": {
|
||||
"category": "Error",
|
||||
"code": 1312
|
||||
|
||||
+46
-78
@@ -73,99 +73,52 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
|
||||
const generatorHelper = `
|
||||
var __generator = (this && this.__generator) || function (body) {
|
||||
var done, finallyStack, executing, yieldStar, trys = [], state = { label: 0, trys: trys };
|
||||
var _ = { label: 0, sent: function() { if (sent[0] === 1 /*throw*/) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent;
|
||||
function step(op) {
|
||||
if (executing) throw new TypeError("Generator is already executing.");
|
||||
if (_.flag) throw new TypeError("Generator is already executing.");
|
||||
while (true) {
|
||||
if (done) {
|
||||
switch (op[0]) {
|
||||
case 0 /*next*/: return { value: void 0, done: true };
|
||||
case 6 /*catch*/:
|
||||
case 1 /*throw*/: throw op[1];
|
||||
case 2 /*return*/: return { value: op[1], done: true };
|
||||
}
|
||||
if (_.done) switch (op[0]) {
|
||||
case 0 /*next*/: return { value: void 0, done: true };
|
||||
case 1 /*throw*/: case 6 /*catch*/: throw op[1];
|
||||
case 2 /*return*/: return { value: op[1], done: true };
|
||||
}
|
||||
try {
|
||||
executing = true;
|
||||
if (yieldStar) {
|
||||
var verb = yieldStar[op[0] === 2 ? "return" : op[0] === 1 ? "throw" : "next"];
|
||||
if (verb) {
|
||||
var yielded = verb.call(yieldStar, op[1]);
|
||||
if (!yielded.done) return { value: yielded.value, done: false };
|
||||
op = [0 /*next*/, yielded.value];
|
||||
}
|
||||
|
||||
yieldStar = void 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (op[0]) {
|
||||
case 0 /*next*/:
|
||||
state.sent = function() { return op[1]; };
|
||||
break;
|
||||
|
||||
case 1 /*throw*/:
|
||||
state.sent = function() { throw op[1]; };
|
||||
break;
|
||||
|
||||
case 4 /*yield*/:
|
||||
state.label++;
|
||||
return { value: op[1], done: false };
|
||||
|
||||
case 5 /*yieldstar*/:
|
||||
state.label++;
|
||||
yieldStar = op[1];
|
||||
op = [0 /*next*/, void 0];
|
||||
continue;
|
||||
|
||||
case 7 /*endfinally*/:
|
||||
op = finallyStack.pop();
|
||||
trys.pop();
|
||||
continue;
|
||||
|
||||
switch (_.flag = true, op[0]) {
|
||||
case 0 /*next*/: case 1 /*throw*/: sent = op; break;
|
||||
case 4 /*yield*/: return _.label++, { value: op[1], done: false };
|
||||
case 7 /*endfinally*/: op = _.stack.pop(), _.trys.pop(); continue;
|
||||
default:
|
||||
var rgn = trys.length && trys[trys.length - 1];
|
||||
if (!rgn && (op[0] === 6 /*catch*/ || op[0] === 1 /*throw*/ || op[0] === 2 /*return*/)) {
|
||||
done = true;
|
||||
finallyStack = void 0;
|
||||
var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
|
||||
if (!r && (op[0] === 1 /*throw*/ || op[0] === 6 /*catch*/ || op[0] === 2 /*return*/)) {
|
||||
_.done = true;
|
||||
continue;
|
||||
}
|
||||
else if (op[0] === 3 /*break*/ && (!rgn || (op[1] > rgn[0] && op[1] < rgn[3]))) {
|
||||
state.label = op[1];
|
||||
if (op[0] === 3 /*break*/ && (!r || (op[1] > r[0] && op[1] < r[3]))) {
|
||||
_.label = op[1];
|
||||
}
|
||||
else if (op[0] === 6 /*catch*/ && rgn && state.label < rgn[1]) {
|
||||
state.error = op[1];
|
||||
state.label = rgn[1];
|
||||
else if (op[0] === 6 /*catch*/ && r && _.label < r[1]) {
|
||||
_.label = r[1], sent = op;
|
||||
}
|
||||
else if (rgn && state.label < rgn[2]) {
|
||||
(finallyStack || []).push(op);
|
||||
state.label = rgn[2];
|
||||
else if (r && _.label < r[2]) {
|
||||
_.label = r[2], _.stack.push(op);
|
||||
}
|
||||
else {
|
||||
if (rgn[2]) finallyStack.pop();
|
||||
trys.pop();
|
||||
if (r[2]) _.stack.pop();
|
||||
_.trys.pop();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
op = body(state);
|
||||
}
|
||||
catch (e) {
|
||||
op = [6 /*catch*/, e];
|
||||
yieldStar = void 0;
|
||||
}
|
||||
finally {
|
||||
executing = false;
|
||||
verb = yielded = void 0;
|
||||
op = body(_);
|
||||
}
|
||||
catch (e) { op = [6 /*catch*/, e]; }
|
||||
finally { _.flag = false, sent = void 0; }
|
||||
}
|
||||
}
|
||||
var g = {
|
||||
return {
|
||||
next: function (v) { return step([0 /*next*/, v]); },
|
||||
"throw": function (v) { return step([1 /*throw*/, v]); },
|
||||
"return": function (v) { return step([2 /*return*/, v]); }
|
||||
};
|
||||
return g;
|
||||
};`;
|
||||
|
||||
// emit output for the __export helper function
|
||||
@@ -782,6 +735,8 @@ const _super = (function (geti, seti) {
|
||||
switch (kind) {
|
||||
// Literals
|
||||
case SyntaxKind.NumericLiteral:
|
||||
return emitNumericLiteral(<NumericLiteral>node);
|
||||
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.RegularExpressionLiteral:
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
@@ -870,6 +825,13 @@ const _super = (function (geti, seti) {
|
||||
//
|
||||
|
||||
// SyntaxKind.NumericLiteral
|
||||
function emitNumericLiteral(node: NumericLiteral) {
|
||||
emitLiteral(node);
|
||||
if (node.trailingComment) {
|
||||
write(` /*${node.trailingComment}*/`);
|
||||
}
|
||||
}
|
||||
|
||||
// SyntaxKind.StringLiteral
|
||||
// SyntaxKind.RegularExpressionLiteral
|
||||
// SyntaxKind.NoSubstitutionTemplateLiteral
|
||||
@@ -1653,15 +1615,21 @@ const _super = (function (geti, seti) {
|
||||
increaseIndent();
|
||||
}
|
||||
|
||||
const savedTempFlags = tempFlags;
|
||||
tempFlags = 0;
|
||||
emitSignatureHead(node);
|
||||
emitBlockFunctionBody(node, body);
|
||||
if (node.emitFlags & NodeEmitFlags.ReuseTempVariableScope) {
|
||||
emitSignatureHead(node);
|
||||
emitBlockFunctionBody(node, body);
|
||||
}
|
||||
else {
|
||||
const savedTempFlags = tempFlags;
|
||||
tempFlags = 0;
|
||||
emitSignatureHead(node);
|
||||
emitBlockFunctionBody(node, body);
|
||||
tempFlags = savedTempFlags;
|
||||
}
|
||||
|
||||
if (indentedFlag) {
|
||||
decreaseIndent();
|
||||
}
|
||||
|
||||
tempFlags = savedTempFlags;
|
||||
}
|
||||
else {
|
||||
emitSignatureHead(node);
|
||||
|
||||
+23
-6
@@ -139,7 +139,7 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createTempVariable(recordTempVariable: (node: Identifier) => void, location?: TextRange): Identifier {
|
||||
export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, location?: TextRange): Identifier {
|
||||
const name = <Identifier>createNode(SyntaxKind.Identifier, location);
|
||||
name.text = "";
|
||||
name.originalKeywordKind = SyntaxKind.Unknown;
|
||||
@@ -366,6 +366,13 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) {
|
||||
if (node.expression !== expression || node.argumentExpression !== argumentExpression) {
|
||||
return updateNode(createElementAccess(expression, argumentExpression, node), node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createCall(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[], location?: TextRange, flags?: NodeFlags) {
|
||||
const node = <CallExpression>createNode(SyntaxKind.CallExpression, location, flags);
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
@@ -1378,19 +1385,29 @@ namespace ts {
|
||||
thisArg: Expression;
|
||||
}
|
||||
|
||||
function shouldBeCapturedInTempVariable(node: Expression): boolean {
|
||||
switch (skipParentheses(node).kind) {
|
||||
function shouldBeCapturedInTempVariable(node: Expression, cacheIdentifiers: boolean): boolean {
|
||||
const target = skipParentheses(node);
|
||||
switch (target.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return cacheIdentifiers;
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.NumericLiteral:
|
||||
case SyntaxKind.StringLiteral:
|
||||
return false;
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
const elements = (<ArrayLiteralExpression>target).elements;
|
||||
if (elements.length === 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return (<ObjectLiteralExpression>target).properties.length > 0;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget): CallBinding {
|
||||
export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean): CallBinding {
|
||||
const callee = skipOuterExpressions(expression, OuterExpressionKinds.All);
|
||||
let thisArg: Expression;
|
||||
let target: LeftHandSideExpression;
|
||||
@@ -1405,7 +1422,7 @@ namespace ts {
|
||||
else {
|
||||
switch (callee.kind) {
|
||||
case SyntaxKind.PropertyAccessExpression: {
|
||||
if (shouldBeCapturedInTempVariable((<PropertyAccessExpression>callee).expression)) {
|
||||
if (shouldBeCapturedInTempVariable((<PropertyAccessExpression>callee).expression, cacheIdentifiers)) {
|
||||
// for `a.b()` target is `(_a = a).b` and thisArg is `_a`
|
||||
thisArg = createTempVariable(recordTempVariable);
|
||||
target = createPropertyAccess(
|
||||
@@ -1426,7 +1443,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
case SyntaxKind.ElementAccessExpression: {
|
||||
if (shouldBeCapturedInTempVariable((<ElementAccessExpression>callee).expression)) {
|
||||
if (shouldBeCapturedInTempVariable((<ElementAccessExpression>callee).expression, cacheIdentifiers)) {
|
||||
// for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a`
|
||||
thisArg = createTempVariable(recordTempVariable);
|
||||
target = createElementAccess(
|
||||
|
||||
@@ -235,9 +235,12 @@ namespace ts {
|
||||
hoistFunctionDeclaration,
|
||||
hoistVariableDeclaration,
|
||||
setSourceMapRange,
|
||||
setCommentRange
|
||||
setCommentRange,
|
||||
setNodeEmitFlags
|
||||
} = context;
|
||||
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
const languageVersion = getEmitScriptTarget(compilerOptions);
|
||||
const resolver = context.getEmitResolver();
|
||||
const previousOnSubstituteNode = context.onSubstituteNode;
|
||||
context.onSubstituteNode = onSubstituteNode;
|
||||
@@ -316,10 +319,10 @@ namespace ts {
|
||||
else if (inGeneratorFunctionBody) {
|
||||
return visitJavaScriptInGeneratorFunctionBody(node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.Generator) {
|
||||
else if (transformFlags & TransformFlags.Generator) {
|
||||
return visitGenerator(node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.ContainsGenerator) {
|
||||
else if (transformFlags & TransformFlags.ContainsGenerator) {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
else {
|
||||
@@ -366,10 +369,6 @@ namespace ts {
|
||||
return visitDoStatement(<DoStatement>node);
|
||||
case SyntaxKind.WhileStatement:
|
||||
return visitWhileStatement(<WhileStatement>node);
|
||||
case SyntaxKind.ForStatement:
|
||||
return visitForStatement(<ForStatement>node);
|
||||
case SyntaxKind.ForInStatement:
|
||||
return visitForInStatement(<ForInStatement>node);
|
||||
case SyntaxKind.SwitchStatement:
|
||||
return visitSwitchStatement(<SwitchStatement>node);
|
||||
case SyntaxKind.LabeledStatement:
|
||||
@@ -395,6 +394,10 @@ namespace ts {
|
||||
return visitAccessorDeclaration(<AccessorDeclaration>node);
|
||||
case SyntaxKind.VariableStatement:
|
||||
return visitVariableStatement(<VariableStatement>node);
|
||||
case SyntaxKind.ForStatement:
|
||||
return visitForStatement(<ForStatement>node);
|
||||
case SyntaxKind.ForInStatement:
|
||||
return visitForInStatement(<ForInStatement>node);
|
||||
case SyntaxKind.BreakStatement:
|
||||
return visitBreakStatement(<BreakStatement>node);
|
||||
case SyntaxKind.ContinueStatement:
|
||||
@@ -402,7 +405,7 @@ namespace ts {
|
||||
case SyntaxKind.ReturnStatement:
|
||||
return visitReturnStatement(<ReturnStatement>node);
|
||||
default:
|
||||
if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsYield | TransformFlags.ContainsHoistedDeclaration)) {
|
||||
if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsYield | TransformFlags.ContainsHoistedDeclarationOrCompletion)) {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
else {
|
||||
@@ -568,7 +571,7 @@ namespace ts {
|
||||
operations = undefined;
|
||||
operationArguments = undefined;
|
||||
operationLocations = undefined;
|
||||
state = createUniqueName("state");
|
||||
state = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
|
||||
// Build the generator
|
||||
startLexicalEnvironment();
|
||||
@@ -646,54 +649,98 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isCompoundAssignment(kind: SyntaxKind) {
|
||||
return kind >= SyntaxKind.FirstCompoundAssignment
|
||||
&& kind <= SyntaxKind.LastCompoundAssignment;
|
||||
}
|
||||
|
||||
function getOperatorForCompoundAssignment(kind: SyntaxKind) {
|
||||
switch (kind) {
|
||||
case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken;
|
||||
case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken;
|
||||
case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken;
|
||||
case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken;
|
||||
case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken;
|
||||
case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken;
|
||||
case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken;
|
||||
case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken;
|
||||
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
|
||||
case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken;
|
||||
case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken;
|
||||
case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a right-associative binary expression containing `yield`.
|
||||
*
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitRightAssociativeBinaryExpression(node: BinaryExpression) {
|
||||
switch (node.left.kind) {
|
||||
case SyntaxKind.PropertyAccessExpression: {
|
||||
// [source]
|
||||
// a.b = yield;
|
||||
//
|
||||
// [intermediate]
|
||||
// .local _a
|
||||
// _a = a;
|
||||
// .yield resumeLabel
|
||||
// .mark resumeLabel
|
||||
// _a.b = %sent%;
|
||||
const { left, right } = node;
|
||||
if (containsYield(right)) {
|
||||
let target: Expression;
|
||||
switch (left.kind) {
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
// [source]
|
||||
// a.b = yield;
|
||||
//
|
||||
// [intermediate]
|
||||
// .local _a
|
||||
// _a = a;
|
||||
// .yield resumeLabel
|
||||
// .mark resumeLabel
|
||||
// _a.b = %sent%;
|
||||
|
||||
const clone = getMutableClone(node);
|
||||
const propertyAccess = <PropertyAccessExpression>node.left;
|
||||
const propertyAccessClone = getMutableClone(propertyAccess);
|
||||
propertyAccessClone.expression = cacheExpression(visitNode(propertyAccess.expression, visitor, isLeftHandSideExpression));
|
||||
clone.left = propertyAccessClone;
|
||||
clone.right = visitNode(node.right, visitor, isExpression);
|
||||
return clone;
|
||||
target = updatePropertyAccess(
|
||||
<PropertyAccessExpression>left,
|
||||
cacheExpression(visitNode((<PropertyAccessExpression>left).expression, visitor, isLeftHandSideExpression)),
|
||||
(<PropertyAccessExpression>left).name
|
||||
);
|
||||
break;
|
||||
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
// [source]
|
||||
// a[b] = yield;
|
||||
//
|
||||
// [intermediate]
|
||||
// .local _a, _b
|
||||
// _a = a;
|
||||
// _b = b;
|
||||
// .yield resumeLabel
|
||||
// .mark resumeLabel
|
||||
// _a[_b] = %sent%;
|
||||
|
||||
target = updateElementAccess(<ElementAccessExpression>left,
|
||||
cacheExpression(visitNode((<ElementAccessExpression>left).expression, visitor, isLeftHandSideExpression)),
|
||||
cacheExpression(visitNode((<ElementAccessExpression>left).argumentExpression, visitor, isExpression))
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
target = visitNode(left, visitor, isExpression);
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ElementAccessExpression: {
|
||||
// [source]
|
||||
// a[b] = yield;
|
||||
//
|
||||
// [intermediate]
|
||||
// .local _a, _b
|
||||
// _a = a;
|
||||
// _b = b;
|
||||
// .yield resumeLabel
|
||||
// .mark resumeLabel
|
||||
// _a[_b] = %sent%;
|
||||
|
||||
const clone = getMutableClone(node);
|
||||
const elementAccess = <ElementAccessExpression>node.left;
|
||||
const elementAccessClone = getMutableClone(elementAccess);
|
||||
elementAccessClone.expression = cacheExpression(visitNode(elementAccess.expression, visitor, isLeftHandSideExpression));
|
||||
elementAccessClone.argumentExpression = cacheExpression(visitNode(elementAccess.argumentExpression, visitor, isExpression));
|
||||
clone.left = elementAccessClone;
|
||||
clone.right = visitNode(node.right, visitor, isExpression);
|
||||
return clone;
|
||||
const operator = node.operatorToken.kind;
|
||||
if (isCompoundAssignment(operator)) {
|
||||
return createBinary(
|
||||
target,
|
||||
SyntaxKind.EqualsToken,
|
||||
createBinary(
|
||||
cacheExpression(target),
|
||||
getOperatorForCompoundAssignment(operator),
|
||||
visitNode(right, visitor, isExpression),
|
||||
node
|
||||
),
|
||||
node
|
||||
);
|
||||
}
|
||||
else {
|
||||
return updateBinary(node, target, visitNode(right, visitor, isExpression));
|
||||
}
|
||||
}
|
||||
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
@@ -902,26 +949,34 @@ namespace ts {
|
||||
// ar = _a.concat([%sent%, 2]);
|
||||
|
||||
const numInitialElements = countInitialNodesWithoutYield(elements);
|
||||
|
||||
const temp = declareLocal();
|
||||
emitAssignment(temp,
|
||||
createArrayLiteral(
|
||||
visitNodes(elements, visitor, isExpression, 0, numInitialElements)
|
||||
)
|
||||
);
|
||||
let hasAssignedTemp = false;
|
||||
if (numInitialElements > 0) {
|
||||
emitAssignment(temp,
|
||||
createArrayLiteral(
|
||||
visitNodes(elements, visitor, isExpression, 0, numInitialElements)
|
||||
)
|
||||
);
|
||||
hasAssignedTemp = true;
|
||||
}
|
||||
|
||||
const expressions = reduceLeft(elements, reduceElement, <Expression[]>[], numInitialElements);
|
||||
return createArrayConcat(temp, [createArrayLiteral(expressions)]);
|
||||
return hasAssignedTemp
|
||||
? createArrayConcat(temp, [createArrayLiteral(expressions)])
|
||||
: createArrayLiteral(expressions);
|
||||
|
||||
function reduceElement(expressions: Expression[], element: Expression) {
|
||||
if (containsYield(element) && expressions.length > 0) {
|
||||
emitAssignment(
|
||||
temp,
|
||||
createArrayConcat(
|
||||
temp,
|
||||
[createArrayLiteral(expressions)]
|
||||
)
|
||||
hasAssignedTemp
|
||||
? createArrayConcat(
|
||||
temp,
|
||||
[createArrayLiteral(expressions)]
|
||||
)
|
||||
: createArrayLiteral(expressions)
|
||||
);
|
||||
hasAssignedTemp = true;
|
||||
expressions = [];
|
||||
}
|
||||
|
||||
@@ -1017,7 +1072,7 @@ namespace ts {
|
||||
// .mark resumeLabel
|
||||
// _b.apply(_a, _c.concat([%sent%, 2]));
|
||||
|
||||
const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration);
|
||||
const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true);
|
||||
return setOriginalNode(
|
||||
createFunctionApply(
|
||||
cacheExpression(visitNode(target, visitor, isLeftHandSideExpression)),
|
||||
@@ -1121,7 +1176,7 @@ namespace ts {
|
||||
case SyntaxKind.TryStatement:
|
||||
return transformAndEmitTryStatement(<TryStatement>node);
|
||||
default:
|
||||
return emitStatement(visitEachChild(node, visitor, context));
|
||||
return emitStatement(visitNode(node, visitor, isStatement, /*optional*/ true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1398,14 +1453,14 @@ namespace ts {
|
||||
// }
|
||||
//
|
||||
// [intermediate]
|
||||
// .local _a, _b, _c
|
||||
// .local _a, _b, _i
|
||||
// _a = [];
|
||||
// for (_b in o) _a.push(_b);
|
||||
// _c = 0;
|
||||
// _i = 0;
|
||||
// .loop incrementLabel, endLoopLabel
|
||||
// .mark conditionLabel
|
||||
// .brfalse endLoopLabel, (_c < _a.length)
|
||||
// p = _a[_c];
|
||||
// .brfalse endLoopLabel, (_i < _a.length)
|
||||
// p = _a[_i];
|
||||
// /*body*/
|
||||
// .mark incrementLabel
|
||||
// _b++;
|
||||
@@ -1415,9 +1470,9 @@ namespace ts {
|
||||
|
||||
const keysArray = declareLocal(); // _a
|
||||
const key = declareLocal(); // _b
|
||||
const keysIndex = declareLocal(); // _c
|
||||
const keysIndex = createLoopVariable(); // _i
|
||||
const initializer = node.initializer;
|
||||
|
||||
hoistVariableDeclaration(keysIndex);
|
||||
emitAssignment(keysArray, createArrayLiteral());
|
||||
|
||||
emitStatement(
|
||||
@@ -1440,6 +1495,9 @@ namespace ts {
|
||||
const incrementLabel = defineLabel();
|
||||
const endLabel = beginLoopBlock(incrementLabel);
|
||||
|
||||
markLabel(conditionLabel);
|
||||
emitBreakWhenFalse(endLabel, createLessThan(keysIndex, createPropertyAccess(keysArray, "length")));
|
||||
|
||||
let variable: Expression;
|
||||
if (isVariableDeclarationList(initializer)) {
|
||||
for (const variable of initializer.declarations) {
|
||||
@@ -1449,13 +1507,10 @@ namespace ts {
|
||||
variable = <Identifier>getSynthesizedClone(initializer.declarations[0].name);
|
||||
}
|
||||
else {
|
||||
variable = initializer;
|
||||
variable = visitNode(initializer, visitor, isExpression);
|
||||
Debug.assert(isLeftHandSideExpression(variable));
|
||||
}
|
||||
|
||||
markLabel(conditionLabel);
|
||||
emitBreakWhenFalse(endLabel, createLessThan(keysIndex, createPropertyAccess(keysArray, "length")));
|
||||
|
||||
emitAssignment(variable, createElementAccess(keysArray, keysIndex));
|
||||
transformAndEmitEmbeddedStatement(node.statement);
|
||||
|
||||
@@ -1580,7 +1635,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function transformAndEmitSwitchStatement(node: SwitchStatement) {
|
||||
if (containsYield(node)) {
|
||||
if (containsYield(node.caseBlock)) {
|
||||
// [source]
|
||||
// switch (x) {
|
||||
// case a:
|
||||
@@ -1636,6 +1691,7 @@ namespace ts {
|
||||
let clausesWritten = 0;
|
||||
let pendingClauses: CaseClause[] = [];
|
||||
while (clausesWritten < numClauses) {
|
||||
let defaultClausesSkipped = 0;
|
||||
for (let i = clausesWritten; i < numClauses; i++) {
|
||||
const clause = caseBlock.clauses[i];
|
||||
if (clause.kind === SyntaxKind.CaseClause) {
|
||||
@@ -1653,6 +1709,9 @@ namespace ts {
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
defaultClausesSkipped++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pendingClauses.length) {
|
||||
@@ -1660,6 +1719,10 @@ namespace ts {
|
||||
clausesWritten += pendingClauses.length;
|
||||
pendingClauses = [];
|
||||
}
|
||||
if (defaultClausesSkipped > 0) {
|
||||
clausesWritten += defaultClausesSkipped;
|
||||
defaultClausesSkipped = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultClauseIndex >= 0) {
|
||||
@@ -1772,10 +1835,6 @@ namespace ts {
|
||||
beginExceptionBlock();
|
||||
transformAndEmitEmbeddedStatement(node.tryBlock);
|
||||
if (node.catchClause) {
|
||||
if (!renamedCatchVariables) {
|
||||
renamedCatchVariables = {};
|
||||
}
|
||||
|
||||
beginCatchBlock(node.catchClause.variableDeclaration);
|
||||
transformAndEmitEmbeddedStatement(node.catchClause.block);
|
||||
}
|
||||
@@ -1844,17 +1903,11 @@ namespace ts {
|
||||
|
||||
function cacheExpression(node: Expression): Identifier {
|
||||
let temp: Identifier;
|
||||
if (isIdentifier(node)) {
|
||||
if (nodeIsSynthesized(node) || isGeneratedIdentifier(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
temp = createUniqueName(node.text);
|
||||
}
|
||||
else {
|
||||
temp = createTempVariable(hoistVariableDeclaration);
|
||||
if (isGeneratedIdentifier(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
temp = createTempVariable(hoistVariableDeclaration);
|
||||
emitAssignment(temp, node, /*location*/ node);
|
||||
return temp;
|
||||
}
|
||||
@@ -1862,7 +1915,7 @@ namespace ts {
|
||||
function declareLocal(name?: string): Identifier {
|
||||
const temp = name
|
||||
? createUniqueName(name)
|
||||
: createTempVariable(hoistVariableDeclaration);
|
||||
: createTempVariable(/*recordTempVariable*/ undefined);
|
||||
hoistVariableDeclaration(temp);
|
||||
return temp;
|
||||
}
|
||||
@@ -1983,7 +2036,7 @@ namespace ts {
|
||||
startLabel,
|
||||
endLabel
|
||||
});
|
||||
emitWorker(OpCode.Nop);
|
||||
emitNop();
|
||||
return endLabel;
|
||||
}
|
||||
|
||||
@@ -1996,7 +2049,7 @@ namespace ts {
|
||||
Debug.assert(peekBlockKind() === CodeBlockKind.Exception);
|
||||
|
||||
const text = (<Identifier>variable.name).text;
|
||||
const name = createUniqueName(text);
|
||||
const name = declareLocal(text);
|
||||
|
||||
if (!renamedCatchVariables) {
|
||||
renamedCatchVariables = {};
|
||||
@@ -2019,8 +2072,8 @@ namespace ts {
|
||||
exception.catchVariable = name;
|
||||
exception.catchLabel = catchLabel;
|
||||
|
||||
emitAssignment(name, createPropertyAccess(state, "error"));
|
||||
emitWorker(OpCode.Nop);
|
||||
emitAssignment(name, createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, []));
|
||||
emitNop();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2056,6 +2109,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
markLabel(exception.endLabel);
|
||||
emitNop();
|
||||
exception.state = ExceptionBlockState.Done;
|
||||
}
|
||||
|
||||
@@ -2352,6 +2406,13 @@ namespace ts {
|
||||
return createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [], location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an empty instruction.
|
||||
*/
|
||||
function emitNop() {
|
||||
emitWorker(OpCode.Nop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a Statement.
|
||||
*
|
||||
@@ -2362,7 +2423,7 @@ namespace ts {
|
||||
emitWorker(OpCode.Statement, [node]);
|
||||
}
|
||||
else {
|
||||
emitWorker(OpCode.Nop);
|
||||
emitNop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2487,18 +2548,24 @@ namespace ts {
|
||||
currentExceptionBlock = undefined;
|
||||
withBlockStack = undefined;
|
||||
|
||||
const buildResult = buildStatements();
|
||||
return createCall(
|
||||
createIdentifier("__generator"),
|
||||
/*typeArguments*/ undefined,
|
||||
[createFunctionExpression(
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(state)],
|
||||
/*type*/ undefined,
|
||||
createBlock(
|
||||
buildStatements()
|
||||
)
|
||||
[setNodeEmitFlags(
|
||||
createFunctionExpression(
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(state)],
|
||||
/*type*/ undefined,
|
||||
createBlock(
|
||||
buildResult,
|
||||
/*location*/ undefined,
|
||||
/*multiLine*/ buildResult.length > 0
|
||||
)
|
||||
),
|
||||
NodeEmitFlags.ReuseTempVariableScope
|
||||
)]
|
||||
);
|
||||
}
|
||||
@@ -2521,6 +2588,7 @@ namespace ts {
|
||||
if (clauses) {
|
||||
const labelExpression = createPropertyAccess(state, "label");
|
||||
const switchStatement = createSwitch(labelExpression, createCaseBlock(clauses));
|
||||
switchStatement.startsOnNewLine = true;
|
||||
return [switchStatement];
|
||||
}
|
||||
|
||||
@@ -2552,6 +2620,7 @@ namespace ts {
|
||||
function flushFinalLabel(operationIndex: number): void {
|
||||
if (!lastOperationWasCompletion) {
|
||||
tryEnterLabel(operationIndex);
|
||||
withBlockStack = undefined;
|
||||
writeReturn(/*expression*/ undefined, /*operationLocation*/ undefined);
|
||||
}
|
||||
|
||||
|
||||
+12
-9
@@ -359,6 +359,8 @@ namespace ts {
|
||||
// Markers
|
||||
FirstAssignment = EqualsToken,
|
||||
LastAssignment = CaretEqualsToken,
|
||||
FirstCompoundAssignment = PlusEqualsToken,
|
||||
LastCompoundAssignment = CaretEqualsToken,
|
||||
FirstReservedWord = BreakKeyword,
|
||||
LastReservedWord = WithKeyword,
|
||||
FirstKeyword = BreakKeyword,
|
||||
@@ -2987,7 +2989,7 @@ namespace ts {
|
||||
ContainsBlockScopedBinding = 1 << 20,
|
||||
ContainsBindingPattern = 1 << 21,
|
||||
ContainsYield = 1 << 22,
|
||||
ContainsHoistedDeclaration = 1 << 23,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 23,
|
||||
|
||||
HasComputedFlags = 1 << 29, // Transform flags have been computed.
|
||||
|
||||
@@ -3002,13 +3004,13 @@ namespace ts {
|
||||
// Scope Exclusions
|
||||
// - Bitmasks that exclude flags from propagating out of a specific context
|
||||
// into the subtree flags of their container.
|
||||
NodeExcludes = TypeScript | Jsx | ES7 | ES6 | DestructuringAssignment | HasComputedFlags,
|
||||
ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
|
||||
FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
|
||||
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
|
||||
MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
|
||||
NodeExcludes = TypeScript | Jsx | ES7 | ES6 | DestructuringAssignment | Generator | HasComputedFlags,
|
||||
ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
|
||||
FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
|
||||
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
|
||||
MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
|
||||
ClassExcludes = NodeExcludes | ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments | ContainsLexicalThisInComputedPropertyName,
|
||||
ModuleExcludes = NodeExcludes | ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclaration,
|
||||
ModuleExcludes = NodeExcludes | ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
|
||||
TypeExcludes = ~ContainsTypeScript,
|
||||
ObjectLiteralExcludes = NodeExcludes | ContainsDecorators | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
|
||||
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsSpreadElementExpression,
|
||||
@@ -3047,13 +3049,14 @@ namespace ts {
|
||||
LocalName = 1 << 18, // Ensure an export prefix is not added for an identifier that points to an exported declaration.
|
||||
Indented = 1 << 19, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
|
||||
AsyncFunctionBody = 1 << 20,
|
||||
ReuseTempVariableScope = 1 << 21, // Reuse the existing temp variable scope during emit.
|
||||
|
||||
// SourceMap Specialization.
|
||||
// TODO(rbuckton): These should be removed once source maps are aligned with the old
|
||||
// emitter and new baselines are taken. This exists solely to
|
||||
// align with the old emitter.
|
||||
SourceMapEmitOpenBraceAsToken = 1 << 21, // Emits the open brace of a block function body as a source mapped token.
|
||||
SourceMapAdjustRestParameterLoop = 1 << 22, // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
|
||||
SourceMapEmitOpenBraceAsToken = 1 << 22, // Emits the open brace of a block function body as a source mapped token.
|
||||
SourceMapAdjustRestParameterLoop = 1 << 23, // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
|
||||
}
|
||||
|
||||
/** Additional context provided to `visitEachChild` */
|
||||
|
||||
Reference in New Issue
Block a user