mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Merge branch 'transforms' into exportTransforms
This commit is contained in:
commit
0409c242af
@ -717,7 +717,7 @@ function runTestsAndWriteOutput(file) {
|
||||
}
|
||||
|
||||
var args = [];
|
||||
args.push("-R", "TAP");
|
||||
args.push("-R", "tap");
|
||||
args.push("--no-colors");
|
||||
args.push("-t", testTimeout);
|
||||
if (tests) {
|
||||
@ -1272,4 +1272,4 @@ function environmentVariableIsEnabled(name) {
|
||||
|
||||
function environmentVariableIsDisabled(name) {
|
||||
return /^(no?|f(alse)?|off|disabled?|0|-)$/.test(process.env[name]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1910,6 +1910,17 @@ namespace ts {
|
||||
// This is so that they can flow through PropertyName transforms unaffected.
|
||||
// Instead, we mark the container as ES6, so that it can properly handle the transform.
|
||||
transformFlags = TransformFlags.ContainsComputedPropertyName;
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
|
||||
// A computed method name like `[this.getName()](x: string) { ... }` needs to
|
||||
// distinguish itself from the normal case of a method body containing `this`:
|
||||
// `this` inside a method doesn't need to be rewritten (the method provides `this`),
|
||||
// whereas `this` inside a computed name *might* need to be rewritten if the class/object
|
||||
// is inside an arrow function:
|
||||
// `_this = this; () => class K { [_this.getName()]() { ... } }`
|
||||
// To make this distinction, use ContainsLexicalThisInComputedPropertyName
|
||||
// instead of ContainsLexicalThis for computed property names
|
||||
transformFlags |= TransformFlags.ContainsLexicalThisInComputedPropertyName;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
@ -1945,6 +1956,11 @@ namespace ts {
|
||||
// is an ES6 node.
|
||||
transformFlags = TransformFlags.AssertES6;
|
||||
}
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
|
||||
// A computed property name containing `this` might need to be rewritten,
|
||||
// so propagate the ContainsLexicalThis flag upward.
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.CallExpression:
|
||||
@ -2256,6 +2272,11 @@ namespace ts {
|
||||
|| hasModifier(node, ModifierFlags.Export)) {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
|
||||
// A computed property name containing `this` might need to be rewritten,
|
||||
// so propagate the ContainsLexicalThis flag upward.
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
}
|
||||
|
||||
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.ClassExcludes);
|
||||
}
|
||||
@ -2272,6 +2293,11 @@ namespace ts {
|
||||
| TransformFlags.ContainsDecorators)) {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
|
||||
// A computed property name containing `this` might need to be rewritten,
|
||||
// so propagate the ContainsLexicalThis flag upward.
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
}
|
||||
|
||||
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.ClassExcludes);
|
||||
}
|
||||
|
||||
@ -1252,7 +1252,18 @@ namespace ts {
|
||||
return (node.expression as StringLiteral).text === "use strict";
|
||||
}
|
||||
|
||||
/**
|
||||
* Add any necessary prologue-directives into target statement-array.
|
||||
* The function needs to be called during each transformation step.
|
||||
* This function needs to be called whenever we transform the statement
|
||||
* list of a source file, namespace, or function-like body.
|
||||
*
|
||||
* @param target: result statements array
|
||||
* @param source: origin statements array
|
||||
* @param ensureUseStrict: boolean determining whether the function need to add prologue-directives
|
||||
*/
|
||||
export function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean): number {
|
||||
Debug.assert(target.length === 0, "PrologueDirectives should be at the first statement in the target statements array");
|
||||
let foundUseStrict = false;
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
if (isPrologueDirective(source[i])) {
|
||||
|
||||
@ -370,16 +370,19 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
else if (isLiteralExpression(propertyName)) {
|
||||
return createElementAccess(
|
||||
expression,
|
||||
getSynthesizedClone(propertyName)
|
||||
);
|
||||
const clone = getSynthesizedClone(propertyName);
|
||||
clone.text = unescapeIdentifier(clone.text);
|
||||
return createElementAccess(expression, clone);
|
||||
}
|
||||
else {
|
||||
return createPropertyAccess(
|
||||
expression,
|
||||
isGeneratedIdentifier(propertyName) ? getSynthesizedClone(propertyName) : createIdentifier(propertyName.text)
|
||||
);
|
||||
if (isGeneratedIdentifier(propertyName)) {
|
||||
const clone = getSynthesizedClone(propertyName);
|
||||
clone.text = unescapeIdentifier(clone.text);
|
||||
return createPropertyAccess(expression, clone);
|
||||
}
|
||||
else {
|
||||
return createPropertyAccess(expression, createIdentifier(unescapeIdentifier(propertyName.text)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1211,7 +1211,15 @@ namespace ts {
|
||||
let statementsLocation: TextRange;
|
||||
|
||||
const statements: Statement[] = [];
|
||||
const body = node.body;
|
||||
let statementOffset: number;
|
||||
|
||||
startLexicalEnvironment();
|
||||
if (isBlock(body)) {
|
||||
// ensureUseStrict is false because no new prologue-directive should be added.
|
||||
// addPrologueDirectives will simply put already-existing directives at the beginning of the target statement-array
|
||||
statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false);
|
||||
}
|
||||
addCaptureThisForNodeIfNeeded(statements, node);
|
||||
addDefaultValueAssignmentsIfNeeded(statements, node);
|
||||
addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false);
|
||||
@ -1221,10 +1229,9 @@ namespace ts {
|
||||
multiLine = true;
|
||||
}
|
||||
|
||||
const body = node.body;
|
||||
if (isBlock(body)) {
|
||||
statementsLocation = body.statements;
|
||||
addRange(statements, visitNodes(body.statements, visitor, isStatement));
|
||||
addRange(statements, visitNodes(body.statements, visitor, isStatement, statementOffset));
|
||||
|
||||
// If the original body was a multi-line block, this must be a multi-line block.
|
||||
if (!multiLine && body.multiLine) {
|
||||
|
||||
@ -34,12 +34,18 @@ namespace ts {
|
||||
return visitImportSpecifier(<ImportSpecifier>node);
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return visitExportAssignment(<ExportAssignment>node);
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return visitExportDeclaration(<ExportDeclaration>node);
|
||||
case SyntaxKind.NamedExports:
|
||||
return visitNamedExports(<NamedExports>node);
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
return visitExportSpecifier(<ExportSpecifier>node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function visitExportAssignment(node: ExportAssignment): ExportDeclaration {
|
||||
function visitExportAssignment(node: ExportAssignment): ExportAssignment {
|
||||
if (node.isExportEquals) {
|
||||
return undefined; // do not emit export equals for ES6
|
||||
}
|
||||
@ -47,6 +53,34 @@ namespace ts {
|
||||
return nodeIsSynthesized(original) || resolver.isValueAliasDeclaration(original) ? node: undefined;
|
||||
}
|
||||
|
||||
function visitExportDeclaration(node: ExportDeclaration): ExportDeclaration {
|
||||
if (!node.exportClause) {
|
||||
return resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined;
|
||||
}
|
||||
if (!resolver.isValueAliasDeclaration(node)) {
|
||||
return undefined;
|
||||
}
|
||||
const newExportClause = visitNode(node.exportClause, visitor, isNamedExports, /*optional*/ true);
|
||||
if (node.exportClause === newExportClause) {
|
||||
return node;
|
||||
}
|
||||
return newExportClause
|
||||
? createExportDeclaration(newExportClause, node.moduleSpecifier)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function visitNamedExports(node: NamedExports): NamedExports {
|
||||
const newExports = visitNodes(node.elements, visitor, isExportSpecifier);
|
||||
if (node.elements === newExports) {
|
||||
return node;
|
||||
}
|
||||
return newExports.length ? createNamedExports(newExports) : undefined;
|
||||
}
|
||||
|
||||
function visitExportSpecifier(node: ExportSpecifier): ExportSpecifier {
|
||||
return resolver.isValueAliasDeclaration(node) ? node : undefined;
|
||||
}
|
||||
|
||||
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): ImportEqualsDeclaration {
|
||||
return !isExternalModuleImportEqualsDeclaration(node) || resolver.isReferencedAliasDeclaration(node) ? node : undefined;
|
||||
}
|
||||
|
||||
@ -358,6 +358,9 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Set emitFlags on the name of the importEqualsDeclaration
|
||||
// This is so the printer will not substitute the identifier
|
||||
setNodeEmitFlags(node.name, NodeEmitFlags.NoSubstitution);
|
||||
const statements: Statement[] = [];
|
||||
if (moduleKind !== ModuleKind.AMD) {
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
@ -672,6 +675,9 @@ namespace ts {
|
||||
function visitClassDeclaration(node: ClassDeclaration): VisitResult<Statement> {
|
||||
const statements: Statement[] = [];
|
||||
const name = node.name || getGeneratedNameForNode(node);
|
||||
// Set emitFlags on the name of the classDeclaration
|
||||
// This is so that when printer will not substitute the identifier
|
||||
setNodeEmitFlags(name, NodeEmitFlags.NoSubstitution);
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
statements.push(
|
||||
createClassDeclaration(
|
||||
@ -804,11 +810,20 @@ namespace ts {
|
||||
else if (declaration.kind === SyntaxKind.ImportSpecifier) {
|
||||
const name = (<ImportSpecifier>declaration).propertyName
|
||||
|| (<ImportSpecifier>declaration).name;
|
||||
return createPropertyAccess(
|
||||
getGeneratedNameForNode(declaration.parent.parent.parent),
|
||||
getSynthesizedClone(name),
|
||||
/*location*/ node
|
||||
);
|
||||
if (name.originalKeywordKind === SyntaxKind.DefaultKeyword && languageVersion <= ScriptTarget.ES3) {
|
||||
return createElementAccess(
|
||||
getGeneratedNameForNode(declaration.parent.parent.parent),
|
||||
createLiteral(name.text),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
else {
|
||||
return createPropertyAccess(
|
||||
getGeneratedNameForNode(declaration.parent.parent.parent),
|
||||
getSynthesizedClone(name),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -840,7 +855,7 @@ namespace ts {
|
||||
|
||||
function createExportAssignment(name: Identifier, value: Expression) {
|
||||
return createAssignment(
|
||||
name.originalKeywordKind && languageVersion === ScriptTarget.ES3
|
||||
name.originalKeywordKind === SyntaxKind.DefaultKeyword && languageVersion === ScriptTarget.ES3
|
||||
? createElementAccess(
|
||||
createIdentifier("exports"),
|
||||
createLiteral(name.text)
|
||||
@ -889,6 +904,9 @@ namespace ts {
|
||||
// Find the name of the module alias, if there is one
|
||||
const importAliasName = getLocalNameForExternalImport(importNode, currentSourceFile);
|
||||
if (includeNonAmdDependencies && importAliasName) {
|
||||
// Set emitFlags on the name of the classDeclaration
|
||||
// This is so that when printer will not substitute the identifier
|
||||
setNodeEmitFlags(importAliasName, NodeEmitFlags.NoSubstitution);
|
||||
aliasedModuleNames.push(externalModuleName);
|
||||
importAliasNames.push(createParameter(importAliasName));
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ namespace ts {
|
||||
startLexicalEnvironment();
|
||||
|
||||
// Add any prologue directives.
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, !compilerOptions.noImplicitUseStrict);
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict);
|
||||
|
||||
// var __moduleName = context_1 && context_1.id;
|
||||
addNode(statements,
|
||||
|
||||
@ -2223,28 +2223,7 @@ namespace ts {
|
||||
|| (isES6ExportedDeclaration(node) && isFirstDeclarationOfKind(node, node.kind));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a leading VariableStatement for an enum or module declaration.
|
||||
*/
|
||||
function addVarForEnumDeclaration(statements: Statement[], node: EnumDeclaration) {
|
||||
// Emit a variable statement for the enum.
|
||||
statements.push(
|
||||
setOriginalNode(
|
||||
createVariableStatement(
|
||||
isES6ExportedDeclaration(node)
|
||||
? visitNodes(node.modifiers, visitor, isModifier)
|
||||
: undefined,
|
||||
[createVariableDeclaration(
|
||||
getDeclarationName(node)
|
||||
)],
|
||||
/*location*/ node
|
||||
),
|
||||
/*original*/ node
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Adds a trailing VariableStatement for an enum or module declaration.
|
||||
*/
|
||||
function addVarForEnumExportedFromNamespace(statements: Statement[], node: EnumDeclaration | ModuleDeclaration) {
|
||||
@ -2274,7 +2253,7 @@ namespace ts {
|
||||
|
||||
const statements: Statement[] = [];
|
||||
if (shouldEmitVarForEnumDeclaration(node)) {
|
||||
addVarForEnumDeclaration(statements, node);
|
||||
addVarForEnumOrModuleDeclaration(statements, node);
|
||||
}
|
||||
|
||||
const localName = getGeneratedNameForNode(node);
|
||||
@ -2411,9 +2390,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a leading VariableStatement for a module declaration.
|
||||
* Adds a leading VariableStatement for a enum or module declaration.
|
||||
*/
|
||||
function addVarForModuleDeclaration(statements: Statement[], node: ModuleDeclaration) {
|
||||
function addVarForEnumOrModuleDeclaration(statements: Statement[], node: ModuleDeclaration | EnumDeclaration) {
|
||||
// Emit a variable statement for the module.
|
||||
statements.push(
|
||||
setOriginalNode(
|
||||
@ -2424,7 +2403,21 @@ namespace ts {
|
||||
[createVariableDeclaration(
|
||||
getDeclarationName(node)
|
||||
)],
|
||||
/*location*/ node
|
||||
// Trailing comments for module declaration should be emitted with function closure instead of variable statement
|
||||
// So do not set the end position for the variable statement node
|
||||
// /** Module comment*/
|
||||
// module m1 {
|
||||
// function foo4Export() {
|
||||
// }
|
||||
// } // trailing comment module
|
||||
// Should emit
|
||||
// /** Module comment*/
|
||||
// var m1;
|
||||
// (function (m1) {
|
||||
// function foo4Export() {
|
||||
// }
|
||||
// })(m1 || (m1 = {})); // trailing comment module
|
||||
/*location*/ { pos: node.pos, end: -1 }
|
||||
),
|
||||
node
|
||||
)
|
||||
@ -2449,7 +2442,7 @@ namespace ts {
|
||||
const statements: Statement[] = [];
|
||||
|
||||
if (shouldEmitVarForModuleDeclaration(node)) {
|
||||
addVarForModuleDeclaration(statements, node);
|
||||
addVarForEnumOrModuleDeclaration(statements, node);
|
||||
}
|
||||
|
||||
const localName = getGeneratedNameForNode(node);
|
||||
|
||||
@ -2830,11 +2830,12 @@ namespace ts {
|
||||
ContainsPropertyInitializer = 1 << 10,
|
||||
ContainsLexicalThis = 1 << 11,
|
||||
ContainsCapturedLexicalThis = 1 << 12,
|
||||
ContainsDefaultValueAssignments = 1 << 13,
|
||||
ContainsParameterPropertyAssignments = 1 << 14,
|
||||
ContainsSpreadElementExpression = 1 << 15,
|
||||
ContainsComputedPropertyName = 1 << 16,
|
||||
ContainsBlockScopedBinding = 1 << 17,
|
||||
ContainsLexicalThisInComputedPropertyName = 1 << 13,
|
||||
ContainsDefaultValueAssignments = 1 << 14,
|
||||
ContainsParameterPropertyAssignments = 1 << 15,
|
||||
ContainsSpreadElementExpression = 1 << 16,
|
||||
ContainsComputedPropertyName = 1 << 17,
|
||||
ContainsBlockScopedBinding = 1 << 18,
|
||||
|
||||
HasComputedFlags = 1 << 31, // Transform flags have been computed.
|
||||
|
||||
@ -2853,10 +2854,10 @@ namespace ts {
|
||||
FunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
|
||||
ConstructorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
|
||||
MethodOrAccessorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
|
||||
ClassExcludes = ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments,
|
||||
ClassExcludes = ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments | ContainsLexicalThisInComputedPropertyName,
|
||||
ModuleExcludes = ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
|
||||
TypeExcludes = ~ContainsTypeScript,
|
||||
ObjectLiteralExcludes = ContainsDecorators | ContainsComputedPropertyName,
|
||||
ObjectLiteralExcludes = ContainsDecorators | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
|
||||
ArrayLiteralOrCallOrNewExcludes = ContainsSpreadElementExpression,
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,8 @@ var C = (function () {
|
||||
var _this = this;
|
||||
(function () {
|
||||
var obj = (_a = {},
|
||||
_a[_this.bar()] = function () { },
|
||||
_a[_this.bar()] = function () { } // needs capture
|
||||
,
|
||||
_a);
|
||||
var _a;
|
||||
});
|
||||
|
||||
@ -38,7 +38,8 @@ var C = (function (_super) {
|
||||
var _this = this;
|
||||
(function () {
|
||||
var obj = (_a = {},
|
||||
_a[_super.prototype.bar.call(_this)] = function () { },
|
||||
_a[_super.prototype.bar.call(_this)] = function () { } // needs capture
|
||||
,
|
||||
_a);
|
||||
var _a;
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user