Merge branch 'master' into improve-spread-helper-emit

This commit is contained in:
Nathan Shively-Sanders
2016-11-16 10:53:05 -08:00
55 changed files with 4910 additions and 4251 deletions
+99 -51
View File
@@ -234,8 +234,8 @@ namespace ts {
if (node.name.kind === SyntaxKind.ComputedPropertyName) {
const nameExpression = (<ComputedPropertyName>node.name).expression;
// treat computed property names where expression is string/numeric literal as just string/numeric literal
if (isStringOrNumericLiteral(nameExpression.kind)) {
return (<LiteralExpression>nameExpression).text;
if (isStringOrNumericLiteral(nameExpression)) {
return nameExpression.text;
}
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
@@ -570,6 +570,31 @@ namespace ts {
}
}
function bindEach(nodes: NodeArray<Node>) {
if (nodes === undefined) {
return;
}
if (skipTransformFlagAggregation) {
forEach(nodes, bind);
}
else {
const savedSubtreeTransformFlags = subtreeTransformFlags;
subtreeTransformFlags = TransformFlags.None;
let nodeArrayFlags = TransformFlags.None;
for (const node of nodes) {
bind(node);
nodeArrayFlags |= node.transformFlags & ~TransformFlags.HasComputedFlags;
}
nodes.transformFlags = nodeArrayFlags | TransformFlags.HasComputedFlags;
subtreeTransformFlags |= savedSubtreeTransformFlags;
}
}
function bindEachChild(node: Node) {
forEachChild(node, bind, bindEach);
}
function bindChildrenWorker(node: Node): void {
// Binding of JsDocComment should be done before the current block scope container changes.
// because the scope of JsDocComment should not be affected by whether the current node is a
@@ -578,7 +603,7 @@ namespace ts {
forEach(node.jsDocComments, bind);
}
if (checkUnreachable(node)) {
forEachChild(node, bind);
bindEachChild(node);
return;
}
switch (node.kind) {
@@ -643,7 +668,7 @@ namespace ts {
bindCallExpressionFlow(<CallExpression>node);
break;
default:
forEachChild(node, bind);
bindEachChild(node);
break;
}
}
@@ -976,7 +1001,7 @@ namespace ts {
return undefined;
}
function bindbreakOrContinueFlow(node: BreakOrContinueStatement, breakTarget: FlowLabel, continueTarget: FlowLabel) {
function bindBreakOrContinueFlow(node: BreakOrContinueStatement, breakTarget: FlowLabel, continueTarget: FlowLabel) {
const flowLabel = node.kind === SyntaxKind.BreakStatement ? breakTarget : continueTarget;
if (flowLabel) {
addAntecedent(flowLabel, currentFlow);
@@ -990,11 +1015,11 @@ namespace ts {
const activeLabel = findActiveLabel(node.label.text);
if (activeLabel) {
activeLabel.referenced = true;
bindbreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget);
bindBreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget);
}
}
else {
bindbreakOrContinueFlow(node, currentBreakTarget, currentContinueTarget);
bindBreakOrContinueFlow(node, currentBreakTarget, currentContinueTarget);
}
}
@@ -1062,6 +1087,8 @@ namespace ts {
}
function bindCaseBlock(node: CaseBlock): void {
const savedSubtreeTransformFlags = subtreeTransformFlags;
subtreeTransformFlags = 0;
const clauses = node.clauses;
let fallthroughFlow = unreachableFlow;
for (let i = 0; i < clauses.length; i++) {
@@ -1081,6 +1108,8 @@ namespace ts {
errorOnFirstToken(clause, Diagnostics.Fallthrough_case_in_switch);
}
}
clauses.transformFlags = subtreeTransformFlags | TransformFlags.HasComputedFlags;
subtreeTransformFlags |= savedSubtreeTransformFlags;
}
function bindCaseClause(node: CaseClause): void {
@@ -1088,7 +1117,7 @@ namespace ts {
currentFlow = preSwitchCaseFlow;
bind(node.expression);
currentFlow = saveCurrentFlow;
forEach(node.statements, bind);
bindEach(node.statements);
}
function pushActiveLabel(name: string, breakTarget: FlowLabel, continueTarget: FlowLabel): ActiveLabel {
@@ -1180,12 +1209,12 @@ namespace ts {
const saveTrueTarget = currentTrueTarget;
currentTrueTarget = currentFalseTarget;
currentFalseTarget = saveTrueTarget;
forEachChild(node, bind);
bindEachChild(node);
currentFalseTarget = currentTrueTarget;
currentTrueTarget = saveTrueTarget;
}
else {
forEachChild(node, bind);
bindEachChild(node);
if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) {
bindAssignmentTargetFlow(node.operand);
}
@@ -1193,7 +1222,7 @@ namespace ts {
}
function bindPostfixUnaryExpressionFlow(node: PostfixUnaryExpression) {
forEachChild(node, bind);
bindEachChild(node);
if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) {
bindAssignmentTargetFlow(node.operand);
}
@@ -1212,7 +1241,7 @@ namespace ts {
}
}
else {
forEachChild(node, bind);
bindEachChild(node);
if (isAssignmentOperator(operator) && !isAssignmentTarget(node)) {
bindAssignmentTargetFlow(node.left);
if (operator === SyntaxKind.EqualsToken && node.left.kind === SyntaxKind.ElementAccessExpression) {
@@ -1226,7 +1255,7 @@ namespace ts {
}
function bindDeleteExpressionFlow(node: DeleteExpression) {
forEachChild(node, bind);
bindEachChild(node);
if (node.expression.kind === SyntaxKind.PropertyAccessExpression) {
bindAssignmentTargetFlow(node.expression);
}
@@ -1251,7 +1280,7 @@ namespace ts {
function bindInitializedVariableFlow(node: VariableDeclaration | ArrayBindingElement) {
const name = !isOmittedExpression(node) ? node.name : undefined;
if (isBindingPattern(name)) {
for (const child of name.elements) {
for (const child of <ArrayBindingElement[]>name.elements) {
bindInitializedVariableFlow(child);
}
}
@@ -1261,7 +1290,7 @@ namespace ts {
}
function bindVariableDeclarationFlow(node: VariableDeclaration) {
forEachChild(node, bind);
bindEachChild(node);
if (node.initializer || node.parent.parent.kind === SyntaxKind.ForInStatement || node.parent.parent.kind === SyntaxKind.ForOfStatement) {
bindInitializedVariableFlow(node);
}
@@ -1276,12 +1305,12 @@ namespace ts {
expr = (<ParenthesizedExpression>expr).expression;
}
if (expr.kind === SyntaxKind.FunctionExpression || expr.kind === SyntaxKind.ArrowFunction) {
forEach(node.typeArguments, bind);
forEach(node.arguments, bind);
bindEach(node.typeArguments);
bindEach(node.arguments);
bind(node.expression);
}
else {
forEachChild(node, bind);
bindEachChild(node);
}
if (node.expression.kind === SyntaxKind.PropertyAccessExpression) {
const propertyAccess = <PropertyAccessExpression>node.expression;
@@ -2517,7 +2546,7 @@ namespace ts {
transformFlags |= TransformFlags.AssertTypeScript;
}
if (subtreeFlags & TransformFlags.ContainsSpreadExpression
if (subtreeFlags & TransformFlags.ContainsSpread
|| isSuperOrSuperProperty(expression, expressionKind)) {
// If the this node contains a SpreadExpression, or is a super call, then it is an ES6
// node.
@@ -2548,7 +2577,7 @@ namespace ts {
if (node.typeArguments) {
transformFlags |= TransformFlags.AssertTypeScript;
}
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
if (subtreeFlags & TransformFlags.ContainsSpread) {
// If the this node contains a SpreadElementExpression then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES2015;
@@ -2557,7 +2586,6 @@ namespace ts {
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
}
function computeBinaryExpression(node: BinaryExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const operatorTokenKind = node.operatorToken.kind;
@@ -2604,7 +2632,7 @@ namespace ts {
}
// parameters with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -2726,7 +2754,7 @@ namespace ts {
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.NodeExcludes;
return transformFlags & ~TransformFlags.CatchClauseExcludes;
}
function computeExpressionWithTypeArguments(node: ExpressionWithTypeArguments, subtreeFlags: TransformFlags) {
@@ -2753,6 +2781,11 @@ namespace ts {
transformFlags |= TransformFlags.AssertTypeScript;
}
// function declarations with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
transformFlags |= TransformFlags.AssertESNext;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.ConstructorExcludes;
}
@@ -2771,6 +2804,11 @@ namespace ts {
transformFlags |= TransformFlags.AssertTypeScript;
}
// function declarations with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
transformFlags |= TransformFlags.AssertESNext;
}
// An async method declaration is ES2017 syntax.
if (hasModifier(node, ModifierFlags.Async)) {
transformFlags |= TransformFlags.AssertES2017;
@@ -2797,6 +2835,11 @@ namespace ts {
transformFlags |= TransformFlags.AssertTypeScript;
}
// function declarations with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
transformFlags |= TransformFlags.AssertESNext;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.MethodOrAccessorExcludes;
}
@@ -2842,7 +2885,7 @@ namespace ts {
}
// function declarations with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -2884,7 +2927,7 @@ namespace ts {
}
// function expressions with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -2927,7 +2970,7 @@ namespace ts {
}
// arrow functions with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -2957,16 +3000,11 @@ namespace ts {
function computeVariableDeclaration(node: VariableDeclaration, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const nameKind = node.name.kind;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
// A VariableDeclaration with an object binding pattern is ES2015 syntax
// and possibly ESNext syntax if it contains an object binding pattern
if (nameKind === SyntaxKind.ObjectBindingPattern) {
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
}
// A VariableDeclaration with an object binding pattern is ES2015 syntax.
else if (nameKind === SyntaxKind.ArrayBindingPattern) {
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
// A VariableDeclaration containing ObjectRest is ESNext syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
transformFlags |= TransformFlags.AssertESNext;
}
// Type annotations are TypeScript syntax.
@@ -3182,16 +3220,12 @@ namespace ts {
break;
case SyntaxKind.SpreadElement:
case SyntaxKind.SpreadAssignment:
// This node is ES6 or ES next syntax, but is handled by a containing node.
transformFlags |= TransformFlags.ContainsSpreadExpression;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsSpread;
break;
case SyntaxKind.BindingElement:
if ((node as BindingElement).dotDotDotToken) {
// this node is ES2015 or ES next syntax, but is handled by a containing node.
transformFlags |= TransformFlags.ContainsSpreadExpression;
}
case SyntaxKind.SpreadAssignment:
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectSpread;
break;
case SyntaxKind.SuperKeyword:
// This node is ES6 syntax.
@@ -3204,13 +3238,22 @@ namespace ts {
break;
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
// These nodes are ES2015 or ES Next syntax.
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsBindingPattern;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
if (subtreeFlags & TransformFlags.ContainsRest) {
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectRest;
}
else {
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
excludeFlags = TransformFlags.BindingPatternExcludes;
break;
case SyntaxKind.ArrayBindingPattern:
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
excludeFlags = TransformFlags.BindingPatternExcludes;
break;
case SyntaxKind.BindingElement:
transformFlags |= TransformFlags.AssertES2015;
if ((<BindingElement>node).dotDotDotToken) {
transformFlags |= TransformFlags.ContainsRest;
}
break;
@@ -3233,7 +3276,7 @@ namespace ts {
transformFlags |= TransformFlags.ContainsLexicalThis;
}
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
if (subtreeFlags & TransformFlags.ContainsObjectSpread) {
// If an ObjectLiteralExpression contains a spread element, then it
// is an ES next node.
transformFlags |= TransformFlags.AssertESNext;
@@ -3244,7 +3287,7 @@ namespace ts {
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.NewExpression:
excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExcludes;
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
if (subtreeFlags & TransformFlags.ContainsSpread) {
// If the this node contains a SpreadExpression, then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES2015;
@@ -3337,6 +3380,11 @@ namespace ts {
return TransformFlags.TypeExcludes;
case SyntaxKind.ObjectLiteralExpression:
return TransformFlags.ObjectLiteralExcludes;
case SyntaxKind.CatchClause:
return TransformFlags.CatchClauseExcludes;
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
return TransformFlags.BindingPatternExcludes;
default:
return TransformFlags.NodeExcludes;
}
+7 -7
View File
@@ -3030,7 +3030,7 @@ namespace ts {
}
function isComputedNonLiteralName(name: PropertyName): boolean {
return name.kind === SyntaxKind.ComputedPropertyName && !isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind);
return name.kind === SyntaxKind.ComputedPropertyName && !isStringOrNumericLiteral((<ComputedPropertyName>name).expression);
}
function getRestType(source: Type, properties: PropertyName[], symbol: Symbol): Type {
@@ -3081,7 +3081,7 @@ namespace ts {
}
const literalMembers: PropertyName[] = [];
for (const element of pattern.elements) {
if (element.kind !== SyntaxKind.OmittedExpression && !(element as BindingElement).dotDotDotToken) {
if (!(element as BindingElement).dotDotDotToken) {
literalMembers.push(element.propertyName || element.name as Identifier);
}
}
@@ -4489,6 +4489,8 @@ namespace ts {
const members: SymbolTable = createMap<Symbol>();
let stringIndexInfo: IndexInfo;
let numberIndexInfo: IndexInfo;
// Resolve upfront such that recursive references see an empty object type.
setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, undefined, undefined);
// In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type,
// and T as the template type.
const typeParameter = getTypeParameterFromMappedType(type);
@@ -8927,7 +8929,7 @@ namespace ts {
return type;
}
function getTypeOfDestructuredProperty(type: Type, name: Identifier | LiteralExpression | ComputedPropertyName) {
function getTypeOfDestructuredProperty(type: Type, name: PropertyName) {
const text = getTextOfPropertyName(name);
return getTypeOfPropertyOfType(type, text) ||
isNumericLiteralName(text) && getIndexTypeOfType(type, IndexKind.Number) ||
@@ -14221,9 +14223,7 @@ namespace ts {
}
}
else if (property.kind === SyntaxKind.SpreadAssignment) {
if (property.expression.kind !== SyntaxKind.Identifier) {
error(property.expression, Diagnostics.An_object_rest_element_must_be_an_identifier);
}
checkReferenceExpression(property.expression, Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access);
}
else {
error(property, Diagnostics.Property_assignment_expected);
@@ -19632,7 +19632,7 @@ namespace ts {
function isNameOfModuleOrEnumDeclaration(node: Identifier) {
const parent = node.parent;
return isModuleOrEnumDeclaration(parent) && node === parent.name;
return parent && isModuleOrEnumDeclaration(parent) && node === parent.name;
}
// When resolved as an expression identifier, if the given node references an exported entity, return the declaration
+29 -1
View File
@@ -571,7 +571,7 @@ namespace ts {
*/
export function append<T>(to: T[] | undefined, value: T | undefined): T[] | undefined {
if (value === undefined) return to;
if (to === undefined) to = [];
if (to === undefined) return [value];
to.push(value);
return to;
}
@@ -592,6 +592,16 @@ namespace ts {
return to;
}
/**
* Stable sort of an array. Elements equal to each other maintain their relative position in the array.
*/
export function stableSort<T>(array: T[], comparer: (x: T, y: T) => Comparison = compareValues) {
return array
.map((_, i) => i) // create array of indices
.sort((x, y) => comparer(array[x], array[y]) || compareValues(x, y)) // sort indices by value then position
.map(i => array[i]); // get sorted array
}
export function rangeEquals<T>(array1: T[], array2: T[], pos: number, end: number) {
while (pos < end) {
if (array1[pos] !== array2[pos]) {
@@ -816,6 +826,13 @@ namespace ts {
}
}
export function appendProperty<T>(map: Map<T>, key: string | number, value: T): Map<T> {
if (key === undefined || value === undefined) return map;
if (map === undefined) map = createMap<T>();
map[key] = value;
return map;
}
export function assign<T1 extends MapLike<{}>, T2, T3>(t: T1, arg1: T2, arg2: T3): T1 & T2 & T3;
export function assign<T1 extends MapLike<{}>, T2>(t: T1, arg1: T2): T1 & T2;
export function assign<T1 extends MapLike<{}>>(t: T1, ...args: any[]): any;
@@ -2092,6 +2109,17 @@ namespace ts {
}
/** Remove an item from an array, moving everything to its right one space left. */
export function orderedRemoveItem<T>(array: T[], item: T): boolean {
for (let i = 0; i < array.length; i++) {
if (array[i] === item) {
orderedRemoveItemAt(array, i);
return true;
}
}
return false;
}
/** Remove an item by index from an array, moving everything to its right one space left. */
export function orderedRemoveItemAt<T>(array: T[], index: number): void {
// This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`.
for (let i = index; i < array.length - 1; i++) {
+1 -1
View File
@@ -1991,7 +1991,7 @@
"category": "Error",
"code": 2700
},
"An object rest element must be an identifier.": {
"The target of an object rest assignment must be a variable or a property access.": {
"category": "Error",
"code": 2701
},
+51 -280
View File
@@ -20,185 +20,6 @@ namespace ts {
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult {
const delimiters = createDelimiterMap();
const brackets = createBracketsMap();
// emit output for the __extends helper function
const extendsHelper = `
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};`;
// Emit output for the __assign helper function.
// This is typically used for JSX spread attributes,
// and can be used for object literal spread properties.
const assignHelper = `
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};`;
const restHelper = `
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
};`;
// emit output for the __decorate helper function
const decorateHelper = `
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};`;
// emit output for the __metadata helper function
const metadataHelper = `
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};`;
// emit output for the __param helper function
const paramHelper = `
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};`;
// emit output for the __awaiter helper function
const awaiterHelper = `
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};`;
// The __generator helper is used by down-level transformations to emulate the runtime
// semantics of an ES2015 generator function. When called, this helper returns an
// object that implements the Iterator protocol, in that it has `next`, `return`, and
// `throw` methods that step through the generator when invoked.
//
// parameters:
// thisArg The value to use as the `this` binding for the transformed generator body.
// body A function that acts as the transformed generator body.
//
// variables:
// _ Persistent state for the generator that is shared between the helper and the
// generator body. The state object has the following members:
// sent() - A method that returns or throws the current completion value.
// label - The next point at which to resume evaluation of the generator body.
// trys - A stack of protected regions (try/catch/finally blocks).
// ops - A stack of pending instructions when inside of a finally block.
// f A value indicating whether the generator is executing.
// y An iterator to delegate for a yield*.
// t A temporary variable that holds one of the following values (note that these
// cases do not overlap):
// - The completion value when resuming from a `yield` or `yield*`.
// - The error value for a catch block.
// - The current protected region (array of try/catch/finally/end labels).
// - The verb (`next`, `throw`, or `return` method) to delegate to the expression
// of a `yield*`.
// - The result of evaluating the verb delegated to the expression of a `yield*`.
//
// functions:
// verb(n) Creates a bound callback to the `step` function for opcode `n`.
// step(op) Evaluates opcodes in a generator body until execution is suspended or
// completed.
//
// The __generator helper understands a limited set of instructions:
// 0: next(value?) - Start or resume the generator with the specified value.
// 1: throw(error) - Resume the generator with an exception. If the generator is
// suspended inside of one or more protected regions, evaluates
// any intervening finally blocks between the current label and
// the nearest catch block or function boundary. If uncaught, the
// exception is thrown to the caller.
// 2: return(value?) - Resume the generator as if with a return. If the generator is
// suspended inside of one or more protected regions, evaluates any
// intervening finally blocks.
// 3: break(label) - Jump to the specified label. If the label is outside of the
// current protected region, evaluates any intervening finally
// blocks.
// 4: yield(value?) - Yield execution to the caller with an optional value. When
// resumed, the generator will continue at the next label.
// 5: yield*(value) - Delegates evaluation to the supplied iterator. When
// delegation completes, the generator will continue at the next
// label.
// 6: catch(error) - Handles an exception thrown from within the generator body. If
// the current label is inside of one or more protected regions,
// evaluates any intervening finally blocks between the current
// label and the nearest catch block or function boundary. If
// uncaught, the exception is thrown to the caller.
// 7: endfinally - Ends a finally block, resuming the last instruction prior to
// entering a finally block.
//
// For examples of how these are used, see the comments in ./transformers/generators.ts
const generatorHelper = `
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;
return { next: verb(0), "throw": verb(1), "return": verb(2) };
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};`;
// emit output for the __export helper function
const exportStarHelper = `
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}`;
// emit output for the UMD helper function.
const umdHelper = `
(function (dependencies, factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports); if (v !== undefined) module.exports = v;
}
else if (typeof define === 'function' && define.amd) {
define(dependencies, factory);
}
})`;
const superHelper = `
const _super = name => super[name];`;
const advancedSuperHelper = `
const _super = (function (geti, seti) {
const cache = Object.create(null);
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
})(name => super[name], (name, value) => super[name] = value);`;
const compilerOptions = host.getCompilerOptions();
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
@@ -235,12 +56,7 @@ const _super = (function (geti, seti) {
let currentSourceFile: SourceFile;
let currentText: string;
let currentFileIdentifiers: Map<string>;
let extendsEmitted: boolean;
let assignEmitted: boolean;
let restEmitted: boolean;
let decorateEmitted: boolean;
let paramEmitted: boolean;
let awaiterEmitted: boolean;
let bundledHelpers: Map<boolean>;
let isOwnFileEmit: boolean;
let emitSkipped = false;
@@ -305,12 +121,13 @@ const _super = (function (geti, seti) {
nodeIdToGeneratedName = [];
autoGeneratedIdToGeneratedName = [];
generatedNameSet = createMap<string>();
bundledHelpers = isBundledEmit ? createMap<boolean>() : undefined;
isOwnFileEmit = !isBundledEmit;
// Emit helpers from all the files
if (isBundledEmit && moduleKind) {
for (const sourceFile of sourceFiles) {
emitEmitHelpers(sourceFile);
emitHelpers(sourceFile, /*isBundle*/ true);
}
}
@@ -345,11 +162,6 @@ const _super = (function (geti, seti) {
tempFlags = TempFlags.Auto;
currentSourceFile = undefined;
currentText = undefined;
extendsEmitted = false;
assignEmitted = false;
decorateEmitted = false;
paramEmitted = false;
awaiterEmitted = false;
isOwnFileEmit = false;
}
@@ -858,6 +670,8 @@ const _super = (function (geti, seti) {
// Transformation nodes
case SyntaxKind.PartiallyEmittedExpression:
return emitPartiallyEmittedExpression(<PartiallyEmittedExpression>node);
case SyntaxKind.RawExpression:
return writeLines((<RawExpression>node).text);
}
}
@@ -895,12 +709,7 @@ const _super = (function (geti, seti) {
//
function emitIdentifier(node: Identifier) {
if (getEmitFlags(node) & EmitFlags.UMDDefine) {
writeLines(umdHelper);
}
else {
write(getTextOfNode(node, /*includeTrivia*/ false));
}
write(getTextOfNode(node, /*includeTrivia*/ false));
}
//
@@ -2204,93 +2013,39 @@ const _super = (function (geti, seti) {
return statements.length;
}
function emitHelpers(node: Node) {
const emitFlags = getEmitFlags(node);
let helpersEmitted = false;
if (emitFlags & EmitFlags.EmitEmitHelpers) {
helpersEmitted = emitEmitHelpers(currentSourceFile);
}
if (emitFlags & EmitFlags.EmitExportStar) {
writeLines(exportStarHelper);
helpersEmitted = true;
}
if (emitFlags & EmitFlags.EmitSuperHelper) {
writeLines(superHelper);
helpersEmitted = true;
}
if (emitFlags & EmitFlags.EmitAdvancedSuperHelper) {
writeLines(advancedSuperHelper);
helpersEmitted = true;
}
return helpersEmitted;
}
function emitEmitHelpers(node: SourceFile) {
// Only emit helpers if the user did not say otherwise.
if (compilerOptions.noEmitHelpers) {
return false;
}
// Don't emit helpers if we can import them.
if (compilerOptions.importHelpers
&& (isExternalModule(node) || compilerOptions.isolatedModules)) {
return false;
}
function emitHelpers(node: Node, isBundle?: boolean) {
const sourceFile = isSourceFile(node) ? node : currentSourceFile;
const shouldSkip = compilerOptions.noEmitHelpers || (sourceFile && getExternalHelpersModuleName(sourceFile) !== undefined);
const shouldBundle = isSourceFile(node) && !isOwnFileEmit;
let helpersEmitted = false;
const helpers = getEmitHelpers(node);
if (helpers) {
for (const helper of stableSort(helpers, compareEmitHelpers)) {
if (!helper.scoped) {
// Skip the helper if it can be skipped and the noEmitHelpers compiler
// option is set, or if it can be imported and the importHelpers compiler
// option is set.
if (shouldSkip) continue;
// Only Emit __extends function when target ES5.
// For target ES6 and above, we can emit classDeclaration as is.
if ((languageVersion < ScriptTarget.ES2015) && (!extendsEmitted && node.flags & NodeFlags.HasClassExtends)) {
writeLines(extendsHelper);
extendsEmitted = true;
helpersEmitted = true;
}
// Skip the helper if it can be bundled but hasn't already been emitted and we
// are emitting a bundled module.
if (shouldBundle) {
if (bundledHelpers[helper.name]) {
continue;
}
if ((languageVersion < ScriptTarget.ESNext || currentSourceFile.scriptKind === ScriptKind.JSX || currentSourceFile.scriptKind === ScriptKind.TSX) &&
compilerOptions.jsx !== JsxEmit.Preserve &&
!assignEmitted &&
node.flags & NodeFlags.HasSpreadAttribute) {
writeLines(assignHelper);
assignEmitted = true;
}
bundledHelpers[helper.name] = true;
}
}
else if (isBundle) {
// Skip the helper if it is scoped and we are emitting bundled helpers
continue;
}
if (languageVersion < ScriptTarget.ESNext && !restEmitted && node.flags & NodeFlags.HasRestAttribute) {
writeLines(restHelper);
restEmitted = true;
}
if (!decorateEmitted && node.flags & NodeFlags.HasDecorators) {
writeLines(decorateHelper);
if (compilerOptions.emitDecoratorMetadata) {
writeLines(metadataHelper);
writeLines(helper.text);
helpersEmitted = true;
}
decorateEmitted = true;
helpersEmitted = true;
}
if (!paramEmitted && node.flags & NodeFlags.HasParamDecorators) {
writeLines(paramHelper);
paramEmitted = true;
helpersEmitted = true;
}
// Only emit __awaiter function when target ES5/ES6.
// Only emit __generator function when target ES5.
// For target ES2017 and above, we can emit async/await as is.
if ((languageVersion < ScriptTarget.ES2017) && (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions)) {
writeLines(awaiterHelper);
if (languageVersion < ScriptTarget.ES2015) {
writeLines(generatorHelper);
}
awaiterEmitted = true;
helpersEmitted = true;
}
if (helpersEmitted) {
@@ -2301,9 +2056,10 @@ const _super = (function (geti, seti) {
}
function writeLines(text: string): void {
const lines = text.split(/\r\n|\r|\n/g);
const lines = text.split(/\r\n?|\n/g);
const indentation = guessIndentation(lines);
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const line = indentation ? lines[i].slice(indentation) : lines[i];
if (line.length) {
if (i > 0) {
writeLine();
@@ -2313,6 +2069,21 @@ const _super = (function (geti, seti) {
}
}
function guessIndentation(lines: string[]) {
let indentation: number;
for (const line of lines) {
for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) {
if (!isWhiteSpace(line.charCodeAt(i))) {
if (indentation === undefined || i < indentation) {
indentation = i;
break;
}
}
}
}
return indentation;
}
//
// Helpers
//
+633 -834
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1168,7 +1168,7 @@ namespace ts {
function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName {
if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) {
return parseLiteralNode(/*internName*/ true);
return <StringLiteral | NumericLiteral>parseLiteralNode(/*internName*/ true);
}
if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) {
return parseComputedPropertyName();
@@ -5514,7 +5514,7 @@ namespace ts {
node.flags |= NodeFlags.GlobalAugmentation;
}
else {
node.name = parseLiteralNode(/*internName*/ true);
node.name = <StringLiteral>parseLiteralNode(/*internName*/ true);
}
if (token() === SyntaxKind.OpenBraceToken) {
+65 -102
View File
@@ -27,84 +27,6 @@ namespace ts {
EmitNotifications = 1 << 1,
}
export interface TransformationResult {
/**
* Gets the transformed source files.
*/
transformed: SourceFile[];
/**
* Emits the substitute for a node, if one is available; otherwise, emits the node.
*
* @param emitContext The current emit context.
* @param node The node to substitute.
* @param emitCallback A callback used to emit the node or its substitute.
*/
emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
/**
* Emits a node with possible notification.
*
* @param emitContext The current emit context.
* @param node The node to emit.
* @param emitCallback A callback used to emit the node.
*/
emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
}
export interface TransformationContext extends LexicalEnvironment {
getCompilerOptions(): CompilerOptions;
getEmitResolver(): EmitResolver;
getEmitHost(): EmitHost;
/**
* Hoists a function declaration to the containing scope.
*/
hoistFunctionDeclaration(node: FunctionDeclaration): void;
/**
* Hoists a variable declaration to the containing scope.
*/
hoistVariableDeclaration(node: Identifier): void;
/**
* Enables expression substitutions in the pretty printer for the provided SyntaxKind.
*/
enableSubstitution(kind: SyntaxKind): void;
/**
* Determines whether expression substitutions are enabled for the provided node.
*/
isSubstitutionEnabled(node: Node): boolean;
/**
* Hook used by transformers to substitute expressions just before they
* are emitted by the pretty printer.
*/
onSubstituteNode?: (emitContext: EmitContext, node: Node) => Node;
/**
* Enables before/after emit notifications in the pretty printer for the provided
* SyntaxKind.
*/
enableEmitNotification(kind: SyntaxKind): void;
/**
* Determines whether before/after emit notifications should be raised in the pretty
* printer when it emits a node.
*/
isEmitNotificationEnabled(node: Node): boolean;
/**
* Hook used to allow transformers to capture state before or after
* the printer emits a node.
*/
onEmitNode?: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void;
}
/* @internal */
export type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile;
export function getTransformers(compilerOptions: CompilerOptions) {
const jsx = compilerOptions.jsx;
const languageVersion = getEmitScriptTarget(compilerOptions);
@@ -154,14 +76,18 @@ namespace ts {
* @param transforms An array of Transformers.
*/
export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]): TransformationResult {
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
let lexicalEnvironmentDisabled = false;
let lexicalEnvironmentVariableDeclarations: VariableDeclaration[];
let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[];
let lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
let lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
let lexicalEnvironmentStackOffset = 0;
let hoistedVariableDeclarations: VariableDeclaration[];
let hoistedFunctionDeclarations: FunctionDeclaration[];
let lexicalEnvironmentDisabled: boolean;
let lexicalEnvironmentSuspended = false;
let emitHelpers: EmitHelper[];
// The transformation context is provided to each transformer as part of transformer
// initialization.
@@ -169,10 +95,14 @@ namespace ts {
getCompilerOptions: () => host.getCompilerOptions(),
getEmitResolver: () => resolver,
getEmitHost: () => host,
startLexicalEnvironment,
suspendLexicalEnvironment,
resumeLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration,
hoistFunctionDeclaration,
startLexicalEnvironment,
endLexicalEnvironment,
requestEmitHelper,
readEmitHelpers,
onSubstituteNode: (_emitContext, node) => node,
enableSubstitution,
isSubstitutionEnabled,
@@ -285,11 +215,11 @@ namespace ts {
function hoistVariableDeclaration(name: Identifier): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
const decl = createVariableDeclaration(name);
if (!hoistedVariableDeclarations) {
hoistedVariableDeclarations = [decl];
if (!lexicalEnvironmentVariableDeclarations) {
lexicalEnvironmentVariableDeclarations = [decl];
}
else {
hoistedVariableDeclarations.push(decl);
lexicalEnvironmentVariableDeclarations.push(decl);
}
}
@@ -298,11 +228,11 @@ namespace ts {
*/
function hoistFunctionDeclaration(func: FunctionDeclaration): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
if (!hoistedFunctionDeclarations) {
hoistedFunctionDeclarations = [func];
if (!lexicalEnvironmentFunctionDeclarations) {
lexicalEnvironmentFunctionDeclarations = [func];
}
else {
hoistedFunctionDeclarations.push(func);
lexicalEnvironmentFunctionDeclarations.push(func);
}
}
@@ -312,16 +242,31 @@ namespace ts {
*/
function startLexicalEnvironment(): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot start a lexical environment during the print phase.");
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended.");
// Save the current lexical environment. Rather than resizing the array we adjust the
// stack size variable. This allows us to reuse existing array slots we've
// already allocated between transformations to avoid allocation and GC overhead during
// transformation.
lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedVariableDeclarations;
lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedFunctionDeclarations;
lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentVariableDeclarations;
lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFunctionDeclarations;
lexicalEnvironmentStackOffset++;
hoistedVariableDeclarations = undefined;
hoistedFunctionDeclarations = undefined;
lexicalEnvironmentVariableDeclarations = undefined;
lexicalEnvironmentFunctionDeclarations = undefined;
}
/** Suspends the current lexical environment, usually after visiting a parameter list. */
function suspendLexicalEnvironment(): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot suspend a lexical environment during the print phase.");
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is already suspended.");
lexicalEnvironmentSuspended = true;
}
/** Resumes a suspended lexical environment, usually before visiting a function body. */
function resumeLexicalEnvironment(): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot resume a lexical environment during the print phase.");
Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended.");
lexicalEnvironmentSuspended = false;
}
/**
@@ -330,17 +275,18 @@ namespace ts {
*/
function endLexicalEnvironment(): Statement[] {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot end a lexical environment during the print phase.");
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended.");
let statements: Statement[];
if (hoistedVariableDeclarations || hoistedFunctionDeclarations) {
if (hoistedFunctionDeclarations) {
statements = [...hoistedFunctionDeclarations];
if (lexicalEnvironmentVariableDeclarations || lexicalEnvironmentFunctionDeclarations) {
if (lexicalEnvironmentFunctionDeclarations) {
statements = [...lexicalEnvironmentFunctionDeclarations];
}
if (hoistedVariableDeclarations) {
if (lexicalEnvironmentVariableDeclarations) {
const statement = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(hoistedVariableDeclarations)
createVariableDeclarationList(lexicalEnvironmentVariableDeclarations)
);
if (!statements) {
@@ -354,9 +300,26 @@ namespace ts {
// Restore the previous lexical environment.
lexicalEnvironmentStackOffset--;
hoistedVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset];
hoistedFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset];
lexicalEnvironmentVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset];
lexicalEnvironmentFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset];
if (lexicalEnvironmentStackOffset === 0) {
lexicalEnvironmentVariableDeclarationsStack = [];
lexicalEnvironmentFunctionDeclarationsStack = [];
}
return statements;
}
function requestEmitHelper(helper: EmitHelper): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
Debug.assert(!helper.scoped, "Cannot request a scoped emit helper.");
emitHelpers = append(emitHelpers, helper);
}
function readEmitHelpers(): EmitHelper[] | undefined {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
const helpers = emitHelpers;
emitHelpers = undefined;
return helpers;
}
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+52 -61
View File
@@ -17,84 +17,75 @@ namespace ts {
}
function visitor(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.ES2016) {
return visitorWorker(node);
}
else if (node.transformFlags & TransformFlags.ContainsES2016) {
return visitEachChild(node, visitor, context);
}
else {
if ((node.transformFlags & TransformFlags.ContainsES2016) === 0) {
return node;
}
}
function visitorWorker(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.BinaryExpression:
return visitBinaryExpression(<BinaryExpression>node);
default:
Debug.failBadSyntaxKind(node);
return visitEachChild(node, visitor, context);
}
}
function visitBinaryExpression(node: BinaryExpression): Expression {
// We are here because ES2016 adds support for the exponentiation operator.
switch (node.operatorToken.kind) {
case SyntaxKind.AsteriskAsteriskEqualsToken:
return visitExponentiationAssignmentExpression(node);
case SyntaxKind.AsteriskAsteriskToken:
return visitExponentiationExpression(node);
default:
return visitEachChild(node, visitor, context);
}
}
function visitExponentiationAssignmentExpression(node: BinaryExpression) {
let target: Expression;
let value: Expression;
const left = visitNode(node.left, visitor, isExpression);
const right = visitNode(node.right, visitor, isExpression);
if (node.operatorToken.kind === SyntaxKind.AsteriskAsteriskEqualsToken) {
let target: Expression;
let value: Expression;
if (isElementAccessExpression(left)) {
// Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)`
const expressionTemp = createTempVariable(hoistVariableDeclaration);
const argumentExpressionTemp = createTempVariable(hoistVariableDeclaration);
target = createElementAccess(
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
createAssignment(argumentExpressionTemp, left.argumentExpression, /*location*/ left.argumentExpression),
/*location*/ left
);
value = createElementAccess(
expressionTemp,
argumentExpressionTemp,
/*location*/ left
);
}
else if (isPropertyAccessExpression(left)) {
// Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)`
const expressionTemp = createTempVariable(hoistVariableDeclaration);
target = createPropertyAccess(
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
left.name,
/*location*/ left
);
value = createPropertyAccess(
expressionTemp,
left.name,
/*location*/ left
);
}
else {
// Transforms `a **= b` into `a = Math.pow(a, b)`
target = left;
value = left;
}
return createAssignment(target, createMathPow(value, right, /*location*/ node), /*location*/ node);
if (isElementAccessExpression(left)) {
// Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)`
const expressionTemp = createTempVariable(hoistVariableDeclaration);
const argumentExpressionTemp = createTempVariable(hoistVariableDeclaration);
target = createElementAccess(
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
createAssignment(argumentExpressionTemp, left.argumentExpression, /*location*/ left.argumentExpression),
/*location*/ left
);
value = createElementAccess(
expressionTemp,
argumentExpressionTemp,
/*location*/ left
);
}
else if (node.operatorToken.kind === SyntaxKind.AsteriskAsteriskToken) {
// Transforms `a ** b` into `Math.pow(a, b)`
return createMathPow(left, right, /*location*/ node);
else if (isPropertyAccessExpression(left)) {
// Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)`
const expressionTemp = createTempVariable(hoistVariableDeclaration);
target = createPropertyAccess(
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
left.name,
/*location*/ left
);
value = createPropertyAccess(
expressionTemp,
left.name,
/*location*/ left
);
}
else {
Debug.failBadSyntaxKind(node);
return visitEachChild(node, visitor, context);
// Transforms `a **= b` into `a = Math.pow(a, b)`
target = left;
value = left;
}
return createAssignment(target, createMathPow(value, right, /*location*/ node), /*location*/ node);
}
function visitExponentiationExpression(node: BinaryExpression) {
// Transforms `a ** b` into `Math.pow(a, b)`
const left = visitNode(node.left, visitor, isExpression);
const right = visitNode(node.right, visitor, isExpression);
return createMathPow(left, right, /*location*/ node);
}
}
}
+149 -143
View File
@@ -5,15 +5,15 @@
namespace ts {
type SuperContainer = ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration;
const enum ES2017SubstitutionFlags {
/** Enables substitutions for async methods with `super` calls. */
AsyncMethodsWithSuper = 1 << 0
}
export function transformES2017(context: TransformationContext) {
const enum ES2017SubstitutionFlags {
/** Enables substitutions for async methods with `super` calls. */
AsyncMethodsWithSuper = 1 << 0
}
const {
startLexicalEnvironment,
resumeLexicalEnvironment,
endLexicalEnvironment,
} = context;
@@ -22,19 +22,14 @@ namespace ts {
const languageVersion = getEmitScriptTarget(compilerOptions);
// These variables contain state that changes as we descend into the tree.
let currentSourceFileExternalHelpersModuleName: Identifier;
let currentSourceFile: SourceFile;
/**
* Keeps track of whether expression substitution has been enabled for specific edge cases.
* They are persisted between each SourceFile transformation and should not be reset.
*/
let enabledSubstitutions: ES2017SubstitutionFlags;
/**
* Keeps track of whether we are within any containing namespaces when performing
* just-in-time substitution while printing an expression identifier.
*/
let applicableSubstitutions: ES2017SubstitutionFlags;
/**
* This keeps track of containers where `super` is valid, for use with
* just-in-time substitution for `super` expressions inside of async methods.
@@ -49,8 +44,6 @@ namespace ts {
context.onEmitNode = onEmitNode;
context.onSubstituteNode = onSubstituteNode;
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
@@ -58,23 +51,20 @@ namespace ts {
return node;
}
currentSourceFileExternalHelpersModuleName = node.externalHelpersModuleName;
currentSourceFile = node;
return visitEachChild(node, visitor, context);
const visited = visitEachChild(node, visitor, context);
addEmitHelpers(visited, context.readEmitHelpers());
currentSourceFile = undefined;
return visited;
}
function visitor(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.ES2017) {
return visitorWorker(node);
}
else if (node.transformFlags & TransformFlags.ContainsES2017) {
return visitEachChild(node, visitor, context);
if ((node.transformFlags & TransformFlags.ContainsES2017) === 0) {
return node;
}
return node;
}
function visitorWorker(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.AsyncKeyword:
// ES2017 async modifier should be elided for targets < ES2017
@@ -101,17 +91,16 @@ namespace ts {
return visitArrowFunction(<ArrowFunction>node);
default:
Debug.failBadSyntaxKind(node);
return node;
return visitEachChild(node, visitor, context);
}
}
/**
* Visits an await expression.
* Visits an AwaitExpression node.
*
* This function will be called any time a ES2017 await expression is encountered.
*
* @param node The await expression node.
* @param node The node to visit.
*/
function visitAwaitExpression(node: AwaitExpression): Expression {
return setOriginalNode(
@@ -125,143 +114,102 @@ namespace ts {
}
/**
* Visits a method declaration of a class.
* Visits a MethodDeclaration node.
*
* This function will be called when one of the following conditions are met:
* - The node is marked as async
*
* @param node The method node.
* @param node The node to visit.
*/
function visitMethodDeclaration(node: MethodDeclaration) {
if (!isAsyncFunctionLike(node)) {
return node;
}
const method = createMethod(
return updateMethod(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node),
/*location*/ node
isAsyncFunctionLike(node)
? transformAsyncFunctionBody(node)
: visitFunctionBody(node.body, visitor, context)
);
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setCommentRange(method, node);
setSourceMapRange(method, moveRangePastDecorators(node));
setOriginalNode(method, node);
return method;
}
/**
* Visits a function declaration.
* Visits a FunctionDeclaration node.
*
* This function will be called when one of the following conditions are met:
* - The node is marked async
*
* @param node The function node.
* @param node The node to visit.
*/
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
if (!isAsyncFunctionLike(node)) {
return node;
}
const func = createFunctionDeclaration(
return updateFunctionDeclaration(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node),
/*location*/ node
isAsyncFunctionLike(node)
? transformAsyncFunctionBody(node)
: visitFunctionBody(node.body, visitor, context)
);
setOriginalNode(func, node);
return func;
}
/**
* Visits a function expression node.
* Visits a FunctionExpression node.
*
* This function will be called when one of the following conditions are met:
* - The node is marked async
*
* @param node The function expression node.
* @param node The node to visit.
*/
function visitFunctionExpression(node: FunctionExpression): Expression {
if (!isAsyncFunctionLike(node)) {
return node;
}
if (nodeIsMissing(node.body)) {
return createOmittedExpression();
}
const func = createFunctionExpression(
return updateFunctionExpression(
node,
/*modifiers*/ undefined,
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node),
/*location*/ node
isAsyncFunctionLike(node)
? transformAsyncFunctionBody(node)
: visitFunctionBody(node.body, visitor, context)
);
setOriginalNode(func, node);
return func;
}
/**
* @remarks
* Visits an ArrowFunction.
*
* This function will be called when one of the following conditions are met:
* - The node is marked async
*
* @param node The node to visit.
*/
function visitArrowFunction(node: ArrowFunction) {
if (!isAsyncFunctionLike(node)) {
return node;
}
const func = createArrowFunction(
return updateArrowFunction(
node,
visitNodes(node.modifiers, visitor, isModifier),
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
node.equalsGreaterThanToken,
transformConciseBody(node),
/*location*/ node
isAsyncFunctionLike(node)
? transformAsyncFunctionBody(node)
: visitFunctionBody(node.body, visitor, context)
);
setOriginalNode(func, node);
return func;
}
function transformFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody {
return <FunctionBody>transformAsyncFunctionBody(node);
}
function transformAsyncFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody;
function transformAsyncFunctionBody(node: ArrowFunction): ConciseBody;
function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody {
resumeLexicalEnvironment();
function transformConciseBody(node: ArrowFunction): ConciseBody {
return transformAsyncFunctionBody(node);
}
function transformFunctionBodyWorker(body: Block, start = 0) {
const savedCurrentScope = currentScope;
currentScope = body;
startLexicalEnvironment();
const statements = visitNodes(body.statements, visitor, isStatement, start);
const visited = updateBlock(body, statements);
const declarations = endLexicalEnvironment();
currentScope = savedCurrentScope;
return mergeFunctionBodyLexicalEnvironment(visited, declarations);
}
function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody {
const original = getOriginalNode(node, isFunctionLike);
const nodeType = original.type;
const promiseConstructor = languageVersion < ScriptTarget.ES2015 ? getPromiseConstructor(nodeType) : undefined;
@@ -274,14 +222,13 @@ namespace ts {
// passed to `__awaiter` is executed inside of the callback to the
// promise constructor.
if (!isArrowFunction) {
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, (<Block>node.body).statements, /*ensureUseStrict*/ false, visitor);
statements.push(
createReturn(
createAwaiterHelper(
currentSourceFileExternalHelpersModuleName,
context,
hasLexicalArguments,
promiseConstructor,
transformFunctionBodyWorker(<Block>node.body, statementOffset)
@@ -289,6 +236,8 @@ namespace ts {
)
);
addRange(statements, endLexicalEnvironment());
const block = createBlock(statements, /*location*/ node.body, /*multiLine*/ true);
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
@@ -296,57 +245,56 @@ namespace ts {
if (languageVersion >= ScriptTarget.ES2015) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
enableSubstitutionForAsyncMethodsWithSuper();
setEmitFlags(block, EmitFlags.EmitAdvancedSuperHelper);
addEmitHelper(block, advancedAsyncSuperHelper);
}
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) {
enableSubstitutionForAsyncMethodsWithSuper();
setEmitFlags(block, EmitFlags.EmitSuperHelper);
addEmitHelper(block, asyncSuperHelper);
}
}
return block;
}
else {
return createAwaiterHelper(
currentSourceFileExternalHelpersModuleName,
const expression = createAwaiterHelper(
context,
hasLexicalArguments,
promiseConstructor,
<Block>transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ true)
transformFunctionBodyWorker(node.body)
);
const declarations = endLexicalEnvironment();
if (some(declarations)) {
const block = convertToFunctionBody(expression);
return updateBlock(block, createNodeArray(concatenate(block.statements, declarations), block.statements));
}
return expression;
}
}
function transformConciseBodyWorker(body: Block | Expression, forceBlockFunctionBody: boolean) {
function transformFunctionBodyWorker(body: ConciseBody, start?: number) {
if (isBlock(body)) {
return transformFunctionBodyWorker(body);
return updateBlock(body, visitLexicalEnvironment(body.statements, visitor, context, start));
}
else {
startLexicalEnvironment();
const visited: Expression | Block = visitNode(body, visitor, isConciseBody);
const visited = convertToFunctionBody(visitNode(body, visitor, isConciseBody));
const declarations = endLexicalEnvironment();
const merged = mergeFunctionBodyLexicalEnvironment(visited, declarations);
if (forceBlockFunctionBody && !isBlock(merged)) {
return createBlock([
createReturn(<Expression>merged)
]);
}
else {
return merged;
}
return updateBlock(visited, createNodeArray(concatenate(visited.statements, declarations), visited.statements));
}
}
function getPromiseConstructor(type: TypeNode) {
if (type) {
const typeName = getEntityNameFromTypeNode(type);
if (typeName && isEntityName(typeName)) {
const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue
|| serializationKind === TypeReferenceSerializationKind.Unknown) {
return typeName;
}
const typeName = type && getEntityNameFromTypeNode(type);
if (typeName && isEntityName(typeName)) {
const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue
|| serializationKind === TypeReferenceSerializationKind.Unknown) {
return typeName;
}
}
return undefined;
}
@@ -452,18 +400,17 @@ namespace ts {
* @param emit A callback used to emit the node in the printer.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
const savedApplicableSubstitutions = applicableSubstitutions;
const savedCurrentSuperContainer = currentSuperContainer;
// If we need to support substitutions for `super` in an async method,
// we should track it here.
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
const savedCurrentSuperContainer = currentSuperContainer;
currentSuperContainer = node;
previousOnEmitNode(emitContext, node, emitCallback);
currentSuperContainer = savedCurrentSuperContainer;
}
else {
previousOnEmitNode(emitContext, node, emitCallback);
}
previousOnEmitNode(emitContext, node, emitCallback);
applicableSubstitutions = savedApplicableSubstitutions;
currentSuperContainer = savedCurrentSuperContainer;
}
/**
@@ -509,4 +456,63 @@ namespace ts {
&& resolver.getNodeCheckFlags(currentSuperContainer) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
}
}
function createAwaiterHelper(context: TransformationContext, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
context.requestEmitHelper(awaiterHelper);
const generatorFunc = createFunctionExpression(
/*modifiers*/ undefined,
createToken(SyntaxKind.AsteriskToken),
/*name*/ undefined,
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
body
);
// Mark this node as originally an async function
(generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody;
return createCall(
getHelperName("__awaiter"),
/*typeArguments*/ undefined,
[
createThis(),
hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(),
promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(),
generatorFunc
]
);
}
const awaiterHelper: EmitHelper = {
name: "typescript:awaiter",
scoped: false,
priority: 5,
text: `
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};`
};
const asyncSuperHelper: EmitHelper = {
name: "typescript:async-super",
scoped: true,
text: `
const _super = name => super[name];`
};
const advancedAsyncSuperHelper: EmitHelper = {
name: "typescript:advanced-async-super",
scoped: true,
text: `
const _super = (function (geti, seti) {
const cache = Object.create(null);
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
})(name => super[name], (name, value) => super[name] = value);`
};
}
+284 -148
View File
@@ -5,41 +5,55 @@
namespace ts {
export function transformESNext(context: TransformationContext) {
const {
hoistVariableDeclaration,
resumeLexicalEnvironment,
endLexicalEnvironment
} = context;
let currentSourceFile: SourceFile;
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
currentSourceFile = node;
return visitEachChild(node, visitor, context);
if (isDeclarationFile(node)) {
return node;
}
const visited = visitEachChild(node, visitor, context);
addEmitHelpers(visited, context.readEmitHelpers());
return visited;
}
function visitor(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.ESNext) {
return visitorWorker(node);
}
else if (node.transformFlags & TransformFlags.ContainsESNext) {
return visitEachChild(node, visitor, context);
}
else {
return node;
}
return visitorWorker(node, /*noDestructuringValue*/ false);
}
function visitorWorker(node: Node): VisitResult<Node> {
function visitorNoDestructuringValue(node: Node): VisitResult<Node> {
return visitorWorker(node, /*noDestructuringValue*/ true);
}
function visitorWorker(node: Node, noDestructuringValue: boolean): VisitResult<Node> {
if ((node.transformFlags & TransformFlags.ContainsESNext) === 0) {
return node;
}
switch (node.kind) {
case SyntaxKind.ObjectLiteralExpression:
return visitObjectLiteralExpression(node as ObjectLiteralExpression);
case SyntaxKind.BinaryExpression:
return visitBinaryExpression(node as BinaryExpression);
return visitBinaryExpression(node as BinaryExpression, noDestructuringValue);
case SyntaxKind.VariableDeclaration:
return visitVariableDeclaration(node as VariableDeclaration);
case SyntaxKind.ForOfStatement:
return visitForOfStatement(node as ForOfStatement);
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
return node;
case SyntaxKind.ForStatement:
return visitForStatement(node as ForStatement);
case SyntaxKind.VoidExpression:
return visitVoidExpression(node as VoidExpression);
case SyntaxKind.Constructor:
return visitConstructorDeclaration(node as ConstructorDeclaration);
case SyntaxKind.MethodDeclaration:
return visitMethodDeclaration(node as MethodDeclaration);
case SyntaxKind.GetAccessor:
return visitGetAccessorDeclaration(node as GetAccessorDeclaration);
case SyntaxKind.SetAccessor:
return visitSetAccessorDeclaration(node as SetAccessorDeclaration);
case SyntaxKind.FunctionDeclaration:
return visitFunctionDeclaration(node as FunctionDeclaration);
case SyntaxKind.FunctionExpression:
@@ -48,8 +62,11 @@ namespace ts {
return visitArrowFunction(node as ArrowFunction);
case SyntaxKind.Parameter:
return visitParameter(node as ParameterDeclaration);
case SyntaxKind.ExpressionStatement:
return visitExpressionStatement(node as ExpressionStatement);
case SyntaxKind.ParenthesizedExpression:
return visitParenthesizedExpression(node as ParenthesizedExpression, noDestructuringValue);
default:
Debug.failBadSyntaxKind(node);
return visitEachChild(node, visitor, context);
}
}
@@ -87,32 +104,51 @@ namespace ts {
}
function visitObjectLiteralExpression(node: ObjectLiteralExpression): Expression {
// spread elements emit like so:
// non-spread elements are chunked together into object literals, and then all are passed to __assign:
// { a, ...o, b } => __assign({a}, o, {b});
// If the first element is a spread element, then the first argument to __assign is {}:
// { ...o, a, b, ...o2 } => __assign({}, o, {a, b}, o2)
if (forEach(node.properties, p => p.kind === SyntaxKind.SpreadAssignment)) {
if (node.transformFlags & TransformFlags.ContainsObjectSpread) {
// spread elements emit like so:
// non-spread elements are chunked together into object literals, and then all are passed to __assign:
// { a, ...o, b } => __assign({a}, o, {b});
// If the first element is a spread element, then the first argument to __assign is {}:
// { ...o, a, b, ...o2 } => __assign({}, o, {a, b}, o2)
const objects = chunkObjectLiteralElements(node.properties);
if (objects.length && objects[0].kind !== SyntaxKind.ObjectLiteralExpression) {
objects.unshift(createObjectLiteral());
}
return aggregateTransformFlags(createCall(createIdentifier("__assign"), undefined, objects));
return createAssignHelper(context, objects);
}
return visitEachChild(node, visitor, context);
}
function visitExpressionStatement(node: ExpressionStatement): ExpressionStatement {
return visitEachChild(node, visitorNoDestructuringValue, context);
}
function visitParenthesizedExpression(node: ParenthesizedExpression, noDestructuringValue: boolean): ParenthesizedExpression {
return visitEachChild(node, noDestructuringValue ? visitorNoDestructuringValue : visitor, context);
}
/**
* Visits a BinaryExpression that contains a destructuring assignment.
*
* @param node A BinaryExpression node.
*/
function visitBinaryExpression(node: BinaryExpression): Expression {
if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.AssertESNext) {
return flattenDestructuringAssignment(context, node, /*needsDestructuringValue*/ true, hoistVariableDeclaration, visitor, /*transformRest*/ true);
function visitBinaryExpression(node: BinaryExpression, noDestructuringValue: boolean): Expression {
if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.ContainsObjectRest) {
return flattenDestructuringAssignment(
node,
visitor,
context,
FlattenLevel.ObjectRest,
!noDestructuringValue
);
}
else if (node.operatorToken.kind === SyntaxKind.CommaToken) {
return updateBinary(
node,
visitNode(node.left, visitorNoDestructuringValue, isExpression),
visitNode(node.right, noDestructuringValue ? visitorNoDestructuringValue : visitor, isExpression)
);
}
return visitEachChild(node, visitor, context);
}
@@ -123,154 +159,254 @@ namespace ts {
*/
function visitVariableDeclaration(node: VariableDeclaration): VisitResult<VariableDeclaration> {
// If we are here it is because the name contains a binding pattern with a rest somewhere in it.
if (isBindingPattern(node.name) && node.name.transformFlags & TransformFlags.AssertESNext) {
const result = flattenVariableDestructuring(node, /*value*/ undefined, visitor, /*recordTempVariable*/ undefined, /*transformRest*/ true);
return result;
if (isBindingPattern(node.name) && node.name.transformFlags & TransformFlags.ContainsObjectRest) {
return flattenDestructuringBinding(
node,
visitor,
context,
FlattenLevel.ObjectRest
);
}
return visitEachChild(node, visitor, context);
}
function visitForStatement(node: ForStatement): VisitResult<Statement> {
return updateFor(
node,
visitNode(node.initializer, visitorNoDestructuringValue, isForInitializer),
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitor, isExpression),
visitNode(node.statement, visitor, isStatement)
);
}
function visitVoidExpression(node: VoidExpression) {
return visitEachChild(node, visitorNoDestructuringValue, context);
}
/**
* Visits a ForOfStatement and converts it into a ES2015-compatible ForOfStatement.
*
* @param node A ForOfStatement.
*/
function visitForOfStatement(node: ForOfStatement): VisitResult<Statement> {
// The following ESNext code:
//
// for (let { x, y, ...rest } of expr) { }
//
// should be emitted as
//
// for (var _a of expr) {
// let { x, y } = _a, rest = __rest(_a, ["x", "y"]);
// }
//
// where _a is a temp emitted to capture the RHS.
// When the left hand side is an expression instead of a let declaration,
// the `let` before the `{ x, y }` is not emitted.
// When the left hand side is a let/const, the v is renamed if there is
// another v in scope.
// Note that all assignments to the LHS are emitted in the body, including
// all destructuring.
// Note also that because an extra statement is needed to assign to the LHS,
// for-of bodies are always emitted as blocks.
// for (<init> of <expression>) <statement>
// where <init> is [let] variabledeclarationlist | expression
const initializer = node.initializer;
if (!isRestBindingPattern(initializer) && !isRestAssignment(initializer)) {
return visitEachChild(node, visitor, context);
let leadingStatements: Statement[];
let temp: Identifier;
const initializer = skipParentheses(node.initializer);
if (initializer.transformFlags & TransformFlags.ContainsObjectRest) {
if (isVariableDeclarationList(initializer)) {
temp = createTempVariable(/*recordTempVariable*/ undefined);
const firstDeclaration = firstOrUndefined(initializer.declarations);
const declarations = flattenDestructuringBinding(
firstDeclaration,
visitor,
context,
FlattenLevel.ObjectRest,
temp,
/*doNotRecordTempVariablesInLine*/ false,
/*skipInitializer*/ true,
);
if (some(declarations)) {
const statement = createVariableStatement(
/*modifiers*/ undefined,
updateVariableDeclarationList(initializer, declarations),
/*location*/ initializer
);
leadingStatements = append(leadingStatements, statement);
}
}
else if (isAssignmentPattern(initializer)) {
temp = createTempVariable(/*recordTempVariable*/ undefined);
const expression = flattenDestructuringAssignment(
aggregateTransformFlags(createAssignment(initializer, temp, /*location*/ node.initializer)),
visitor,
context,
FlattenLevel.ObjectRest
);
leadingStatements = append(leadingStatements, createStatement(expression, /*location*/ node.initializer));
}
}
return convertForOf(node, undefined, visitor, noop, context, /*transformRest*/ true);
}
function isRestBindingPattern(initializer: ForInitializer) {
if (isVariableDeclarationList(initializer)) {
const declaration = firstOrUndefined(initializer.declarations);
return declaration && declaration.name &&
declaration.name.kind === SyntaxKind.ObjectBindingPattern &&
!!(declaration.name.transformFlags & TransformFlags.ContainsSpreadExpression);
if (temp) {
const expression = visitNode(node.expression, visitor, isExpression);
const statement = visitNode(node.statement, visitor, isStatement);
const block = isBlock(statement)
? updateBlock(statement, createNodeArray(concatenate(leadingStatements, statement.statements), statement.statements))
: createBlock(append(leadingStatements, statement), statement, /*multiLine*/ true);
return updateForOf(
node,
createVariableDeclarationList(
[
createVariableDeclaration(temp, /*type*/ undefined, /*initializer*/ undefined, node.initializer)
],
node.initializer,
NodeFlags.Let
),
expression,
block
);
}
return false;
}
function isRestAssignment(initializer: ForInitializer) {
return initializer.kind === SyntaxKind.ObjectLiteralExpression &&
initializer.transformFlags & TransformFlags.ContainsSpreadExpression;
return visitEachChild(node, visitor, context);
}
function visitParameter(node: ParameterDeclaration): ParameterDeclaration {
if (isObjectRestParameter(node)) {
if (node.transformFlags & TransformFlags.ContainsObjectRest) {
// Binding patterns are converted into a generated name and are
// evaluated inside the function body.
return setOriginalNode(
createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
getGeneratedNameForNode(node),
/*questionToken*/ undefined,
/*type*/ undefined,
node.initializer,
/*location*/ node
),
/*original*/ node
return updateParameter(
node,
/*decorators*/ undefined,
/*modifiers*/ undefined,
node.dotDotDotToken,
getGeneratedNameForNode(node),
/*type*/ undefined,
visitNode(node.initializer, visitor, isExpression)
);
}
else {
return node;
}
return visitEachChild(node, visitor, context);
}
function isObjectRestParameter(node: ParameterDeclaration) {
return node.name &&
node.name.kind === SyntaxKind.ObjectBindingPattern &&
!!(node.name.transformFlags & TransformFlags.ContainsSpreadExpression);
function visitConstructorDeclaration(node: ConstructorDeclaration) {
return updateConstructor(
node,
/*decorators*/ undefined,
node.modifiers,
visitParameterList(node.parameters, visitor, context),
transformFunctionBody(node)
);
}
function visitFunctionDeclaration(node: FunctionDeclaration): FunctionDeclaration {
const hasRest = forEach(node.parameters, isObjectRestParameter);
const body = hasRest ?
transformFunctionBody(node, visitor, currentSourceFile, context, noop, /*convertObjectRest*/ true) as Block :
visitEachChild(node.body, visitor, context);
function visitGetAccessorDeclaration(node: GetAccessorDeclaration) {
return updateGetAccessor(
node,
/*decorators*/ undefined,
node.modifiers,
visitNode(node.name, visitor, isPropertyName),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node)
);
}
return setOriginalNode(
createFunctionDeclaration(
/*decorators*/ undefined,
node.modifiers,
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
/*type*/ undefined,
body,
/*location*/ node
),
/*original*/ node);
function visitSetAccessorDeclaration(node: SetAccessorDeclaration) {
return updateSetAccessor(
node,
/*decorators*/ undefined,
node.modifiers,
visitNode(node.name, visitor, isPropertyName),
visitParameterList(node.parameters, visitor, context),
transformFunctionBody(node)
);
}
function visitMethodDeclaration(node: MethodDeclaration) {
return updateMethod(
node,
/*decorators*/ undefined,
node.modifiers,
visitNode(node.name, visitor, isPropertyName),
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node)
);
}
function visitFunctionDeclaration(node: FunctionDeclaration) {
return updateFunctionDeclaration(
node,
/*decorators*/ undefined,
node.modifiers,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node)
);
}
function visitArrowFunction(node: ArrowFunction) {
const hasRest = forEach(node.parameters, isObjectRestParameter);
const body = hasRest ?
transformFunctionBody(node, visitor, currentSourceFile, context, noop, /*convertObjectRest*/ true) as Block :
visitEachChild(node.body, visitor, context);
const func = setOriginalNode(
createArrowFunction(
node.modifiers,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
/*type*/ undefined,
node.equalsGreaterThanToken,
body,
/*location*/ node
),
/*original*/ node
return updateArrowFunction(
node,
node.modifiers,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node)
);
setEmitFlags(func, EmitFlags.CapturesThis);
return func;
}
function visitFunctionExpression(node: FunctionExpression): Expression {
const hasRest = forEach(node.parameters, isObjectRestParameter);
const body = hasRest ?
transformFunctionBody(node, visitor, currentSourceFile, context, noop, /*convertObjectRest*/ true) as Block :
visitEachChild(node.body, visitor, context);
return setOriginalNode(
createFunctionExpression(
node.modifiers,
node.asteriskToken,
name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
/*type*/ undefined,
body,
/*location*/ node
),
/*original*/ node
function visitFunctionExpression(node: FunctionExpression) {
return updateFunctionExpression(
node,
node.modifiers,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node)
);
}
function transformFunctionBody(node: FunctionDeclaration | FunctionExpression | ConstructorDeclaration | MethodDeclaration | AccessorDeclaration): FunctionBody;
function transformFunctionBody(node: ArrowFunction): ConciseBody;
function transformFunctionBody(node: FunctionLikeDeclaration): ConciseBody {
resumeLexicalEnvironment();
let leadingStatements: Statement[];
for (const parameter of node.parameters) {
if (parameter.transformFlags & TransformFlags.ContainsObjectRest) {
const temp = getGeneratedNameForNode(parameter);
const declarations = flattenDestructuringBinding(
parameter,
visitor,
context,
FlattenLevel.ObjectRest,
temp,
/*doNotRecordTempVariablesInLine*/ false,
/*skipInitializer*/ true,
);
if (some(declarations)) {
const statement = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(
declarations
)
);
setEmitFlags(statement, EmitFlags.CustomPrologue);
leadingStatements = append(leadingStatements, statement);
}
}
}
const body = visitNode(node.body, visitor, isConciseBody);
const trailingStatements = endLexicalEnvironment();
if (some(leadingStatements) || some(trailingStatements)) {
const block = convertToFunctionBody(body, /*multiLine*/ true);
return updateBlock(block, createNodeArray(concatenate(concatenate(leadingStatements, block.statements), trailingStatements), block.statements));
}
return body;
}
}
const assignHelper: EmitHelper = {
name: "typescript:assign",
scoped: false,
priority: 1,
text: `
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};`
};
export function createAssignHelper(context: TransformationContext, attributesSegments: Expression[]) {
context.requestEmitHelper(assignHelper);
return createCall(
getHelperName("__assign"),
/*typeArguments*/ undefined,
attributesSegments
);
}
}
+132 -34
View File
@@ -227,7 +227,7 @@ namespace ts {
export function transformGenerators(context: TransformationContext) {
const {
startLexicalEnvironment,
resumeLexicalEnvironment,
endLexicalEnvironment,
hoistFunctionDeclaration,
hoistVariableDeclaration,
@@ -291,17 +291,18 @@ namespace ts {
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
if (isDeclarationFile(node)) {
if (isDeclarationFile(node)
|| (node.transformFlags & TransformFlags.ContainsGenerator) === 0) {
return node;
}
if (node.transformFlags & TransformFlags.ContainsGenerator) {
currentSourceFile = node;
node = visitEachChild(node, visitor, context);
currentSourceFile = undefined;
}
currentSourceFile = node;
return node;
const visited = visitEachChild(node, visitor, context);
addEmitHelpers(visited, context.readEmitHelpers());
currentSourceFile = undefined;
return visited;
}
/**
@@ -449,11 +450,11 @@ namespace ts {
node = setOriginalNode(
createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
node.modifiers,
/*asteriskToken*/ undefined,
node.name,
/*typeParameters*/ undefined,
node.parameters,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformGeneratorFunctionBody(node.body),
/*location*/ node
@@ -500,7 +501,7 @@ namespace ts {
/*asteriskToken*/ undefined,
node.name,
/*typeParameters*/ undefined,
node.parameters,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformGeneratorFunctionBody(node.body),
/*location*/ node
@@ -578,7 +579,7 @@ namespace ts {
state = createTempVariable(/*recordTempVariable*/ undefined);
// Build the generator
startLexicalEnvironment();
resumeLexicalEnvironment();
const statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor);
@@ -2597,28 +2598,24 @@ namespace ts {
withBlockStack = undefined;
const buildResult = buildStatements();
return createCall(
createHelperName(currentSourceFile.externalHelpersModuleName, "__generator"),
/*typeArguments*/ undefined,
[
createThis(),
setEmitFlags(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)],
/*type*/ undefined,
createBlock(
buildResult,
/*location*/ undefined,
/*multiLine*/ buildResult.length > 0
)
),
EmitFlags.ReuseTempVariableScope
)
]
return createGeneratorHelper(
context,
setEmitFlags(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)],
/*type*/ undefined,
createBlock(
buildResult,
/*location*/ undefined,
/*multiLine*/ buildResult.length > 0
)
),
EmitFlags.ReuseTempVariableScope
)
);
}
@@ -3094,4 +3091,105 @@ namespace ts {
);
}
}
function createGeneratorHelper(context: TransformationContext, body: FunctionExpression) {
context.requestEmitHelper(generatorHelper);
return createCall(
getHelperName("__generator"),
/*typeArguments*/ undefined,
[createThis(), body]);
}
// The __generator helper is used by down-level transformations to emulate the runtime
// semantics of an ES2015 generator function. When called, this helper returns an
// object that implements the Iterator protocol, in that it has `next`, `return`, and
// `throw` methods that step through the generator when invoked.
//
// parameters:
// thisArg The value to use as the `this` binding for the transformed generator body.
// body A function that acts as the transformed generator body.
//
// variables:
// _ Persistent state for the generator that is shared between the helper and the
// generator body. The state object has the following members:
// sent() - A method that returns or throws the current completion value.
// label - The next point at which to resume evaluation of the generator body.
// trys - A stack of protected regions (try/catch/finally blocks).
// ops - A stack of pending instructions when inside of a finally block.
// f A value indicating whether the generator is executing.
// y An iterator to delegate for a yield*.
// t A temporary variable that holds one of the following values (note that these
// cases do not overlap):
// - The completion value when resuming from a `yield` or `yield*`.
// - The error value for a catch block.
// - The current protected region (array of try/catch/finally/end labels).
// - The verb (`next`, `throw`, or `return` method) to delegate to the expression
// of a `yield*`.
// - The result of evaluating the verb delegated to the expression of a `yield*`.
//
// functions:
// verb(n) Creates a bound callback to the `step` function for opcode `n`.
// step(op) Evaluates opcodes in a generator body until execution is suspended or
// completed.
//
// The __generator helper understands a limited set of instructions:
// 0: next(value?) - Start or resume the generator with the specified value.
// 1: throw(error) - Resume the generator with an exception. If the generator is
// suspended inside of one or more protected regions, evaluates
// any intervening finally blocks between the current label and
// the nearest catch block or function boundary. If uncaught, the
// exception is thrown to the caller.
// 2: return(value?) - Resume the generator as if with a return. If the generator is
// suspended inside of one or more protected regions, evaluates any
// intervening finally blocks.
// 3: break(label) - Jump to the specified label. If the label is outside of the
// current protected region, evaluates any intervening finally
// blocks.
// 4: yield(value?) - Yield execution to the caller with an optional value. When
// resumed, the generator will continue at the next label.
// 5: yield*(value) - Delegates evaluation to the supplied iterator. When
// delegation completes, the generator will continue at the next
// label.
// 6: catch(error) - Handles an exception thrown from within the generator body. If
// the current label is inside of one or more protected regions,
// evaluates any intervening finally blocks between the current
// label and the nearest catch block or function boundary. If
// uncaught, the exception is thrown to the caller.
// 7: endfinally - Ends a finally block, resuming the last instruction prior to
// entering a finally block.
//
// For examples of how these are used, see the comments in ./transformers/generators.ts
const generatorHelper: EmitHelper = {
name: "typescript:generator",
scoped: false,
priority: 6,
text: `
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;
return { next: verb(0), "throw": verb(1), "return": verb(2) };
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};`
};
}
+268 -269
View File
@@ -1,13 +1,13 @@
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/// <reference path="./esnext.ts" />
/*@internal*/
namespace ts {
const entities: Map<number> = createEntitiesMap();
export function transformJsx(context: TransformationContext) {
const compilerOptions = context.getCompilerOptions();
let currentSourceFile: SourceFile;
return transformSourceFile;
/**
@@ -21,18 +21,18 @@ namespace ts {
}
currentSourceFile = node;
node = visitEachChild(node, visitor, context);
const visited = visitEachChild(node, visitor, context);
addEmitHelpers(visited, context.readEmitHelpers());
currentSourceFile = undefined;
return node;
return visited;
}
function visitor(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.Jsx) {
if (node.transformFlags & TransformFlags.ContainsJsx) {
return visitorWorker(node);
}
else if (node.transformFlags & TransformFlags.ContainsJsx) {
return visitEachChild(node, visitor, context);
}
else {
return node;
}
@@ -50,8 +50,7 @@ namespace ts {
return visitJsxExpression(<JsxExpression>node);
default:
Debug.failBadSyntaxKind(node);
return undefined;
return visitEachChild(node, visitor, context);
}
}
@@ -109,8 +108,10 @@ namespace ts {
// Either emit one big object literal (no spread attribs), or
// a call to the __assign helper.
objectProperties = singleOrUndefined(segments)
|| createAssignHelper(currentSourceFile.externalHelpersModuleName, segments);
objectProperties = singleOrUndefined(segments);
if (!objectProperties) {
objectProperties = createAssignHelper(context, segments);
}
}
const element = createExpressionForJsxElement(
@@ -276,261 +277,259 @@ namespace ts {
}
}
function createEntitiesMap(): Map<number> {
return createMap<number>({
"quot": 0x0022,
"amp": 0x0026,
"apos": 0x0027,
"lt": 0x003C,
"gt": 0x003E,
"nbsp": 0x00A0,
"iexcl": 0x00A1,
"cent": 0x00A2,
"pound": 0x00A3,
"curren": 0x00A4,
"yen": 0x00A5,
"brvbar": 0x00A6,
"sect": 0x00A7,
"uml": 0x00A8,
"copy": 0x00A9,
"ordf": 0x00AA,
"laquo": 0x00AB,
"not": 0x00AC,
"shy": 0x00AD,
"reg": 0x00AE,
"macr": 0x00AF,
"deg": 0x00B0,
"plusmn": 0x00B1,
"sup2": 0x00B2,
"sup3": 0x00B3,
"acute": 0x00B4,
"micro": 0x00B5,
"para": 0x00B6,
"middot": 0x00B7,
"cedil": 0x00B8,
"sup1": 0x00B9,
"ordm": 0x00BA,
"raquo": 0x00BB,
"frac14": 0x00BC,
"frac12": 0x00BD,
"frac34": 0x00BE,
"iquest": 0x00BF,
"Agrave": 0x00C0,
"Aacute": 0x00C1,
"Acirc": 0x00C2,
"Atilde": 0x00C3,
"Auml": 0x00C4,
"Aring": 0x00C5,
"AElig": 0x00C6,
"Ccedil": 0x00C7,
"Egrave": 0x00C8,
"Eacute": 0x00C9,
"Ecirc": 0x00CA,
"Euml": 0x00CB,
"Igrave": 0x00CC,
"Iacute": 0x00CD,
"Icirc": 0x00CE,
"Iuml": 0x00CF,
"ETH": 0x00D0,
"Ntilde": 0x00D1,
"Ograve": 0x00D2,
"Oacute": 0x00D3,
"Ocirc": 0x00D4,
"Otilde": 0x00D5,
"Ouml": 0x00D6,
"times": 0x00D7,
"Oslash": 0x00D8,
"Ugrave": 0x00D9,
"Uacute": 0x00DA,
"Ucirc": 0x00DB,
"Uuml": 0x00DC,
"Yacute": 0x00DD,
"THORN": 0x00DE,
"szlig": 0x00DF,
"agrave": 0x00E0,
"aacute": 0x00E1,
"acirc": 0x00E2,
"atilde": 0x00E3,
"auml": 0x00E4,
"aring": 0x00E5,
"aelig": 0x00E6,
"ccedil": 0x00E7,
"egrave": 0x00E8,
"eacute": 0x00E9,
"ecirc": 0x00EA,
"euml": 0x00EB,
"igrave": 0x00EC,
"iacute": 0x00ED,
"icirc": 0x00EE,
"iuml": 0x00EF,
"eth": 0x00F0,
"ntilde": 0x00F1,
"ograve": 0x00F2,
"oacute": 0x00F3,
"ocirc": 0x00F4,
"otilde": 0x00F5,
"ouml": 0x00F6,
"divide": 0x00F7,
"oslash": 0x00F8,
"ugrave": 0x00F9,
"uacute": 0x00FA,
"ucirc": 0x00FB,
"uuml": 0x00FC,
"yacute": 0x00FD,
"thorn": 0x00FE,
"yuml": 0x00FF,
"OElig": 0x0152,
"oelig": 0x0153,
"Scaron": 0x0160,
"scaron": 0x0161,
"Yuml": 0x0178,
"fnof": 0x0192,
"circ": 0x02C6,
"tilde": 0x02DC,
"Alpha": 0x0391,
"Beta": 0x0392,
"Gamma": 0x0393,
"Delta": 0x0394,
"Epsilon": 0x0395,
"Zeta": 0x0396,
"Eta": 0x0397,
"Theta": 0x0398,
"Iota": 0x0399,
"Kappa": 0x039A,
"Lambda": 0x039B,
"Mu": 0x039C,
"Nu": 0x039D,
"Xi": 0x039E,
"Omicron": 0x039F,
"Pi": 0x03A0,
"Rho": 0x03A1,
"Sigma": 0x03A3,
"Tau": 0x03A4,
"Upsilon": 0x03A5,
"Phi": 0x03A6,
"Chi": 0x03A7,
"Psi": 0x03A8,
"Omega": 0x03A9,
"alpha": 0x03B1,
"beta": 0x03B2,
"gamma": 0x03B3,
"delta": 0x03B4,
"epsilon": 0x03B5,
"zeta": 0x03B6,
"eta": 0x03B7,
"theta": 0x03B8,
"iota": 0x03B9,
"kappa": 0x03BA,
"lambda": 0x03BB,
"mu": 0x03BC,
"nu": 0x03BD,
"xi": 0x03BE,
"omicron": 0x03BF,
"pi": 0x03C0,
"rho": 0x03C1,
"sigmaf": 0x03C2,
"sigma": 0x03C3,
"tau": 0x03C4,
"upsilon": 0x03C5,
"phi": 0x03C6,
"chi": 0x03C7,
"psi": 0x03C8,
"omega": 0x03C9,
"thetasym": 0x03D1,
"upsih": 0x03D2,
"piv": 0x03D6,
"ensp": 0x2002,
"emsp": 0x2003,
"thinsp": 0x2009,
"zwnj": 0x200C,
"zwj": 0x200D,
"lrm": 0x200E,
"rlm": 0x200F,
"ndash": 0x2013,
"mdash": 0x2014,
"lsquo": 0x2018,
"rsquo": 0x2019,
"sbquo": 0x201A,
"ldquo": 0x201C,
"rdquo": 0x201D,
"bdquo": 0x201E,
"dagger": 0x2020,
"Dagger": 0x2021,
"bull": 0x2022,
"hellip": 0x2026,
"permil": 0x2030,
"prime": 0x2032,
"Prime": 0x2033,
"lsaquo": 0x2039,
"rsaquo": 0x203A,
"oline": 0x203E,
"frasl": 0x2044,
"euro": 0x20AC,
"image": 0x2111,
"weierp": 0x2118,
"real": 0x211C,
"trade": 0x2122,
"alefsym": 0x2135,
"larr": 0x2190,
"uarr": 0x2191,
"rarr": 0x2192,
"darr": 0x2193,
"harr": 0x2194,
"crarr": 0x21B5,
"lArr": 0x21D0,
"uArr": 0x21D1,
"rArr": 0x21D2,
"dArr": 0x21D3,
"hArr": 0x21D4,
"forall": 0x2200,
"part": 0x2202,
"exist": 0x2203,
"empty": 0x2205,
"nabla": 0x2207,
"isin": 0x2208,
"notin": 0x2209,
"ni": 0x220B,
"prod": 0x220F,
"sum": 0x2211,
"minus": 0x2212,
"lowast": 0x2217,
"radic": 0x221A,
"prop": 0x221D,
"infin": 0x221E,
"ang": 0x2220,
"and": 0x2227,
"or": 0x2228,
"cap": 0x2229,
"cup": 0x222A,
"int": 0x222B,
"there4": 0x2234,
"sim": 0x223C,
"cong": 0x2245,
"asymp": 0x2248,
"ne": 0x2260,
"equiv": 0x2261,
"le": 0x2264,
"ge": 0x2265,
"sub": 0x2282,
"sup": 0x2283,
"nsub": 0x2284,
"sube": 0x2286,
"supe": 0x2287,
"oplus": 0x2295,
"otimes": 0x2297,
"perp": 0x22A5,
"sdot": 0x22C5,
"lceil": 0x2308,
"rceil": 0x2309,
"lfloor": 0x230A,
"rfloor": 0x230B,
"lang": 0x2329,
"rang": 0x232A,
"loz": 0x25CA,
"spades": 0x2660,
"clubs": 0x2663,
"hearts": 0x2665,
"diams": 0x2666
});
}
const entities = createMap<number>({
"quot": 0x0022,
"amp": 0x0026,
"apos": 0x0027,
"lt": 0x003C,
"gt": 0x003E,
"nbsp": 0x00A0,
"iexcl": 0x00A1,
"cent": 0x00A2,
"pound": 0x00A3,
"curren": 0x00A4,
"yen": 0x00A5,
"brvbar": 0x00A6,
"sect": 0x00A7,
"uml": 0x00A8,
"copy": 0x00A9,
"ordf": 0x00AA,
"laquo": 0x00AB,
"not": 0x00AC,
"shy": 0x00AD,
"reg": 0x00AE,
"macr": 0x00AF,
"deg": 0x00B0,
"plusmn": 0x00B1,
"sup2": 0x00B2,
"sup3": 0x00B3,
"acute": 0x00B4,
"micro": 0x00B5,
"para": 0x00B6,
"middot": 0x00B7,
"cedil": 0x00B8,
"sup1": 0x00B9,
"ordm": 0x00BA,
"raquo": 0x00BB,
"frac14": 0x00BC,
"frac12": 0x00BD,
"frac34": 0x00BE,
"iquest": 0x00BF,
"Agrave": 0x00C0,
"Aacute": 0x00C1,
"Acirc": 0x00C2,
"Atilde": 0x00C3,
"Auml": 0x00C4,
"Aring": 0x00C5,
"AElig": 0x00C6,
"Ccedil": 0x00C7,
"Egrave": 0x00C8,
"Eacute": 0x00C9,
"Ecirc": 0x00CA,
"Euml": 0x00CB,
"Igrave": 0x00CC,
"Iacute": 0x00CD,
"Icirc": 0x00CE,
"Iuml": 0x00CF,
"ETH": 0x00D0,
"Ntilde": 0x00D1,
"Ograve": 0x00D2,
"Oacute": 0x00D3,
"Ocirc": 0x00D4,
"Otilde": 0x00D5,
"Ouml": 0x00D6,
"times": 0x00D7,
"Oslash": 0x00D8,
"Ugrave": 0x00D9,
"Uacute": 0x00DA,
"Ucirc": 0x00DB,
"Uuml": 0x00DC,
"Yacute": 0x00DD,
"THORN": 0x00DE,
"szlig": 0x00DF,
"agrave": 0x00E0,
"aacute": 0x00E1,
"acirc": 0x00E2,
"atilde": 0x00E3,
"auml": 0x00E4,
"aring": 0x00E5,
"aelig": 0x00E6,
"ccedil": 0x00E7,
"egrave": 0x00E8,
"eacute": 0x00E9,
"ecirc": 0x00EA,
"euml": 0x00EB,
"igrave": 0x00EC,
"iacute": 0x00ED,
"icirc": 0x00EE,
"iuml": 0x00EF,
"eth": 0x00F0,
"ntilde": 0x00F1,
"ograve": 0x00F2,
"oacute": 0x00F3,
"ocirc": 0x00F4,
"otilde": 0x00F5,
"ouml": 0x00F6,
"divide": 0x00F7,
"oslash": 0x00F8,
"ugrave": 0x00F9,
"uacute": 0x00FA,
"ucirc": 0x00FB,
"uuml": 0x00FC,
"yacute": 0x00FD,
"thorn": 0x00FE,
"yuml": 0x00FF,
"OElig": 0x0152,
"oelig": 0x0153,
"Scaron": 0x0160,
"scaron": 0x0161,
"Yuml": 0x0178,
"fnof": 0x0192,
"circ": 0x02C6,
"tilde": 0x02DC,
"Alpha": 0x0391,
"Beta": 0x0392,
"Gamma": 0x0393,
"Delta": 0x0394,
"Epsilon": 0x0395,
"Zeta": 0x0396,
"Eta": 0x0397,
"Theta": 0x0398,
"Iota": 0x0399,
"Kappa": 0x039A,
"Lambda": 0x039B,
"Mu": 0x039C,
"Nu": 0x039D,
"Xi": 0x039E,
"Omicron": 0x039F,
"Pi": 0x03A0,
"Rho": 0x03A1,
"Sigma": 0x03A3,
"Tau": 0x03A4,
"Upsilon": 0x03A5,
"Phi": 0x03A6,
"Chi": 0x03A7,
"Psi": 0x03A8,
"Omega": 0x03A9,
"alpha": 0x03B1,
"beta": 0x03B2,
"gamma": 0x03B3,
"delta": 0x03B4,
"epsilon": 0x03B5,
"zeta": 0x03B6,
"eta": 0x03B7,
"theta": 0x03B8,
"iota": 0x03B9,
"kappa": 0x03BA,
"lambda": 0x03BB,
"mu": 0x03BC,
"nu": 0x03BD,
"xi": 0x03BE,
"omicron": 0x03BF,
"pi": 0x03C0,
"rho": 0x03C1,
"sigmaf": 0x03C2,
"sigma": 0x03C3,
"tau": 0x03C4,
"upsilon": 0x03C5,
"phi": 0x03C6,
"chi": 0x03C7,
"psi": 0x03C8,
"omega": 0x03C9,
"thetasym": 0x03D1,
"upsih": 0x03D2,
"piv": 0x03D6,
"ensp": 0x2002,
"emsp": 0x2003,
"thinsp": 0x2009,
"zwnj": 0x200C,
"zwj": 0x200D,
"lrm": 0x200E,
"rlm": 0x200F,
"ndash": 0x2013,
"mdash": 0x2014,
"lsquo": 0x2018,
"rsquo": 0x2019,
"sbquo": 0x201A,
"ldquo": 0x201C,
"rdquo": 0x201D,
"bdquo": 0x201E,
"dagger": 0x2020,
"Dagger": 0x2021,
"bull": 0x2022,
"hellip": 0x2026,
"permil": 0x2030,
"prime": 0x2032,
"Prime": 0x2033,
"lsaquo": 0x2039,
"rsaquo": 0x203A,
"oline": 0x203E,
"frasl": 0x2044,
"euro": 0x20AC,
"image": 0x2111,
"weierp": 0x2118,
"real": 0x211C,
"trade": 0x2122,
"alefsym": 0x2135,
"larr": 0x2190,
"uarr": 0x2191,
"rarr": 0x2192,
"darr": 0x2193,
"harr": 0x2194,
"crarr": 0x21B5,
"lArr": 0x21D0,
"uArr": 0x21D1,
"rArr": 0x21D2,
"dArr": 0x21D3,
"hArr": 0x21D4,
"forall": 0x2200,
"part": 0x2202,
"exist": 0x2203,
"empty": 0x2205,
"nabla": 0x2207,
"isin": 0x2208,
"notin": 0x2209,
"ni": 0x220B,
"prod": 0x220F,
"sum": 0x2211,
"minus": 0x2212,
"lowast": 0x2217,
"radic": 0x221A,
"prop": 0x221D,
"infin": 0x221E,
"ang": 0x2220,
"and": 0x2227,
"or": 0x2228,
"cap": 0x2229,
"cup": 0x222A,
"int": 0x222B,
"there4": 0x2234,
"sim": 0x223C,
"cong": 0x2245,
"asymp": 0x2248,
"ne": 0x2260,
"equiv": 0x2261,
"le": 0x2264,
"ge": 0x2265,
"sub": 0x2282,
"sup": 0x2283,
"nsub": 0x2284,
"sube": 0x2286,
"supe": 0x2287,
"oplus": 0x2295,
"otimes": 0x2297,
"perp": 0x22A5,
"sdot": 0x22C5,
"lceil": 0x2308,
"rceil": 0x2309,
"lfloor": 0x230A,
"rfloor": 0x230B,
"lang": 0x2329,
"rang": 0x232A,
"loz": 0x25CA,
"spades": 0x2660,
"clubs": 0x2663,
"hearts": 0x2665,
"diams": 0x2666
});
}
+79 -1
View File
@@ -5,6 +5,14 @@
namespace ts {
export function transformES2015Module(context: TransformationContext) {
const compilerOptions = context.getCompilerOptions();
const previousOnEmitNode = context.onEmitNode;
const previousOnSubstituteNode = context.onSubstituteNode;
context.onEmitNode = onEmitNode;
context.onSubstituteNode = onSubstituteNode;
context.enableEmitNotification(SyntaxKind.SourceFile);
context.enableSubstitution(SyntaxKind.Identifier);
let currentSourceFile: SourceFile;
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
@@ -13,7 +21,27 @@ namespace ts {
}
if (isExternalModule(node) || compilerOptions.isolatedModules) {
return visitEachChild(node, visitor, context);
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(node, compilerOptions);
if (externalHelpersModuleName) {
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, node.statements);
append(statements,
createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
createLiteral(externalHelpersModuleNameText)
)
);
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
return updateSourceFileNode(
node,
createNodeArray(statements, node.statements));
}
else {
return visitEachChild(node, visitor, context);
}
}
return node;
@@ -35,5 +63,55 @@ namespace ts {
// Elide `export=` as it is not legal with --module ES6
return node.isExportEquals ? undefined : node;
}
//
// Emit Notification
//
/**
* Hook for node emit.
*
* @param emitContext A context hint for the emitter.
* @param node The node to emit.
* @param emit A callback used to emit the node in the printer.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
if (isSourceFile(node)) {
currentSourceFile = node;
previousOnEmitNode(emitContext, node, emitCallback);
currentSourceFile = undefined;
}
else {
previousOnEmitNode(emitContext, node, emitCallback);
}
}
//
// Substitutions
//
/**
* Hooks node substitutions.
*
* @param emitContext A context hint for the emitter.
* @param node The node to substitute.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
node = previousOnSubstituteNode(emitContext, node);
if (isIdentifier(node) && emitContext === EmitContext.Expression) {
return substituteExpressionIdentifier(node);
}
return node;
}
function substituteExpressionIdentifier(node: Identifier): Expression {
if (getEmitFlags(node) & EmitFlags.HelperName) {
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile);
if (externalHelpersModuleName) {
return createPropertyAccess(externalHelpersModuleName, node);
}
}
return node;
}
}
}
+41 -9
View File
@@ -19,8 +19,7 @@ namespace ts {
const {
startLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration,
endLexicalEnvironment
} = context;
const compilerOptions = context.getCompilerOptions();
@@ -61,7 +60,7 @@ namespace ts {
}
currentSourceFile = node;
currentModuleInfo = moduleInfoMap[getOriginalNodeId(node)] = collectExternalModuleInfo(node, resolver);
currentModuleInfo = moduleInfoMap[getOriginalNodeId(node)] = collectExternalModuleInfo(node, resolver, compilerOptions);
// Perform the transformation.
const transformModule = transformModuleDelegates[moduleKind] || transformModuleDelegates[ModuleKind.None];
@@ -82,13 +81,14 @@ namespace ts {
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
addRange(statements, endLexicalEnvironment());
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
const updated = updateSourceFileNode(node, createNodeArray(statements, node.statements));
if (currentModuleInfo.hasExportStarsToExportValues) {
setEmitFlags(updated, EmitFlags.EmitExportStar | getEmitFlags(node));
addEmitHelper(updated, exportStarHelper);
}
return updated;
@@ -111,8 +111,7 @@ namespace ts {
* @param node The SourceFile node.
*/
function transformUMDModule(node: SourceFile) {
const define = createIdentifier("define");
setEmitFlags(define, EmitFlags.UMDDefine);
const define = createRawExpression(umdHelper);
return transformAsynchronousModule(node, define, /*moduleName*/ undefined, /*includeNonAmdDependencies*/ false);
}
@@ -257,6 +256,7 @@ namespace ts {
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
// Visit each statement of the module body.
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
// End the lexical environment for the module body
@@ -270,7 +270,7 @@ namespace ts {
if (currentModuleInfo.hasExportStarsToExportValues) {
// If we have any `export * from ...` declarations
// we need to inform the emitter to add the __export helper.
setEmitFlags(body, EmitFlags.EmitExportStar);
addEmitHelper(body, exportStarHelper);
}
return body;
@@ -757,9 +757,12 @@ namespace ts {
*/
function transformInitializedVariable(node: VariableDeclaration): Expression {
if (isBindingPattern(node.name)) {
return flattenVariableDestructuringToExpression(
return flattenDestructuringAssignment(
node,
hoistVariableDeclaration,
/*visitor*/ undefined,
context,
FlattenLevel.All,
/*needsValue*/ false,
createExportExpression
);
}
@@ -1186,6 +1189,14 @@ namespace ts {
* @param node The node to substitute.
*/
function substituteExpressionIdentifier(node: Identifier): Expression {
if (getEmitFlags(node) & EmitFlags.HelperName) {
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile);
if (externalHelpersModuleName) {
return createPropertyAccess(externalHelpersModuleName, node);
}
return node;
}
if (!isGeneratedIdentifier(node) && !isLocalName(node)) {
const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node));
if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) {
@@ -1312,4 +1323,25 @@ namespace ts {
}
}
}
// emit output for the __export helper function
const exportStarHelper: EmitHelper = {
name: "typescript:export-star",
scoped: true,
text: `
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}`
};
// emit output for the UMD helper function.
const umdHelper = `
(function (dependencies, factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports); if (v !== undefined) module.exports = v;
}
else if (typeof define === 'function' && define.amd) {
define(dependencies, factory);
}
})`;
}
+40 -9
View File
@@ -73,7 +73,7 @@ namespace ts {
// see comment to 'substitutePostfixUnaryExpression' for more details
// Collect information about the external module and dependency groups.
moduleInfo = moduleInfoMap[id] = collectExternalModuleInfo(node, resolver);
moduleInfo = moduleInfoMap[id] = collectExternalModuleInfo(node, resolver, compilerOptions);
// Make sure that the name of the 'exports' function does not conflict with
// existing identifiers.
@@ -82,6 +82,7 @@ namespace ts {
// Add the body of the module.
const dependencyGroups = collectDependencyGroups(moduleInfo.externalImports);
const moduleBodyBlock = createSystemModuleBody(node, dependencyGroups);
const moduleBodyFunction = createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
@@ -92,7 +93,7 @@ namespace ts {
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, contextObject)
],
/*type*/ undefined,
createSystemModuleBody(node, dependencyGroups)
moduleBodyBlock
);
// Write the call to `System.register`
@@ -115,7 +116,9 @@ namespace ts {
], node.statements)
);
setEmitFlags(updated, getEmitFlags(node) & ~EmitFlags.EmitEmitHelpers);
if (!(compilerOptions.outFile || compilerOptions.out)) {
moveEmitHelpers(updated, moduleBodyBlock, helper => !helper.scoped);
}
if (noSubstitution) {
noSubstitutionMap[id] = noSubstitution;
@@ -236,6 +239,9 @@ namespace ts {
)
);
// Visit the synthetic external helpers import declaration if present
visitNode(moduleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true);
// Visit the statements of the source file, emitting any transformations into
// the `executeStatements` array. We do this *before* we fill the `setters` array
// as we both emit transformations as well as aggregate some data used when creating
@@ -280,9 +286,7 @@ namespace ts {
)
);
const body = createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
setEmitFlags(body, EmitFlags.EmitEmitHelpers);
return body;
return createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
}
/**
@@ -394,7 +398,13 @@ namespace ts {
if (localNames) {
condition = createLogicalAnd(
condition,
createLogicalNot(createHasOwnProperty(localNames, n))
createLogicalNot(
createCall(
createPropertyAccess(localNames, "hasOwnProperty"),
/*typeArguments*/ undefined,
[n]
)
)
);
}
@@ -808,7 +818,14 @@ namespace ts {
function transformInitializedVariable(node: VariableDeclaration, isExportedDeclaration: boolean): Expression {
const createAssignment = isExportedDeclaration ? createExportedVariableAssignment : createNonExportedVariableAssignment;
return isBindingPattern(node.name)
? flattenVariableDestructuringToExpression(node, hoistVariableDeclaration, createAssignment, destructuringVisitor)
? flattenDestructuringAssignment(
node,
destructuringVisitor,
context,
FlattenLevel.All,
/*needsValue*/ false,
createAssignment
)
: createAssignment(node.name, visitNode(node.initializer, destructuringVisitor, isExpression));
}
@@ -1459,7 +1476,13 @@ namespace ts {
*/
function visitDestructuringAssignment(node: DestructuringAssignment): VisitResult<Expression> {
if (hasExportedReferenceInDestructuringTarget(node.left)) {
return flattenDestructuringAssignment(context, node, /*needsValue*/ true, hoistVariableDeclaration, destructuringVisitor);
return flattenDestructuringAssignment(
node,
destructuringVisitor,
context,
FlattenLevel.All,
/*needsValue*/ true
);
}
return visitEachChild(node, destructuringVisitor, context);
@@ -1599,6 +1622,14 @@ namespace ts {
* @param node The node to substitute.
*/
function substituteExpressionIdentifier(node: Identifier): Expression {
if (getEmitFlags(node) & EmitFlags.HelperName) {
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile);
if (externalHelpersModuleName) {
return createPropertyAccess(externalHelpersModuleName, node);
}
return node;
}
// When we see an identifier in an expression position that
// points to an imported symbol, we should substitute a qualified
// reference to the imported symbol if one is needed.
+186 -228
View File
@@ -21,6 +21,7 @@ namespace ts {
export function transformTypeScript(context: TransformationContext) {
const {
startLexicalEnvironment,
resumeLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration,
} = context;
@@ -48,7 +49,6 @@ namespace ts {
let currentNamespaceContainerName: Identifier;
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
let currentScopeFirstDeclarationsOfName: Map<Node>;
let currentExternalHelpersModuleName: Identifier;
/**
* Keeps track of whether expression substitution has been enabled for specific edge cases.
@@ -80,7 +80,13 @@ namespace ts {
return node;
}
return visitNode(node, visitor, isSourceFile);
currentSourceFile = node;
const visited = saveStateAndInvoke(node, visitSourceFile);
addEmitHelpers(visited, context.readEmitHelpers());
currentSourceFile = undefined;
return visited;
}
/**
@@ -107,6 +113,32 @@ namespace ts {
return visited;
}
/**
* Performs actions that should always occur immediately before visiting a node.
*
* @param node The node to visit.
*/
function onBeforeVisitNode(node: Node) {
switch (node.kind) {
case SyntaxKind.SourceFile:
case SyntaxKind.CaseBlock:
case SyntaxKind.ModuleBlock:
case SyntaxKind.Block:
currentScope = <SourceFile | CaseBlock | ModuleBlock | Block>node;
currentScopeFirstDeclarationsOfName = undefined;
break;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.FunctionDeclaration:
if (hasModifier(node, ModifierFlags.Ambient)) {
break;
}
recordEmittedDeclarationInScope(node);
break;
}
}
/**
* General-purpose node visitor.
*
@@ -122,10 +154,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitorWorker(node: Node): VisitResult<Node> {
if (node.kind === SyntaxKind.SourceFile) {
return visitSourceFile(<SourceFile>node);
}
else if (node.transformFlags & TransformFlags.TypeScript) {
if (node.transformFlags & TransformFlags.TypeScript) {
// This node is explicitly marked as TypeScript, so we should transform the node.
return visitTypeScript(node);
}
@@ -252,7 +281,6 @@ namespace ts {
return node;
}
/**
* Branching visitor, visits a TypeScript syntax node.
*
@@ -442,78 +470,11 @@ namespace ts {
}
}
/**
* Performs actions that should always occur immediately before visiting a node.
*
* @param node The node to visit.
*/
function onBeforeVisitNode(node: Node) {
switch (node.kind) {
case SyntaxKind.SourceFile:
case SyntaxKind.CaseBlock:
case SyntaxKind.ModuleBlock:
case SyntaxKind.Block:
currentScope = <SourceFile | CaseBlock | ModuleBlock | Block>node;
currentScopeFirstDeclarationsOfName = undefined;
break;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.FunctionDeclaration:
if (hasModifier(node, ModifierFlags.Ambient)) {
break;
}
recordEmittedDeclarationInScope(node);
break;
}
}
function visitSourceFile(node: SourceFile) {
currentSourceFile = node;
// ensure "use strict" is emitted in all scenarios in alwaysStrict mode
// There is no need to emit "use strict" in the following cases:
// 1. The file is an external module and target is es2015 or higher
// or 2. The file is an external module and module-kind is es6 or es2015 as such value is not allowed when targeting es5 or lower
if (compilerOptions.alwaysStrict &&
!(isExternalModule(node) && (compilerOptions.target >= ScriptTarget.ES2015 || compilerOptions.module === ModuleKind.ES2015))) {
node = ensureUseStrict(node);
}
// If the source file requires any helpers and is an external module, and
// the importHelpers compiler option is enabled, emit a synthesized import
// statement for the helpers library.
if (node.flags & NodeFlags.EmitHelperFlags
&& compilerOptions.importHelpers
&& (isExternalModule(node) || compilerOptions.isolatedModules)) {
startLexicalEnvironment();
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ false, visitor);
const externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText);
const externalHelpersModuleImport = createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
createLiteral(externalHelpersModuleNameText));
externalHelpersModuleImport.parent = node;
externalHelpersModuleImport.flags &= ~NodeFlags.Synthesized;
statements.push(externalHelpersModuleImport);
currentExternalHelpersModuleName = externalHelpersModuleName;
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
addRange(statements, endLexicalEnvironment());
currentExternalHelpersModuleName = undefined;
node = updateSourceFileNode(node, createNodeArray(statements, node.statements));
node.externalHelpersModuleName = externalHelpersModuleName;
}
else {
node = visitEachChild(node, sourceElementVisitor, context);
}
setEmitFlags(node, EmitFlags.EmitEmitHelpers | getEmitFlags(node));
return node;
const alwaysStrict = compilerOptions.alwaysStrict && !(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
return updateSourceFileNode(
node,
visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict));
}
/**
@@ -885,9 +846,8 @@ namespace ts {
// downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array.
// Instead, we'll avoid using a rest parameter and spread into the super call as
// 'super(...arguments)' instead of 'super(...args)', as you can see in "transformConstructorBody".
return constructor
? visitNodes(constructor.parameters, visitor, isParameter)
: <ParameterDeclaration[]>[];
return visitParameterList(constructor && constructor.parameters, visitor, context)
|| <ParameterDeclaration[]>[];
}
/**
@@ -902,8 +862,7 @@ namespace ts {
const statements: Statement[] = [];
let indexOfFirstStatement = 0;
// The body of a constructor is a new lexical environment
startLexicalEnvironment();
resumeLexicalEnvironment();
if (constructor) {
indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements);
@@ -959,15 +918,13 @@ namespace ts {
// End the lexical environment.
addRange(statements, endLexicalEnvironment());
return setMultiLine(
createBlock(
createNodeArray(
statements,
/*location*/ constructor ? constructor.body.statements : node.members
),
/*location*/ constructor ? constructor.body : /*location*/ undefined
return createBlock(
createNodeArray(
statements,
/*location*/ constructor ? constructor.body.statements : node.members
),
true
/*location*/ constructor ? constructor.body : /*location*/ undefined,
/*multiLine*/ true
);
}
@@ -1425,7 +1382,7 @@ namespace ts {
: undefined;
const helper = createDecorateHelper(
currentExternalHelpersModuleName,
context,
decoratorExpressions,
prefix,
memberName,
@@ -1463,7 +1420,7 @@ namespace ts {
const classAlias = classAliases && classAliases[getOriginalNodeId(node)];
const localName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true);
const decorate = createDecorateHelper(currentExternalHelpersModuleName, decoratorExpressions, localName);
const decorate = createDecorateHelper(context, decoratorExpressions, localName);
const expression = createAssignment(localName, classAlias ? createAssignment(classAlias, decorate) : decorate);
setEmitFlags(expression, EmitFlags.NoComments);
setSourceMapRange(expression, moveRangePastDecorators(node));
@@ -1491,7 +1448,7 @@ namespace ts {
expressions = [];
for (const decorator of decorators) {
const helper = createParamHelper(
currentExternalHelpersModuleName,
context,
transformDecorator(decorator),
parameterOffset,
/*location*/ decorator.expression);
@@ -1521,13 +1478,13 @@ namespace ts {
function addOldTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
if (compilerOptions.emitDecoratorMetadata) {
if (shouldAddTypeMetadata(node)) {
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:type", serializeTypeOfNode(node)));
decoratorExpressions.push(createMetadataHelper(context, "design:type", serializeTypeOfNode(node)));
}
if (shouldAddParamTypesMetadata(node)) {
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:paramtypes", serializeParameterTypesOfNode(node)));
decoratorExpressions.push(createMetadataHelper(context, "design:paramtypes", serializeParameterTypesOfNode(node)));
}
if (shouldAddReturnTypeMetadata(node)) {
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:returntype", serializeReturnTypeOfNode(node)));
decoratorExpressions.push(createMetadataHelper(context, "design:returntype", serializeReturnTypeOfNode(node)));
}
}
}
@@ -1545,7 +1502,7 @@ namespace ts {
(properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node))));
}
if (properties) {
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
}
}
}
@@ -1819,12 +1776,7 @@ namespace ts {
const temp = createTempVariable(hoistVariableDeclaration);
return createLogicalOr(
createLogicalAnd(
createStrictEquality(
createTypeOf(
createAssignment(temp, serialized)
),
createLiteral("function")
),
createTypeCheck(createAssignment(temp, serialized), "function"),
temp
),
createIdentifier("Object")
@@ -1933,13 +1885,8 @@ namespace ts {
*/
function getGlobalSymbolNameWithFallback(): Expression {
return createConditional(
createStrictEquality(
createTypeOf(createIdentifier("Symbol")),
createLiteral("function")
),
createToken(SyntaxKind.QuestionToken),
createTypeCheck(createIdentifier("Symbol"), "function"),
createIdentifier("Symbol"),
createToken(SyntaxKind.ColonToken),
createIdentifier("Object")
);
}
@@ -2063,26 +2010,23 @@ namespace ts {
if (!shouldEmitFunctionLikeDeclaration(node)) {
return undefined;
}
const method = createMethod(
const updated = updateMethod(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
visitPropertyNameOfClassElement(node),
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node),
/*location*/ node
visitFunctionBody(node.body, visitor, context)
);
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setCommentRange(method, node);
setSourceMapRange(method, moveRangePastDecorators(node));
setOriginalNode(method, node);
return method;
if (updated !== node) {
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setCommentRange(updated, node);
setSourceMapRange(updated, moveRangePastDecorators(node));
}
return updated;
}
/**
@@ -2108,24 +2052,22 @@ namespace ts {
if (!shouldEmitAccessorDeclaration(node)) {
return undefined;
}
const accessor = createGetAccessor(
const updated = updateGetAccessor(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
visitPropertyNameOfClassElement(node),
visitNodes(node.parameters, visitor, isParameter),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
node.body ? visitEachChild(node.body, visitor, context) : createBlock([]),
/*location*/ node
visitFunctionBody(node.body, visitor, context) || createBlock([])
);
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setOriginalNode(accessor, node);
setCommentRange(accessor, node);
setSourceMapRange(accessor, moveRangePastDecorators(node));
return accessor;
if (updated !== node) {
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setCommentRange(updated, node);
setSourceMapRange(updated, moveRangePastDecorators(node));
}
return updated;
}
/**
@@ -2141,23 +2083,21 @@ namespace ts {
if (!shouldEmitAccessorDeclaration(node)) {
return undefined;
}
const accessor = createSetAccessor(
const updated = updateSetAccessor(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
visitPropertyNameOfClassElement(node),
visitNodes(node.parameters, visitor, isParameter),
node.body ? visitEachChild(node.body, visitor, context) : createBlock([]),
/*location*/ node
visitParameterList(node.parameters, visitor, context),
visitFunctionBody(node.body, visitor, context) || createBlock([])
);
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setOriginalNode(accessor, node);
setCommentRange(accessor, node);
setSourceMapRange(accessor, moveRangePastDecorators(node));
return accessor;
if (updated !== node) {
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setCommentRange(updated, node);
setSourceMapRange(updated, moveRangePastDecorators(node));
}
return updated;
}
/**
@@ -2174,27 +2114,22 @@ namespace ts {
if (!shouldEmitFunctionLikeDeclaration(node)) {
return createNotEmittedStatement(node);
}
const func = createFunctionDeclaration(
const updated = updateFunctionDeclaration(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node),
/*location*/ node
visitFunctionBody(node.body, visitor, context) || createBlock([])
);
setOriginalNode(func, node);
if (isNamespaceExport(node)) {
const statements: Statement[] = [func];
const statements: Statement[] = [updated];
addExportMemberAssignment(statements, node);
return statements;
}
return func;
return updated;
}
/**
@@ -2209,21 +2144,16 @@ namespace ts {
if (nodeIsMissing(node.body)) {
return createOmittedExpression();
}
const func = createFunctionExpression(
const updated = updateFunctionExpression(
node,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node),
/*location*/ node
visitFunctionBody(node.body, visitor, context)
);
setOriginalNode(func, node);
return func;
return updated;
}
/**
@@ -2232,62 +2162,15 @@ namespace ts {
* - The node has type annotations
*/
function visitArrowFunction(node: ArrowFunction) {
const func = createArrowFunction(
const updated = updateArrowFunction(
node,
visitNodes(node.modifiers, modifierVisitor, isModifier),
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
node.equalsGreaterThanToken,
transformConciseBody(node),
/*location*/ node
visitFunctionBody(node.body, visitor, context)
);
setOriginalNode(func, node);
return func;
}
function transformFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody {
return transformFunctionBodyWorker(node.body);
}
function transformFunctionBodyWorker(body: Block, start = 0) {
const savedCurrentScope = currentScope;
const savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName;
currentScope = body;
currentScopeFirstDeclarationsOfName = createMap<Node>();
startLexicalEnvironment();
const statements = visitNodes(body.statements, visitor, isStatement, start);
const visited = updateBlock(body, statements);
const declarations = endLexicalEnvironment();
currentScope = savedCurrentScope;
currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName;
return mergeFunctionBodyLexicalEnvironment(visited, declarations);
}
function transformConciseBody(node: ArrowFunction): ConciseBody {
return transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ false);
}
function transformConciseBodyWorker(body: Block | Expression, forceBlockFunctionBody: boolean) {
if (isBlock(body)) {
return transformFunctionBodyWorker(body);
}
else {
startLexicalEnvironment();
const visited: Expression | Block = visitNode(body, visitor, isConciseBody);
const declarations = endLexicalEnvironment();
const merged = mergeFunctionBodyLexicalEnvironment(visited, declarations);
if (forceBlockFunctionBody && !isBlock(merged)) {
return createBlock([
createReturn(<Expression>merged)
]);
}
else {
return merged;
}
}
return updated;
}
/**
@@ -2355,11 +2238,13 @@ namespace ts {
function transformInitializedVariable(node: VariableDeclaration): Expression {
const name = node.name;
if (isBindingPattern(name)) {
return flattenVariableDestructuringToExpression(
return flattenDestructuringAssignment(
node,
hoistVariableDeclaration,
createNamespaceExportExpression,
visitor
visitor,
context,
FlattenLevel.All,
/*needsValue*/ false,
createNamespaceExportExpression
);
}
else {
@@ -3359,7 +3244,7 @@ namespace ts {
function trySubstituteNamespaceExportedName(node: Identifier): Expression {
// If this is explicitly a local name, do not substitute.
if (enabledSubstitutions & applicableSubstitutions && !isLocalName(node)) {
if (enabledSubstitutions & applicableSubstitutions && !isGeneratedIdentifier(node) && !isLocalName(node)) {
// If we are nested within a namespace declaration, we may need to qualifiy
// an identifier that is exported from a merged namespace.
const container = resolver.getReferencedExportContainer(node, /*prefixLocals*/ false);
@@ -3414,4 +3299,77 @@ namespace ts {
: undefined;
}
}
const paramHelper: EmitHelper = {
name: "typescript:param",
scoped: false,
priority: 4,
text: `
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};`
};
function createParamHelper(context: TransformationContext, expression: Expression, parameterOffset: number, location?: TextRange) {
context.requestEmitHelper(paramHelper);
return createCall(
getHelperName("__param"),
/*typeArguments*/ undefined,
[
createLiteral(parameterOffset),
expression
],
location
);
}
const metadataHelper: EmitHelper = {
name: "typescript:metadata",
scoped: false,
priority: 3,
text: `
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};`
};
function createMetadataHelper(context: TransformationContext, metadataKey: string, metadataValue: Expression) {
context.requestEmitHelper(metadataHelper);
return createCall(
getHelperName("__metadata"),
/*typeArguments*/ undefined,
[
createLiteral(metadataKey),
metadataValue
]
);
}
const decorateHelper: EmitHelper = {
name: "typescript:decorate",
scoped: false,
priority: 2,
text: `
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};`
};
function createDecorateHelper(context: TransformationContext, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
context.requestEmitHelper(decorateHelper);
const argumentsArray: Expression[] = [];
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true));
argumentsArray.push(target);
if (memberName) {
argumentsArray.push(memberName);
if (descriptor) {
argumentsArray.push(descriptor);
}
}
return createCall(getHelperName("__decorate"), /*typeArguments*/ undefined, argumentsArray, location);
}
}
+266 -95
View File
@@ -369,6 +369,7 @@ namespace ts {
PartiallyEmittedExpression,
MergeDeclarationMarker,
EndOfDeclarationMarker,
RawExpression,
// Enum value count
Count,
@@ -507,6 +508,7 @@ namespace ts {
export interface NodeArray<T extends Node> extends Array<T>, TextRange {
hasTrailingComma?: boolean;
/* @internal */ transformFlags?: TransformFlags;
}
export interface Token<TKind extends SyntaxKind> extends Node {
@@ -578,9 +580,9 @@ namespace ts {
export type EntityName = Identifier | QualifiedName;
export type PropertyName = Identifier | LiteralExpression | ComputedPropertyName;
export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName;
export type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern;
export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern;
export interface Declaration extends Node {
_declarationBrand: any;
@@ -588,7 +590,7 @@ namespace ts {
}
export interface DeclarationStatement extends Declaration, Statement {
name?: Identifier | LiteralExpression;
name?: Identifier | StringLiteral | NumericLiteral;
}
export interface ComputedPropertyName extends Node {
@@ -723,22 +725,20 @@ namespace ts {
name: PropertyName;
}
export interface BindingPattern extends Node {
elements: NodeArray<BindingElement | ArrayBindingElement>;
}
export interface ObjectBindingPattern extends BindingPattern {
export interface ObjectBindingPattern extends Node {
kind: SyntaxKind.ObjectBindingPattern;
elements: NodeArray<BindingElement>;
}
export type ArrayBindingElement = BindingElement | OmittedExpression;
export interface ArrayBindingPattern extends BindingPattern {
export interface ArrayBindingPattern extends Node {
kind: SyntaxKind.ArrayBindingPattern;
elements: NodeArray<ArrayBindingElement>;
}
export type BindingPattern = ObjectBindingPattern | ArrayBindingPattern;
export type ArrayBindingElement = BindingElement | OmittedExpression;
/**
* Several node kinds share function-like features such as a signature,
* a name, and a body. These nodes should extend FunctionLikeDeclaration.
@@ -920,7 +920,7 @@ namespace ts {
export interface StringLiteral extends LiteralExpression {
kind: SyntaxKind.StringLiteral;
/* @internal */ textSourceNode?: Identifier | StringLiteral; // Allows a StringLiteral to get its text from another node (used by transforms).
/* @internal */ textSourceNode?: Identifier | StringLiteral | NumericLiteral; // Allows a StringLiteral to get its text from another node (used by transforms).
}
// Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing.
@@ -1185,20 +1185,64 @@ namespace ts {
right: Expression;
}
export interface AssignmentExpression extends BinaryExpression {
export type AssignmentOperatorToken = Token<AssignmentOperator>;
export interface AssignmentExpression<TOperator extends AssignmentOperatorToken> extends BinaryExpression {
left: LeftHandSideExpression;
operatorToken: Token<SyntaxKind.EqualsToken>;
operatorToken: TOperator;
}
export interface ObjectDestructuringAssignment extends AssignmentExpression {
export interface ObjectDestructuringAssignment extends AssignmentExpression<EqualsToken> {
left: ObjectLiteralExpression;
}
export interface ArrayDestructuringAssignment extends AssignmentExpression {
export interface ArrayDestructuringAssignment extends AssignmentExpression<EqualsToken> {
left: ArrayLiteralExpression;
}
export type DestructuringAssignment = ObjectDestructuringAssignment | ArrayDestructuringAssignment;
export type DestructuringAssignment
= ObjectDestructuringAssignment
| ArrayDestructuringAssignment
;
export type BindingOrAssignmentElement
= VariableDeclaration
| ParameterDeclaration
| BindingElement
| PropertyAssignment // AssignmentProperty
| ShorthandPropertyAssignment // AssignmentProperty
| SpreadAssignment // AssignmentRestProperty
| OmittedExpression // Elision
| SpreadElement // AssignmentRestElement
| ArrayLiteralExpression // ArrayAssignmentPattern
| ObjectLiteralExpression // ObjectAssignmentPattern
| AssignmentExpression<EqualsToken> // AssignmentElement
| Identifier // DestructuringAssignmentTarget
| PropertyAccessExpression // DestructuringAssignmentTarget
| ElementAccessExpression // DestructuringAssignmentTarget
;
export type BindingOrAssignmentElementRestIndicator
= DotDotDotToken // from BindingElement
| SpreadElement // AssignmentRestElement
| SpreadAssignment // AssignmentRestProperty
;
export type BindingOrAssignmentElementTarget = BindingOrAssignmentPattern | Expression;
export type ObjectBindingOrAssignmentPattern
= ObjectBindingPattern
| ObjectLiteralExpression // ObjectAssignmentPattern
;
export type ArrayBindingOrAssignmentPattern
= ArrayBindingPattern
| ArrayLiteralExpression // ArrayAssignmentPattern
;
export type AssignmentPattern = ObjectLiteralExpression | ArrayLiteralExpression;
export type BindingOrAssignmentPattern = ObjectBindingOrAssignmentPattern | ArrayBindingOrAssignmentPattern;
export interface ConditionalExpression extends Expression {
kind: SyntaxKind.ConditionalExpression;
@@ -1480,6 +1524,16 @@ namespace ts {
kind: SyntaxKind.EndOfDeclarationMarker;
}
/**
* Emits a string of raw text in an expression position. Raw text is never transformed, should
* be ES3 compliant, and should have the same precedence as PrimaryExpression.
*/
/* @internal */
export interface RawExpression extends PrimaryExpression {
kind: SyntaxKind.RawExpression;
text: string;
}
/**
* Marks the beginning of a merged transformed declaration.
*/
@@ -1519,6 +1573,11 @@ namespace ts {
expression: Expression;
}
/* @internal */
export interface PrologueDirective extends ExpressionStatement {
expression: StringLiteral;
}
export interface IfStatement extends Statement {
kind: SyntaxKind.IfStatement;
expression: Expression;
@@ -1703,7 +1762,7 @@ namespace ts {
export interface ModuleDeclaration extends DeclarationStatement {
kind: SyntaxKind.ModuleDeclaration;
name: Identifier | LiteralExpression;
name: Identifier | StringLiteral;
body?: ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | Identifier;
}
@@ -1909,7 +1968,7 @@ namespace ts {
export interface JSDocRecordMember extends PropertySignature {
kind: SyntaxKind.JSDocRecordMember;
name: Identifier | LiteralExpression;
name: Identifier | StringLiteral | NumericLiteral;
type?: JSDocType;
}
@@ -2119,8 +2178,6 @@ namespace ts {
/* @internal */ moduleAugmentations: LiteralExpression[];
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
/* @internal */ ambientModuleNames: string[];
// The synthesized identifier for an imported external helpers module.
/* @internal */ externalHelpersModuleName?: Identifier;
}
export interface ScriptReferenceHost {
@@ -2678,7 +2735,7 @@ namespace ts {
resolvedSignature?: Signature; // Cached signature of signature node or call expression
resolvedSymbol?: Symbol; // Cached name resolution result
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate
maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate
enumMemberValue?: number; // Constant value of enum member
isVisible?: boolean; // Is this node visible
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
@@ -3514,46 +3571,45 @@ namespace ts {
// - Flags used to indicate that a node or subtree contains syntax that requires transformation.
TypeScript = 1 << 0,
ContainsTypeScript = 1 << 1,
Jsx = 1 << 2,
ContainsJsx = 1 << 3,
ESNext = 1 << 4,
ContainsESNext = 1 << 5,
ES2017 = 1 << 6,
ContainsES2017 = 1 << 7,
ES2016 = 1 << 8,
ContainsES2016 = 1 << 9,
ES2015 = 1 << 10,
ContainsES2015 = 1 << 11,
Generator = 1 << 12,
ContainsGenerator = 1 << 13,
DestructuringAssignment = 1 << 14,
ContainsDestructuringAssignment = 1 << 15,
ContainsJsx = 1 << 2,
ContainsESNext = 1 << 3,
ContainsES2017 = 1 << 4,
ContainsES2016 = 1 << 5,
ES2015 = 1 << 6,
ContainsES2015 = 1 << 7,
Generator = 1 << 8,
ContainsGenerator = 1 << 9,
DestructuringAssignment = 1 << 10,
ContainsDestructuringAssignment = 1 << 11,
// Markers
// - Flags used to indicate that a subtree contains a specific transformation.
ContainsDecorators = 1 << 16,
ContainsPropertyInitializer = 1 << 17,
ContainsLexicalThis = 1 << 18,
ContainsCapturedLexicalThis = 1 << 19,
ContainsLexicalThisInComputedPropertyName = 1 << 20,
ContainsDefaultValueAssignments = 1 << 21,
ContainsParameterPropertyAssignments = 1 << 22,
ContainsSpreadExpression = 1 << 23,
ContainsComputedPropertyName = 1 << 24,
ContainsBlockScopedBinding = 1 << 25,
ContainsBindingPattern = 1 << 26,
ContainsYield = 1 << 27,
ContainsHoistedDeclarationOrCompletion = 1 << 28,
ContainsDecorators = 1 << 12,
ContainsPropertyInitializer = 1 << 13,
ContainsLexicalThis = 1 << 14,
ContainsCapturedLexicalThis = 1 << 15,
ContainsLexicalThisInComputedPropertyName = 1 << 16,
ContainsDefaultValueAssignments = 1 << 17,
ContainsParameterPropertyAssignments = 1 << 18,
ContainsSpread = 1 << 19,
ContainsObjectSpread = 1 << 20,
ContainsRest = ContainsSpread,
ContainsObjectRest = ContainsObjectSpread,
ContainsComputedPropertyName = 1 << 21,
ContainsBlockScopedBinding = 1 << 22,
ContainsBindingPattern = 1 << 23,
ContainsYield = 1 << 24,
ContainsHoistedDeclarationOrCompletion = 1 << 25,
HasComputedFlags = 1 << 29, // Transform flags have been computed.
// Assertions
// - Bitmasks that are used to assert facts about the syntax of a node and its subtree.
AssertTypeScript = TypeScript | ContainsTypeScript,
AssertJsx = Jsx | ContainsJsx,
AssertESNext = ESNext | ContainsESNext,
AssertES2017 = ES2017 | ContainsES2017,
AssertES2016 = ES2016 | ContainsES2016,
AssertJsx = ContainsJsx,
AssertESNext = ContainsESNext,
AssertES2017 = ContainsES2017,
AssertES2016 = ContainsES2016,
AssertES2015 = ES2015 | ContainsES2015,
AssertGenerator = Generator | ContainsGenerator,
AssertDestructuringAssignment = DestructuringAssignment | ContainsDestructuringAssignment,
@@ -3561,18 +3617,20 @@ 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 | ESNext | ES2017 | ES2016 | ES2015 | 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,
NodeExcludes = TypeScript | ES2015 | DestructuringAssignment | Generator | HasComputedFlags,
ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
ClassExcludes = NodeExcludes | ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments | ContainsLexicalThisInComputedPropertyName,
ModuleExcludes = NodeExcludes | ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
TypeExcludes = ~ContainsTypeScript,
ObjectLiteralExcludes = NodeExcludes | ContainsDecorators | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsSpreadExpression,
VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern,
ParameterExcludes = NodeExcludes | ContainsBindingPattern,
ObjectLiteralExcludes = NodeExcludes | ContainsDecorators | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName | ContainsObjectSpread,
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsSpread,
VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectRest,
ParameterExcludes = NodeExcludes,
CatchClauseExcludes = NodeExcludes | ContainsObjectRest,
BindingPatternExcludes = NodeExcludes | ContainsRest,
// Masks
// - Additional bitmasks
@@ -3582,45 +3640,51 @@ namespace ts {
/* @internal */
export interface EmitNode {
flags?: EmitFlags;
commentRange?: TextRange;
sourceMapRange?: TextRange;
tokenSourceMapRanges?: Map<TextRange>;
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
constantValue?: number;
flags?: EmitFlags; // Flags that customize emit
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
sourceMapRange?: TextRange; // The text range to use when emitting leading or trailing source mappings
tokenSourceMapRanges?: Map<TextRange>; // The text range to use when emitting source mappings for tokens
constantValue?: number; // The constant value of an expression
externalHelpersModuleName?: Identifier; // The local name for an imported helpers module
helpers?: EmitHelper[]; // Emit helpers for the node
}
/* @internal */
export const enum EmitFlags {
EmitEmitHelpers = 1 << 0, // Any emit helpers should be written to this node.
EmitExportStar = 1 << 1, // The export * helper should be written to this node.
EmitSuperHelper = 1 << 2, // Emit the basic _super helper for async methods.
EmitAdvancedSuperHelper = 1 << 3, // Emit the advanced _super helper for async methods.
UMDDefine = 1 << 4, // This node should be replaced with the UMD define helper.
SingleLine = 1 << 5, // The contents of this node should be emitted on a single line.
AdviseOnEmitNode = 1 << 6, // The printer should invoke the onEmitNode callback when printing this node.
NoSubstitution = 1 << 7, // Disables further substitution of an expression.
CapturesThis = 1 << 8, // The function captures a lexical `this`
NoLeadingSourceMap = 1 << 9, // Do not emit a leading source map location for this node.
NoTrailingSourceMap = 1 << 10, // Do not emit a trailing source map location for this node.
SingleLine = 1 << 0, // The contents of this node should be emitted on a single line.
AdviseOnEmitNode = 1 << 1, // The printer should invoke the onEmitNode callback when printing this node.
NoSubstitution = 1 << 2, // Disables further substitution of an expression.
CapturesThis = 1 << 3, // The function captures a lexical `this`
NoLeadingSourceMap = 1 << 4, // Do not emit a leading source map location for this node.
NoTrailingSourceMap = 1 << 5, // Do not emit a trailing source map location for this node.
NoSourceMap = NoLeadingSourceMap | NoTrailingSourceMap, // Do not emit a source map location for this node.
NoNestedSourceMaps = 1 << 11, // Do not emit source map locations for children of this node.
NoTokenLeadingSourceMaps = 1 << 12, // Do not emit leading source map location for token nodes.
NoTokenTrailingSourceMaps = 1 << 13, // Do not emit trailing source map location for token nodes.
NoNestedSourceMaps = 1 << 6, // Do not emit source map locations for children of this node.
NoTokenLeadingSourceMaps = 1 << 7, // Do not emit leading source map location for token nodes.
NoTokenTrailingSourceMaps = 1 << 8, // Do not emit trailing source map location for token nodes.
NoTokenSourceMaps = NoTokenLeadingSourceMaps | NoTokenTrailingSourceMaps, // Do not emit source map locations for tokens of this node.
NoLeadingComments = 1 << 14, // Do not emit leading comments for this node.
NoTrailingComments = 1 << 15, // Do not emit trailing comments for this node.
NoLeadingComments = 1 << 9, // Do not emit leading comments for this node.
NoTrailingComments = 1 << 10, // Do not emit trailing comments for this node.
NoComments = NoLeadingComments | NoTrailingComments, // Do not emit comments for this node.
NoNestedComments = 1 << 16,
ExportName = 1 << 17, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal).
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).
NoIndentation = 1 << 20, // Do not indent the node.
AsyncFunctionBody = 1 << 21,
ReuseTempVariableScope = 1 << 22, // Reuse the existing temp variable scope during emit.
CustomPrologue = 1 << 23, // Treat the statement as if it were a prologue directive (NOTE: Prologue directives are *not* transformed).
NoHoisting = 1 << 24, // Do not hoist this declaration in --module system
HasEndOfDeclarationMarker = 1 << 25, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
NoNestedComments = 1 << 11,
HelperName = 1 << 12,
ExportName = 1 << 13, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal).
LocalName = 1 << 14, // Ensure an export prefix is not added for an identifier that points to an exported declaration.
Indented = 1 << 15, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
NoIndentation = 1 << 16, // Do not indent the node.
AsyncFunctionBody = 1 << 17,
ReuseTempVariableScope = 1 << 18, // Reuse the existing temp variable scope during emit.
CustomPrologue = 1 << 19, // Treat the statement as if it were a prologue directive (NOTE: Prologue directives are *not* transformed).
NoHoisting = 1 << 20, // Do not hoist this declaration in --module system
HasEndOfDeclarationMarker = 1 << 21, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
}
/* @internal */
export interface EmitHelper {
readonly name: string; // A unique name for this helper.
readonly scoped: boolean; // Indicates whether ther helper MUST be emitted in the current scope.
readonly text: string; // ES3-compatible raw script text.
readonly priority?: number; // Helpers with a higher priority are emitted earlier than other helpers on the node.
}
/* @internal */
@@ -3631,16 +3695,123 @@ namespace ts {
Unspecified, // Emitting an otherwise unspecified node
}
/** Additional context provided to `visitEachChild` */
/* @internal */
export interface LexicalEnvironment {
export interface EmitHost extends ScriptReferenceHost {
getSourceFiles(): SourceFile[];
/* @internal */
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
getCommonSourceDirectory(): string;
getCanonicalFileName(fileName: string): string;
getNewLine(): string;
isEmitBlocked(emitFileName: string): boolean;
writeFile: WriteFileCallback;
}
/* @internal */
export interface TransformationContext {
getCompilerOptions(): CompilerOptions;
getEmitResolver(): EmitResolver;
getEmitHost(): EmitHost;
/** Starts a new lexical environment. */
startLexicalEnvironment(): void;
/** Suspends the current lexical environment, usually after visiting a parameter list. */
suspendLexicalEnvironment(): void;
/** Resumes a suspended lexical environment, usually before visiting a function body. */
resumeLexicalEnvironment(): void;
/** Ends a lexical environment, returning any declarations. */
endLexicalEnvironment(): Statement[];
/**
* Hoists a function declaration to the containing scope.
*/
hoistFunctionDeclaration(node: FunctionDeclaration): void;
/**
* Hoists a variable declaration to the containing scope.
*/
hoistVariableDeclaration(node: Identifier): void;
/**
* Records a request for a non-scoped emit helper in the current context.
*/
requestEmitHelper(helper: EmitHelper): void;
/**
* Gets and resets the requested non-scoped emit helpers.
*/
readEmitHelpers(): EmitHelper[] | undefined;
/**
* Enables expression substitutions in the pretty printer for the provided SyntaxKind.
*/
enableSubstitution(kind: SyntaxKind): void;
/**
* Determines whether expression substitutions are enabled for the provided node.
*/
isSubstitutionEnabled(node: Node): boolean;
/**
* Hook used by transformers to substitute expressions just before they
* are emitted by the pretty printer.
*/
onSubstituteNode?: (emitContext: EmitContext, node: Node) => Node;
/**
* Enables before/after emit notifications in the pretty printer for the provided
* SyntaxKind.
*/
enableEmitNotification(kind: SyntaxKind): void;
/**
* Determines whether before/after emit notifications should be raised in the pretty
* printer when it emits a node.
*/
isEmitNotificationEnabled(node: Node): boolean;
/**
* Hook used to allow transformers to capture state before or after
* the printer emits a node.
*/
onEmitNode?: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void;
}
/* @internal */
export interface TransformationResult {
/**
* Gets the transformed source files.
*/
transformed: SourceFile[];
/**
* Emits the substitute for a node, if one is available; otherwise, emits the node.
*
* @param emitContext The current emit context.
* @param node The node to substitute.
* @param emitCallback A callback used to emit the node or its substitute.
*/
emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
/**
* Emits a node with possible notification.
*
* @param emitContext The current emit context.
* @param node The node to emit.
* @param emitCallback A callback used to emit the node.
*/
emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
}
/* @internal */
export type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile;
export interface TextSpan {
start: number;
+87 -178
View File
@@ -28,21 +28,6 @@ namespace ts {
string(): string;
}
export interface EmitHost extends ScriptReferenceHost {
getSourceFiles(): SourceFile[];
/* @internal */
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
getCommonSourceDirectory(): string;
getCanonicalFileName(fileName: string): string;
getNewLine(): string;
isEmitBlocked(emitFileName: string): boolean;
writeFile: WriteFileCallback;
}
// Pool writers to avoid needing to allocate them for every symbol we write.
const stringWriters: StringSymbolWriter[] = [];
export function getSingleLineStringWriter(): StringSymbolWriter {
@@ -493,7 +478,7 @@ namespace ts {
case SyntaxKind.NumericLiteral:
return (<LiteralExpression>name).text;
case SyntaxKind.ComputedPropertyName:
if (isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind)) {
if (isStringOrNumericLiteral((<ComputedPropertyName>name).expression)) {
return (<LiteralExpression>(<ComputedPropertyName>name).expression).text;
}
}
@@ -626,8 +611,9 @@ namespace ts {
return n.kind === SyntaxKind.CallExpression && (<CallExpression>n).expression.kind === SyntaxKind.SuperKeyword;
}
export function isPrologueDirective(node: Node): boolean {
return node.kind === SyntaxKind.ExpressionStatement && (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
export function isPrologueDirective(node: Node): node is PrologueDirective {
return node.kind === SyntaxKind.ExpressionStatement
&& (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
}
export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: SourceFile) {
@@ -1880,8 +1866,10 @@ namespace ts {
return isFunctionLike(node) && hasModifier(node, ModifierFlags.Async) && !isAccessor(node);
}
export function isStringOrNumericLiteral(kind: SyntaxKind): boolean {
return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NumericLiteral;
export function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral {
const kind = node.kind;
return kind === SyntaxKind.StringLiteral
|| kind === SyntaxKind.NumericLiteral;
}
/**
@@ -1897,7 +1885,7 @@ namespace ts {
export function isDynamicName(name: DeclarationName): boolean {
return name.kind === SyntaxKind.ComputedPropertyName &&
!isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind) &&
!isStringOrNumericLiteral((<ComputedPropertyName>name).expression) &&
!isWellKnownSymbolSyntactically((<ComputedPropertyName>name).expression);
}
@@ -1910,7 +1898,7 @@ namespace ts {
return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression);
}
export function getPropertyNameForPropertyNameNode(name: DeclarationName): string {
export function getPropertyNameForPropertyNameNode(name: DeclarationName | ParameterDeclaration): string {
if (name.kind === SyntaxKind.Identifier || name.kind === SyntaxKind.StringLiteral || name.kind === SyntaxKind.NumericLiteral || name.kind === SyntaxKind.Parameter) {
return (<Identifier | LiteralExpression>name).text;
}
@@ -2146,6 +2134,7 @@ namespace ts {
case SyntaxKind.TemplateExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.OmittedExpression:
case SyntaxKind.RawExpression:
return 19;
case SyntaxKind.TaggedTemplateExpression:
@@ -3138,19 +3127,21 @@ namespace ts {
}
}
export function isAssignmentExpression(node: Node): node is AssignmentExpression {
export function isAssignmentExpression(node: Node, excludeCompoundAssignment: true): node is AssignmentExpression<EqualsToken>;
export function isAssignmentExpression(node: Node, excludeCompoundAssignment?: false): node is AssignmentExpression<AssignmentOperatorToken>;
export function isAssignmentExpression(node: Node, excludeCompoundAssignment?: boolean): node is AssignmentExpression<AssignmentOperatorToken> {
return isBinaryExpression(node)
&& isAssignmentOperator(node.operatorToken.kind)
&& (excludeCompoundAssignment
? node.operatorToken.kind === SyntaxKind.EqualsToken
: isAssignmentOperator(node.operatorToken.kind))
&& isLeftHandSideExpression(node.left);
}
export function isDestructuringAssignment(node: Node): node is DestructuringAssignment {
if (isBinaryExpression(node)) {
if (node.operatorToken.kind === SyntaxKind.EqualsToken) {
const kind = node.left.kind;
return kind === SyntaxKind.ObjectLiteralExpression
|| kind === SyntaxKind.ArrayLiteralExpression;
}
if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) {
const kind = node.left.kind;
return kind === SyntaxKind.ObjectLiteralExpression
|| kind === SyntaxKind.ArrayLiteralExpression;
}
return false;
@@ -3568,153 +3559,6 @@ namespace ts {
return positionIsSynthesized(range.pos) ? -1 : skipTrivia(sourceFile.text, range.pos);
}
export interface ExternalModuleInfo {
externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; // imports of other external modules
exportSpecifiers: Map<ExportSpecifier[]>; // export specifiers by name
exportedBindings: Map<Identifier[]>; // exported names of local declarations
exportedNames: Identifier[]; // all exported names local to module
exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
hasExportStarsToExportValues: boolean; // whether this module contains export*
}
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver): ExternalModuleInfo {
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
const exportSpecifiers = createMap<ExportSpecifier[]>();
const exportedBindings = createMap<Identifier[]>();
const uniqueExports = createMap<Identifier>();
let hasExportDefault = false;
let exportEquals: ExportAssignment = undefined;
let hasExportStarsToExportValues = false;
for (const node of sourceFile.statements) {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
// import "mod"
// import x from "mod"
// import * as x from "mod"
// import { x, y } from "mod"
externalImports.push(<ImportDeclaration>node);
break;
case SyntaxKind.ImportEqualsDeclaration:
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference) {
// import x = require("mod")
externalImports.push(<ImportEqualsDeclaration>node);
}
break;
case SyntaxKind.ExportDeclaration:
if ((<ExportDeclaration>node).moduleSpecifier) {
if (!(<ExportDeclaration>node).exportClause) {
// export * from "mod"
externalImports.push(<ExportDeclaration>node);
hasExportStarsToExportValues = true;
}
else {
// export { x, y } from "mod"
externalImports.push(<ExportDeclaration>node);
}
}
else {
// export { x, y }
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
if (!uniqueExports[specifier.name.text]) {
const name = specifier.propertyName || specifier.name;
multiMapAdd(exportSpecifiers, name.text, specifier);
const decl = resolver.getReferencedImportDeclaration(name)
|| resolver.getReferencedValueDeclaration(name);
if (decl) {
multiMapAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
}
uniqueExports[specifier.name.text] = specifier.name;
}
}
}
break;
case SyntaxKind.ExportAssignment:
if ((<ExportAssignment>node).isExportEquals && !exportEquals) {
// export = x
exportEquals = <ExportAssignment>node;
}
break;
case SyntaxKind.VariableStatement:
if (hasModifier(node, ModifierFlags.Export)) {
for (const decl of (<VariableStatement>node).declarationList.declarations) {
collectExportedVariableInfo(decl, uniqueExports);
}
}
break;
case SyntaxKind.FunctionDeclaration:
if (hasModifier(node, ModifierFlags.Export)) {
if (hasModifier(node, ModifierFlags.Default)) {
// export default function() { }
if (!hasExportDefault) {
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<FunctionDeclaration>node));
hasExportDefault = true;
}
}
else {
// export function x() { }
const name = (<FunctionDeclaration>node).name;
if (!uniqueExports[name.text]) {
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports[name.text] = name;
}
}
}
break;
case SyntaxKind.ClassDeclaration:
if (hasModifier(node, ModifierFlags.Export)) {
if (hasModifier(node, ModifierFlags.Default)) {
// export default class { }
if (!hasExportDefault) {
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<ClassDeclaration>node));
hasExportDefault = true;
}
}
else {
// export class x { }
const name = (<ClassDeclaration>node).name;
if (!uniqueExports[name.text]) {
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports[name.text] = name;
}
}
}
break;
}
}
let exportedNames: Identifier[];
for (const key in uniqueExports) {
exportedNames = ts.append(exportedNames, uniqueExports[key]);
}
return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames };
}
function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map<Identifier>) {
if (isBindingPattern(decl.name)) {
for (const element of decl.name.elements) {
if (!isOmittedExpression(element)) {
collectExportedVariableInfo(element, uniqueExports);
}
}
}
else if (!isGeneratedIdentifier(decl.name)) {
if (!uniqueExports[decl.name.text]) {
uniqueExports[decl.name.text] = decl.name;
}
}
}
/**
* Determines whether a name was originally the declaration name of an enum or namespace
* declaration.
@@ -3931,6 +3775,14 @@ namespace ts {
// Binding patterns
export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern {
return node.kind === SyntaxKind.ArrayBindingPattern;
}
export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern {
return node.kind === SyntaxKind.ObjectBindingPattern;
}
export function isBindingPattern(node: Node): node is BindingPattern {
if (node) {
const kind = node.kind;
@@ -3941,6 +3793,12 @@ namespace ts {
return false;
}
export function isAssignmentPattern(node: Node): node is AssignmentPattern {
const kind = node.kind;
return kind === SyntaxKind.ArrayLiteralExpression
|| kind === SyntaxKind.ObjectLiteralExpression;
}
export function isBindingElement(node: Node): node is BindingElement {
return node.kind === SyntaxKind.BindingElement;
}
@@ -3951,6 +3809,55 @@ namespace ts {
|| kind === SyntaxKind.OmittedExpression;
}
/**
* Determines whether the BindingOrAssignmentElement is a BindingElement-like declaration
*/
export function isDeclarationBindingElement(bindingElement: BindingOrAssignmentElement): bindingElement is VariableDeclaration | ParameterDeclaration | BindingElement {
switch (bindingElement.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.BindingElement:
return true;
}
return false;
}
/**
* Determines whether a node is a BindingOrAssignmentPattern
*/
export function isBindingOrAssignmentPattern(node: BindingOrAssignmentElementTarget): node is BindingOrAssignmentPattern {
return isObjectBindingOrAssignmentPattern(node)
|| isArrayBindingOrAssignmentPattern(node);
}
/**
* Determines whether a node is an ObjectBindingOrAssignmentPattern
*/
export function isObjectBindingOrAssignmentPattern(node: BindingOrAssignmentElementTarget): node is ObjectBindingOrAssignmentPattern {
switch (node.kind) {
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ObjectLiteralExpression:
return true;
}
return false;
}
/**
* Determines whether a node is an ArrayBindingOrAssignmentPattern
*/
export function isArrayBindingOrAssignmentPattern(node: BindingOrAssignmentElementTarget): node is ArrayBindingOrAssignmentPattern {
switch (node.kind) {
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.ArrayLiteralExpression:
return true;
}
return false;
}
// Expression
export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression {
@@ -4019,7 +3926,8 @@ namespace ts {
|| kind === SyntaxKind.ThisKeyword
|| kind === SyntaxKind.TrueKeyword
|| kind === SyntaxKind.SuperKeyword
|| kind === SyntaxKind.NonNullExpression;
|| kind === SyntaxKind.NonNullExpression
|| kind === SyntaxKind.RawExpression;
}
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
@@ -4049,6 +3957,7 @@ namespace ts {
|| kind === SyntaxKind.SpreadElement
|| kind === SyntaxKind.AsExpression
|| kind === SyntaxKind.OmittedExpression
|| kind === SyntaxKind.RawExpression
|| isUnaryExpressionKind(kind);
}
+310 -212
View File
@@ -99,20 +99,26 @@ namespace ts {
return node ? f(initial, node) : initial;
}
function reduceNodeArray<T>(nodes: Node[], f: (memo: T, nodes: Node[]) => T, initial: T) {
return nodes ? f(initial, nodes) : initial;
}
/**
* Similar to `reduceLeft`, performs a reduction against each child of a node.
* NOTE: Unlike `forEachChild`, this does *not* visit every node. Only nodes added to the
* `nodeEdgeTraversalMap` above will be visited.
*
* @param node The node containing the children to reduce.
* @param f The callback function
* @param initial The initial value to supply to the reduction.
* @param f The callback function
*/
export function reduceEachChild<T>(node: Node, f: (memo: T, node: Node) => T, initial: T): T {
export function reduceEachChild<T>(node: Node, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: Node[]) => T): T {
if (node === undefined) {
return initial;
}
const reduceNodes: (nodes: Node[], f: (memo: T, node: Node | Node[]) => T, initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft;
const cbNodes = cbNodeArray || cbNode;
const kind = node.kind;
// No need to visit nodes with no children.
@@ -138,127 +144,127 @@ namespace ts {
// Names
case SyntaxKind.ComputedPropertyName:
result = reduceNode((<ComputedPropertyName>node).expression, f, result);
result = reduceNode((<ComputedPropertyName>node).expression, cbNode, result);
break;
// Signature elements
case SyntaxKind.Parameter:
result = reduceLeft((<ParameterDeclaration>node).decorators, f, result);
result = reduceLeft((<ParameterDeclaration>node).modifiers, f, result);
result = reduceNode((<ParameterDeclaration>node).name, f, result);
result = reduceNode((<ParameterDeclaration>node).type, f, result);
result = reduceNode((<ParameterDeclaration>node).initializer, f, result);
result = reduceNodes((<ParameterDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ParameterDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ParameterDeclaration>node).name, cbNode, result);
result = reduceNode((<ParameterDeclaration>node).type, cbNode, result);
result = reduceNode((<ParameterDeclaration>node).initializer, cbNode, result);
break;
case SyntaxKind.Decorator:
result = reduceNode((<Decorator>node).expression, f, result);
result = reduceNode((<Decorator>node).expression, cbNode, result);
break;
// Type member
case SyntaxKind.PropertyDeclaration:
result = reduceLeft((<PropertyDeclaration>node).decorators, f, result);
result = reduceLeft((<PropertyDeclaration>node).modifiers, f, result);
result = reduceNode((<PropertyDeclaration>node).name, f, result);
result = reduceNode((<PropertyDeclaration>node).type, f, result);
result = reduceNode((<PropertyDeclaration>node).initializer, f, result);
result = reduceNodes((<PropertyDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<PropertyDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<PropertyDeclaration>node).name, cbNode, result);
result = reduceNode((<PropertyDeclaration>node).type, cbNode, result);
result = reduceNode((<PropertyDeclaration>node).initializer, cbNode, result);
break;
case SyntaxKind.MethodDeclaration:
result = reduceLeft((<MethodDeclaration>node).decorators, f, result);
result = reduceLeft((<MethodDeclaration>node).modifiers, f, result);
result = reduceNode((<MethodDeclaration>node).name, f, result);
result = reduceLeft((<MethodDeclaration>node).typeParameters, f, result);
result = reduceLeft((<MethodDeclaration>node).parameters, f, result);
result = reduceNode((<MethodDeclaration>node).type, f, result);
result = reduceNode((<MethodDeclaration>node).body, f, result);
result = reduceNodes((<MethodDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<MethodDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<MethodDeclaration>node).name, cbNode, result);
result = reduceNodes((<MethodDeclaration>node).typeParameters, cbNodes, result);
result = reduceNodes((<MethodDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<MethodDeclaration>node).type, cbNode, result);
result = reduceNode((<MethodDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.Constructor:
result = reduceLeft((<ConstructorDeclaration>node).modifiers, f, result);
result = reduceLeft((<ConstructorDeclaration>node).parameters, f, result);
result = reduceNode((<ConstructorDeclaration>node).body, f, result);
result = reduceNodes((<ConstructorDeclaration>node).modifiers, cbNodes, result);
result = reduceNodes((<ConstructorDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<ConstructorDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.GetAccessor:
result = reduceLeft((<GetAccessorDeclaration>node).decorators, f, result);
result = reduceLeft((<GetAccessorDeclaration>node).modifiers, f, result);
result = reduceNode((<GetAccessorDeclaration>node).name, f, result);
result = reduceLeft((<GetAccessorDeclaration>node).parameters, f, result);
result = reduceNode((<GetAccessorDeclaration>node).type, f, result);
result = reduceNode((<GetAccessorDeclaration>node).body, f, result);
result = reduceNodes((<GetAccessorDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<GetAccessorDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).name, cbNode, result);
result = reduceNodes((<GetAccessorDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).type, cbNode, result);
result = reduceNode((<GetAccessorDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.SetAccessor:
result = reduceLeft((<GetAccessorDeclaration>node).decorators, f, result);
result = reduceLeft((<GetAccessorDeclaration>node).modifiers, f, result);
result = reduceNode((<GetAccessorDeclaration>node).name, f, result);
result = reduceLeft((<GetAccessorDeclaration>node).parameters, f, result);
result = reduceNode((<GetAccessorDeclaration>node).body, f, result);
result = reduceNodes((<GetAccessorDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<GetAccessorDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).name, cbNode, result);
result = reduceNodes((<GetAccessorDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).body, cbNode, result);
break;
// Binding patterns
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
result = reduceLeft((<BindingPattern>node).elements, f, result);
result = reduceNodes((<BindingPattern>node).elements, cbNodes, result);
break;
case SyntaxKind.BindingElement:
result = reduceNode((<BindingElement>node).propertyName, f, result);
result = reduceNode((<BindingElement>node).name, f, result);
result = reduceNode((<BindingElement>node).initializer, f, result);
result = reduceNode((<BindingElement>node).propertyName, cbNode, result);
result = reduceNode((<BindingElement>node).name, cbNode, result);
result = reduceNode((<BindingElement>node).initializer, cbNode, result);
break;
// Expression
case SyntaxKind.ArrayLiteralExpression:
result = reduceLeft((<ArrayLiteralExpression>node).elements, f, result);
result = reduceNodes((<ArrayLiteralExpression>node).elements, cbNodes, result);
break;
case SyntaxKind.ObjectLiteralExpression:
result = reduceLeft((<ObjectLiteralExpression>node).properties, f, result);
result = reduceNodes((<ObjectLiteralExpression>node).properties, cbNodes, result);
break;
case SyntaxKind.PropertyAccessExpression:
result = reduceNode((<PropertyAccessExpression>node).expression, f, result);
result = reduceNode((<PropertyAccessExpression>node).name, f, result);
result = reduceNode((<PropertyAccessExpression>node).expression, cbNode, result);
result = reduceNode((<PropertyAccessExpression>node).name, cbNode, result);
break;
case SyntaxKind.ElementAccessExpression:
result = reduceNode((<ElementAccessExpression>node).expression, f, result);
result = reduceNode((<ElementAccessExpression>node).argumentExpression, f, result);
result = reduceNode((<ElementAccessExpression>node).expression, cbNode, result);
result = reduceNode((<ElementAccessExpression>node).argumentExpression, cbNode, result);
break;
case SyntaxKind.CallExpression:
result = reduceNode((<CallExpression>node).expression, f, result);
result = reduceLeft((<CallExpression>node).typeArguments, f, result);
result = reduceLeft((<CallExpression>node).arguments, f, result);
result = reduceNode((<CallExpression>node).expression, cbNode, result);
result = reduceNodes((<CallExpression>node).typeArguments, cbNodes, result);
result = reduceNodes((<CallExpression>node).arguments, cbNodes, result);
break;
case SyntaxKind.NewExpression:
result = reduceNode((<NewExpression>node).expression, f, result);
result = reduceLeft((<NewExpression>node).typeArguments, f, result);
result = reduceLeft((<NewExpression>node).arguments, f, result);
result = reduceNode((<NewExpression>node).expression, cbNode, result);
result = reduceNodes((<NewExpression>node).typeArguments, cbNodes, result);
result = reduceNodes((<NewExpression>node).arguments, cbNodes, result);
break;
case SyntaxKind.TaggedTemplateExpression:
result = reduceNode((<TaggedTemplateExpression>node).tag, f, result);
result = reduceNode((<TaggedTemplateExpression>node).template, f, result);
result = reduceNode((<TaggedTemplateExpression>node).tag, cbNode, result);
result = reduceNode((<TaggedTemplateExpression>node).template, cbNode, result);
break;
case SyntaxKind.FunctionExpression:
result = reduceLeft((<FunctionExpression>node).modifiers, f, result);
result = reduceNode((<FunctionExpression>node).name, f, result);
result = reduceLeft((<FunctionExpression>node).typeParameters, f, result);
result = reduceLeft((<FunctionExpression>node).parameters, f, result);
result = reduceNode((<FunctionExpression>node).type, f, result);
result = reduceNode((<FunctionExpression>node).body, f, result);
result = reduceNodes((<FunctionExpression>node).modifiers, cbNodes, result);
result = reduceNode((<FunctionExpression>node).name, cbNode, result);
result = reduceNodes((<FunctionExpression>node).typeParameters, cbNodes, result);
result = reduceNodes((<FunctionExpression>node).parameters, cbNodes, result);
result = reduceNode((<FunctionExpression>node).type, cbNode, result);
result = reduceNode((<FunctionExpression>node).body, cbNode, result);
break;
case SyntaxKind.ArrowFunction:
result = reduceLeft((<ArrowFunction>node).modifiers, f, result);
result = reduceLeft((<ArrowFunction>node).typeParameters, f, result);
result = reduceLeft((<ArrowFunction>node).parameters, f, result);
result = reduceNode((<ArrowFunction>node).type, f, result);
result = reduceNode((<ArrowFunction>node).body, f, result);
result = reduceNodes((<ArrowFunction>node).modifiers, cbNodes, result);
result = reduceNodes((<ArrowFunction>node).typeParameters, cbNodes, result);
result = reduceNodes((<ArrowFunction>node).parameters, cbNodes, result);
result = reduceNode((<ArrowFunction>node).type, cbNode, result);
result = reduceNode((<ArrowFunction>node).body, cbNode, result);
break;
case SyntaxKind.ParenthesizedExpression:
@@ -269,258 +275,258 @@ namespace ts {
case SyntaxKind.YieldExpression:
case SyntaxKind.SpreadElement:
case SyntaxKind.NonNullExpression:
result = reduceNode((<ParenthesizedExpression | DeleteExpression | TypeOfExpression | VoidExpression | AwaitExpression | YieldExpression | SpreadElement | NonNullExpression>node).expression, f, result);
result = reduceNode((<ParenthesizedExpression | DeleteExpression | TypeOfExpression | VoidExpression | AwaitExpression | YieldExpression | SpreadElement | NonNullExpression>node).expression, cbNode, result);
break;
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
result = reduceNode((<PrefixUnaryExpression | PostfixUnaryExpression>node).operand, f, result);
result = reduceNode((<PrefixUnaryExpression | PostfixUnaryExpression>node).operand, cbNode, result);
break;
case SyntaxKind.BinaryExpression:
result = reduceNode((<BinaryExpression>node).left, f, result);
result = reduceNode((<BinaryExpression>node).right, f, result);
result = reduceNode((<BinaryExpression>node).left, cbNode, result);
result = reduceNode((<BinaryExpression>node).right, cbNode, result);
break;
case SyntaxKind.ConditionalExpression:
result = reduceNode((<ConditionalExpression>node).condition, f, result);
result = reduceNode((<ConditionalExpression>node).whenTrue, f, result);
result = reduceNode((<ConditionalExpression>node).whenFalse, f, result);
result = reduceNode((<ConditionalExpression>node).condition, cbNode, result);
result = reduceNode((<ConditionalExpression>node).whenTrue, cbNode, result);
result = reduceNode((<ConditionalExpression>node).whenFalse, cbNode, result);
break;
case SyntaxKind.TemplateExpression:
result = reduceNode((<TemplateExpression>node).head, f, result);
result = reduceLeft((<TemplateExpression>node).templateSpans, f, result);
result = reduceNode((<TemplateExpression>node).head, cbNode, result);
result = reduceNodes((<TemplateExpression>node).templateSpans, cbNodes, result);
break;
case SyntaxKind.ClassExpression:
result = reduceLeft((<ClassExpression>node).modifiers, f, result);
result = reduceNode((<ClassExpression>node).name, f, result);
result = reduceLeft((<ClassExpression>node).typeParameters, f, result);
result = reduceLeft((<ClassExpression>node).heritageClauses, f, result);
result = reduceLeft((<ClassExpression>node).members, f, result);
result = reduceNodes((<ClassExpression>node).modifiers, cbNodes, result);
result = reduceNode((<ClassExpression>node).name, cbNode, result);
result = reduceNodes((<ClassExpression>node).typeParameters, cbNodes, result);
result = reduceNodes((<ClassExpression>node).heritageClauses, cbNodes, result);
result = reduceNodes((<ClassExpression>node).members, cbNodes, result);
break;
case SyntaxKind.ExpressionWithTypeArguments:
result = reduceNode((<ExpressionWithTypeArguments>node).expression, f, result);
result = reduceLeft((<ExpressionWithTypeArguments>node).typeArguments, f, result);
result = reduceNode((<ExpressionWithTypeArguments>node).expression, cbNode, result);
result = reduceNodes((<ExpressionWithTypeArguments>node).typeArguments, cbNodes, result);
break;
// Misc
case SyntaxKind.TemplateSpan:
result = reduceNode((<TemplateSpan>node).expression, f, result);
result = reduceNode((<TemplateSpan>node).literal, f, result);
result = reduceNode((<TemplateSpan>node).expression, cbNode, result);
result = reduceNode((<TemplateSpan>node).literal, cbNode, result);
break;
// Element
case SyntaxKind.Block:
result = reduceLeft((<Block>node).statements, f, result);
result = reduceNodes((<Block>node).statements, cbNodes, result);
break;
case SyntaxKind.VariableStatement:
result = reduceLeft((<VariableStatement>node).modifiers, f, result);
result = reduceNode((<VariableStatement>node).declarationList, f, result);
result = reduceNodes((<VariableStatement>node).modifiers, cbNodes, result);
result = reduceNode((<VariableStatement>node).declarationList, cbNode, result);
break;
case SyntaxKind.ExpressionStatement:
result = reduceNode((<ExpressionStatement>node).expression, f, result);
result = reduceNode((<ExpressionStatement>node).expression, cbNode, result);
break;
case SyntaxKind.IfStatement:
result = reduceNode((<IfStatement>node).expression, f, result);
result = reduceNode((<IfStatement>node).thenStatement, f, result);
result = reduceNode((<IfStatement>node).elseStatement, f, result);
result = reduceNode((<IfStatement>node).expression, cbNode, result);
result = reduceNode((<IfStatement>node).thenStatement, cbNode, result);
result = reduceNode((<IfStatement>node).elseStatement, cbNode, result);
break;
case SyntaxKind.DoStatement:
result = reduceNode((<DoStatement>node).statement, f, result);
result = reduceNode((<DoStatement>node).expression, f, result);
result = reduceNode((<DoStatement>node).statement, cbNode, result);
result = reduceNode((<DoStatement>node).expression, cbNode, result);
break;
case SyntaxKind.WhileStatement:
case SyntaxKind.WithStatement:
result = reduceNode((<WhileStatement | WithStatement>node).expression, f, result);
result = reduceNode((<WhileStatement | WithStatement>node).statement, f, result);
result = reduceNode((<WhileStatement | WithStatement>node).expression, cbNode, result);
result = reduceNode((<WhileStatement | WithStatement>node).statement, cbNode, result);
break;
case SyntaxKind.ForStatement:
result = reduceNode((<ForStatement>node).initializer, f, result);
result = reduceNode((<ForStatement>node).condition, f, result);
result = reduceNode((<ForStatement>node).incrementor, f, result);
result = reduceNode((<ForStatement>node).statement, f, result);
result = reduceNode((<ForStatement>node).initializer, cbNode, result);
result = reduceNode((<ForStatement>node).condition, cbNode, result);
result = reduceNode((<ForStatement>node).incrementor, cbNode, result);
result = reduceNode((<ForStatement>node).statement, cbNode, result);
break;
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
result = reduceNode((<ForInStatement | ForOfStatement>node).initializer, f, result);
result = reduceNode((<ForInStatement | ForOfStatement>node).expression, f, result);
result = reduceNode((<ForInStatement | ForOfStatement>node).statement, f, result);
result = reduceNode((<ForInStatement | ForOfStatement>node).initializer, cbNode, result);
result = reduceNode((<ForInStatement | ForOfStatement>node).expression, cbNode, result);
result = reduceNode((<ForInStatement | ForOfStatement>node).statement, cbNode, result);
break;
case SyntaxKind.ReturnStatement:
case SyntaxKind.ThrowStatement:
result = reduceNode((<ReturnStatement>node).expression, f, result);
result = reduceNode((<ReturnStatement>node).expression, cbNode, result);
break;
case SyntaxKind.SwitchStatement:
result = reduceNode((<SwitchStatement>node).expression, f, result);
result = reduceNode((<SwitchStatement>node).caseBlock, f, result);
result = reduceNode((<SwitchStatement>node).expression, cbNode, result);
result = reduceNode((<SwitchStatement>node).caseBlock, cbNode, result);
break;
case SyntaxKind.LabeledStatement:
result = reduceNode((<LabeledStatement>node).label, f, result);
result = reduceNode((<LabeledStatement>node).statement, f, result);
result = reduceNode((<LabeledStatement>node).label, cbNode, result);
result = reduceNode((<LabeledStatement>node).statement, cbNode, result);
break;
case SyntaxKind.TryStatement:
result = reduceNode((<TryStatement>node).tryBlock, f, result);
result = reduceNode((<TryStatement>node).catchClause, f, result);
result = reduceNode((<TryStatement>node).finallyBlock, f, result);
result = reduceNode((<TryStatement>node).tryBlock, cbNode, result);
result = reduceNode((<TryStatement>node).catchClause, cbNode, result);
result = reduceNode((<TryStatement>node).finallyBlock, cbNode, result);
break;
case SyntaxKind.VariableDeclaration:
result = reduceNode((<VariableDeclaration>node).name, f, result);
result = reduceNode((<VariableDeclaration>node).type, f, result);
result = reduceNode((<VariableDeclaration>node).initializer, f, result);
result = reduceNode((<VariableDeclaration>node).name, cbNode, result);
result = reduceNode((<VariableDeclaration>node).type, cbNode, result);
result = reduceNode((<VariableDeclaration>node).initializer, cbNode, result);
break;
case SyntaxKind.VariableDeclarationList:
result = reduceLeft((<VariableDeclarationList>node).declarations, f, result);
result = reduceNodes((<VariableDeclarationList>node).declarations, cbNodes, result);
break;
case SyntaxKind.FunctionDeclaration:
result = reduceLeft((<FunctionDeclaration>node).decorators, f, result);
result = reduceLeft((<FunctionDeclaration>node).modifiers, f, result);
result = reduceNode((<FunctionDeclaration>node).name, f, result);
result = reduceLeft((<FunctionDeclaration>node).typeParameters, f, result);
result = reduceLeft((<FunctionDeclaration>node).parameters, f, result);
result = reduceNode((<FunctionDeclaration>node).type, f, result);
result = reduceNode((<FunctionDeclaration>node).body, f, result);
result = reduceNodes((<FunctionDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<FunctionDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<FunctionDeclaration>node).name, cbNode, result);
result = reduceNodes((<FunctionDeclaration>node).typeParameters, cbNodes, result);
result = reduceNodes((<FunctionDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<FunctionDeclaration>node).type, cbNode, result);
result = reduceNode((<FunctionDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.ClassDeclaration:
result = reduceLeft((<ClassDeclaration>node).decorators, f, result);
result = reduceLeft((<ClassDeclaration>node).modifiers, f, result);
result = reduceNode((<ClassDeclaration>node).name, f, result);
result = reduceLeft((<ClassDeclaration>node).typeParameters, f, result);
result = reduceLeft((<ClassDeclaration>node).heritageClauses, f, result);
result = reduceLeft((<ClassDeclaration>node).members, f, result);
result = reduceNodes((<ClassDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ClassDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ClassDeclaration>node).name, cbNode, result);
result = reduceNodes((<ClassDeclaration>node).typeParameters, cbNodes, result);
result = reduceNodes((<ClassDeclaration>node).heritageClauses, cbNodes, result);
result = reduceNodes((<ClassDeclaration>node).members, cbNodes, result);
break;
case SyntaxKind.CaseBlock:
result = reduceLeft((<CaseBlock>node).clauses, f, result);
result = reduceNodes((<CaseBlock>node).clauses, cbNodes, result);
break;
case SyntaxKind.ImportDeclaration:
result = reduceLeft((<ImportDeclaration>node).decorators, f, result);
result = reduceLeft((<ImportDeclaration>node).modifiers, f, result);
result = reduceNode((<ImportDeclaration>node).importClause, f, result);
result = reduceNode((<ImportDeclaration>node).moduleSpecifier, f, result);
result = reduceNodes((<ImportDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ImportDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ImportDeclaration>node).importClause, cbNode, result);
result = reduceNode((<ImportDeclaration>node).moduleSpecifier, cbNode, result);
break;
case SyntaxKind.ImportClause:
result = reduceNode((<ImportClause>node).name, f, result);
result = reduceNode((<ImportClause>node).namedBindings, f, result);
result = reduceNode((<ImportClause>node).name, cbNode, result);
result = reduceNode((<ImportClause>node).namedBindings, cbNode, result);
break;
case SyntaxKind.NamespaceImport:
result = reduceNode((<NamespaceImport>node).name, f, result);
result = reduceNode((<NamespaceImport>node).name, cbNode, result);
break;
case SyntaxKind.NamedImports:
case SyntaxKind.NamedExports:
result = reduceLeft((<NamedImports | NamedExports>node).elements, f, result);
result = reduceNodes((<NamedImports | NamedExports>node).elements, cbNodes, result);
break;
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
result = reduceNode((<ImportSpecifier | ExportSpecifier>node).propertyName, f, result);
result = reduceNode((<ImportSpecifier | ExportSpecifier>node).name, f, result);
result = reduceNode((<ImportSpecifier | ExportSpecifier>node).propertyName, cbNode, result);
result = reduceNode((<ImportSpecifier | ExportSpecifier>node).name, cbNode, result);
break;
case SyntaxKind.ExportAssignment:
result = reduceLeft((<ExportAssignment>node).decorators, f, result);
result = reduceLeft((<ExportAssignment>node).modifiers, f, result);
result = reduceNode((<ExportAssignment>node).expression, f, result);
result = reduceLeft((<ExportAssignment>node).decorators, cbNode, result);
result = reduceLeft((<ExportAssignment>node).modifiers, cbNode, result);
result = reduceNode((<ExportAssignment>node).expression, cbNode, result);
break;
case SyntaxKind.ExportDeclaration:
result = reduceLeft((<ExportDeclaration>node).decorators, f, result);
result = reduceLeft((<ExportDeclaration>node).modifiers, f, result);
result = reduceNode((<ExportDeclaration>node).exportClause, f, result);
result = reduceNode((<ExportDeclaration>node).moduleSpecifier, f, result);
result = reduceLeft((<ExportDeclaration>node).decorators, cbNode, result);
result = reduceLeft((<ExportDeclaration>node).modifiers, cbNode, result);
result = reduceNode((<ExportDeclaration>node).exportClause, cbNode, result);
result = reduceNode((<ExportDeclaration>node).moduleSpecifier, cbNode, result);
break;
// JSX
case SyntaxKind.JsxElement:
result = reduceNode((<JsxElement>node).openingElement, f, result);
result = reduceLeft((<JsxElement>node).children, f, result);
result = reduceNode((<JsxElement>node).closingElement, f, result);
result = reduceNode((<JsxElement>node).openingElement, cbNode, result);
result = reduceLeft((<JsxElement>node).children, cbNode, result);
result = reduceNode((<JsxElement>node).closingElement, cbNode, result);
break;
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).tagName, f, result);
result = reduceLeft((<JsxSelfClosingElement | JsxOpeningElement>node).attributes, f, result);
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).tagName, cbNode, result);
result = reduceNodes((<JsxSelfClosingElement | JsxOpeningElement>node).attributes, cbNodes, result);
break;
case SyntaxKind.JsxClosingElement:
result = reduceNode((<JsxClosingElement>node).tagName, f, result);
result = reduceNode((<JsxClosingElement>node).tagName, cbNode, result);
break;
case SyntaxKind.JsxAttribute:
result = reduceNode((<JsxAttribute>node).name, f, result);
result = reduceNode((<JsxAttribute>node).initializer, f, result);
result = reduceNode((<JsxAttribute>node).name, cbNode, result);
result = reduceNode((<JsxAttribute>node).initializer, cbNode, result);
break;
case SyntaxKind.JsxSpreadAttribute:
result = reduceNode((<JsxSpreadAttribute>node).expression, f, result);
result = reduceNode((<JsxSpreadAttribute>node).expression, cbNode, result);
break;
case SyntaxKind.JsxExpression:
result = reduceNode((<JsxExpression>node).expression, f, result);
result = reduceNode((<JsxExpression>node).expression, cbNode, result);
break;
// Clauses
case SyntaxKind.CaseClause:
result = reduceNode((<CaseClause>node).expression, f, result);
result = reduceNode((<CaseClause>node).expression, cbNode, result);
// fall-through
case SyntaxKind.DefaultClause:
result = reduceLeft((<CaseClause | DefaultClause>node).statements, f, result);
result = reduceNodes((<CaseClause | DefaultClause>node).statements, cbNodes, result);
break;
case SyntaxKind.HeritageClause:
result = reduceLeft((<HeritageClause>node).types, f, result);
result = reduceNodes((<HeritageClause>node).types, cbNodes, result);
break;
case SyntaxKind.CatchClause:
result = reduceNode((<CatchClause>node).variableDeclaration, f, result);
result = reduceNode((<CatchClause>node).block, f, result);
result = reduceNode((<CatchClause>node).variableDeclaration, cbNode, result);
result = reduceNode((<CatchClause>node).block, cbNode, result);
break;
// Property assignments
case SyntaxKind.PropertyAssignment:
result = reduceNode((<PropertyAssignment>node).name, f, result);
result = reduceNode((<PropertyAssignment>node).initializer, f, result);
result = reduceNode((<PropertyAssignment>node).name, cbNode, result);
result = reduceNode((<PropertyAssignment>node).initializer, cbNode, result);
break;
case SyntaxKind.ShorthandPropertyAssignment:
result = reduceNode((<ShorthandPropertyAssignment>node).name, f, result);
result = reduceNode((<ShorthandPropertyAssignment>node).objectAssignmentInitializer, f, result);
result = reduceNode((<ShorthandPropertyAssignment>node).name, cbNode, result);
result = reduceNode((<ShorthandPropertyAssignment>node).objectAssignmentInitializer, cbNode, result);
break;
case SyntaxKind.SpreadAssignment:
result = reduceNode((node as SpreadAssignment).expression, f, result);
result = reduceNode((node as SpreadAssignment).expression, cbNode, result);
break;
// Top-level nodes
case SyntaxKind.SourceFile:
result = reduceLeft((<SourceFile>node).statements, f, result);
result = reduceNodes((<SourceFile>node).statements, cbNodes, result);
break;
case SyntaxKind.PartiallyEmittedExpression:
result = reduceNode((<PartiallyEmittedExpression>node).expression, f, result);
result = reduceNode((<PartiallyEmittedExpression>node).expression, cbNode, result);
break;
default:
@@ -530,8 +536,8 @@ namespace ts {
const value = (<MapLike<any>>node)[edge.name];
if (value !== undefined) {
result = isArray(value)
? reduceLeft(<NodeArray<Node>>value, f, result)
: f(result, <Node>value);
? reduceNodes(<NodeArray<Node>>value, cbNodes, result)
: cbNode(result, <Node>value);
}
}
}
@@ -553,8 +559,8 @@ namespace ts {
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T;
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional: boolean, lift: (node: NodeArray<Node>) => T, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): T;
export function visitNode(node: Node, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: Node[]) => Node, parenthesize?: (node: Node, parentNode: Node) => Node, parentNode?: Node): Node {
if (node === undefined) {
return undefined;
if (node === undefined || visitor === undefined) {
return node;
}
aggregateTransformFlags(node);
@@ -659,6 +665,53 @@ namespace ts {
return updated || nodes;
}
/**
* Starts a new lexical environment and visits a statement list, ending the lexical environment
* and merging hoisted declarations upon completion.
*/
export function visitLexicalEnvironment(statements: NodeArray<Statement>, visitor: (node: Node) => VisitResult<Node>, context: TransformationContext, start?: number, ensureUseStrict?: boolean) {
context.startLexicalEnvironment();
statements = visitNodes(statements, visitor, isStatement, start);
if (ensureUseStrict && !startsWithUseStrict(statements)) {
statements = createNodeArray([createStatement(createLiteral("use strict")), ...statements], statements);
}
const declarations = context.endLexicalEnvironment();
return createNodeArray(concatenate(statements, declarations), statements);
}
/**
* Starts a new lexical environment and visits a parameter list, suspending the lexical
* environment upon completion.
*/
export function visitParameterList(nodes: NodeArray<ParameterDeclaration>, visitor: (node: Node) => VisitResult<Node>, context: TransformationContext) {
context.startLexicalEnvironment();
const updated = visitNodes(nodes, visitor, isParameterDeclaration);
context.suspendLexicalEnvironment();
return updated;
}
/**
* Resumes a suspended lexical environment and visits a function body, ending the lexical
* environment and merging hoisted declarations upon completion.
*/
export function visitFunctionBody(node: FunctionBody, visitor: (node: Node) => VisitResult<Node>, context: TransformationContext): FunctionBody;
/**
* Resumes a suspended lexical environment and visits a concise body, ending the lexical
* environment and merging hoisted declarations upon completion.
*/
export function visitFunctionBody(node: ConciseBody, visitor: (node: Node) => VisitResult<Node>, context: TransformationContext): ConciseBody;
export function visitFunctionBody(node: ConciseBody, visitor: (node: Node) => VisitResult<Node>, context: TransformationContext): ConciseBody {
context.resumeLexicalEnvironment();
const updated = visitNode(node, visitor, isConciseBody);
const declarations = context.endLexicalEnvironment();
if (some(declarations)) {
const block = convertToFunctionBody(updated);
const statements = mergeLexicalEnvironment(block.statements, declarations);
return updateBlock(block, statements);
}
return updated;
}
/**
* Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
*
@@ -666,8 +719,8 @@ namespace ts {
* @param visitor The callback used to visit each child.
* @param context A lexical environment context for the visitor.
*/
export function visitEachChild<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, context: LexicalEnvironment): T;
export function visitEachChild(node: Node, visitor: (node: Node) => VisitResult<Node>, context: LexicalEnvironment): Node {
export function visitEachChild<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, context: TransformationContext): T;
export function visitEachChild(node: Node, visitor: (node: Node) => VisitResult<Node>, context: TransformationContext): Node {
if (node === undefined) {
return undefined;
}
@@ -701,6 +754,7 @@ namespace ts {
return updateParameter(<ParameterDeclaration>node,
visitNodes((<ParameterDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ParameterDeclaration>node).modifiers, visitor, isModifier),
(<ParameterDeclaration>node).dotDotDotToken,
visitNode((<ParameterDeclaration>node).name, visitor, isBindingName),
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode, /*optional*/ true),
visitNode((<ParameterDeclaration>node).initializer, visitor, isExpression, /*optional*/ true));
@@ -720,41 +774,33 @@ namespace ts {
visitNodes((<MethodDeclaration>node).modifiers, visitor, isModifier),
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
visitNodes((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
(context.startLexicalEnvironment(), visitNodes((<MethodDeclaration>node).parameters, visitor, isParameter)),
visitParameterList((<MethodDeclaration>node).parameters, visitor, context),
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode, /*optional*/ true),
mergeFunctionBodyLexicalEnvironment(
visitNode((<MethodDeclaration>node).body, visitor, isFunctionBody, /*optional*/ true),
context.endLexicalEnvironment()));
visitFunctionBody((<MethodDeclaration>node).body, visitor, context));
case SyntaxKind.Constructor:
return updateConstructor(<ConstructorDeclaration>node,
visitNodes((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
(context.startLexicalEnvironment(), visitNodes((<ConstructorDeclaration>node).parameters, visitor, isParameter)),
mergeFunctionBodyLexicalEnvironment(
visitNode((<ConstructorDeclaration>node).body, visitor, isFunctionBody, /*optional*/ true),
context.endLexicalEnvironment()));
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context),
visitFunctionBody((<ConstructorDeclaration>node).body, visitor, context));
case SyntaxKind.GetAccessor:
return updateGetAccessor(<GetAccessorDeclaration>node,
visitNodes((<GetAccessorDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<GetAccessorDeclaration>node).modifiers, visitor, isModifier),
visitNode((<GetAccessorDeclaration>node).name, visitor, isPropertyName),
(context.startLexicalEnvironment(), visitNodes((<GetAccessorDeclaration>node).parameters, visitor, isParameter)),
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context),
visitNode((<GetAccessorDeclaration>node).type, visitor, isTypeNode, /*optional*/ true),
mergeFunctionBodyLexicalEnvironment(
visitNode((<GetAccessorDeclaration>node).body, visitor, isFunctionBody, /*optional*/ true),
context.endLexicalEnvironment()));
visitFunctionBody((<GetAccessorDeclaration>node).body, visitor, context));
case SyntaxKind.SetAccessor:
return updateSetAccessor(<SetAccessorDeclaration>node,
visitNodes((<SetAccessorDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
visitNode((<SetAccessorDeclaration>node).name, visitor, isPropertyName),
(context.startLexicalEnvironment(), visitNodes((<SetAccessorDeclaration>node).parameters, visitor, isParameter)),
mergeFunctionBodyLexicalEnvironment(
visitNode((<SetAccessorDeclaration>node).body, visitor, isFunctionBody, /*optional*/ true),
context.endLexicalEnvironment()));
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context),
visitFunctionBody((<SetAccessorDeclaration>node).body, visitor, context));
// Binding patterns
case SyntaxKind.ObjectBindingPattern:
@@ -767,6 +813,7 @@ namespace ts {
case SyntaxKind.BindingElement:
return updateBindingElement(<BindingElement>node,
(<BindingElement>node).dotDotDotToken,
visitNode((<BindingElement>node).propertyName, visitor, isPropertyName, /*optional*/ true),
visitNode((<BindingElement>node).name, visitor, isBindingName),
visitNode((<BindingElement>node).initializer, visitor, isExpression, /*optional*/ true));
@@ -816,21 +863,17 @@ namespace ts {
visitNodes((<FunctionExpression>node).modifiers, visitor, isModifier),
visitNode((<FunctionExpression>node).name, visitor, isPropertyName),
visitNodes((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
(context.startLexicalEnvironment(), visitNodes((<FunctionExpression>node).parameters, visitor, isParameter)),
visitParameterList((<FunctionExpression>node).parameters, visitor, context),
visitNode((<FunctionExpression>node).type, visitor, isTypeNode, /*optional*/ true),
mergeFunctionBodyLexicalEnvironment(
visitNode((<FunctionExpression>node).body, visitor, isFunctionBody, /*optional*/ true),
context.endLexicalEnvironment()));
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
case SyntaxKind.ArrowFunction:
return updateArrowFunction(<ArrowFunction>node,
visitNodes((<ArrowFunction>node).modifiers, visitor, isModifier),
visitNodes((<ArrowFunction>node).typeParameters, visitor, isTypeParameter),
(context.startLexicalEnvironment(), visitNodes((<ArrowFunction>node).parameters, visitor, isParameter)),
visitParameterList((<ArrowFunction>node).parameters, visitor, context),
visitNode((<ArrowFunction>node).type, visitor, isTypeNode, /*optional*/ true),
mergeFunctionBodyLexicalEnvironment(
visitNode((<ArrowFunction>node).body, visitor, isConciseBody, /*optional*/ true),
context.endLexicalEnvironment()));
visitFunctionBody((<ArrowFunction>node).body, visitor, context));
case SyntaxKind.DeleteExpression:
return updateDelete(<DeleteExpression>node,
@@ -1001,11 +1044,9 @@ namespace ts {
visitNodes((<FunctionDeclaration>node).modifiers, visitor, isModifier),
visitNode((<FunctionDeclaration>node).name, visitor, isPropertyName),
visitNodes((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
(context.startLexicalEnvironment(), visitNodes((<FunctionDeclaration>node).parameters, visitor, isParameter)),
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context),
visitNode((<FunctionDeclaration>node).type, visitor, isTypeNode, /*optional*/ true),
mergeFunctionBodyLexicalEnvironment(
visitNode((<FunctionDeclaration>node).body, visitor, isFunctionBody, /*optional*/ true),
context.endLexicalEnvironment()));
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
case SyntaxKind.ClassDeclaration:
return updateClassDeclaration(<ClassDeclaration>node,
@@ -1137,13 +1178,8 @@ namespace ts {
// Top-level nodes
case SyntaxKind.SourceFile:
context.startLexicalEnvironment();
return updateSourceFileNode(<SourceFile>node,
createNodeArray(
concatenate(
visitNodes((<SourceFile>node).statements, visitor, isStatement),
context.endLexicalEnvironment()),
(<SourceFile>node).statements));
visitLexicalEnvironment((<SourceFile>node).statements, visitor, context));
// Transformation nodes
case SyntaxKind.PartiallyEmittedExpression:
@@ -1177,6 +1213,24 @@ namespace ts {
// return node;
}
/**
* Merges generated lexical declarations into a new statement list.
*/
export function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: Statement[]): NodeArray<Statement>;
/**
* Appends generated lexical declarations to an array of statements.
*/
export function mergeLexicalEnvironment(statements: Statement[], declarations: Statement[]): Statement[];
export function mergeLexicalEnvironment(statements: Statement[], declarations: Statement[]) {
if (!some(declarations)) {
return statements;
}
return isNodeArray(statements)
? createNodeArray(concatenate(statements, declarations), statements)
: addRange(statements, declarations);
}
/**
* Merges generated lexical declarations into the FunctionBody of a non-arrow function-like declaration.
*
@@ -1247,13 +1301,25 @@ namespace ts {
if (node === undefined) {
return TransformFlags.None;
}
else if (node.transformFlags & TransformFlags.HasComputedFlags) {
if (node.transformFlags & TransformFlags.HasComputedFlags) {
return node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind);
}
else {
const subtreeFlags = aggregateTransformFlagsForSubtree(node);
return computeTransformFlagsForNode(node, subtreeFlags);
const subtreeFlags = aggregateTransformFlagsForSubtree(node);
return computeTransformFlagsForNode(node, subtreeFlags);
}
function aggregateTransformFlagsForNodeArray(nodes: NodeArray<Node>): TransformFlags {
if (nodes === undefined) {
return TransformFlags.None;
}
let subtreeFlags = TransformFlags.None;
let nodeArrayFlags = TransformFlags.None;
for (const node of nodes) {
subtreeFlags |= aggregateTransformFlagsForNode(node);
nodeArrayFlags |= node.transformFlags & ~TransformFlags.HasComputedFlags;
}
nodes.transformFlags = nodeArrayFlags | TransformFlags.HasComputedFlags;
return subtreeFlags;
}
/**
@@ -1267,15 +1333,19 @@ namespace ts {
}
// Aggregate the transform flags of each child.
return reduceEachChild(node, aggregateTransformFlagsForChildNode, TransformFlags.None);
return reduceEachChild(node, TransformFlags.None, aggregateTransformFlagsForChildNode, aggregateTransformFlagsForChildNodes);
}
/**
* Aggregates the TransformFlags of a child node with the TransformFlags of its
* siblings.
*/
function aggregateTransformFlagsForChildNode(transformFlags: TransformFlags, child: Node): TransformFlags {
return transformFlags | aggregateTransformFlagsForNode(child);
function aggregateTransformFlagsForChildNode(transformFlags: TransformFlags, node: Node): TransformFlags {
return transformFlags | aggregateTransformFlagsForNode(node);
}
function aggregateTransformFlagsForChildNodes(transformFlags: TransformFlags, nodes: NodeArray<Node>): TransformFlags {
return transformFlags | aggregateTransformFlagsForNodeArray(nodes);
}
export namespace Debug {
@@ -1287,6 +1357,13 @@ namespace ts {
? (node: Node, message?: string) => assert(false, message || "Unexpected node.", () => `Node ${formatSyntaxKind(node.kind)} was unexpected.`)
: noop;
export const assertEachNode = shouldAssert(AssertionLevel.Normal)
? (nodes: Node[], test: (node: Node) => boolean, message?: string) => assert(
test === undefined || every(nodes, test),
message || "Unexpected node.",
() => `Node array did not pass test '${getFunctionName(test)}'.`)
: noop;
export const assertNode = shouldAssert(AssertionLevel.Normal)
? (node: Node, test: (node: Node) => boolean, message?: string) => assert(
test === undefined || test(node),
@@ -1294,6 +1371,27 @@ namespace ts {
() => `Node ${formatSyntaxKind(node.kind)} did not pass test '${getFunctionName(test)}'.`)
: noop;
export const assertOptionalNode = shouldAssert(AssertionLevel.Normal)
? (node: Node, test: (node: Node) => boolean, message?: string) => assert(
test === undefined || node === undefined || test(node),
message || "Unexpected node.",
() => `Node ${formatSyntaxKind(node.kind)} did not pass test '${getFunctionName(test)}'.`)
: noop;
export const assertOptionalToken = shouldAssert(AssertionLevel.Normal)
? (node: Node, kind: SyntaxKind, message?: string) => assert(
kind === undefined || node === undefined || node.kind === kind,
message || "Unexpected node.",
() => `Node ${formatSyntaxKind(node.kind)} was not a '${formatSyntaxKind(kind)}' token.`)
: noop;
export const assertMissingNode = shouldAssert(AssertionLevel.Normal)
? (node: Node, message?: string) => assert(
node === undefined,
message || "Unexpected node.",
() => `Node ${formatSyntaxKind(node.kind)} was unexpected'.`)
: noop;
function getFunctionName(func: Function) {
if (typeof func !== "function") {
return "";
+4
View File
@@ -61,6 +61,10 @@ function createRunner(kind: TestRunnerKind): RunnerBase {
}
}
if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable("NODE_ENV"))) {
Harness.IO.tryEnableSourceMapsForHost();
}
// users can define tests to run in mytest.config that will override cmd line args, otherwise use cmd line args (test.config), otherwise no options
const mytestconfigFileName = "mytest.config";
+1 -1
View File
@@ -1188,7 +1188,7 @@ namespace ts.FindAllReferences {
if (node.name.kind === SyntaxKind.ComputedPropertyName) {
const nameExpression = (<ComputedPropertyName>node.name).expression;
// treat computed property names where expression is string/numeric literal as just string/numeric literal
if (isStringOrNumericLiteral(nameExpression.kind)) {
if (isStringOrNumericLiteral(nameExpression)) {
return (<LiteralExpression>nameExpression).text;
}
return undefined;
+1 -1
View File
@@ -1282,7 +1282,7 @@ namespace ts {
if (isImportOrExportSpecifierName(location)) {
return location.getText();
}
else if (isStringOrNumericLiteral(location.kind) &&
else if (isStringOrNumericLiteral(location) &&
location.parent.kind === SyntaxKind.ComputedPropertyName) {
return (<LiteralExpression>location).text;
}