Early support for generators.

This commit is contained in:
Ron Buckton 2016-02-29 11:04:56 -08:00
parent 72bfd2f5b6
commit d506e92e84
16 changed files with 3732 additions and 183 deletions

View File

@ -49,6 +49,7 @@ var compilerSources = [
"transformers/module/module.ts",
"transformers/jsx.ts",
"transformers/es7.ts",
"transformers/generators.ts",
"transformers/es6.ts",
"transformer.ts",
"sourcemap.ts",
@ -82,6 +83,7 @@ var servicesSources = [
"transformers/module/module.ts",
"transformers/jsx.ts",
"transformers/es7.ts",
"transformers/generators.ts",
"transformers/es6.ts",
"transformer.ts",
"sourcemap.ts",

View File

@ -1115,7 +1115,7 @@ namespace ts {
}
}
function checkStrictModeNumericLiteral(node: LiteralExpression) {
function checkStrictModeNumericLiteral(node: NumericLiteral) {
if (inStrictMode && node.isOctalLiteral) {
file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode));
}
@ -1296,7 +1296,7 @@ namespace ts {
case SyntaxKind.DeleteExpression:
return checkStrictModeDeleteExpression(<DeleteExpression>node);
case SyntaxKind.NumericLiteral:
return checkStrictModeNumericLiteral(<LiteralExpression>node);
return checkStrictModeNumericLiteral(<NumericLiteral>node);
case SyntaxKind.PostfixUnaryExpression:
return checkStrictModePostfixUnaryExpression(<PostfixUnaryExpression>node);
case SyntaxKind.PrefixUnaryExpression:
@ -1852,11 +1852,14 @@ namespace ts {
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.ForOfStatement:
case SyntaxKind.YieldExpression:
// These nodes are ES6 syntax.
transformFlags |= TransformFlags.AssertES6;
break;
case SyntaxKind.YieldExpression:
// This node is ES6 syntax.
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsYield;
break;
case SyntaxKind.AnyKeyword:
case SyntaxKind.NumberKeyword:
@ -2026,10 +2029,13 @@ namespace ts {
// A FunctionExpression excludes markers that should not escape the scope of a FunctionExpression.
excludeFlags = TransformFlags.FunctionExcludes;
if ((<FunctionExpression>node).asteriskToken) {
transformFlags |= TransformFlags.ContainsGenerators;
}
// If a FunctionExpression contains an asterisk token, or its subtree has marked the container
// as needing to capture the lexical this, then this node is ES6 syntax.
if ((<FunctionLikeDeclaration>node).asteriskToken
|| subtreeFlags & TransformFlags.ContainsCapturedLexicalThis
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis
|| subtreeFlags & TransformFlags.ContainsDefaultValueAssignments) {
transformFlags |= TransformFlags.AssertES6;
}
@ -2051,11 +2057,14 @@ namespace ts {
break;
}
if ((<FunctionDeclaration>node).asteriskToken) {
transformFlags |= TransformFlags.ContainsGenerators;
}
// If a FunctionDeclaration has an asterisk token, is exported, or its
// subtree has marked the container as needing to capture the lexical `this`,
// then this node is ES6 syntax.
if ((<FunctionDeclaration>node).asteriskToken
|| node.flags & NodeFlags.Export
if (node.flags & NodeFlags.Export
|| subtreeFlags & TransformFlags.ContainsCapturedLexicalThis
|| subtreeFlags & TransformFlags.ContainsDefaultValueAssignments) {
transformFlags |= TransformFlags.AssertES6;
@ -2183,6 +2192,10 @@ namespace ts {
excludeFlags = TransformFlags.MethodOrAccessorExcludes;
transformFlags |= TransformFlags.AssertES6;
if ((<MethodDeclaration>node).asteriskToken) {
transformFlags |= TransformFlags.ContainsGenerators;
}
// A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
// generic, or has both a computed property name and a decorator.
if ((<MethodDeclaration>node).body === undefined

View File

@ -11404,7 +11404,7 @@ namespace ts {
return type;
}
function checkNumericLiteral(node: LiteralExpression): Type {
function checkNumericLiteral(node: NumericLiteral): Type {
// Grammar checking
checkGrammarNumericLiteral(node);
return numberType;
@ -11424,7 +11424,7 @@ namespace ts {
case SyntaxKind.FalseKeyword:
return booleanType;
case SyntaxKind.NumericLiteral:
return checkNumericLiteral(<LiteralExpression>node);
return checkNumericLiteral(<NumericLiteral>node);
case SyntaxKind.TemplateExpression:
return checkTemplateExpression(<TemplateExpression>node);
case SyntaxKind.StringLiteral:
@ -14328,7 +14328,7 @@ namespace ts {
}
return undefined;
case SyntaxKind.NumericLiteral:
return +(<LiteralExpression>e).text;
return +(<NumericLiteral>e).text;
case SyntaxKind.ParenthesizedExpression:
return evalConstant((<ParenthesizedExpression>e).expression);
case SyntaxKind.Identifier:
@ -15499,7 +15499,7 @@ namespace ts {
if (objectType === unknownType) return undefined;
const apparentType = getApparentType(objectType);
if (apparentType === unknownType) return undefined;
return getPropertyOfType(apparentType, (<LiteralExpression>node).text);
return getPropertyOfType(apparentType, (<NumericLiteral>node).text);
}
break;
}
@ -16693,7 +16693,7 @@ namespace ts {
// Grammar checking for computedPropertName and shorthandPropertyAssignment
checkGrammarForInvalidQuestionMark(prop, (<PropertyAssignment>prop).questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
if (name.kind === SyntaxKind.NumericLiteral) {
checkGrammarNumericLiteral(<LiteralExpression>name);
checkGrammarNumericLiteral(<NumericLiteral>name);
}
currentKind = Property;
}
@ -17194,7 +17194,7 @@ namespace ts {
}
}
function checkGrammarNumericLiteral(node: LiteralExpression): boolean {
function checkGrammarNumericLiteral(node: NumericLiteral): boolean {
// Grammar checking
if (node.isOctalLiteral && languageVersion >= ScriptTarget.ES5) {
return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher);

View File

@ -307,13 +307,14 @@ namespace ts {
return ~low;
}
export function reduceLeft<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U): U;
export function reduceLeft<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U;
export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T): T;
export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T): T {
if (array) {
const count = array.length;
if (count > 0) {
let pos = 0;
export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T {
if (array && array.length > 0) {
const size = array.length;
if (size > 0) {
let pos = start === undefined || start < 0 ? 0 : start;
const end = count === undefined || pos + count > size - 1 ? size - 1 : pos + count;
let result: T;
if (arguments.length <= 2) {
result = array[pos];
@ -322,7 +323,7 @@ namespace ts {
else {
result = initial;
}
while (pos < count) {
while (pos <= end) {
result = f(result, array[pos], pos);
pos++;
}
@ -332,12 +333,14 @@ namespace ts {
return initial;
}
export function reduceRight<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U): U;
export function reduceRight<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U;
export function reduceRight<T>(array: T[], f: (memo: T, value: T, i: number) => T): T;
export function reduceRight<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T): T {
export function reduceRight<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T {
if (array) {
let pos = array.length - 1;
if (pos >= 0) {
const size = array.length;
if (size > 0) {
let pos = start === undefined || start > size - 1 ? size - 1 : start;
const end = count === undefined || pos - count < 0 ? 0 : pos - count;
let result: T;
if (arguments.length <= 2) {
result = array[pos];
@ -346,7 +349,7 @@ namespace ts {
else {
result = initial;
}
while (pos >= 0) {
while (pos >= end) {
result = f(result, array[pos], pos);
pos--;
}

View File

@ -1406,7 +1406,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
write("\"");
if (node.kind === SyntaxKind.NumericLiteral) {
write((<LiteralExpression>node).text);
write((<NumericLiteral>node).text);
}
else {
writeTextOfNode(currentText, node);
@ -3645,7 +3645,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
function createVoidZero(): Expression {
const zero = <LiteralExpression>createSynthesizedNode(SyntaxKind.NumericLiteral);
const zero = <NumericLiteral>createSynthesizedNode(SyntaxKind.NumericLiteral);
zero.text = "0";
const result = <VoidExpression>createSynthesizedNode(SyntaxKind.VoidExpression);
result.expression = zero;
@ -3889,7 +3889,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
function createNumericLiteral(value: number) {
const node = <LiteralExpression>createSynthesizedNode(SyntaxKind.NumericLiteral);
const node = <NumericLiteral>createSynthesizedNode(SyntaxKind.NumericLiteral);
node.text = "" + value;
return node;
}

View File

@ -152,8 +152,22 @@ namespace ts {
/**
* Creates a shallow, memberwise clone of a node for mutation.
*/
export function getMutableNode<T extends Node>(node: T): T {
return cloneNode<T>(node, node, node.flags, node.parent, node);
export function getMutableClone<T extends Node>(node: T): T {
return cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
}
/**
* Creates a shallow, memberwise clone with no position information.
*/
export function getSynthesizedClone<T extends Node>(node: T): T {
return cloneNode(node, /*location*/ undefined, node.flags, /*parent*/ undefined, /*original*/ node);
}
/**
* Creates a shallow, memberwise clone with the specified position information.
*/
export function getRelocatedClone<T extends Node>(node: T, location: TextRange) {
return cloneNode(node, location, node.flags, /*parent*/ undefined, /*original*/ node);
}
export function createNodeArrayNode<T extends Node>(elements: T[]): NodeArrayNode<T> {
@ -165,12 +179,13 @@ namespace ts {
// Literals
export function createLiteral(value: string, location?: TextRange): StringLiteral;
export function createLiteral(value: number, location?: TextRange): LiteralExpression;
export function createLiteral(value: number, location?: TextRange, trailingComment?: string): NumericLiteral;
export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression;
export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression {
export function createLiteral(value: string | number | boolean, location?: TextRange, trailingComment?: string): PrimaryExpression {
if (typeof value === "number") {
const node = <LiteralExpression>createNode(SyntaxKind.NumericLiteral, location);
const node = <NumericLiteral>createNode(SyntaxKind.NumericLiteral, location);
node.text = value.toString();
node.trailingComment = trailingComment;
return node;
}
else if (typeof value === "boolean") {
@ -185,8 +200,8 @@ namespace ts {
// Identifiers
export function createIdentifier(text: string): Identifier {
const node = <Identifier>createNode(SyntaxKind.Identifier);
export function createIdentifier(text: string, location?: TextRange): Identifier {
const node = <Identifier>createNode(SyntaxKind.Identifier, location);
node.text = text;
return node;
}
@ -194,7 +209,7 @@ namespace ts {
export function createTempVariable(): Identifier {
const name = <Identifier>createNode(SyntaxKind.Identifier);
name.text = undefined;
name.tempKind = TempVariableKind.Auto;
name.tempKind = GeneratedIdentifierKind.Auto;
getNodeId(name);
return name;
}
@ -202,7 +217,15 @@ namespace ts {
export function createLoopVariable(): Identifier {
const name = <Identifier>createNode(SyntaxKind.Identifier);
name.text = undefined;
name.tempKind = TempVariableKind.Loop;
name.tempKind = GeneratedIdentifierKind.Loop;
getNodeId(name);
return name;
}
export function createUniqueName(text: string): Identifier {
const name = <Identifier>createNode(SyntaxKind.Identifier);
name.text = text;
name.tempKind = GeneratedIdentifierKind.Unique;
getNodeId(name);
return name;
}
@ -292,15 +315,23 @@ namespace ts {
// Expression
export function createArrayLiteral(elements?: Expression[]) {
const node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression);
export function createArrayLiteral(elements?: Expression[], location?: TextRange, multiLine?: boolean) {
const node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression, location);
node.elements = parenthesizeListElements(createNodeArray(elements));
if (multiLine) {
node.multiLine = true;
}
return node;
}
export function createObjectLiteral(properties?: ObjectLiteralElement[], location?: TextRange) {
export function createObjectLiteral(properties?: ObjectLiteralElement[], location?: TextRange, multiLine?: boolean) {
const node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression, location);
node.properties = createNodeArray(properties);
if (multiLine) {
node.multiLine = true;
}
return node;
}
@ -319,16 +350,16 @@ namespace ts {
return node;
}
export function createCall(expression: Expression, argumentsArray: Expression[], location?: TextRange) {
export function createCall(expression: string | Expression, argumentsArray: Expression[], location?: TextRange) {
const node = <CallExpression>createNode(SyntaxKind.CallExpression, location);
node.expression = parenthesizeForAccess(expression);
node.expression = typeof expression === "string" ? createIdentifier(expression) : parenthesizeForAccess(expression);
node.arguments = parenthesizeListElements(createNodeArray(argumentsArray));
return node;
}
export function createNew(expression: Expression, argumentsArray: Expression[], location?: TextRange) {
const node = <NewExpression>createNode(SyntaxKind.NewExpression, location);
node.expression = parenthesizeForAccess(expression);
node.expression = parenthesizeForNew(expression);
node.arguments = argumentsArray
? parenthesizeListElements(createNodeArray(argumentsArray))
: undefined;
@ -341,7 +372,7 @@ namespace ts {
return node;
}
export function createFunctionExpression(asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
export function createFunctionExpression(asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, original?: Node) {
const node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression, location);
node.modifiers = undefined;
node.asteriskToken = asteriskToken;
@ -350,6 +381,10 @@ namespace ts {
node.parameters = createNodeArray(parameters);
node.type = undefined;
node.body = body;
if (original) {
node.original = original;
}
return node;
}
@ -390,11 +425,15 @@ namespace ts {
return node;
}
export function createBinary(left: Expression, operator: SyntaxKind, right: Expression, location?: TextRange) {
export function createBinary(left: Expression, operator: SyntaxKind, right: Expression, location?: TextRange, original?: Node) {
const node = <BinaryExpression>createNode(SyntaxKind.BinaryExpression, location);
node.left = parenthesizeBinaryOperand(operator, left, /*isLeftSideOfBinary*/ true);
node.operatorToken = createSynthesizedNode(operator);
node.right = parenthesizeBinaryOperand(operator, right, /*isLeftSideOfBinary*/ false);
if (original) {
node.original = original;
}
return node;
}
@ -440,9 +479,13 @@ namespace ts {
// Element
export function createBlock(statements: Statement[], location?: TextRange): Block {
export function createBlock(statements: Statement[], location?: TextRange, multiLine?: boolean): Block {
const block = <Block>createNode(SyntaxKind.Block, location);
block.statements = createNodeArray(statements);
if (multiLine) {
block.multiLine = true;
}
return block;
}
@ -545,6 +588,42 @@ namespace ts {
return node;
}
export function createWith(expression: Expression, statement: Statement, location?: TextRange): ReturnStatement {
const node = <WithStatement>createNode(SyntaxKind.WithStatement, location);
node.expression = expression;
node.statement = statement;
return node;
}
export function createSwitch(expression: Expression, caseBlock: CaseBlock, location?: TextRange): ReturnStatement {
const node = <SwitchStatement>createNode(SyntaxKind.SwitchStatement, location);
node.expression = expression;
node.caseBlock = caseBlock;
return node;
}
export function createThrow(expression: Expression, location?: TextRange): ReturnStatement {
const node = <ThrowStatement>createNode(SyntaxKind.ThrowStatement, location);
node.expression = expression;
return node;
}
export function createTryCatchFinally(tryBlock: Block, catchClause: CatchClause, finallyBlock: Block, location?: TextRange) {
const node = <TryStatement>createNode(SyntaxKind.TryStatement, location);
node.tryBlock = tryBlock;
node.catchClause = catchClause;
node.finallyBlock = finallyBlock;
return node;
}
export function createTryCatch(tryBlock: Block, catchClause: CatchClause, location?: TextRange) {
return createTryCatchFinally(tryBlock, catchClause, /*finallyBlock*/ undefined, location);
}
export function createTryFinally(tryBlock: Block, finallyBlock: Block, location?: TextRange) {
return createTryCatchFinally(tryBlock, /*catchClause*/ undefined, finallyBlock, location);
}
export function createFunctionDeclaration(modifiers: Modifier[], asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
const node = <FunctionDeclaration>createNode(SyntaxKind.FunctionDeclaration, location);
node.decorators = undefined;
@ -569,6 +648,12 @@ namespace ts {
return node;
}
export function createCaseBlock(clauses: CaseOrDefaultClause[], location?: TextRange) {
const node = <CaseBlock>createNode(SyntaxKind.CaseBlock, location);
node.clauses = createNodeArray(clauses);
return node;
}
export function createExportDefault(expression: Expression) {
const node = <ExportAssignment>createNode(SyntaxKind.ExportAssignment);
node.isExportEquals = false;
@ -632,7 +717,7 @@ namespace ts {
return <Expression>createBinary(left, SyntaxKind.LessThanToken, right, location);
}
export function createAssignment(left: Expression, right: Expression, location?: TextRange) {
export function createAssignment(left: Expression, right: Expression, location?: TextRange, original?: Node) {
return createBinary(left, SyntaxKind.EqualsToken, right, location);
}
@ -1040,6 +1125,58 @@ namespace ts {
);
}
export interface CallTarget {
target: LeftHandSideExpression;
thisArg: Expression;
}
export function createCallBinding(expression: Expression): CallTarget {
const callee = skipParentheses(expression);
let thisArg: Expression;
let target: LeftHandSideExpression;
switch (callee.kind) {
case SyntaxKind.PropertyAccessExpression: {
// for `a.b()` target is `(_a = a).b` and thisArg is `_a`
thisArg = createTempVariable();
target = createPropertyAccess(
createAssignment(
thisArg,
(<PropertyAccessExpression>callee).expression,
/*location*/ (<PropertyAccessExpression>callee).expression
),
(<PropertyAccessExpression>callee).name,
/*location*/ callee
);
break;
}
case SyntaxKind.ElementAccessExpression: {
// for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a`
thisArg = createTempVariable();
target = createElementAccess(
createAssignment(
thisArg,
(<ElementAccessExpression>callee).expression,
/*location*/ (<ElementAccessExpression>callee).expression
),
(<ElementAccessExpression>callee).argumentExpression,
/*location*/ callee
);
break;
}
default: {
// for `a()` target is `a` and thisArg is `void 0`
thisArg = createVoidZero();
target = parenthesizeForAccess(expression);
break;
}
}
return { target, thisArg };
}
export function inlineExpressions(expressions: Expression[]) {
return reduceLeft(expressions, createComma);
}
@ -1059,6 +1196,96 @@ namespace ts {
: cloneNode(memberName, location);
}
export function createExpressionForObjectLiteralElement(node: ObjectLiteralExpression, property: ObjectLiteralElement, receiver: Expression): Expression {
switch (property.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return createExpressionForAccessorDeclaration(node.properties, <AccessorDeclaration>property, receiver, node.multiLine);
case SyntaxKind.PropertyAssignment:
return createExpressionForPropertyAssignment(<PropertyAssignment>property, receiver);
case SyntaxKind.ShorthandPropertyAssignment:
return createExpressionForShorthandPropertyAssignment(<ShorthandPropertyAssignment>property, receiver);
case SyntaxKind.MethodDeclaration:
return createExpressionForMethodDeclaration(<MethodDeclaration>property, receiver);
}
}
function createExpressionForAccessorDeclaration(properties: NodeArray<Declaration>, property: AccessorDeclaration, receiver: Expression, multiLine: boolean) {
const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property);
if (property === firstAccessor) {
return aggregateTransformFlags(
createObjectDefineProperty(
receiver,
createExpressionForPropertyName(property.name, /*location*/ property.name),
{
get: getAccessor && createFunctionExpression(
/*asteriskToken*/ undefined,
/*name*/ undefined,
getAccessor.parameters,
getAccessor.body,
/*location*/ getAccessor,
/*original*/ getAccessor
),
set: setAccessor && createFunctionExpression(
/*asteriskToken*/ undefined,
/*name*/ undefined,
setAccessor.parameters,
setAccessor.body,
/*location*/ setAccessor,
/*original*/ setAccessor
),
enumerable: true,
configurable: true
},
multiLine,
/*location*/ firstAccessor
)
);
}
return undefined;
}
function createExpressionForPropertyAssignment(property: PropertyAssignment, receiver: Expression) {
return aggregateTransformFlags(
createAssignment(
createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name),
property.initializer,
/*location*/ property,
/*original*/ property
)
);
}
function createExpressionForShorthandPropertyAssignment(property: ShorthandPropertyAssignment, receiver: Expression) {
return aggregateTransformFlags(
createAssignment(
createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name),
getSynthesizedClone(property.name),
/*location*/ property,
/*original*/ property
)
);
}
function createExpressionForMethodDeclaration(method: MethodDeclaration, receiver: Expression) {
return aggregateTransformFlags(
createAssignment(
createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name),
createFunctionExpression(
method.asteriskToken,
/*name*/ undefined,
method.parameters,
method.body,
/*location*/ method,
/*original*/ method
),
/*location*/ method,
/*original*/ method
)
);
}
// Utilities
/**
@ -1178,6 +1405,17 @@ namespace ts {
|| binaryOperator === SyntaxKind.CaretToken;
}
export function parenthesizeForNew(expression: Expression): LeftHandSideExpression {
const lhs = parenthesizeForAccess(expression);
switch (lhs.kind) {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
return createParen(lhs);
}
return lhs;
}
/**
* Wraps an expression in parentheses if it is needed in order to use the expression for
* property or element access.
@ -1335,8 +1573,4 @@ namespace ts {
nodes.hasTrailingComma = hasTrailingComma;
return nodes;
}
export function getSynthesizedNode<T extends Node>(node: T): T {
return nodeIsSynthesized(node) ? node : cloneNode(node, /*location*/ undefined, node.flags, /*parent*/ undefined, /*original*/ node);
}
}

View File

@ -58,6 +58,165 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};`;
const keysHelper = `
var __keys = (this && this.__keys) || function (o) {
var a = [];
for (var k in o) a.push(k);
return __values(a);
};`;
const valuesHelper = `
var __values = (this && this.__values) || function (o) {
if (typeof o.next === "function") {
return o;
}
if (typeof o.length === "number") {
var i, done;
return {
next: function() {
return done || (done = i >= o.length)
? { value: undefined, done: true }
: { value: o[i++], done: false };
}
};
}
};`;
const generatorHelper = `
var __generator = (this && this.__generator) || function (body) {
var done, finallyStack, executing, state, yieldStar;
function step(opcode, arg) {
if (typeof Debug !== "undefined" && "setNonUserCodeExceptions" in Debug) {
Debug.setNonUserCodeExceptions = true;
}
if (executing) {
throw new TypeError("Generator is already executing.");
}
state = state || { label: 0 };
while (true) {
executing = false;
verb = yielded = undefined;
if (!done) {
var trys = state.trys;
var region = trys && trys[trys.length - 1];
if (region) {
var tryLabel = region[0 /*try*/];
var catchLabel = region[1 /*catch*/];
var finallyLabel = region[2 /*finally*/];
var endLabel = region[3 /*endtry*/];
}
else {
if (opcode === 6 /*catch*/) {
opcode = 1 /*throw*/;
}
if (opcode === 1 /*throw*/ || opcode === 2 /*return*/) {
done = true;
}
}
}
if (done) {
finallyStack = void 0;
switch (opcode) {
case 0 /*next*/: return { value: void 0, done: true };
case 1 /*throw*/: throw arg;
case 2 /*return*/: return { value: arg, done: true };
}
}
try {
if (yieldStar) {
executing = true;
var verb = yieldStar[opcode === 2 ? "return" : opcode === 1 ? "throw" : "next"];
executing = false;
if (verb) {
executing = true;
var yielded = verb.call(yieldStar, arg);
executing = false;
if (!yielded.done) {
return yielded;
}
opcode = 0 /*next*/;
arg = yielded.value;
}
yieldStar = void 0;
continue;
}
switch (opcode) {
case 0 /*next*/:
state.sent = function() { return arg };
break;
case 1 /*throw*/:
state.sent = function() { throw arg };
break;
case 4 /*yield*/:
state.label++;
return { value: arg, done: false };
case 5 /*yield**/:
state.label++;
yieldStar = arg;
opcode = 0 /*next*/;
arg = void 0;
continue;
case 7 /*endfinally*/:
arg = finallyStack.pop();
opcode = finallyStack.pop();
trys.pop();
continue;
default:
if (opcode === 3 /*break*/ && (!region || (arg > tryLabel && arg < endLabel))) {
state.label = arg;
}
else if (opcode === 6 /*catch*/ && state.label < catchLabel) {
state.error = arg;
state.label = catchLabel;
}
else if (state.label < finallyLabel) {
finallyStack = finallyStack || [];
finallyStack.push(opcode, arg);
state.label = finallyLabel;
}
else {
if (finallyLabel) {
finallyStack.pop();
finallyStack.pop();
}
trys.pop();
continue;
}
break;
}
executing = true;
var operation = body(state);
opcode = operation[0];
arg = operation[1];
}
catch (e) {
opcode = 6 /*catch*/;
arg = e;
yieldStar = void 0;
}
}
}
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); },
};
};`;
// emit output for the __export helper function
const exportStarHelper = `
function __export(m) {
@ -154,11 +313,12 @@ const _super = (function (geti, seti) {
let identifierSubstitution: (node: Identifier) => Identifier;
let onBeforeEmitNode: (node: Node) => void;
let onAfterEmitNode: (node: Node) => void;
let isUniqueName: (name: string) => boolean;
let temporaryVariables: string[] = [];
let tempFlags: TempFlags;
let generatedNameSet: Map<string>;
let currentSourceFile: SourceFile;
let currentText: string;
let currentFileIdentifiers: Map<string>;
let extendsEmitted: boolean;
let decorateEmitted: boolean;
let paramEmitted: boolean;
@ -169,6 +329,8 @@ const _super = (function (geti, seti) {
function doPrint(jsFilePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit);
generatedNameSet = {};
isOwnFileEmit = !isBundledEmit;
// Emit helpers from all the files
@ -213,7 +375,6 @@ const _super = (function (geti, seti) {
identifierSubstitution = undefined;
onBeforeEmitNode = undefined;
onAfterEmitNode = undefined;
isUniqueName = undefined;
temporaryVariables = undefined;
tempFlags = TempFlags.Auto;
currentSourceFile = undefined;
@ -236,13 +397,13 @@ const _super = (function (geti, seti) {
identifierSubstitution = context.identifierSubstitution;
onBeforeEmitNode = context.onBeforeEmitNode;
onAfterEmitNode = context.onAfterEmitNode;
isUniqueName = context.isUniqueName;
return printSourceFile;
}
function printSourceFile(node: SourceFile) {
currentSourceFile = node;
currentText = node.text;
currentFileIdentifiers = node.identifiers;
sourceMap.setSourceFile(node);
comments.setSourceFile(node);
emitWorker(node);
@ -659,13 +820,16 @@ const _super = (function (geti, seti) {
//
function emitIdentifier(node: Identifier) {
if (node.text === undefined) {
// Emit a temporary variable name for this node.
const nodeId = getOriginalNodeId(node);
const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeTempVariableName(tempKindToFlags(node.tempKind)));
write(text);
switch (node.tempKind) {
case GeneratedIdentifierKind.Auto:
return emitAutoIdentifier(node);
case GeneratedIdentifierKind.Loop:
return emitLoopIdentifier(node);
case GeneratedIdentifierKind.Unique:
return emitUniqueIdentifier(node);
}
else if (nodeIsSynthesized(node) || !node.parent) {
if (nodeIsSynthesized(node) || !node.parent) {
if (getNodeEmitFlags(node) & NodeEmitFlags.UMDDefine) {
writeLines(umdHelper);
}
@ -678,6 +842,24 @@ const _super = (function (geti, seti) {
}
}
function emitAutoIdentifier(node: Identifier) {
const nodeId = getOriginalNodeId(node);
const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeTempVariableName(TempFlags.Auto));
write(text);
}
function emitLoopIdentifier(node: Identifier) {
const nodeId = getOriginalNodeId(node);
const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeTempVariableName(TempFlags._i));
write(text);
}
function emitUniqueIdentifier(node: Identifier) {
const nodeId = getOriginalNodeId(node);
const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeUniqueName(node.text));
write(text);
}
//
// Names
//
@ -2368,12 +2550,18 @@ const _super = (function (geti, seti) {
&& rangeEndIsOnSameLineAsRangeStart(block, block);
}
function tempKindToFlags(kind: TempVariableKind) {
return kind === TempVariableKind.Loop
function tempKindToFlags(kind: GeneratedIdentifierKind) {
return kind === GeneratedIdentifierKind.Loop
? TempFlags._i
: TempFlags.Auto;
}
function isUniqueName(name: string): boolean {
return !resolver.hasGlobalName(name) &&
!hasProperty(currentFileIdentifiers, name) &&
!hasProperty(generatedNameSet, name);
}
/**
* Return the next available name in the pattern _a ... _z, _0, _1, ...
* TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name.
@ -2401,6 +2589,29 @@ const _super = (function (geti, seti) {
}
}
}
/**
* Generate a name that is unique within the current file and doesn't conflict with any names
* in global scope. The name is formed by adding an '_n' suffix to the specified base name,
* where n is a positive integer. Note that names generated by makeTempVariableName and
* makeUniqueName are guaranteed to never conflict.
*/
function makeUniqueName(baseName: string): string {
// Find the first unique 'name_n', where n is a positive number
if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
baseName += "_";
}
let i = 1;
while (true) {
const generatedName = baseName + i;
if (isUniqueName(generatedName)) {
return generatedNameSet[generatedName] = generatedName;
}
i++;
}
}
}
}

View File

@ -3,6 +3,7 @@
/// <reference path="transformers/jsx.ts" />
/// <reference path="transformers/es7.ts" />
/// <reference path="transformers/es6.ts" />
/// <reference path="transformers/generators.ts" />
/// <reference path="transformers/module/module.ts" />
/// <reference path="transformers/module/system.ts" />
/// <reference path="transformers/module/es6.ts" />
@ -40,6 +41,7 @@ namespace ts {
if (languageVersion < ScriptTarget.ES6) {
transformers.push(transformES6);
transformers.push(transformGenerators);
}
return transformers;
@ -55,7 +57,6 @@ namespace ts {
*/
export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]) {
const nodeToGeneratedName: Identifier[] = [];
const generatedNameSet: Map<string> = {};
const nodeEmitFlags: NodeEmitFlags[] = [];
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
@ -72,10 +73,8 @@ namespace ts {
getEmitResolver: () => resolver,
getNodeEmitFlags,
setNodeEmitFlags,
isUniqueName,
getGeneratedNameForNode,
nodeHasGeneratedName,
makeUniqueName,
hoistVariableDeclaration,
hoistFunctionDeclaration,
startLexicalEnvironment,
@ -151,28 +150,28 @@ namespace ts {
return node;
}
/**
* Generate a name that is unique within the current file and doesn't conflict with any names
* in global scope. The name is formed by adding an '_n' suffix to the specified base name,
* where n is a positive integer. Note that names generated by makeTempVariableName and
* makeUniqueName are guaranteed to never conflict.
*/
function makeUniqueName(baseName: string): Identifier {
// Find the first unique 'name_n', where n is a positive number
if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
baseName += "_";
}
// /**
// * Generate a name that is unique within the current file and doesn't conflict with any names
// * in global scope. The name is formed by adding an '_n' suffix to the specified base name,
// * where n is a positive integer. Note that names generated by makeTempVariableName and
// * makeUniqueName are guaranteed to never conflict.
// */
// function makeUniqueName(baseName: string): Identifier {
// // Find the first unique 'name_n', where n is a positive number
// if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
// baseName += "_";
// }
let i = 1;
while (true) {
const generatedName = baseName + i;
if (isUniqueName(generatedName)) {
return createIdentifier(generatedNameSet[generatedName] = generatedName);
}
// let i = 1;
// while (true) {
// const generatedName = baseName + i;
// if (isUniqueName(generatedName)) {
// return createIdentifier(generatedNameSet[generatedName] = generatedName);
// }
i++;
}
}
// i++;
// }
// }
/**
* Gets the generated name for a node.
@ -190,14 +189,14 @@ namespace ts {
return nodeToGeneratedName[id] !== undefined;
}
/**
* Tests whether the provided name is unique.
*/
function isUniqueName(name: string): boolean {
return !resolver.hasGlobalName(name)
&& !hasProperty(currentSourceFile.identifiers, name)
&& !hasProperty(generatedNameSet, name);
}
// /**
// * Tests whether the provided name is unique.
// */
// function isUniqueName(name: string): boolean {
// return !resolver.hasGlobalName(name)
// && !hasProperty(currentSourceFile.identifiers, name)
// && !hasProperty(generatedNameSet, name);
// }
/**
* Tests whether the provided name is unique within a container.
@ -221,7 +220,7 @@ namespace ts {
function generateNameForNode(node: Node): Identifier {
switch (node.kind) {
case SyntaxKind.Identifier:
return makeUniqueName((<Identifier>node).text);
return createUniqueName((<Identifier>node).text);
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
return generateNameForModuleOrEnum(<ModuleDeclaration | EnumDeclaration>node);
@ -244,7 +243,7 @@ namespace ts {
function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) {
const name = node.name;
// Use module/enum name itself if it is unique, otherwise make a unique variation
return isUniqueLocalName(name.text, node) ? name : makeUniqueName(name.text);
return isUniqueLocalName(name.text, node) ? name : createUniqueName(name.text);
}
function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) {
@ -252,15 +251,15 @@ namespace ts {
const baseName = expr.kind === SyntaxKind.StringLiteral
? escapeIdentifier(makeIdentifierFromModuleName((<LiteralExpression>expr).text))
: "module";
return makeUniqueName(baseName);
return createUniqueName(baseName);
}
function generateNameForExportDefault() {
return makeUniqueName("default");
return createUniqueName("default");
}
function generateNameForClassExpression() {
return makeUniqueName("class");
return createUniqueName("class");
}
/**

View File

@ -6,7 +6,6 @@ namespace ts {
export function transformES6(context: TransformationContext) {
const {
getGeneratedNameForNode,
makeUniqueName,
startLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration,
@ -399,14 +398,14 @@ namespace ts {
addNode(statements,
createIf(
createStrictEquality(
getSynthesizedNode(name),
getSynthesizedClone(name),
createVoidZero()
),
setNodeEmitFlags(
createBlock([
createStatement(
createAssignment(
getSynthesizedNode(name),
getSynthesizedClone(name),
visitNode(initializer, visitor, isExpression)
)
)
@ -431,7 +430,7 @@ namespace ts {
return;
}
const name = getSynthesizedNode(<Identifier>parameter.name);
const name = getSynthesizedClone(<Identifier>parameter.name);
const restIndex = node.parameters.length - 1;
const temp = createLoopVariable();
@ -611,7 +610,7 @@ namespace ts {
return setOriginalNode(
createFunctionDeclaration(
/*modifiers*/ undefined,
node.asteriskToken, // TODO(rbuckton): downlevel support for generators
node.asteriskToken,
node.name,
visitNodes(node.parameters, visitor, isParameter),
transformFunctionBody(node),
@ -779,6 +778,119 @@ namespace ts {
return visitEachChild(node, visitor, context);
}
// // TODO(rbuckton): Switch to using __values helper for for..of?
// function visitForOfStatement2(node: ForOfStatement): OneOrMany<Statement> {
// // [source]
// // for (let v of expr) {
// // }
// //
// // [output]
// // var __values = ...;
// // try {
// // for (_a = __values(expr), _b = _a.next(); !_b.done || (_a = void 0); _b = _a.next()) {
// // var v = _b.value;
// // }
// // }
// // finally {
// // if (_a && typeof _a.return === "function") _a.return();
// // }
// // var _a, b;
// const iterator = createTempVariable();
// const iteratorResult = createTempVariable();
// hoistVariableDeclaration(iterator);
// hoistVariableDeclaration(iteratorResult);
// const expression = visitNode(node.expression, visitor, isExpression);
// const initializer = node.initializer;
// const statements: Statement[] = [];
// if (isVariableDeclarationList(initializer)) {
// const variable = getMutableClone(initializer.declarations[0]);
// variable.initializer = createPropertyAccess(iteratorResult, "value");
// statements.push(
// createVariableStatement(
// /*modifiers*/ undefined,
// createVariableDeclarationList(
// isBindingPattern(variable.name)
// ? flattenVariableDestructuring(variable, /*value*/ undefined, visitor)
// : [variable]
// )
// )
// );
// }
// else {
// statements.push(
// createStatement(
// createAssignment(
// <Expression>node.initializer,
// createPropertyAccess(iteratorResult, "value")
// )
// )
// );
// }
// if (isBlock(node.statement)) {
// addNodes(statements, visitNodes((<Block>node.statement).statements, visitor, isStatement));
// }
// else {
// addNodes(statements, visitNodes(createNodeArray([node.statement]), visitor, isStatement));
// }
// return createTryFinally(
// createBlock([
// createFor(
// createComma(
// createAssignment(
// iterator,
// createCall(
// createIdentifier("__values"),
// [expression]
// )
// ),
// createAssignment(
// iteratorResult,
// createCall(
// createPropertyAccess(iterator, "next"),
// []
// )
// )
// ),
// createLogicalOr(
// createLogicalNot(createPropertyAccess(iteratorResult, "done")),
// createAssignment(iterator, createVoidZero())
// ),
// createAssignment(
// iteratorResult,
// createCall(
// createPropertyAccess(iterator, "next"),
// []
// )
// ),
// createBlock(statements)
// )
// ]),
// createBlock([
// createIf(
// createLogicalAnd(
// iterator,
// createStrictEquality(
// createTypeOf(
// createPropertyAccess(iterator, "return")
// ),
// createLiteral("function")
// )
// ),
// createStatement(
// createCall(
// createPropertyAccess(iterator, "return"),
// [],
// /*location*/ node.expression
// )
// )
// )
// ])
// );
// }
function visitForOfStatement(node: ForOfStatement): Statement {
// TODO: Convert loop body for block scoped bindings.
@ -814,7 +926,7 @@ namespace ts {
// we don't want to emit a temporary variable for the RHS, just use it directly.
const counter = createLoopVariable();
const rhsReference = expression.kind === SyntaxKind.Identifier
? makeUniqueName((<Identifier>expression).text)
? createUniqueName((<Identifier>expression).text)
: createTempVariable();
// Initialize LHS
@ -906,22 +1018,24 @@ namespace ts {
);
}
function visitObjectLiteralExpression(node: ObjectLiteralExpression): LeftHandSideExpression {
function visitObjectLiteralExpression(node: ObjectLiteralExpression): Expression {
// We are here because a ComputedPropertyName was used somewhere in the expression.
const properties = node.properties;
const numProperties = properties.length;
// Find the first computed property.
// Everything until that point can be emitted as part of the initial object literal.
let numInitialNonComputedProperties = numProperties;
for (let i = 0, n = properties.length; i < n; i++) {
if (properties[i].name.kind === SyntaxKind.ComputedPropertyName) {
numInitialNonComputedProperties = i;
let numInitialProperties = numProperties;
for (let i = 0; i < numProperties; i++) {
const property = properties[i];
if (property.transformFlags & TransformFlags.ContainsYield
|| property.name.kind === SyntaxKind.ComputedPropertyName) {
numInitialProperties = i;
break;
}
}
Debug.assert(numInitialNonComputedProperties !== numProperties);
Debug.assert(numInitialProperties !== numProperties);
// For computed properties, we need to create a unique handle to the object
// literal so we can modify it without risking internal assignments tainting the object.
@ -933,27 +1047,27 @@ namespace ts {
addNode(expressions,
createAssignment(
temp,
setMultiLine(
createObjectLiteral(
visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialNonComputedProperties)
),
createObjectLiteral(
visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialProperties),
/*location*/ undefined,
node.multiLine
)
),
node.multiLine
);
addObjectLiteralMembers(expressions, node, temp, numInitialNonComputedProperties);
addObjectLiteralMembers(expressions, node, temp, numInitialProperties);
// We need to clone the temporary identifier so that we can write it on a
// new line
addNode(expressions, cloneNode(temp), node.multiLine);
return createParen(inlineExpressions(expressions));
return inlineExpressions(expressions);
}
function addObjectLiteralMembers(expressions: Expression[], node: ObjectLiteralExpression, receiver: Identifier, numInitialNonComputedProperties: number) {
function addObjectLiteralMembers(expressions: Expression[], node: ObjectLiteralExpression, receiver: Identifier, start: number) {
const properties = node.properties;
for (let i = numInitialNonComputedProperties, len = properties.length; i < len; i++) {
const numProperties = properties.length;
for (let i = start; i < numProperties; i++) {
const property = properties[i];
switch (property.kind) {
case SyntaxKind.GetAccessor:
@ -1001,7 +1115,7 @@ namespace ts {
receiver,
visitNode(property.name, visitor, isPropertyName)
),
getSynthesizedNode(property.name),
getSynthesizedClone(property.name),
/*location*/ property
);
}
@ -1032,7 +1146,7 @@ namespace ts {
function visitShorthandPropertyAssignment(node: ShorthandPropertyAssignment): ObjectLiteralElement {
return createPropertyAssignment(
node.name,
getSynthesizedNode(node.name),
getSynthesizedClone(node.name),
/*location*/ node
);
}
@ -1188,7 +1302,7 @@ namespace ts {
addNode(segments,
setMultiLine(
createArrayLiteral(
visitNodes(elements, visitor, isExpression, start, i)
visitNodes(elements, visitor, isExpression, start, i - start)
),
multiLine
)
@ -1204,7 +1318,7 @@ namespace ts {
addNode(segments,
setMultiLine(
createArrayLiteral(
visitNodes(elements, visitor, isExpression, start, length)
visitNodes(elements, visitor, isExpression, start, length - start)
),
multiLine
)
@ -1469,7 +1583,7 @@ namespace ts {
}
function getDeclarationName(node: ClassExpression | ClassDeclaration | FunctionDeclaration) {
return node.name ? getSynthesizedNode(node.name) : getGeneratedNameForNode(node);
return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node);
}
function getClassMemberPrefix(node: ClassExpression | ClassDeclaration, member: ClassElement) {

File diff suppressed because it is too large Load Diff

View File

@ -229,7 +229,7 @@ namespace ts {
// import * as n from "mod";
addNode(variables,
createVariableDeclaration(
getSynthesizedNode(namespaceDeclaration.name),
getSynthesizedClone(namespaceDeclaration.name),
createRequireCall(node)
)
);
@ -249,7 +249,7 @@ namespace ts {
if (namespaceDeclaration && isDefaultImport(node)) {
addNode(variables,
createVariableDeclaration(
getSynthesizedNode(namespaceDeclaration.name),
getSynthesizedClone(namespaceDeclaration.name),
getGeneratedNameForNode(node)
)
);
@ -272,7 +272,7 @@ namespace ts {
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
getSynthesizedNode(namespaceDeclaration.name),
getSynthesizedClone(namespaceDeclaration.name),
getGeneratedNameForNode(node),
/*location*/ node
)
@ -309,7 +309,7 @@ namespace ts {
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
getSynthesizedNode(node.name),
getSynthesizedClone(node.name),
createRequireCall(node),
/*location*/ node
)
@ -519,7 +519,7 @@ namespace ts {
);
if (node.flags & NodeFlags.Default) {
addExportDefault(statements, getSynthesizedNode(node.name), /*location*/ node);
addExportDefault(statements, getSynthesizedClone(node.name), /*location*/ node);
}
}
else {
@ -559,7 +559,7 @@ namespace ts {
);
if (node.flags & NodeFlags.Default) {
addExportDefault(statements, getSynthesizedNode(node.name), /*location*/ node);
addExportDefault(statements, getSynthesizedClone(node.name), /*location*/ node);
}
}
else {
@ -598,7 +598,7 @@ namespace ts {
if (container && container.kind === SyntaxKind.SourceFile) {
return createPropertyAccess(
createIdentifier("exports"),
getSynthesizedNode(node),
getSynthesizedClone(node),
/*location*/ node
);
}
@ -638,7 +638,7 @@ namespace ts {
const moduleName = getExternalModuleName(importNode);
if (moduleName.kind === SyntaxKind.StringLiteral) {
return tryRenameExternalModule(<StringLiteral>moduleName)
|| getSynthesizedNode(<StringLiteral>moduleName);
|| getSynthesizedClone(<StringLiteral>moduleName);
}
return undefined;
@ -685,7 +685,7 @@ namespace ts {
)
: createPropertyAccess(
createIdentifier("exports"),
getSynthesizedNode(name)
getSynthesizedClone(name)
),
value
);

View File

@ -11,7 +11,6 @@ namespace ts {
const {
getGeneratedNameForNode,
makeUniqueName,
startLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration,
@ -83,8 +82,8 @@ namespace ts {
// Make sure that the name of the 'exports' function does not conflict with
// existing identifiers.
exportFunctionForFile = makeUniqueName("exports");
contextObjectForFile = makeUniqueName("context");
exportFunctionForFile = createUniqueName("exports");
contextObjectForFile = createUniqueName("context");
const dependencyGroups = collectDependencyGroups(externalImports);
@ -299,7 +298,7 @@ namespace ts {
}
}
const exportedNamesStorageRef = makeUniqueName("exportedNames");
const exportedNamesStorageRef = createUniqueName("exportedNames");
addNode(statements,
createVariableStatement(
/*modifiers*/ undefined,
@ -323,7 +322,7 @@ namespace ts {
const setters: Expression[] = [];
for (const group of dependencyGroups) {
// derive a unique name for parameter from the first named entry in the group
const parameterName = makeUniqueName(forEach(group.externalImports, getLocalNameTextForExternalImport) || "");
const parameterName = createUniqueName(forEach(group.externalImports, getLocalNameTextForExternalImport) || "");
const statements: Statement[] = [];
for (const entry of group.externalImports) {
const importVariableName = getLocalNameForExternalImport(entry);
@ -705,7 +704,7 @@ namespace ts {
function visitForInStatement(node: ForInStatement): ForInStatement {
const initializer = node.initializer;
if (isVariableDeclarationList(initializer)) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.initializer = transformForBinding(initializer);
updated.statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
return updated;
@ -723,7 +722,7 @@ namespace ts {
function visitForOfStatement(node: ForOfStatement): ForOfStatement {
const initializer = node.initializer;
if (isVariableDeclarationList(initializer)) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.initializer = transformForBinding(initializer);
updated.statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
return updated;
@ -741,7 +740,7 @@ namespace ts {
function visitDoStatement(node: DoStatement) {
const statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
if (statement !== node.statement) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.statement = statement;
return updated;
}
@ -756,7 +755,7 @@ namespace ts {
function visitWhileStatement(node: WhileStatement) {
const statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
if (statement !== node.statement) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.statement = statement;
return updated;
}
@ -771,7 +770,7 @@ namespace ts {
function visitLabeledStatement(node: LabeledStatement) {
const statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
if (statement !== node.statement) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.statement = statement;
return updated;
}
@ -786,7 +785,7 @@ namespace ts {
function visitWithStatement(node: WithStatement) {
const statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
if (statement !== node.statement) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.statement = statement;
return updated;
}
@ -801,7 +800,7 @@ namespace ts {
function visitSwitchStatement(node: SwitchStatement) {
const caseBlock = visitNode(node.caseBlock, visitNestedNode, isCaseBlock);
if (caseBlock !== node.caseBlock) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.caseBlock = caseBlock;
return updated;
}
@ -816,7 +815,7 @@ namespace ts {
function visitCaseBlock(node: CaseBlock) {
const clauses = visitNodes(node.clauses, visitNestedNode, isCaseOrDefaultClause);
if (clauses !== node.clauses) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.clauses = clauses;
return updated;
}
@ -831,7 +830,7 @@ namespace ts {
function visitCaseClause(node: CaseClause) {
const statements = visitNodes(node.statements, visitNestedNode, isStatement);
if (statements !== node.statements) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.statements = statements;
return updated;
}
@ -864,7 +863,7 @@ namespace ts {
function visitCatchClause(node: CatchClause) {
const block = visitNode(node.block, visitNestedNode, isBlock);
if (block !== node.block) {
const updated = getMutableNode(node);
const updated = getMutableClone(node);
updated.block = block;
return updated;
}
@ -1055,7 +1054,7 @@ namespace ts {
const moduleName = getExternalModuleName(importNode);
if (moduleName.kind === SyntaxKind.StringLiteral) {
return tryRenameExternalModule(<StringLiteral>moduleName)
|| getSynthesizedNode(<StringLiteral>moduleName);
|| getSynthesizedClone(<StringLiteral>moduleName);
}
return undefined;
@ -1096,11 +1095,11 @@ namespace ts {
* @param node The declaration statement.
*/
function getDeclarationName(node: DeclarationStatement) {
return node.name ? getSynthesizedNode(node.name) : getGeneratedNameForNode(node);
return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node);
}
function addExportStarFunction(statements: Statement[], localNames: Identifier) {
const exportStarFunction = makeUniqueName("exportStar");
const exportStarFunction = createUniqueName("exportStar");
const m = createIdentifier("m");
const n = createIdentifier("n");
const exports = createIdentifier("exports");
@ -1204,7 +1203,7 @@ namespace ts {
return createElementAccess(importAlias, createLiteral(name.text));
}
else {
return createPropertyAccess(importAlias, getSynthesizedNode(name));
return createPropertyAccess(importAlias, getSynthesizedClone(name));
}
}
@ -1256,7 +1255,7 @@ namespace ts {
function hoistBindingElement(node: VariableDeclaration | BindingElement, isExported: boolean) {
const name = node.name;
if (isIdentifier(name)) {
hoistVariableDeclaration(getSynthesizedNode(name));
hoistVariableDeclaration(getSynthesizedClone(name));
if (isExported) {
recordExportName(name);
}

View File

@ -9,7 +9,6 @@ namespace ts {
export function transformTypeScript(context: TransformationContext) {
const {
getGeneratedNameForNode,
makeUniqueName,
setNodeEmitFlags,
startLexicalEnvironment,
endLexicalEnvironment,
@ -502,7 +501,7 @@ namespace ts {
// Record an alias to avoid class double-binding.
if (resolver.getNodeCheckFlags(getOriginalNode(node)) & NodeCheckFlags.ClassWithBodyScopedClassBinding) {
enableExpressionSubstitutionForDecoratedClasses();
decoratedClassAlias = makeUniqueName(node.name ? node.name.text : "default");
decoratedClassAlias = createUniqueName(node.name ? node.name.text : "default");
decoratedClassAliases[getOriginalNodeId(node)] = decoratedClassAlias;
// We emit the class alias as a `let` declaration here so that it has the same
@ -697,7 +696,7 @@ namespace ts {
function transformConstructorParameters(constructor: ConstructorDeclaration, hasExtendsClause: boolean) {
return constructor
? visitNodes(constructor.parameters, visitor, isParameter)
: hasExtendsClause ? [createRestParameter(makeUniqueName("args"))] : [];
: hasExtendsClause ? [createRestParameter(createUniqueName("args"))] : [];
}
/**
@ -1667,7 +1666,7 @@ namespace ts {
return createLiteral(name.text);
}
else {
return getSynthesizedNode(name);
return getSynthesizedClone(name);
}
}
@ -1836,7 +1835,7 @@ namespace ts {
if (isNamespaceExport(node)) {
return createNodeArrayNode([
func,
createNamespaceExport(getSynthesizedNode(node.name), getSynthesizedNode(node.name))
createNamespaceExport(getSynthesizedClone(node.name), getSynthesizedClone(node.name))
]);
}
@ -2136,7 +2135,7 @@ namespace ts {
const name = isNamespaceExport(node)
? getNamespaceMemberName(node.name)
: getSynthesizedNode(node.name);
: getSynthesizedClone(node.name);
currentNamespaceLocalName = getGeneratedNameForNode(node);
addNode(statements,
@ -2352,7 +2351,7 @@ namespace ts {
const name = isNamespaceExport(node)
? getNamespaceMemberName(node.name)
: getSynthesizedNode(node.name);
: getSynthesizedClone(node.name);
let moduleParam: Expression = createLogicalOr(
name,
@ -2463,7 +2462,7 @@ namespace ts {
// exports.${name} = ${moduleReference};
return setOriginalNode(
createNamespaceExport(
getSynthesizedNode(node.name),
getSynthesizedClone(node.name),
moduleReference,
node
),
@ -2551,11 +2550,11 @@ namespace ts {
}
function getNamespaceMemberName(name: Identifier): Expression {
return createPropertyAccess(currentNamespaceLocalName, getSynthesizedNode(name));
return createPropertyAccess(currentNamespaceLocalName, getSynthesizedClone(name));
}
function getDeclarationName(node: ClassExpression | ClassDeclaration | FunctionDeclaration | EnumDeclaration) {
return node.name ? getSynthesizedNode(node.name) : getGeneratedNameForNode(node);
return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node);
}
function getClassPrototype(node: ClassExpression | ClassDeclaration) {

View File

@ -497,16 +497,18 @@ namespace ts {
// @kind(SyntaxKind.StaticKeyword)
export interface Modifier extends Node { }
export const enum TempVariableKind {
export const enum GeneratedIdentifierKind {
None, // Not automatically generated
Auto, // Automatically generated identifier
Loop, // Automatically generated identifier with a preference for '_i'
Unique, // Automatically generated identifier based on specified text
}
// @kind(SyntaxKind.Identifier)
export interface Identifier extends PrimaryExpression {
text: string; // Text of identifier (with escapes converted to characters)
tempKind?: TempVariableKind; // Specifies whether to auto-generate the text for an identifier.
originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later
tempKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier.
}
// @kind(SyntaxKind.QualifiedName)
@ -944,13 +946,18 @@ namespace ts {
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
// or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
// @kind(SyntaxKind.NumericLiteral)
// @kind(SyntaxKind.RegularExpressionLiteral)
// @kind(SyntaxKind.NoSubstitutionTemplateLiteral)
export interface LiteralExpression extends LiteralLikeNode, PrimaryExpression {
_literalExpressionBrand: any;
}
// @kind(SyntaxKind.NumericLiteral)
export interface NumericLiteral extends LiteralExpression {
_numericLiteralBrand: any;
trailingComment?: string;
}
// @kind(SyntaxKind.TemplateHead)
// @kind(SyntaxKind.TemplateMiddle)
// @kind(SyntaxKind.TemplateTail)
@ -2759,18 +2766,20 @@ namespace ts {
ContainsES7 = 1 << 5,
ES6 = 1 << 6,
ContainsES6 = 1 << 7,
ContainsGenerators = 1 << 8,
// Markers
// - Flags used to indicate that a subtree contains a specific transformation.
ContainsDecorators = 1 << 8,
ContainsPropertyInitializer = 1 << 9,
ContainsLexicalThis = 1 << 10,
ContainsCapturedLexicalThis = 1 << 11,
ContainsDefaultValueAssignments = 1 << 12,
ContainsParameterPropertyAssignments = 1 << 13,
ContainsSpreadElementExpression = 1 << 14,
ContainsComputedPropertyName = 1 << 15,
ContainsBlockScopedBinding = 1 << 16,
ContainsDecorators = 1 << 9,
ContainsPropertyInitializer = 1 << 10,
ContainsLexicalThis = 1 << 11,
ContainsCapturedLexicalThis = 1 << 12,
ContainsDefaultValueAssignments = 1 << 13,
ContainsParameterPropertyAssignments = 1 << 14,
ContainsSpreadElementExpression = 1 << 15,
ContainsComputedPropertyName = 1 << 16,
ContainsBlockScopedBinding = 1 << 17,
ContainsYield = 1 << 18,
// Assertions
// - Bitmasks that are used to assert facts about the syntax of a node and its subtree.
@ -2783,10 +2792,10 @@ namespace ts {
// - Bitmasks that exclude flags from propagating out of a specific context
// into the subtree flags of their container.
NodeExcludes = TypeScript | Jsx | ES7 | ES6,
ArrowFunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
FunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
ConstructorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
MethodOrAccessorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
ArrowFunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield,
FunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield,
ConstructorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield,
MethodOrAccessorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield,
ClassExcludes = ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments,
ModuleExcludes = ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
TypeExcludes = ~ContainsTypeScript,
@ -2825,10 +2834,8 @@ namespace ts {
setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags): T;
hoistFunctionDeclaration(node: FunctionDeclaration): void;
hoistVariableDeclaration(node: Identifier): void;
isUniqueName(name: string): boolean;
getGeneratedNameForNode(node: Node): Identifier;
nodeHasGeneratedName(node: Node): boolean;
makeUniqueName(baseName: string): Identifier;
/**
* Hook used by transformers to substitute non-expression identifiers

View File

@ -2563,6 +2563,12 @@ namespace ts {
return 0;
}
export function isLogicalOperator(token: SyntaxKind): boolean {
return token === SyntaxKind.BarBarToken
|| token === SyntaxKind.AmpersandAmpersandToken
|| token === SyntaxKind.ExclamationToken;
}
export function isAssignmentOperator(token: SyntaxKind): boolean {
return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
}
@ -3003,6 +3009,10 @@ namespace ts {
return node.kind === SyntaxKind.Identifier;
}
export function isGeneratedIdentifier(node: Node): node is Identifier {
return isIdentifier(node) && node.tempKind > GeneratedIdentifierKind.None;
}
// Keywords
export function isModifier(node: Node): node is Modifier {

View File

@ -134,7 +134,7 @@ namespace ts {
{ name: "arguments", test: isExpression },
],
[SyntaxKind.NewExpression]: [
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForNew },
{ name: "typeArguments", test: isTypeNode },
{ name: "arguments", test: isExpression },
],
@ -630,7 +630,7 @@ namespace ts {
if (updated !== undefined || visited !== value) {
if (updated === undefined) {
updated = getMutableNode(node);
updated = getMutableClone(node);
updated.flags &= ~NodeFlags.Modifier;
}
@ -897,8 +897,9 @@ namespace ts {
/**
* Aggregates the TransformFlags for a Node and its subtree.
*/
export function aggregateTransformFlags(node: Node): void {
export function aggregateTransformFlags<T extends Node>(node: T): T {
aggregateTransformFlagsForNode(node);
return node;
}
/**