Added tests and fixed related emit issues.

This commit is contained in:
Ron Buckton
2016-06-14 17:59:44 -07:00
parent 27931d5f75
commit ea61f2b32b
90 changed files with 11065 additions and 201 deletions
+9 -2
View File
@@ -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;
-4
View File
@@ -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:
-4
View File
@@ -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
View File
@@ -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
View File
@@ -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(
+167 -98
View File
@@ -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
View File
@@ -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` */