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
82 changes: 39 additions & 43 deletions crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,51 +214,47 @@ impl<'a> SemanticBuilder<'a> {
if self.build_jsdoc {
self.jsdoc = JSDocBuilder::new(self.source_text, &program.comments);
}
if self.source_type.is_typescript_definition() {
let scope_id = self.scoping.add_scope(None, NodeId::DUMMY, ScopeFlags::Top);
program.scope_id.set(Some(scope_id));

// Use counts of nodes, scopes, symbols, and references to pre-allocate sufficient capacity
// in `AstNodes`, `ScopeTree` and `SymbolTable`.
//
// This means that as we traverse the AST and fill up these structures with data,
// they never need to grow and reallocate - which is an expensive operation as it
// involves copying all the memory from the old allocation to the new one.
// For large source files, these structures are very large, so growth is very costly
// as it involves copying massive chunks of memory.
// Avoiding this growth produces up to 30% perf boost on our benchmarks.
//
// If user did not provide existing `Stats`, calculate them by visiting AST.
#[cfg_attr(not(debug_assertions), expect(unused_variables))]
let (stats, check_stats) = if let Some(stats) = self.stats {
(stats, None)
} else {
// Use counts of nodes, scopes, symbols, and references to pre-allocate sufficient capacity
// in `AstNodes`, `ScopeTree` and `SymbolTable`.
//
// This means that as we traverse the AST and fill up these structures with data,
// they never need to grow and reallocate - which is an expensive operation as it
// involves copying all the memory from the old allocation to the new one.
// For large source files, these structures are very large, so growth is very costly
// as it involves copying massive chunks of memory.
// Avoiding this growth produces up to 30% perf boost on our benchmarks.
//
// If user did not provide existing `Stats`, calculate them by visiting AST.
#[cfg_attr(not(debug_assertions), expect(unused_variables))]
let (stats, check_stats) = if let Some(stats) = self.stats {
(stats, None)
} else {
let stats = Stats::count(program);
let stats_with_excess = stats.increase_by(self.excess_capacity);
(stats_with_excess, Some(stats))
};
self.nodes.reserve(stats.nodes as usize);
self.scoping.reserve(
stats.symbols as usize,
stats.references as usize,
stats.scopes as usize,
);
let stats = Stats::count(program);
let stats_with_excess = stats.increase_by(self.excess_capacity);
(stats_with_excess, Some(stats))
};
self.nodes.reserve(stats.nodes as usize);
self.scoping.reserve(
stats.symbols as usize,
stats.references as usize,
stats.scopes as usize,
);

// Visit AST to generate scopes tree etc
self.visit_program(program);

// Check that estimated counts accurately (unless in release mode)
#[cfg(debug_assertions)]
if let Some(stats) = check_stats {
#[expect(clippy::cast_possible_truncation)]
let actual_stats = Stats::new(
self.nodes.len() as u32,
self.scoping.scopes_len() as u32,
self.scoping.symbols_len() as u32,
self.scoping.references.len() as u32,
);
stats.assert_accurate(actual_stats);
}
// Visit AST to generate scopes tree etc
self.visit_program(program);

// Check that estimated counts accurately (unless in release mode)
#[cfg(debug_assertions)]
if let Some(stats) = check_stats {
#[expect(clippy::cast_possible_truncation)]
let actual_stats = Stats::new(
self.nodes.len() as u32,
self.scoping.scopes_len() as u32,
self.scoping.symbols_len() as u32,
self.scoping.references.len() as u32,
);
stats.assert_accurate(actual_stats);
}

let comments = self.alloc(&program.comments);
Expand Down
70 changes: 69 additions & 1 deletion tasks/coverage/snapshots/parser_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ commit: 1d4546bc

parser_babel Summary:
AST Parsed : 2351/2362 (99.53%)
Positive Passed: 2330/2362 (98.65%)
Positive Passed: 2328/2362 (98.56%)
Negative Passed: 1600/1698 (94.23%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-startindex-and-startline-specified-without-startcolumn/input.js

Expand Down Expand Up @@ -628,6 +628,74 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
10 │
╰────

Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts

× Cannot assign to 'eval' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts:4:25]
3 │ export namespace ns {
4 │ export function eval(): void;
· ────
5 │ export function arguments(): void;
╰────

× Cannot assign to 'arguments' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts:5:25]
4 │ export function eval(): void;
5 │ export function arguments(): void;
· ─────────
6 │ }
╰────

× Cannot assign to 'eval' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts:9:18]
8 │
9 │ declare function eval(): void;
· ────
10 │ declare function arguments(): void;
╰────

× Cannot assign to 'arguments' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts:10:18]
9 │ declare function eval(): void;
10 │ declare function arguments(): void;
· ─────────
11 │
╰────

Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts

× Cannot assign to 'eval' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts:4:25]
3 │ export namespace ns {
4 │ export function eval(): void;
· ────
5 │ export function arguments(): void;
╰────

× Cannot assign to 'arguments' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts:5:25]
4 │ export function eval(): void;
5 │ export function arguments(): void;
· ─────────
6 │ }
╰────

× Cannot assign to 'eval' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts:9:18]
8 │
9 │ declare function eval(): void;
· ────
10 │ declare function arguments(): void;
╰────

× Cannot assign to 'arguments' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts:10:18]
9 │ declare function eval(): void;
10 │ declare function arguments(): void;
· ─────────
11 │
╰────

Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/explicit-resource-management/valid-for-using-declaration-binding-of/input.js

