Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2109,20 +2109,39 @@ namespace ts {
}

// The binder visits every node in the syntax tree so it is a convenient place to perform a single localized
// check for reserved words used as identifiers in strict mode code.
function checkStrictModeIdentifier(node: Identifier) {
if (inStrictMode &&
node.originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord &&
node.originalKeywordKind! <= SyntaxKind.LastFutureReservedWord &&
!isIdentifierName(node) &&
// check for reserved words used as identifiers in strict mode code, as well as `yield` or `await` in
// [Yield] or [Await] contexts, respectively.
function checkContextualIdentifier(node: Identifier) {
// Report error only if there are no parse errors in file
if (!file.parseDiagnostics.length &&
!(node.flags & NodeFlags.Ambient) &&
!(node.flags & NodeFlags.JSDoc)) {
!(node.flags & NodeFlags.JSDoc) &&
!isIdentifierName(node)) {

// Report error only if there are no parse errors in file
if (!file.parseDiagnostics.length) {
// strict mode identifiers
if (inStrictMode &&
node.originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord &&
node.originalKeywordKind! <= SyntaxKind.LastFutureReservedWord) {
file.bindDiagnostics.push(createDiagnosticForNode(node,
getStrictModeIdentifierMessage(node), declarationNameToString(node)));
}
else if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) {
if (isExternalModule(file) && isInTopLevelContext(node)) {
file.bindDiagnostics.push(createDiagnosticForNode(node,
Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module,
declarationNameToString(node)));
}
else if (node.flags & NodeFlags.AwaitContext) {
file.bindDiagnostics.push(createDiagnosticForNode(node,
Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here,
declarationNameToString(node)));
}
}
else if (node.originalKeywordKind === SyntaxKind.YieldKeyword && node.flags & NodeFlags.YieldContext) {
file.bindDiagnostics.push(createDiagnosticForNode(node,
Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here,
declarationNameToString(node)));
}
}
}

Expand Down Expand Up @@ -2423,7 +2442,7 @@ namespace ts {
if (currentFlow && (isExpression(node) || parent.kind === SyntaxKind.ShorthandPropertyAssignment)) {
node.flowNode = currentFlow;
}
return checkStrictModeIdentifier(<Identifier>node);
return checkContextualIdentifier(<Identifier>node);
case SyntaxKind.SuperKeyword:
node.flowNode = currentFlow;
break;
Expand Down
27 changes: 1 addition & 26 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28255,11 +28255,6 @@ namespace ts {
return undefinedWideningType;
}

function isInTopLevelContext(node: Node) {
const container = getThisContainer(node, /*includeArrowFunctions*/ true);
return isSourceFile(container);
}

function checkAwaitExpression(node: AwaitExpression): Type {
// Grammar checking
if (produceDiagnostics) {
Expand Down Expand Up @@ -34861,7 +34856,6 @@ namespace ts {
}

function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
checkGrammarAwaitIdentifier(node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name!);
checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!);
checkAliasSymbol(node);
Expand Down Expand Up @@ -37627,31 +37621,19 @@ namespace ts {
return false;
}

function checkGrammarAwaitIdentifier(name: Identifier | undefined): boolean {
if (name && isIdentifier(name) && name.originalKeywordKind === SyntaxKind.AwaitKeyword && isInTopLevelContext(name.parent)) {
const file = getSourceFileOfNode(name);
if (!file.isDeclarationFile && isExternalModule(file)) {
return grammarErrorOnNode(name, Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, idText(name));
}
}
return false;
}

function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature): boolean {
// Prevent cascading error by short-circuit
const file = getSourceFileOfNode(node);
return checkGrammarDecoratorsAndModifiers(node) ||
checkGrammarTypeParameterList(node.typeParameters, file) ||
(isFunctionDeclaration(node) && checkGrammarAwaitIdentifier(node.name)) ||
checkGrammarParameterList(node.parameters) ||
checkGrammarArrowFunction(node, file) ||
(isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node));
}

function checkGrammarClassLikeDeclaration(node: ClassLikeDeclaration): boolean {
const file = getSourceFileOfNode(node);
return (isClassDeclaration(node) && checkGrammarAwaitIdentifier(node.name)) ||
checkGrammarClassDeclarationHeritageClauses(node) ||
return checkGrammarClassDeclarationHeritageClauses(node) ||
checkGrammarTypeParameterList(node.typeParameters, file);
}

Expand Down Expand Up @@ -38294,10 +38276,6 @@ namespace ts {
}
}

if (isIdentifier(node.name) && checkGrammarAwaitIdentifier(node.name)) {
return true;
}

if (node.dotDotDotToken && node.initializer) {
// Error on equals token which immediately precedes the initializer
return grammarErrorAtPos(node, node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
Expand Down Expand Up @@ -38361,9 +38339,6 @@ namespace ts {
}
}
}
if (isIdentifier(node.name) && checkGrammarAwaitIdentifier(node.name)) {
return true;
}

if (node.exclamationToken && (node.parent.parent.kind !== SyntaxKind.VariableStatement || !node.type || node.initializer || node.flags & NodeFlags.Ambient)) {
return grammarErrorOnNode(node.exclamationToken, Diagnostics.Definite_assignment_assertions_can_only_be_used_along_with_a_type_annotation);
Expand Down
Loading