mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into map5
This commit is contained in:
@@ -3136,6 +3136,7 @@ namespace ts {
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.StaticKeyword:
|
||||
case SyntaxKind.MetaProperty:
|
||||
// These nodes are ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
break;
|
||||
|
||||
+65
-1
@@ -241,6 +241,7 @@ namespace ts {
|
||||
const visitedFlowNodes: FlowNode[] = [];
|
||||
const visitedFlowTypes: FlowType[] = [];
|
||||
const potentialThisCollisions: Node[] = [];
|
||||
const potentialNewTargetCollisions: Node[] = [];
|
||||
const awaitedTypeStack: number[] = [];
|
||||
|
||||
const diagnostics = createDiagnosticCollection();
|
||||
@@ -10368,6 +10369,7 @@ namespace ts {
|
||||
|
||||
checkCollisionWithCapturedSuperVariable(node, node);
|
||||
checkCollisionWithCapturedThisVariable(node, node);
|
||||
checkCollisionWithCapturedNewTargetVariable(node, node);
|
||||
checkNestedBlockScopedBinding(node, symbol);
|
||||
|
||||
const type = getTypeOfSymbol(localOrExportSymbol);
|
||||
@@ -10409,7 +10411,7 @@ namespace ts {
|
||||
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
|
||||
// declaration container are the same).
|
||||
const assumeInitialized = isParameter || isOuterVariable ||
|
||||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0) ||
|
||||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isInTypeQuery(node)) ||
|
||||
isInAmbientContext(declaration);
|
||||
const flowType = getFlowTypeOfReference(node, type, assumeInitialized, flowContainer);
|
||||
// A variable is considered uninitialized when it is possible to analyze the entire control flow graph
|
||||
@@ -13893,6 +13895,24 @@ namespace ts {
|
||||
return getNonNullableType(checkExpression(node.expression));
|
||||
}
|
||||
|
||||
function checkMetaProperty(node: MetaProperty) {
|
||||
checkGrammarMetaProperty(node);
|
||||
Debug.assert(node.keywordToken === SyntaxKind.NewKeyword && node.name.text === "target", "Unrecognized meta-property.");
|
||||
const container = getNewTargetContainer(node);
|
||||
if (!container) {
|
||||
error(node, Diagnostics.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, "new.target");
|
||||
return unknownType;
|
||||
}
|
||||
else if (container.kind === SyntaxKind.Constructor) {
|
||||
const symbol = getSymbolOfNode(container.parent);
|
||||
return getTypeOfSymbol(symbol);
|
||||
}
|
||||
else {
|
||||
const symbol = getSymbolOfNode(container);
|
||||
return getTypeOfSymbol(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeOfParameter(symbol: Symbol) {
|
||||
const type = getTypeOfSymbol(symbol);
|
||||
if (strictNullChecks) {
|
||||
@@ -14301,6 +14321,7 @@ namespace ts {
|
||||
if (produceDiagnostics && node.kind !== SyntaxKind.MethodDeclaration) {
|
||||
checkCollisionWithCapturedSuperVariable(node, (<FunctionExpression>node).name);
|
||||
checkCollisionWithCapturedThisVariable(node, (<FunctionExpression>node).name);
|
||||
checkCollisionWithCapturedNewTargetVariable(node, (<FunctionExpression>node).name);
|
||||
}
|
||||
|
||||
return type;
|
||||
@@ -15335,6 +15356,8 @@ namespace ts {
|
||||
return checkAssertion(<AssertionExpression>node);
|
||||
case SyntaxKind.NonNullExpression:
|
||||
return checkNonNullAssertion(<NonNullExpression>node);
|
||||
case SyntaxKind.MetaProperty:
|
||||
return checkMetaProperty(<MetaProperty>node);
|
||||
case SyntaxKind.DeleteExpression:
|
||||
return checkDeleteExpression(<DeleteExpression>node);
|
||||
case SyntaxKind.VoidExpression:
|
||||
@@ -16742,6 +16765,7 @@ namespace ts {
|
||||
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithCapturedNewTargetVariable(node, node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
|
||||
checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
|
||||
}
|
||||
@@ -17034,6 +17058,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkCollisionWithCapturedNewTargetVariable(node: Node, name: Identifier): void {
|
||||
if (needCollisionCheckForIdentifier(node, name, "_newTarget")) {
|
||||
potentialNewTargetCollisions.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
// this function will run after checking the source file so 'CaptureThis' is correct for all nodes
|
||||
function checkIfThisIsCapturedInEnclosingScope(node: Node): void {
|
||||
let current = node;
|
||||
@@ -17052,6 +17082,23 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkIfNewTargetIsCapturedInEnclosingScope(node: Node): void {
|
||||
let current = node;
|
||||
while (current) {
|
||||
if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureNewTarget) {
|
||||
const isDeclaration = node.kind !== SyntaxKind.Identifier;
|
||||
if (isDeclaration) {
|
||||
error((<Declaration>node).name, Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference);
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.Expression_resolves_to_variable_declaration_newTarget_that_compiler_uses_to_capture_new_target_meta_property_reference);
|
||||
}
|
||||
return;
|
||||
}
|
||||
current = current.parent;
|
||||
}
|
||||
}
|
||||
|
||||
function checkCollisionWithCapturedSuperVariable(node: Node, name: Identifier) {
|
||||
if (!needCollisionCheckForIdentifier(node, name, "_super")) {
|
||||
return;
|
||||
@@ -17348,6 +17395,7 @@ namespace ts {
|
||||
}
|
||||
checkCollisionWithCapturedSuperVariable(node, <Identifier>node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, <Identifier>node.name);
|
||||
checkCollisionWithCapturedNewTargetVariable(node, <Identifier>node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, <Identifier>node.name);
|
||||
checkCollisionWithGlobalPromiseInGeneratedCode(node, <Identifier>node.name);
|
||||
}
|
||||
@@ -18184,6 +18232,7 @@ namespace ts {
|
||||
if (node.name) {
|
||||
checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithCapturedNewTargetVariable(node, node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
|
||||
checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
|
||||
}
|
||||
@@ -18719,6 +18768,7 @@ namespace ts {
|
||||
|
||||
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithCapturedNewTargetVariable(node, node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
|
||||
checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
@@ -19424,6 +19474,7 @@ namespace ts {
|
||||
checkGrammarSourceFile(node);
|
||||
|
||||
potentialThisCollisions.length = 0;
|
||||
potentialNewTargetCollisions.length = 0;
|
||||
|
||||
deferredNodes = [];
|
||||
deferredUnusedIdentifierNodes = produceDiagnostics && noUnusedIdentifiers ? [] : undefined;
|
||||
@@ -19452,6 +19503,11 @@ namespace ts {
|
||||
potentialThisCollisions.length = 0;
|
||||
}
|
||||
|
||||
if (potentialNewTargetCollisions.length) {
|
||||
forEach(potentialNewTargetCollisions, checkIfNewTargetIsCapturedInEnclosingScope)
|
||||
potentialNewTargetCollisions.length = 0;
|
||||
}
|
||||
|
||||
links.flags |= NodeCheckFlags.TypeChecked;
|
||||
}
|
||||
}
|
||||
@@ -21780,6 +21836,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkGrammarMetaProperty(node: MetaProperty) {
|
||||
if (node.keywordToken === SyntaxKind.NewKeyword) {
|
||||
if (node.name.text !== "target") {
|
||||
return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_0, node.name.text, tokenToString(node.keywordToken), "target");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hasParseDiagnostics(sourceFile: SourceFile): boolean {
|
||||
return sourceFile.parseDiagnostics.length > 0;
|
||||
}
|
||||
|
||||
@@ -1775,6 +1775,14 @@
|
||||
"category": "Error",
|
||||
"code": 2542
|
||||
},
|
||||
"Duplicate identifier '_newTarget'. Compiler uses variable declaration '_newTarget' to capture 'new.target' meta-property reference.": {
|
||||
"category": "Error",
|
||||
"code": 2543
|
||||
},
|
||||
"Expression resolves to variable declaration '_newTarget' that compiler uses to capture 'new.target' meta-property reference.": {
|
||||
"category": "Error",
|
||||
"code": 2544
|
||||
},
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
@@ -3197,6 +3205,14 @@
|
||||
"category": "Error",
|
||||
"code": 17011
|
||||
},
|
||||
"'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{0}'?": {
|
||||
"category": "Error",
|
||||
"code": 17012
|
||||
},
|
||||
"Meta-property '{0}' is only allowed in the body of a function declaration, function expression, or constructor.": {
|
||||
"category": "Error",
|
||||
"code": 17013
|
||||
},
|
||||
|
||||
"Circularity detected while resolving configuration: {0}": {
|
||||
"category": "Error",
|
||||
|
||||
+25
-2
@@ -660,6 +660,8 @@ namespace ts {
|
||||
return emitAsExpression(<AsExpression>node);
|
||||
case SyntaxKind.NonNullExpression:
|
||||
return emitNonNullExpression(<NonNullExpression>node);
|
||||
case SyntaxKind.MetaProperty:
|
||||
return emitMetaProperty(<MetaProperty>node);
|
||||
|
||||
// JSX
|
||||
case SyntaxKind.JsxElement:
|
||||
@@ -1247,6 +1249,12 @@ namespace ts {
|
||||
write("!");
|
||||
}
|
||||
|
||||
function emitMetaProperty(node: MetaProperty) {
|
||||
writeToken(node.keywordToken, node.pos);
|
||||
write(".");
|
||||
emit(node.name);
|
||||
}
|
||||
|
||||
//
|
||||
// Misc
|
||||
//
|
||||
@@ -2586,6 +2594,13 @@ namespace ts {
|
||||
return makeUniqueName("class");
|
||||
}
|
||||
|
||||
function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration) {
|
||||
if (isIdentifier(node.name)) {
|
||||
return generateNameForNodeCached(node.name);
|
||||
}
|
||||
return makeTempVariableName(TempFlags.Auto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique name from a node.
|
||||
*
|
||||
@@ -2607,6 +2622,10 @@ namespace ts {
|
||||
return generateNameForExportDefault();
|
||||
case SyntaxKind.ClassExpression:
|
||||
return generateNameForClassExpression();
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return generateNameForMethodOrAccessor(<MethodDeclaration | AccessorDeclaration>node);
|
||||
default:
|
||||
return makeTempVariableName(TempFlags.Auto);
|
||||
}
|
||||
@@ -2657,6 +2676,11 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
function generateNameForNodeCached(node: Node) {
|
||||
const nodeId = getNodeId(node);
|
||||
return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = unescapeIdentifier(generateNameForNode(node)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the generated identifier text from a generated identifier.
|
||||
*
|
||||
@@ -2667,8 +2691,7 @@ namespace ts {
|
||||
// Generated names generate unique names based on their original node
|
||||
// and are cached based on that node's id
|
||||
const node = getNodeForGeneratedName(name);
|
||||
const nodeId = getNodeId(node);
|
||||
return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = unescapeIdentifier(generateNameForNode(node)));
|
||||
return generateNameForNodeCached(node);
|
||||
}
|
||||
else {
|
||||
// Auto, Loop, and Unique names are cached based on their unique
|
||||
|
||||
+12
-3
@@ -198,6 +198,8 @@ namespace ts {
|
||||
visitNode(cbNode, (<AsExpression>node).type);
|
||||
case SyntaxKind.NonNullExpression:
|
||||
return visitNode(cbNode, (<NonNullExpression>node).expression);
|
||||
case SyntaxKind.MetaProperty:
|
||||
return visitNode(cbNode, (<MetaProperty>node).name);
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
return visitNode(cbNode, (<ConditionalExpression>node).condition) ||
|
||||
visitNode(cbNode, (<ConditionalExpression>node).questionToken) ||
|
||||
@@ -4335,15 +4337,22 @@ namespace ts {
|
||||
return isIdentifier() ? parseIdentifier() : undefined;
|
||||
}
|
||||
|
||||
function parseNewExpression(): NewExpression {
|
||||
const node = <NewExpression>createNode(SyntaxKind.NewExpression);
|
||||
function parseNewExpression(): NewExpression | MetaProperty {
|
||||
const fullStart = scanner.getStartPos();
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
if (parseOptional(SyntaxKind.DotToken)) {
|
||||
const node = <MetaProperty>createNode(SyntaxKind.MetaProperty, fullStart);
|
||||
node.keywordToken = SyntaxKind.NewKeyword;
|
||||
node.name = parseIdentifierName();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
const node = <NewExpression>createNode(SyntaxKind.NewExpression, fullStart);
|
||||
node.expression = parseMemberExpressionOrHigher();
|
||||
node.typeArguments = tryParse(parseTypeArgumentsInExpression);
|
||||
if (node.typeArguments || token() === SyntaxKind.OpenParenToken) {
|
||||
node.arguments = parseArgumentList();
|
||||
}
|
||||
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -248,14 +248,16 @@ namespace ts {
|
||||
//
|
||||
// Subtree facts
|
||||
//
|
||||
NewTarget = 1 << 14, // Contains a 'new.target' meta-property
|
||||
NewTargetInComputedPropertyName = 1 << 15, // Contains a 'new.target' meta-property in a computed property name.
|
||||
|
||||
// NOTE: To be added in a later PR
|
||||
|
||||
//
|
||||
// Subtree masks
|
||||
//
|
||||
|
||||
SubtreeFactsMask = ~AncestorFactsMask,
|
||||
PropagateNewTargetMask = NewTarget | NewTargetInComputedPropertyName,
|
||||
}
|
||||
|
||||
export function transformES2015(context: TransformationContext) {
|
||||
@@ -480,6 +482,9 @@ namespace ts {
|
||||
case SyntaxKind.ThisKeyword:
|
||||
return visitThisKeyword(node);
|
||||
|
||||
case SyntaxKind.MetaProperty:
|
||||
return visitMetaProperty(<MetaProperty>node);
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return visitMethodDeclaration(<MethodDeclaration>node);
|
||||
|
||||
@@ -564,7 +569,7 @@ namespace ts {
|
||||
function visitThisKeyword(node: Node): Node {
|
||||
if (convertedLoopState) {
|
||||
if (hierarchyFacts & HierarchyFacts.ArrowFunction) {
|
||||
// if the enclosing function is an ArrowFunction is then we use the captured 'this' keyword.
|
||||
// if the enclosing function is an ArrowFunction then we use the captured 'this' keyword.
|
||||
convertedLoopState.containsLexicalThis = true;
|
||||
return node;
|
||||
}
|
||||
@@ -867,7 +872,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
statements.push(constructorFunction);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
}
|
||||
|
||||
@@ -948,6 +953,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
|
||||
if (constructor) {
|
||||
prependCaptureNewTargetIfNeeded(statements, constructor, /*copyOnWrite*/ false);
|
||||
}
|
||||
|
||||
const block = createBlock(
|
||||
createNodeArray(
|
||||
statements,
|
||||
@@ -1391,6 +1401,77 @@ namespace ts {
|
||||
statements.push(captureThisStatement);
|
||||
}
|
||||
|
||||
function prependCaptureNewTargetIfNeeded(statements: Statement[], node: FunctionLikeDeclaration, copyOnWrite: boolean): Statement[] {
|
||||
if (hierarchyFacts & HierarchyFacts.NewTarget) {
|
||||
let newTarget: Expression;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return statements;
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
// Methods and accessors cannot be constructors, so 'new.target' will
|
||||
// always return 'undefined'.
|
||||
newTarget = createVoidZero();
|
||||
break;
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
// Class constructors can only be called with `new`, so `this.constructor`
|
||||
// should be relatively safe to use.
|
||||
newTarget = createPropertyAccess(
|
||||
setEmitFlags(createThis(), EmitFlags.NoSubstitution),
|
||||
"constructor"
|
||||
);
|
||||
break;
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
// Functions can be called or constructed, and may have a `this` due to
|
||||
// being a member or when calling an imported function via `other_1.f()`.
|
||||
newTarget = createConditional(
|
||||
createLogicalAnd(
|
||||
setEmitFlags(createThis(), EmitFlags.NoSubstitution),
|
||||
createBinary(
|
||||
setEmitFlags(createThis(), EmitFlags.NoSubstitution),
|
||||
SyntaxKind.InstanceOfKeyword,
|
||||
getLocalName(node)
|
||||
)
|
||||
),
|
||||
createPropertyAccess(
|
||||
setEmitFlags(createThis(), EmitFlags.NoSubstitution),
|
||||
"constructor"
|
||||
),
|
||||
createVoidZero()
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.failBadSyntaxKind(node);
|
||||
break;
|
||||
}
|
||||
|
||||
const captureNewTargetStatement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"_newTarget",
|
||||
/*type*/ undefined,
|
||||
newTarget
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
if (copyOnWrite) {
|
||||
return [captureNewTargetStatement, ...statements];
|
||||
}
|
||||
|
||||
statements.unshift(captureNewTargetStatement);
|
||||
}
|
||||
|
||||
return statements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the class body function for a class to define the members of the
|
||||
* class.
|
||||
@@ -1466,7 +1547,7 @@ namespace ts {
|
||||
// old emitter.
|
||||
setEmitFlags(statement, EmitFlags.NoSourceMap);
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTarget : HierarchyFacts.None);
|
||||
return statement;
|
||||
}
|
||||
|
||||
@@ -1545,7 +1626,7 @@ namespace ts {
|
||||
call.startsOnNewLine = true;
|
||||
}
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTarget : HierarchyFacts.None);
|
||||
return call;
|
||||
}
|
||||
|
||||
@@ -1589,20 +1670,26 @@ namespace ts {
|
||||
: enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes);
|
||||
const savedConvertedLoopState = convertedLoopState;
|
||||
convertedLoopState = undefined;
|
||||
const updated = updateFunctionExpression(
|
||||
|
||||
const parameters = visitParameterList(node.parameters, visitor, context);
|
||||
const body = node.transformFlags & TransformFlags.ES2015
|
||||
? transformFunctionBody(node)
|
||||
: visitFunctionBodyDownLevel(node);
|
||||
const name = hierarchyFacts & HierarchyFacts.NewTarget
|
||||
? getLocalName(node)
|
||||
: node.name;
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return updateFunctionExpression(
|
||||
node,
|
||||
/*modifiers*/ undefined,
|
||||
node.name,
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
parameters,
|
||||
/*type*/ undefined,
|
||||
node.transformFlags & TransformFlags.ES2015
|
||||
? transformFunctionBody(node)
|
||||
: visitFunctionBody(node.body, functionBodyVisitor, context)
|
||||
body
|
||||
);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1614,22 +1701,26 @@ namespace ts {
|
||||
const savedConvertedLoopState = convertedLoopState;
|
||||
convertedLoopState = undefined;
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes);
|
||||
const updated = updateFunctionDeclaration(
|
||||
const parameters = visitParameterList(node.parameters, visitor, context);
|
||||
const body = node.transformFlags & TransformFlags.ES2015
|
||||
? transformFunctionBody(node)
|
||||
: visitFunctionBodyDownLevel(node);
|
||||
const name = hierarchyFacts & HierarchyFacts.NewTarget
|
||||
? getLocalName(node)
|
||||
: node.name;
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return updateFunctionDeclaration(
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
node.name,
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
parameters,
|
||||
/*type*/ undefined,
|
||||
node.transformFlags & TransformFlags.ES2015
|
||||
? transformFunctionBody(node)
|
||||
: visitFunctionBody(node.body, functionBodyVisitor, context)
|
||||
body
|
||||
);
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1645,22 +1736,27 @@ namespace ts {
|
||||
const ancestorFacts = container && isClassLike(container) && !hasModifier(node, ModifierFlags.Static)
|
||||
? enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes | HierarchyFacts.NonStaticClassElement)
|
||||
: enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes);
|
||||
const expression = setOriginalNode(
|
||||
const parameters = visitParameterList(node.parameters, visitor, context);
|
||||
const body = transformFunctionBody(node);
|
||||
if (hierarchyFacts & HierarchyFacts.NewTarget && !name && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) {
|
||||
name = getGeneratedNameForNode(node);
|
||||
}
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return setOriginalNode(
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
node.asteriskToken,
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
parameters,
|
||||
/*type*/ undefined,
|
||||
transformFunctionBody(node),
|
||||
body,
|
||||
location
|
||||
),
|
||||
/*original*/ node
|
||||
);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1735,6 +1831,8 @@ namespace ts {
|
||||
const lexicalEnvironment = context.endLexicalEnvironment();
|
||||
addRange(statements, lexicalEnvironment);
|
||||
|
||||
prependCaptureNewTargetIfNeeded(statements, node, /*copyOnWrite*/ false);
|
||||
|
||||
// If we added any final generated statements, this must be a multi-line block
|
||||
if (!multiLine && lexicalEnvironment && lexicalEnvironment.length) {
|
||||
multiLine = true;
|
||||
@@ -1753,6 +1851,17 @@ namespace ts {
|
||||
return block;
|
||||
}
|
||||
|
||||
function visitFunctionBodyDownLevel(node: FunctionDeclaration | FunctionExpression) {
|
||||
const updated = visitFunctionBody(node.body, functionBodyVisitor, context);
|
||||
return updateBlock(
|
||||
updated,
|
||||
createNodeArray(
|
||||
prependCaptureNewTargetIfNeeded(updated.statements, node, /*copyOnWrite*/ true),
|
||||
/*location*/ updated.statements
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function visitBlock(node: Block, isFunctionBody: boolean): Block {
|
||||
if (isFunctionBody) {
|
||||
// A function body is not a block scope.
|
||||
@@ -2832,7 +2941,7 @@ namespace ts {
|
||||
if (startsOnNewLine) {
|
||||
expression.startsOnNewLine = true;
|
||||
}
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTarget : HierarchyFacts.None);
|
||||
return expression;
|
||||
}
|
||||
|
||||
@@ -2897,7 +3006,7 @@ namespace ts {
|
||||
convertedLoopState = undefined;
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes);
|
||||
const updated = visitEachChild(node, visitor, context);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return updated;
|
||||
}
|
||||
@@ -2918,7 +3027,7 @@ namespace ts {
|
||||
function visitComputedPropertyName(node: ComputedPropertyName) {
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.ComputedPropertyNameExcludes, HierarchyFacts.ComputedPropertyNameIncludes);
|
||||
const updated = visitEachChild(node, visitor, context);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTargetInComputedPropertyName : HierarchyFacts.None);
|
||||
return updated;
|
||||
}
|
||||
|
||||
@@ -3297,6 +3406,19 @@ namespace ts {
|
||||
: createIdentifier("_super");
|
||||
}
|
||||
|
||||
function visitMetaProperty(node: MetaProperty) {
|
||||
if (node.keywordToken === SyntaxKind.NewKeyword && node.name.text === "target") {
|
||||
if (hierarchyFacts & HierarchyFacts.ComputedPropertyName) {
|
||||
hierarchyFacts |= HierarchyFacts.NewTargetInComputedPropertyName;
|
||||
}
|
||||
else {
|
||||
hierarchyFacts |= HierarchyFacts.NewTarget;
|
||||
}
|
||||
return createIdentifier("_newTarget");
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the printer just before a node is printed.
|
||||
*
|
||||
|
||||
@@ -272,6 +272,7 @@
|
||||
ExpressionWithTypeArguments,
|
||||
AsExpression,
|
||||
NonNullExpression,
|
||||
MetaProperty,
|
||||
|
||||
// Misc
|
||||
TemplateSpan,
|
||||
@@ -1462,6 +1463,14 @@
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
// NOTE: MetaProperty is really a MemberExpression, but we consider it a PrimaryExpression
|
||||
// for the same reasons we treat NewExpression as a PrimaryExpression.
|
||||
export interface MetaProperty extends PrimaryExpression {
|
||||
kind: SyntaxKind.MetaProperty;
|
||||
keywordToken: SyntaxKind;
|
||||
name: Identifier;
|
||||
}
|
||||
|
||||
/// A JSX expression of the form <TagName attrs>...</TagName>
|
||||
export interface JsxElement extends PrimaryExpression {
|
||||
kind: SyntaxKind.JsxElement;
|
||||
@@ -2722,6 +2731,7 @@
|
||||
TypeChecked = 0x00000001, // Node has been type checked
|
||||
LexicalThis = 0x00000002, // Lexical 'this' reference
|
||||
CaptureThis = 0x00000004, // Lexical 'this' used in body
|
||||
CaptureNewTarget = 0x00000008, // Lexical 'new.target' used in body
|
||||
SuperInstance = 0x00000100, // Instance 'super' reference
|
||||
SuperStatic = 0x00000200, // Static 'super' reference
|
||||
ContextChecked = 0x00000400, // Contextual types have been assigned
|
||||
|
||||
@@ -1026,6 +1026,20 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function getNewTargetContainer(node: Node) {
|
||||
const container = getThisContainer(node, /*includeArrowFunctions*/ false);
|
||||
if (container) {
|
||||
switch (container.kind) {
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an super call/property node, returns the closest node where
|
||||
* - a super call/property access is legal in the node and not legal in the parent node the node.
|
||||
@@ -1233,6 +1247,7 @@ namespace ts {
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.YieldExpression:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
case SyntaxKind.MetaProperty:
|
||||
return true;
|
||||
case SyntaxKind.QualifiedName:
|
||||
while (node.parent.kind === SyntaxKind.QualifiedName) {
|
||||
@@ -3882,7 +3897,8 @@ namespace ts {
|
||||
|| kind === SyntaxKind.ThisKeyword
|
||||
|| kind === SyntaxKind.TrueKeyword
|
||||
|| kind === SyntaxKind.SuperKeyword
|
||||
|| kind === SyntaxKind.NonNullExpression;
|
||||
|| kind === SyntaxKind.NonNullExpression
|
||||
|| kind === SyntaxKind.MetaProperty;
|
||||
}
|
||||
|
||||
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
|
||||
|
||||
@@ -113,7 +113,10 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
registerCodeFix({
|
||||
errorCodes: [Diagnostics.Cannot_find_name_0.code],
|
||||
errorCodes: [
|
||||
Diagnostics.Cannot_find_name_0.code,
|
||||
Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code
|
||||
],
|
||||
getCodeActions: (context: CodeFixContext) => {
|
||||
const sourceFile = context.sourceFile;
|
||||
const checker = context.program.getTypeChecker();
|
||||
@@ -128,6 +131,12 @@ namespace ts.codefix {
|
||||
const cachedImportDeclarations: (ImportDeclaration | ImportEqualsDeclaration)[][] = [];
|
||||
let cachedNewImportInsertPosition: number;
|
||||
|
||||
const currentTokenMeaning = getMeaningFromLocation(token);
|
||||
if (context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) {
|
||||
const symbol = checker.getAliasedSymbol(checker.getSymbolAtLocation(token));
|
||||
return getCodeActionForImport(symbol, /*isDefault*/ false, /*isNamespaceImport*/ true);
|
||||
}
|
||||
|
||||
const allPotentialModules = checker.getAmbientModules();
|
||||
for (const otherSourceFile of allSourceFiles) {
|
||||
if (otherSourceFile !== sourceFile && isExternalOrCommonJsModule(otherSourceFile)) {
|
||||
@@ -135,7 +144,6 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
const currentTokenMeaning = getMeaningFromLocation(token);
|
||||
for (const moduleSymbol of allPotentialModules) {
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
@@ -205,7 +213,7 @@ namespace ts.codefix {
|
||||
return declarations ? some(symbol.declarations, decl => !!(getMeaningFromDeclaration(decl) & meaning)) : false;
|
||||
}
|
||||
|
||||
function getCodeActionForImport(moduleSymbol: Symbol, isDefault?: boolean): ImportCodeAction[] {
|
||||
function getCodeActionForImport(moduleSymbol: Symbol, isDefault?: boolean, isNamespaceImport?: boolean): ImportCodeAction[] {
|
||||
const existingDeclarations = getImportDeclarations(moduleSymbol);
|
||||
if (existingDeclarations.length > 0) {
|
||||
// With an existing import statement, there are more than one actions the user can do.
|
||||
@@ -215,8 +223,6 @@ namespace ts.codefix {
|
||||
return [getCodeActionForNewImport()];
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getCodeActionsForExistingImport(declarations: (ImportDeclaration | ImportEqualsDeclaration)[]): ImportCodeAction[] {
|
||||
const actions: ImportCodeAction[] = [];
|
||||
|
||||
@@ -264,7 +270,7 @@ namespace ts.codefix {
|
||||
actions.push(getCodeActionForNamespaceImport(namespaceImportDeclaration));
|
||||
}
|
||||
|
||||
if (namedImportDeclaration && namedImportDeclaration.importClause &&
|
||||
if (!isNamespaceImport && namedImportDeclaration && namedImportDeclaration.importClause &&
|
||||
(namedImportDeclaration.importClause.name || namedImportDeclaration.importClause.namedBindings)) {
|
||||
/**
|
||||
* If the existing import declaration already has a named import list, just
|
||||
@@ -388,7 +394,9 @@ namespace ts.codefix {
|
||||
const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier || getModuleSpecifierForNewImport());
|
||||
const importStatementText = isDefault
|
||||
? `import ${name} from "${moduleSpecifierWithoutQuotes}"`
|
||||
: `import { ${name} } from "${moduleSpecifierWithoutQuotes}"`;
|
||||
: isNamespaceImport
|
||||
? `import * as ${name} from "${moduleSpecifierWithoutQuotes}"`
|
||||
: `import { ${name} } from "${moduleSpecifierWithoutQuotes}"`;
|
||||
|
||||
// if this file doesn't have any import statements, insert an import statement and then insert a new line
|
||||
// between the only import statement and user code. Otherwise just insert the statement because chances
|
||||
|
||||
Reference in New Issue
Block a user