× Unexpected token
Expand Down
92 changes: 82 additions & 10 deletions tasks/coverage/snapshots/parser_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ commit: 81c95189

parser_typescript Summary:
AST Parsed : 6693/6700 (99.90%)
Positive Passed: 6682/6700 (99.73%)
Negative Passed: 1418/5598 (25.33%)
Positive Passed: 6680/6700 (99.70%)
Negative Passed: 1422/5598 (25.40%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment7.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment8.ts
Expand Down Expand Up @@ -4362,8 +4362,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/c

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractConstructorAssignability.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractDeclarations.d.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractExtends.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractFactoryFunction.ts
Expand Down Expand Up @@ -7114,10 +7112,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserBlockStatement1.d.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserBreakStatement1.d.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserContinueStatement1.d.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserDebuggerStatement1.d.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserDoStatement1.d.ts
Expand Down Expand Up @@ -7180,8 +7174,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserWhileStatement1.d.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserWithStatement1.d.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/StrictMode/parserStrictMode1.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/StrictMode/parserStrictMode15-negative.ts
Expand Down Expand Up @@ -8471,6 +8463,40 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/elidedEmbeddedSt
24 │ const enum H {}
╰────

Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts

× Cannot assign to 'eval' in strict mode
╭─[typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts:3:25]
2 │ export namespace ns {
3 │ export function eval(): void;
· ────
4 │ export function arguments(): void;
╰────

× Cannot assign to 'arguments' in strict mode
╭─[typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts:4:25]
3 │ export function eval(): void;
4 │ export function arguments(): void;
· ─────────
5 │ }
╰────

× Cannot assign to 'eval' in strict mode
╭─[typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts:8:18]
7 │
8 │ declare function eval(): void;
· ────
9 │ declare function arguments(): void;
╰────

× Cannot assign to 'arguments' in strict mode
╭─[typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts:9:18]
8 │ declare function eval(): void;
9 │ declare function arguments(): void;
· ─────────
10 │
╰────

Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/moduleResolutionWithExtensions_unexpected2.ts

× Expected a semicolon or an implicit semicolon after a statement, but found none
Expand Down Expand Up @@ -8630,6 +8656,23 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/es6/moduleExp
65 │ var y = _;
╰────

Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/externalModules/topLevelAwait.3.ts

× The keyword 'await' is reserved
╭─[typescript/tests/cases/conformance/externalModules/topLevelAwait.3.ts:3:15]
2 │ export {};
3 │ declare const await: any;
· ──────────
4 │ declare class C extends await {}
╰────

× The keyword 'await' is reserved
╭─[typescript/tests/cases/conformance/externalModules/topLevelAwait.3.ts:4:25]
3 │ declare const await: any;
4 │ declare class C extends await {}
· ─────
╰────

Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/moduleResolution/untypedModuleImport.ts

× Expected a semicolon or an implicit semicolon after a statement, but found none
Expand Down Expand Up @@ -18590,6 +18633,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
9 │ }
╰────

× TS(1242): 'abstract' modifier can only appear on a class, method, or property declaration.
╭─[typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractDeclarations.d.ts:2:14]
1 │ declare abstract class A {
2 │ abstract constructor() {}
· ───────────
3 │ }
╰────

× Function implementation is missing or not immediately following the declaration.
╭─[typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts:46:5]
45 │ abstract nom(): boolean;
Expand Down Expand Up @@ -28110,6 +28161,20 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
3 │ }
╰────

× Illegal break statement
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserBreakStatement1.d.ts:1:1]
1 │ break;
· ──────
╰────
help: A `break` statement can only be used within an enclosing iteration or switch statement.

× Illegal continue statement: no surrounding iteration statement
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserContinueStatement1.d.ts:1:1]
1 │ continue;
· ─────────
╰────
help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while`

× Expected `;` but found `Identifier`
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement2.ts:1:13]
1 │ for (var of X) {
Expand Down Expand Up @@ -28262,6 +28327,13 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
· ──────
╰────

× 'with' statements are not allowed
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserWithStatement1.d.ts:1:1]
1 │ with (foo) {
· ────
2 │ }
╰────

× TS(1108): A 'return' statement can only be used within a function body.
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserWithStatement2.ts:2:3]
1 │ with (1)
Expand Down
14 changes: 13 additions & 1 deletion tasks/coverage/snapshots/semantic_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ commit: 1d4546bc

semantic_babel Summary:
AST Parsed : 2362/2362 (100.00%)
Positive Passed: 1953/2362 (82.68%)
Positive Passed: 1951/2362 (82.60%)
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js
Symbol span mismatch for "C":
after transform: SymbolId(0): Span { start: 65, end: 66 }
Expand Down Expand Up @@ -574,6 +574,18 @@ Cannot assign to 'arguments' in strict mode
Cannot assign to 'eval' in strict mode
Cannot assign to 'arguments' in strict mode

semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts
Cannot assign to 'eval' in strict mode
Cannot assign to 'arguments' in strict mode
Cannot assign to 'eval' in strict mode
Cannot assign to 'arguments' in strict mode

semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts
Cannot assign to 'eval' in strict mode
Cannot assign to 'arguments' in strict mode
Cannot assign to 'eval' in strict mode
Cannot assign to 'arguments' in strict mode

semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/function-rest-trailing-comma/input.ts
Bindings mismatch:
after transform: ScopeId(0): ["foo"]
Expand Down
Loading
Loading