Skip to content

Commit 87b0e74

Browse files
jakebaileyCopilot
authored andcommitted
Assume alwaysStrict (#2777)
1 parent 97cd51e commit 87b0e74

File tree

395 files changed

+6895
-3213
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

395 files changed

+6895
-3213
lines changed

internal/ast/parseoptions.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,9 @@ import (
88
type SourceFileParseOptions struct {
99
FileName string
1010
Path tspath.Path
11-
CompilerOptions core.SourceFileAffectingCompilerOptions
1211
ExternalModuleIndicatorOptions ExternalModuleIndicatorOptions
1312
}
1413

15-
func GetSourceFileAffectingCompilerOptions(fileName string, options *core.CompilerOptions) core.SourceFileAffectingCompilerOptions {
16-
// Declaration files are not parsed/bound differently depending on compiler options.
17-
if tspath.IsDeclarationFileName(fileName) {
18-
return core.SourceFileAffectingCompilerOptions{}
19-
}
20-
return options.SourceFileAffecting()
21-
}
22-
2314
type ExternalModuleIndicatorOptions struct {
2415
JSX bool
2516
Force bool

internal/binder/binder.go

Lines changed: 16 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ type Binder struct {
7070
seenThisKeyword bool
7171
hasExplicitReturn bool
7272
hasFlowEffects bool
73-
inStrictMode bool
7473
inAssignmentPattern bool
7574
seenParseError bool
7675
symbolCount int
@@ -83,10 +82,6 @@ type Binder struct {
8382
expandoAssignments []ExpandoAssignmentInfo
8483
}
8584

86-
func (b *Binder) options() core.SourceFileAffectingCompilerOptions {
87-
return b.file.ParseOptions().CompilerOptions
88-
}
89-
9085
type ActiveLabel struct {
9186
next *ActiveLabel
9287
breakTarget *ast.FlowLabel
@@ -128,7 +123,6 @@ func bindSourceFile(file *ast.SourceFile) {
128123
b := getBinder()
129124
defer putBinder(b)
130125
b.file = file
131-
b.inStrictMode = b.options().BindInStrictMode && !file.IsDeclarationFile || ast.IsExternalModule(file)
132126
b.unreachableFlow = b.newFlowNode(ast.FlowFlagsUnreachable)
133127
b.bind(file.AsNode())
134128
b.bindDeferredExpandoAssignments()
@@ -590,7 +584,6 @@ func (b *Binder) bind(node *ast.Node) bool {
590584
if node == nil {
591585
return false
592586
}
593-
saveInStrictMode := b.inStrictMode
594587
// Even though in the AST the jsdoc @typedef node belongs to the current node,
595588
// its symbol might be in the same scope with the current node's symbol. Consider:
596589
//
@@ -692,7 +685,6 @@ func (b *Binder) bind(node *ast.Node) bool {
692685
case ast.KindFunctionExpression, ast.KindArrowFunction:
693686
b.bindFunctionExpression(node)
694687
case ast.KindClassExpression, ast.KindClassDeclaration:
695-
b.inStrictMode = true
696688
b.bindClassLikeDeclaration(node)
697689
case ast.KindInterfaceDeclaration:
698690
b.bindBlockScopedDeclaration(node, ast.SymbolFlagsInterface, ast.SymbolFlagsInterfaceExcludes)
@@ -723,14 +715,7 @@ func (b *Binder) bind(node *ast.Node) bool {
723715
case ast.KindExportAssignment, ast.KindJSExportAssignment:
724716
b.bindExportAssignment(node)
725717
case ast.KindSourceFile:
726-
b.updateStrictModeStatementList(node.StatementList())
727718
b.bindSourceFileIfExternalModule()
728-
case ast.KindBlock:
729-
if ast.IsFunctionLikeOrClassStaticBlockDeclaration(node.Parent) {
730-
b.updateStrictModeStatementList(node.StatementList())
731-
}
732-
case ast.KindModuleBlock:
733-
b.updateStrictModeStatementList(node.StatementList())
734719
case ast.KindJsxAttributes:
735720
b.bindJsxAttributes(node)
736721
case ast.KindJsxAttribute:
@@ -760,7 +745,6 @@ func (b *Binder) bind(node *ast.Node) bool {
760745
node.Flags |= ast.NodeFlagsThisNodeOrAnySubNodesHasError
761746
b.seenParseError = true
762747
}
763-
b.inStrictMode = saveInStrictMode
764748
return false
765749
}
766750

@@ -1151,9 +1135,7 @@ func (b *Binder) bindEnumDeclaration(node *ast.Node) {
11511135
}
11521136

11531137
func (b *Binder) bindVariableDeclarationOrBindingElement(node *ast.Node) {
1154-
if b.inStrictMode {
1155-
b.checkStrictModeEvalOrArguments(node, node.Name())
1156-
}
1138+
b.checkStrictModeEvalOrArguments(node, node.Name())
11571139
if name := node.Name(); name != nil && !ast.IsBindingPattern(name) {
11581140
switch {
11591141
case ast.IsVariableDeclarationInitializedToRequire(node):
@@ -1179,7 +1161,7 @@ func (b *Binder) bindVariableDeclarationOrBindingElement(node *ast.Node) {
11791161

11801162
func (b *Binder) bindParameter(node *ast.Node) {
11811163
decl := node.AsParameterDeclaration()
1182-
if b.inStrictMode && node.Flags&ast.NodeFlagsAmbient == 0 {
1164+
if node.Flags&ast.NodeFlagsAmbient == 0 {
11831165
// It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a
11841166
// strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
11851167
b.checkStrictModeEvalOrArguments(node, decl.Name())
@@ -1201,11 +1183,7 @@ func (b *Binder) bindParameter(node *ast.Node) {
12011183

12021184
func (b *Binder) bindFunctionDeclaration(node *ast.Node) {
12031185
b.checkStrictModeFunctionName(node)
1204-
if b.inStrictMode {
1205-
b.bindBlockScopedDeclaration(node, ast.SymbolFlagsFunction, ast.SymbolFlagsFunctionExcludes)
1206-
} else {
1207-
b.declareSymbolAndAddToSymbolTable(node, ast.SymbolFlagsFunction, ast.SymbolFlagsFunctionExcludes)
1208-
}
1186+
b.bindBlockScopedDeclaration(node, ast.SymbolFlagsFunction, ast.SymbolFlagsFunctionExcludes)
12091187
}
12101188

12111189
func (b *Binder) getInferTypeContainer(node *ast.Node) *ast.Node {
@@ -1298,7 +1276,7 @@ func (b *Binder) checkContextualIdentifier(node *ast.Node) {
12981276
if originalKeywordKind == ast.KindIdentifier {
12991277
return
13001278
}
1301-
if b.inStrictMode && originalKeywordKind >= ast.KindFirstFutureReservedWord && originalKeywordKind <= ast.KindLastFutureReservedWord {
1279+
if originalKeywordKind >= ast.KindFirstFutureReservedWord && originalKeywordKind <= ast.KindLastFutureReservedWord {
13021280
b.errorOnNode(node, b.getStrictModeIdentifierMessage(node), scanner.DeclarationNameToString(node))
13031281
} else if originalKeywordKind == ast.KindAwaitKeyword {
13041282
if ast.IsExternalModule(b.file) && ast.IsInTopLevelContext(node) {
@@ -1333,15 +1311,6 @@ func (b *Binder) getStrictModeIdentifierMessage(node *ast.Node) *diagnostics.Mes
13331311
return diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode
13341312
}
13351313

1336-
func (b *Binder) updateStrictModeStatementList(statements *ast.NodeList) {
1337-
if !b.inStrictMode {
1338-
useStrictDirective := FindUseStrictPrologue(b.file, statements.Nodes)
1339-
if useStrictDirective != nil {
1340-
b.inStrictMode = true
1341-
}
1342-
}
1343-
}
1344-
13451314
// Should be called only on prologue directives (ast.IsPrologueDirective(node) should be true)
13461315
func isUseStrictPrologueDirective(sourceFile *ast.SourceFile, node *ast.Node) bool {
13471316
nodeText := scanner.GetSourceTextOfNodeFromSourceFile(sourceFile, node.Expression(), false /*includeTrivia*/)
@@ -1365,7 +1334,7 @@ func FindUseStrictPrologue(sourceFile *ast.SourceFile, statements []*ast.Node) *
13651334
}
13661335

13671336
func (b *Binder) checkStrictModeFunctionName(node *ast.Node) {
1368-
if b.inStrictMode && node.Flags&ast.NodeFlagsAmbient == 0 {
1337+
if node.Flags&ast.NodeFlagsAmbient == 0 {
13691338
// It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1))
13701339
b.checkStrictModeEvalOrArguments(node, node.Name())
13711340
}
@@ -1384,7 +1353,7 @@ func (b *Binder) getStrictModeBlockScopeFunctionDeclarationMessage(node *ast.Nod
13841353

13851354
func (b *Binder) checkStrictModeBinaryExpression(node *ast.Node) {
13861355
expr := node.AsBinaryExpression()
1387-
if b.inStrictMode && ast.IsLeftHandSideExpression(expr.Left) && ast.IsAssignmentOperator(expr.OperatorToken.Kind) {
1356+
if ast.IsLeftHandSideExpression(expr.Left) && ast.IsAssignmentOperator(expr.OperatorToken.Kind) {
13881357
// ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
13891358
// Assignment operator(11.13) or of a PostfixExpression(11.3)
13901359
b.checkStrictModeEvalOrArguments(node, expr.Left)
@@ -1395,15 +1364,15 @@ func (b *Binder) checkStrictModeCatchClause(node *ast.Node) {
13951364
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
13961365
// Catch production is eval or arguments
13971366
clause := node.AsCatchClause()
1398-
if b.inStrictMode && clause.VariableDeclaration != nil {
1367+
if clause.VariableDeclaration != nil {
13991368
b.checkStrictModeEvalOrArguments(node, clause.VariableDeclaration.AsVariableDeclaration().Name())
14001369
}
14011370
}
14021371

14031372
func (b *Binder) checkStrictModeDeleteExpression(node *ast.Node) {
14041373
// Grammar checking
14051374
expr := node.AsDeleteExpression()
1406-
if b.inStrictMode && expr.Expression.Kind == ast.KindIdentifier {
1375+
if expr.Expression.Kind == ast.KindIdentifier {
14071376
// When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
14081377
// UnaryExpression is a direct reference to a variable, function argument, or function name
14091378
b.errorOnNode(expr.Expression, diagnostics.X_delete_cannot_be_called_on_an_identifier_in_strict_mode)
@@ -1415,35 +1384,27 @@ func (b *Binder) checkStrictModePostfixUnaryExpression(node *ast.Node) {
14151384
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
14161385
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
14171386
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator.
1418-
if b.inStrictMode {
1419-
b.checkStrictModeEvalOrArguments(node, node.AsPostfixUnaryExpression().Operand)
1420-
}
1387+
b.checkStrictModeEvalOrArguments(node, node.AsPostfixUnaryExpression().Operand)
14211388
}
14221389

14231390
func (b *Binder) checkStrictModePrefixUnaryExpression(node *ast.Node) {
14241391
// Grammar checking
1425-
if b.inStrictMode {
1426-
expr := node.AsPrefixUnaryExpression()
1427-
if expr.Operator == ast.KindPlusPlusToken || expr.Operator == ast.KindMinusMinusToken {
1428-
b.checkStrictModeEvalOrArguments(node, expr.Operand)
1429-
}
1392+
expr := node.AsPrefixUnaryExpression()
1393+
if expr.Operator == ast.KindPlusPlusToken || expr.Operator == ast.KindMinusMinusToken {
1394+
b.checkStrictModeEvalOrArguments(node, expr.Operand)
14301395
}
14311396
}
14321397

14331398
func (b *Binder) checkStrictModeWithStatement(node *ast.Node) {
14341399
// Grammar checking for withStatement
1435-
if b.inStrictMode {
1436-
b.errorOnFirstToken(node, diagnostics.X_with_statements_are_not_allowed_in_strict_mode)
1437-
}
1400+
b.errorOnFirstToken(node, diagnostics.X_with_statements_are_not_allowed_in_strict_mode)
14381401
}
14391402

14401403
func (b *Binder) checkStrictModeLabeledStatement(node *ast.Node) {
14411404
// Grammar checking for labeledStatement
1442-
if b.inStrictMode {
1443-
data := node.AsLabeledStatement()
1444-
if ast.IsDeclarationStatement(data.Statement) || ast.IsVariableStatement(data.Statement) {
1445-
b.errorOnFirstToken(data.Label, diagnostics.A_label_is_not_allowed_here)
1446-
}
1405+
data := node.AsLabeledStatement()
1406+
if ast.IsDeclarationStatement(data.Statement) || ast.IsVariableStatement(data.Statement) {
1407+
b.errorOnFirstToken(data.Label, diagnostics.A_label_is_not_allowed_here)
14471408
}
14481409
}
14491410

internal/binder/binder_test.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,9 @@ func BenchmarkBind(b *testing.B) {
2121
path := tspath.ToPath(fileName, "/", osvfs.FS().UseCaseSensitiveFileNames())
2222
sourceText := f.ReadFile(b)
2323

24-
compilerOptions := &core.CompilerOptions{Target: core.ScriptTargetESNext, Module: core.ModuleKindNodeNext}
25-
sourceAffecting := compilerOptions.SourceFileAffecting()
26-
2724
parseOptions := ast.SourceFileParseOptions{
28-
FileName: fileName,
29-
Path: path,
30-
CompilerOptions: sourceAffecting,
25+
FileName: fileName,
26+
Path: path,
3127
}
3228
scriptKind := core.GetScriptKindFromFileName(fileName)
3329

internal/compiler/fileloader.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ func (p *fileLoader) parseSourceFile(t *parseTask) *ast.SourceFile {
294294
sourceFile := p.opts.Host.GetSourceFile(ast.SourceFileParseOptions{
295295
FileName: t.normalizedFilePath,
296296
Path: path,
297-
CompilerOptions: ast.GetSourceFileAffectingCompilerOptions(t.normalizedFilePath, options),
298297
ExternalModuleIndicatorOptions: ast.GetExternalModuleIndicatorOptions(t.normalizedFilePath, options, t.metadata),
299298
})
300299
return sourceFile

internal/compiler/program.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,10 @@ func (p *Program) verifyCompilerOptions() {
684684
createRemovedOptionDiagnostic("module", "UMD", "")
685685
}
686686

687+
if options.AlwaysStrict.IsFalse() {
688+
createRemovedOptionDiagnostic("alwaysStrict", "false", "")
689+
}
690+
687691
if options.StrictPropertyInitialization.IsTrue() && !options.GetStrictOptionValue(options.StrictNullChecks) {
688692
createDiagnosticForOptionName(diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks")
689693
}

internal/core/compileroptions.go

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package core
33
import (
44
"reflect"
55
"strings"
6-
"sync"
76

87
"github.com/microsoft/typescript-go/internal/collections"
98
"github.com/microsoft/typescript-go/internal/tspath"
@@ -25,7 +24,6 @@ type CompilerOptions struct {
2524
AllowUnreachableCode Tristate `json:"allowUnreachableCode,omitzero"`
2625
AllowUnusedLabels Tristate `json:"allowUnusedLabels,omitzero"`
2726
AssumeChangesOnlyAffectDirectDependencies Tristate `json:"assumeChangesOnlyAffectDirectDependencies,omitzero"`
28-
AlwaysStrict Tristate `json:"alwaysStrict,omitzero"`
2927
CheckJs Tristate `json:"checkJs,omitzero"`
3028
CustomConditions []string `json:"customConditions,omitzero"`
3129
Composite Tristate `json:"composite,omitzero"`
@@ -121,6 +119,8 @@ type CompilerOptions struct {
121119
VerbatimModuleSyntax Tristate `json:"verbatimModuleSyntax,omitzero"`
122120
MaxNodeModuleJsDepth *int `json:"maxNodeModuleJsDepth,omitzero"`
123121

122+
// Deprecated: Do not use outside of options parsing and validation.
123+
AlwaysStrict Tristate `json:"alwaysStrict,omitzero"`
124124
// Deprecated: Do not use outside of options parsing and validation.
125125
BaseUrl string `json:"baseUrl,omitzero"`
126126
// Deprecated: Do not use outside of options parsing and validation.
@@ -152,9 +152,6 @@ type CompilerOptions struct {
152152
SingleThreaded Tristate `json:"singleThreaded,omitzero"`
153153
Quiet Tristate `json:"quiet,omitzero"`
154154
Checkers *int `json:"checkers,omitzero"`
155-
156-
sourceFileAffectingCompilerOptionsOnce sync.Once
157-
sourceFileAffectingCompilerOptions SourceFileAffectingCompilerOptions
158155
}
159156

160157
// noCopy may be embedded into structs which must not be copied
@@ -367,21 +364,6 @@ func (options *CompilerOptions) GetPathsBasePath(currentDirectory string) string
367364
return currentDirectory
368365
}
369366

370-
// SourceFileAffectingCompilerOptions are the precomputed CompilerOptions values which
371-
// affect the parse and bind of a source file.
372-
type SourceFileAffectingCompilerOptions struct {
373-
BindInStrictMode bool
374-
}
375-
376-
func (options *CompilerOptions) SourceFileAffecting() SourceFileAffectingCompilerOptions {
377-
options.sourceFileAffectingCompilerOptionsOnce.Do(func() {
378-
options.sourceFileAffectingCompilerOptions = SourceFileAffectingCompilerOptions{
379-
BindInStrictMode: options.AlwaysStrict.IsTrue() || options.Strict.IsTrue(),
380-
}
381-
})
382-
return options.sourceFileAffectingCompilerOptions
383-
}
384-
385367
type ModuleDetectionKind int32
386368

387369
const (

internal/project/autoimport.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"github.com/microsoft/typescript-go/internal/ast"
77
"github.com/microsoft/typescript-go/internal/collections"
88
"github.com/microsoft/typescript-go/internal/compiler"
9-
"github.com/microsoft/typescript-go/internal/core"
109
"github.com/microsoft/typescript-go/internal/ls/autoimport"
1110
"github.com/microsoft/typescript-go/internal/packagejson"
1211
"github.com/microsoft/typescript-go/internal/tspath"
@@ -152,9 +151,8 @@ func (a *autoImportRegistryCloneHost) GetSourceFile(fileName string, path tspath
152151
return nil
153152
}
154153
opts := ast.SourceFileParseOptions{
155-
FileName: fileName,
156-
Path: path,
157-
CompilerOptions: core.EmptyCompilerOptions.SourceFileAffecting(),
154+
FileName: fileName,
155+
Path: path,
158156
}
159157
key := NewParseCacheKey(opts, fh.Hash(), fh.Kind())
160158
result := a.parseCache.Load(key, fh)

internal/project/session_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,9 +477,12 @@ func TestSession(t *testing.T) {
477477
files := maps.Clone(defaultFiles)
478478
files["/home/projects/TS/p2/tsconfig.json"] = `{
479479
"compilerOptions": {
480+
"noLib": true,
480481
"module": "nodenext",
481-
"jsx": "react"
482-
}
482+
"strict": true,
483+
"moduleDetection": "auto"
484+
},
485+
"include": ["src"]
483486
}`
484487
files["/home/projects/TS/p2/src/index.ts"] = `import { x } from "../../p1/src/x";`
485488
session, _ := projecttestutil.Setup(files)

internal/testutil/tsbaseline/js_emit_baseline.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,8 @@ func DoJSEmitBaseline(
5555
}
5656
if len(result.Diagnostics) == 0 && strings.HasSuffix(file.UnitName, tspath.ExtensionJson) {
5757
fileParseResult := parser.ParseSourceFile(ast.SourceFileParseOptions{
58-
FileName: file.UnitName,
59-
Path: tspath.Path(file.UnitName),
60-
CompilerOptions: options.SourceFileAffecting(),
58+
FileName: file.UnitName,
59+
Path: tspath.Path(file.UnitName),
6160
}, file.Content, core.ScriptKindJSON)
6261
if len(fileParseResult.Diagnostics()) > 0 {
6362
jsCode.WriteString(GetErrorBaseline(t, []*harnessutil.TestFile{file}, diagnosticwriter.WrapASTDiagnostics(fileParseResult.Diagnostics()), diagnosticwriter.CompareASTDiagnostics, false /*pretty*/))

internal/transformers/estransforms/usestrict.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,8 @@ func (tx *useStrictTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node
4343
return node.AsNode()
4444
}
4545

46-
if isExternalModule ||
47-
tx.compilerOptions.AlwaysStrict.IsTrueOrUnknown() {
48-
statements := tx.Factory().EnsureUseStrict(node.Statements.Nodes)
49-
statementList := tx.Factory().NewNodeList(statements)
50-
statementList.Loc = node.Statements.Loc
51-
return tx.Factory().UpdateSourceFile(node, statementList, node.EndOfFileToken).AsSourceFile().AsNode()
52-
}
53-
54-
return node.AsNode()
46+
statements := tx.Factory().EnsureUseStrict(node.Statements.Nodes)
47+
statementList := tx.Factory().NewNodeList(statements)
48+
statementList.Loc = node.Statements.Loc
49+
return tx.Factory().UpdateSourceFile(node, statementList, node.EndOfFileToken).AsSourceFile().AsNode()
5550
}

0 commit comments

Comments
 (0)