From d558e42d948b0de1722e7f2f76d20b3ef59bb41f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 15 Jun 2015 18:20:44 -0700 Subject: [PATCH] External modules are always in strict mode in ES6 --- src/compiler/binder.ts | 56 +++++++++++++------ .../diagnosticInformationMap.generated.ts | 2 + src/compiler/diagnosticMessages.json | 8 +++ ...xportNonInitializedVariablesAMD.errors.txt | 4 +- ...NonInitializedVariablesCommonJS.errors.txt | 4 +- ...xportNonInitializedVariablesES6.errors.txt | 4 +- ...rtNonInitializedVariablesSystem.errors.txt | 4 +- ...xportNonInitializedVariablesUMD.errors.txt | 4 +- ...rtsWithContextualKeywordNames01.errors.txt | 4 +- ...vedWordInImportEqualDeclaration.errors.txt | 4 +- ...rictModeWordInImportDeclaration.errors.txt | 12 ++-- 11 files changed, 70 insertions(+), 36 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 54376159784..30a7b9cbde2 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -618,19 +618,31 @@ namespace ts { // Report error only if there are no parse errors in file if (!file.parseDiagnostics.length) { - let message = getAncestor(node, SyntaxKind.ClassDeclaration) || getAncestor(node, SyntaxKind.ClassExpression) ? - Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode : - Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; - file.bindDiagnostics.push(createDiagnosticForNode(node, message, declarationNameToString(node))); + file.bindDiagnostics.push(createDiagnosticForNode(node, + getStrictModeIdentifierMessage(node), declarationNameToString(node))); } } } + function getStrictModeIdentifierMessage(node: Node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (getAncestor(node, SyntaxKind.ClassDeclaration) || getAncestor(node, SyntaxKind.ClassExpression)) { + return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; + } + + if (file.externalModuleIndicator) { + return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; + } + + return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; + } + function checkStrictModeBinaryExpression(node: BinaryExpression) { if (inStrictMode && isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operatorToken.kind)) { // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an // Assignment operator(11.13) or of a PostfixExpression(11.3) - checkGrammarEvalOrArgumentsInStrictMode(node, node.left); + checkStrictModeEvalOrArguments(node, node.left); } } @@ -638,7 +650,7 @@ namespace ts { // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the // Catch production is eval or arguments if (inStrictMode && node.variableDeclaration) { - checkGrammarEvalOrArgumentsInStrictMode(node, node.variableDeclaration.name); + checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); } } @@ -657,25 +669,37 @@ namespace ts { ((node).text === "eval" || (node).text === "arguments"); } - function checkGrammarEvalOrArgumentsInStrictMode(contextNode: Node, name: Node) { + function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) { if (name && name.kind === SyntaxKind.Identifier) { let identifier = name; if (isEvalOrArgumentsIdentifier(identifier)) { // We check first if the name is inside class declaration or class expression; if so give explicit message // otherwise report generic error message. let span = getErrorSpanForNode(file, name); - let message = getAncestor(identifier, SyntaxKind.ClassDeclaration) || getAncestor(identifier, SyntaxKind.ClassExpression) ? - Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode : - Diagnostics.Invalid_use_of_0_in_strict_mode; - file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, identifier.text)); + file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, + getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); } } } + function getStrictModeEvalOrArgumentsMessage(node: Node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (getAncestor(node, SyntaxKind.ClassDeclaration) || getAncestor(node, SyntaxKind.ClassExpression)) { + return Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; + } + + if (file.externalModuleIndicator) { + return Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; + } + + return Diagnostics.Invalid_use_of_0_in_strict_mode; + } + function checkStrictModeFunctionName(node: FunctionLikeDeclaration) { if (inStrictMode) { // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) - checkGrammarEvalOrArgumentsInStrictMode(node, node.name); + checkStrictModeEvalOrArguments(node, node.name); } } @@ -691,7 +715,7 @@ namespace ts { // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. if (inStrictMode) { - checkGrammarEvalOrArgumentsInStrictMode(node, node.operand); + checkStrictModeEvalOrArguments(node, node.operand); } } @@ -699,7 +723,7 @@ namespace ts { // Grammar checking if (inStrictMode) { if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) { - checkGrammarEvalOrArgumentsInStrictMode(node, node.operand); + checkStrictModeEvalOrArguments(node, node.operand); } } } @@ -962,7 +986,7 @@ namespace ts { function bindVariableDeclarationOrBindingElement(node: VariableDeclaration | BindingElement) { if (inStrictMode) { - checkGrammarEvalOrArgumentsInStrictMode(node, node.name) + checkStrictModeEvalOrArguments(node, node.name) } if (!isBindingPattern(node.name)) { @@ -991,7 +1015,7 @@ namespace ts { if (inStrictMode) { // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) - checkGrammarEvalOrArgumentsInStrictMode(node, node.name); + checkStrictModeEvalOrArguments(node, node.name); } if (isBindingPattern(node.name)) { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index de5e0f552d5..f6fd2a60f56 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -171,6 +171,8 @@ namespace ts { A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1211, category: DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" }, Identifier_expected_0_is_a_reserved_word_in_strict_mode: { code: 1212, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode" }, Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1213, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." }, + Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode: { code: 1214, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. Modules are automatically in strict mode." }, + Invalid_use_of_0_Modules_are_automatically_in_strict_mode: { code: 1215, category: DiagnosticCategory.Error, key: "Invalid use of '{0}'. Modules are automatically in strict mode." }, Export_assignment_is_not_supported_when_module_flag_is_system: { code: 1218, category: DiagnosticCategory.Error, key: "Export assignment is not supported when '--module' flag is 'system'." }, Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Specify_experimentalDecorators_to_remove_this_warning: { code: 1219, category: DiagnosticCategory.Error, key: "Experimental support for decorators is a feature that is subject to change in a future release. Specify '--experimentalDecorators' to remove this warning." }, Generators_are_only_available_when_targeting_ECMAScript_6_or_higher: { code: 1220, category: DiagnosticCategory.Error, key: "Generators are only available when targeting ECMAScript 6 or higher." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c4a805413e7..cf25e77bf66 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -671,6 +671,14 @@ "category": "Error", "code": 1213 }, + "Identifier expected. '{0}' is a reserved word in strict mode. Modules are automatically in strict mode.": { + "category": "Error", + "code": 1214 + }, + "Invalid use of '{0}'. Modules are automatically in strict mode.": { + "category": "Error", + "code": 1215 + }, "Export assignment is not supported when '--module' flag is 'system'.": { "category": "Error", "code": 1218 diff --git a/tests/baselines/reference/exportNonInitializedVariablesAMD.errors.txt b/tests/baselines/reference/exportNonInitializedVariablesAMD.errors.txt index 27679cf6071..28d7253a70c 100644 --- a/tests/baselines/reference/exportNonInitializedVariablesAMD.errors.txt +++ b/tests/baselines/reference/exportNonInitializedVariablesAMD.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesAMD.ts(2,4): error TS1123: Variable declaration list cannot be empty. -tests/cases/conformance/externalModules/exportNonInitializedVariablesAMD.ts(3,1): error TS1212: Identifier expected. 'let' is a reserved word in strict mode +tests/cases/conformance/externalModules/exportNonInitializedVariablesAMD.ts(3,1): error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. tests/cases/conformance/externalModules/exportNonInitializedVariablesAMD.ts(3,1): error TS2304: Cannot find name 'let'. tests/cases/conformance/externalModules/exportNonInitializedVariablesAMD.ts(4,6): error TS1123: Variable declaration list cannot be empty. @@ -11,7 +11,7 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesAMD.ts(4,6) !!! error TS1123: Variable declaration list cannot be empty. let; ~~~ -!!! error TS1212: Identifier expected. 'let' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. ~~~ !!! error TS2304: Cannot find name 'let'. const; diff --git a/tests/baselines/reference/exportNonInitializedVariablesCommonJS.errors.txt b/tests/baselines/reference/exportNonInitializedVariablesCommonJS.errors.txt index 1b05c756d71..84d4cab9c83 100644 --- a/tests/baselines/reference/exportNonInitializedVariablesCommonJS.errors.txt +++ b/tests/baselines/reference/exportNonInitializedVariablesCommonJS.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesCommonJS.ts(2,4): error TS1123: Variable declaration list cannot be empty. -tests/cases/conformance/externalModules/exportNonInitializedVariablesCommonJS.ts(3,1): error TS1212: Identifier expected. 'let' is a reserved word in strict mode +tests/cases/conformance/externalModules/exportNonInitializedVariablesCommonJS.ts(3,1): error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. tests/cases/conformance/externalModules/exportNonInitializedVariablesCommonJS.ts(3,1): error TS2304: Cannot find name 'let'. tests/cases/conformance/externalModules/exportNonInitializedVariablesCommonJS.ts(4,6): error TS1123: Variable declaration list cannot be empty. @@ -11,7 +11,7 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesCommonJS.ts !!! error TS1123: Variable declaration list cannot be empty. let; ~~~ -!!! error TS1212: Identifier expected. 'let' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. ~~~ !!! error TS2304: Cannot find name 'let'. const; diff --git a/tests/baselines/reference/exportNonInitializedVariablesES6.errors.txt b/tests/baselines/reference/exportNonInitializedVariablesES6.errors.txt index f0ae7a83a1d..08e1d9588b6 100644 --- a/tests/baselines/reference/exportNonInitializedVariablesES6.errors.txt +++ b/tests/baselines/reference/exportNonInitializedVariablesES6.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesES6.ts(2,4): error TS1123: Variable declaration list cannot be empty. -tests/cases/conformance/externalModules/exportNonInitializedVariablesES6.ts(3,1): error TS1212: Identifier expected. 'let' is a reserved word in strict mode +tests/cases/conformance/externalModules/exportNonInitializedVariablesES6.ts(3,1): error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. tests/cases/conformance/externalModules/exportNonInitializedVariablesES6.ts(3,1): error TS2304: Cannot find name 'let'. tests/cases/conformance/externalModules/exportNonInitializedVariablesES6.ts(4,6): error TS1123: Variable declaration list cannot be empty. @@ -11,7 +11,7 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesES6.ts(4,6) !!! error TS1123: Variable declaration list cannot be empty. let; ~~~ -!!! error TS1212: Identifier expected. 'let' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. ~~~ !!! error TS2304: Cannot find name 'let'. const; diff --git a/tests/baselines/reference/exportNonInitializedVariablesSystem.errors.txt b/tests/baselines/reference/exportNonInitializedVariablesSystem.errors.txt index 55249c36c75..1e461ea7253 100644 --- a/tests/baselines/reference/exportNonInitializedVariablesSystem.errors.txt +++ b/tests/baselines/reference/exportNonInitializedVariablesSystem.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesSystem.ts(2,4): error TS1123: Variable declaration list cannot be empty. -tests/cases/conformance/externalModules/exportNonInitializedVariablesSystem.ts(3,1): error TS1212: Identifier expected. 'let' is a reserved word in strict mode +tests/cases/conformance/externalModules/exportNonInitializedVariablesSystem.ts(3,1): error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. tests/cases/conformance/externalModules/exportNonInitializedVariablesSystem.ts(3,1): error TS2304: Cannot find name 'let'. tests/cases/conformance/externalModules/exportNonInitializedVariablesSystem.ts(4,6): error TS1123: Variable declaration list cannot be empty. @@ -11,7 +11,7 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesSystem.ts(4 !!! error TS1123: Variable declaration list cannot be empty. let; ~~~ -!!! error TS1212: Identifier expected. 'let' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. ~~~ !!! error TS2304: Cannot find name 'let'. const; diff --git a/tests/baselines/reference/exportNonInitializedVariablesUMD.errors.txt b/tests/baselines/reference/exportNonInitializedVariablesUMD.errors.txt index b21d9a89715..b180c138501 100644 --- a/tests/baselines/reference/exportNonInitializedVariablesUMD.errors.txt +++ b/tests/baselines/reference/exportNonInitializedVariablesUMD.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesUMD.ts(2,4): error TS1123: Variable declaration list cannot be empty. -tests/cases/conformance/externalModules/exportNonInitializedVariablesUMD.ts(3,1): error TS1212: Identifier expected. 'let' is a reserved word in strict mode +tests/cases/conformance/externalModules/exportNonInitializedVariablesUMD.ts(3,1): error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. tests/cases/conformance/externalModules/exportNonInitializedVariablesUMD.ts(3,1): error TS2304: Cannot find name 'let'. tests/cases/conformance/externalModules/exportNonInitializedVariablesUMD.ts(4,6): error TS1123: Variable declaration list cannot be empty. @@ -11,7 +11,7 @@ tests/cases/conformance/externalModules/exportNonInitializedVariablesUMD.ts(4,6) !!! error TS1123: Variable declaration list cannot be empty. let; ~~~ -!!! error TS1212: Identifier expected. 'let' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. ~~~ !!! error TS2304: Cannot find name 'let'. const; diff --git a/tests/baselines/reference/exportsAndImportsWithContextualKeywordNames01.errors.txt b/tests/baselines/reference/exportsAndImportsWithContextualKeywordNames01.errors.txt index 94d216724a5..6d443464d99 100644 --- a/tests/baselines/reference/exportsAndImportsWithContextualKeywordNames01.errors.txt +++ b/tests/baselines/reference/exportsAndImportsWithContextualKeywordNames01.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/modules/t3.ts(1,17): error TS1212: Identifier expected. 'yield' is a reserved word in strict mode +tests/cases/conformance/es6/modules/t3.ts(1,17): error TS1214: Identifier expected. 'yield' is a reserved word in strict mode. Modules are automatically in strict mode. ==== tests/cases/conformance/es6/modules/t1.ts (0 errors) ==== @@ -17,7 +17,7 @@ tests/cases/conformance/es6/modules/t3.ts(1,17): error TS1212: Identifier expect ==== tests/cases/conformance/es6/modules/t3.ts (1 errors) ==== import { set as yield } from "./t1"; ~~~~~ -!!! error TS1212: Identifier expected. 'yield' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'yield' is a reserved word in strict mode. Modules are automatically in strict mode. ==== tests/cases/conformance/es6/modules/t4.ts (0 errors) ==== import { get } from "./t1"; \ No newline at end of file diff --git a/tests/baselines/reference/strictModeReservedWordInImportEqualDeclaration.errors.txt b/tests/baselines/reference/strictModeReservedWordInImportEqualDeclaration.errors.txt index 7511e88f53a..3405db573a9 100644 --- a/tests/baselines/reference/strictModeReservedWordInImportEqualDeclaration.errors.txt +++ b/tests/baselines/reference/strictModeReservedWordInImportEqualDeclaration.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/strictModeReservedWordInImportEqualDeclaration.ts(3,8): error TS1212: Identifier expected. 'public' is a reserved word in strict mode +tests/cases/compiler/strictModeReservedWordInImportEqualDeclaration.ts(3,8): error TS1214: Identifier expected. 'public' is a reserved word in strict mode. Modules are automatically in strict mode. tests/cases/compiler/strictModeReservedWordInImportEqualDeclaration.ts(3,25): error TS2307: Cannot find module '1'. @@ -7,6 +7,6 @@ tests/cases/compiler/strictModeReservedWordInImportEqualDeclaration.ts(3,25): er "use strict" import public = require("1"); ~~~~~~ -!!! error TS1212: Identifier expected. 'public' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'public' is a reserved word in strict mode. Modules are automatically in strict mode. ~~~ !!! error TS2307: Cannot find module '1'. \ No newline at end of file diff --git a/tests/baselines/reference/strictModeWordInImportDeclaration.errors.txt b/tests/baselines/reference/strictModeWordInImportDeclaration.errors.txt index aed48e1d3fd..b6e20cfc188 100644 --- a/tests/baselines/reference/strictModeWordInImportDeclaration.errors.txt +++ b/tests/baselines/reference/strictModeWordInImportDeclaration.errors.txt @@ -1,8 +1,8 @@ -tests/cases/compiler/strictModeWordInImportDeclaration.ts(2,13): error TS1212: Identifier expected. 'package' is a reserved word in strict mode +tests/cases/compiler/strictModeWordInImportDeclaration.ts(2,13): error TS1214: Identifier expected. 'package' is a reserved word in strict mode. Modules are automatically in strict mode. tests/cases/compiler/strictModeWordInImportDeclaration.ts(2,26): error TS2307: Cannot find module './1'. -tests/cases/compiler/strictModeWordInImportDeclaration.ts(3,16): error TS1212: Identifier expected. 'private' is a reserved word in strict mode +tests/cases/compiler/strictModeWordInImportDeclaration.ts(3,16): error TS1214: Identifier expected. 'private' is a reserved word in strict mode. Modules are automatically in strict mode. tests/cases/compiler/strictModeWordInImportDeclaration.ts(3,30): error TS2307: Cannot find module './1'. -tests/cases/compiler/strictModeWordInImportDeclaration.ts(4,8): error TS1212: Identifier expected. 'public' is a reserved word in strict mode +tests/cases/compiler/strictModeWordInImportDeclaration.ts(4,8): error TS1214: Identifier expected. 'public' is a reserved word in strict mode. Modules are automatically in strict mode. tests/cases/compiler/strictModeWordInImportDeclaration.ts(4,20): error TS2307: Cannot find module './1'. @@ -10,16 +10,16 @@ tests/cases/compiler/strictModeWordInImportDeclaration.ts(4,20): error TS2307: C "use strict" import * as package from "./1" ~~~~~~~ -!!! error TS1212: Identifier expected. 'package' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'package' is a reserved word in strict mode. Modules are automatically in strict mode. ~~~~~ !!! error TS2307: Cannot find module './1'. import {foo as private} from "./1" ~~~~~~~ -!!! error TS1212: Identifier expected. 'private' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'private' is a reserved word in strict mode. Modules are automatically in strict mode. ~~~~~ !!! error TS2307: Cannot find module './1'. import public from "./1" ~~~~~~ -!!! error TS1212: Identifier expected. 'public' is a reserved word in strict mode +!!! error TS1214: Identifier expected. 'public' is a reserved word in strict mode. Modules are automatically in strict mode. ~~~~~ !!! error TS2307: Cannot find module './1'. \ No newline at end of file