Skip to content

Commit 93b94c7

Browse files
committed
refactor(semantic): keep consistent SymbolFlags for function id
1 parent abb0e0e commit 93b94c7

File tree

10 files changed

+17655
-6702
lines changed

10 files changed

+17655
-6702
lines changed

crates/oxc_semantic/src/binder.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl<'a> Binder<'a> for Class<'a> {
122122
// unless the source text matched by this production is not strict mode code
123123
// and the duplicate entries are only bound by FunctionDeclarations.
124124
// https://tc39.es/ecma262/#sec-block-level-function-declarations-web-legacy-compatibility-semantics
125-
fn function_as_var(flags: ScopeFlags, source_type: SourceType) -> bool {
125+
pub fn function_as_var(flags: ScopeFlags, source_type: SourceType) -> bool {
126126
flags.is_function() || (source_type.is_script() && flags.is_top())
127127
}
128128

@@ -166,20 +166,16 @@ impl<'a> Binder<'a> for Function<'a> {
166166
// The visitor is already inside the function scope,
167167
// retrieve the parent scope for the function id to bind to.
168168

169-
let (includes, excludes) =
169+
let (includes, excludes) = (
170+
SymbolFlags::Function,
170171
if (scope_flags.is_strict_mode() || self.r#async || self.generator)
171172
&& !function_as_var(scope_flags, builder.source_type)
172173
{
173-
(
174-
SymbolFlags::Function | SymbolFlags::BlockScopedVariable,
175-
SymbolFlags::BlockScopedVariableExcludes,
176-
)
174+
SymbolFlags::BlockScopedVariableExcludes | SymbolFlags::Function
177175
} else {
178-
(
179-
SymbolFlags::FunctionScopedVariable,
180-
SymbolFlags::FunctionScopedVariableExcludes,
181-
)
182-
};
176+
SymbolFlags::FunctionScopedVariableExcludes
177+
},
178+
);
183179

184180
let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes);
185181
ident.symbol_id.set(Some(symbol_id));

crates/oxc_semantic/src/builder.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use oxc_span::{Atom, CompactStr, SourceType, Span};
1818
use oxc_syntax::module_record::ModuleRecord;
1919

2020
use crate::{
21-
binder::Binder,
21+
binder::{function_as_var, Binder},
2222
checker,
2323
class::ClassTableBuilder,
2424
diagnostics::redeclaration,
@@ -461,9 +461,19 @@ impl<'a> SemanticBuilder<'a> {
461461
let symbol_id = self.scope.get_binding(scope_id, name).or_else(|| {
462462
self.hoisting_variables.get(&scope_id).and_then(|symbols| symbols.get(name).copied())
463463
})?;
464-
if report_error && self.symbols.get_flags(symbol_id).intersects(excludes) {
465-
let symbol_span = self.symbols.get_span(symbol_id);
466-
self.error(redeclaration(name, symbol_span, span));
464+
if report_error {
465+
let flags = self.symbols.get_flags(symbol_id);
466+
if flags.intersects(excludes)
467+
|| ((excludes == SymbolFlags::FunctionScopedVariableExcludes
468+
|| excludes == SymbolFlags::BlockScopedVariableExcludes)
469+
&& flags.is_function()
470+
&& !function_as_var(self.current_scope_flags(), self.source_type)
471+
&& (self.scope.get_flags(scope_id).is_strict_mode()
472+
|| matches!(self.nodes.kind(self.symbols.get_declaration(symbol_id)), AstKind::Function(func) if func.generator || func.r#async)))
473+
{
474+
let symbol_span = self.symbols.get_span(symbol_id);
475+
self.error(redeclaration(name, symbol_span, span));
476+
}
467477
}
468478
Some(symbol_id)
469479
}

crates/oxc_syntax/src/symbol.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,18 @@ bitflags! {
102102

103103
const BlockScoped = Self::BlockScopedVariable.bits() | Self::Enum.bits() | Self::Class.bits();
104104

105-
const Value = Self::Variable.bits() | Self::Class.bits() | Self::Enum.bits() | Self::EnumMember.bits() | Self::ValueModule.bits();
105+
const Value = Self::Variable.bits() | Self::Class.bits() | Self::Function.bits() | Self::Enum.bits() | Self::EnumMember.bits() | Self::ValueModule.bits();
106106
const Type = Self::Class.bits() | Self::Interface.bits() | Self::Enum.bits() | Self::EnumMember.bits() | Self::TypeParameter.bits() | Self::TypeAlias.bits();
107107

108108
/// Variables can be redeclared, but can not redeclare a block-scoped declaration with the
109109
/// same name, or any other value that is not a variable, e.g. ValueModule or Class
110-
const FunctionScopedVariableExcludes = Self::Value.bits() - Self::FunctionScopedVariable.bits();
110+
const FunctionScopedVariableExcludes = Self::Value.bits() - Self::FunctionScopedVariable.bits() - Self::Function.bits();
111111

112112
/// Block-scoped declarations are not allowed to be re-declared
113113
/// they can not merge with anything in the value space
114-
const BlockScopedVariableExcludes = Self::Value.bits();
114+
const BlockScopedVariableExcludes = Self::Value.bits() - Self::Function.bits();
115115

116-
const ClassExcludes = (Self::Value.bits() | Self::TypeAlias.bits()) & !(Self::ValueModule.bits() | Self::Interface.bits() | Self::Function.bits());
116+
const ClassExcludes = (Self::Value.bits() | Self::TypeAlias.bits()) & !(Self::ValueModule.bits() | Self::Interface.bits());
117117
const ImportBindingExcludes = Self::Import.bits() | Self::TypeImport.bits();
118118
// Type specific excludes
119119
const TypeAliasExcludes = Self::Type.bits();

tasks/coverage/snapshots/semantic_babel.snap

Lines changed: 123 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ commit: 54a8389f
22

33
semantic_babel Summary:
44
AST Parsed : 2218/2218 (100.00%)
5-
Positive Passed: 1846/2218 (83.23%)
5+
Positive Passed: 1825/2218 (82.28%)
66
tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-b/enabled/3.3-function-in-if-body/input.js
77
semantic error: Symbol scope ID mismatch for "f":
88
after transform: SymbolId(0): ScopeId(4294967294)
@@ -11,6 +11,11 @@ Symbol scope ID mismatch for "g":
1111
after transform: SymbolId(1): ScopeId(4294967294)
1212
rebuilt : SymbolId(1): ScopeId(4294967294)
1313

14+
tasks/coverage/babel/packages/babel-parser/test/fixtures/comments/basic/async-function/input.js
15+
semantic error: Symbol flags mismatch for "_f":
16+
after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable)
17+
rebuilt : SymbolId(2): SymbolFlags(Function)
18+
1419
tasks/coverage/babel/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/input.js
1520
semantic error: Unexpected new.target expression
1621
Unexpected new.target expression
@@ -29,20 +34,125 @@ semantic error: A 'return' statement can only be used within a function body.
2934
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/uncategorised/385/input.js
3035
semantic error: Symbol flags mismatch for "_foo":
3136
after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable)
32-
rebuilt : SymbolId(2): SymbolFlags(BlockScopedVariable | Function)
37+
rebuilt : SymbolId(2): SymbolFlags(Function)
38+
39+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2016/simple-parameter-list/async-arrow-function-concise-body/input.js
40+
semantic error: Symbol flags mismatch for "a":
41+
after transform: SymbolId(3): SymbolFlags(FunctionScopedVariable)
42+
rebuilt : SymbolId(4): SymbolFlags(Function)
43+
44+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/12/input.js
45+
semantic error: Symbol flags mismatch for "_foo":
46+
after transform: SymbolId(3): SymbolFlags(FunctionScopedVariable)
47+
rebuilt : SymbolId(3): SymbolFlags(Function)
48+
49+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/13/input.js
50+
semantic error: Symbol flags mismatch for "_inner":
51+
after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable)
52+
rebuilt : SymbolId(3): SymbolFlags(Function)
53+
54+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/14/input.js
55+
semantic error: Symbol flags mismatch for "foo":
56+
after transform: SymbolId(4): SymbolFlags(FunctionScopedVariable)
57+
rebuilt : SymbolId(4): SymbolFlags(Function)
3358

3459
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/25/input.js
3560
semantic error: Symbol flags mismatch for "_foo":
3661
after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable)
37-
rebuilt : SymbolId(2): SymbolFlags(BlockScopedVariable | Function)
62+
rebuilt : SymbolId(2): SymbolFlags(Function)
63+
64+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/31/input.js
65+
semantic error: Symbol flags mismatch for "foo":
66+
after transform: SymbolId(4): SymbolFlags(FunctionScopedVariable)
67+
rebuilt : SymbolId(4): SymbolFlags(Function)
68+
69+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/32/input.js
70+
semantic error: Symbol flags mismatch for "foo":
71+
after transform: SymbolId(4): SymbolFlags(FunctionScopedVariable)
72+
rebuilt : SymbolId(4): SymbolFlags(Function)
73+
74+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/33/input.js
75+
semantic error: Symbol flags mismatch for "foo":
76+
after transform: SymbolId(4): SymbolFlags(FunctionScopedVariable)
77+
rebuilt : SymbolId(4): SymbolFlags(Function)
78+
79+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/34/input.js
80+
semantic error: Symbol flags mismatch for "foo":
81+
after transform: SymbolId(4): SymbolFlags(FunctionScopedVariable)
82+
rebuilt : SymbolId(4): SymbolFlags(Function)
83+
84+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/await-async-function-declaration-name/input.js
85+
semantic error: Symbol flags mismatch for "_await":
86+
after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable)
87+
rebuilt : SymbolId(2): SymbolFlags(Function)
88+
89+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/await-function-expression-name-inside-async-function/input.js
90+
semantic error: Symbol flags mismatch for "_fn":
91+
after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable)
92+
rebuilt : SymbolId(2): SymbolFlags(Function)
93+
94+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/await-identifier-inside-parameters-of-nested-function/input.js
95+
semantic error: Symbol flags mismatch for "_fn":
96+
after transform: SymbolId(3): SymbolFlags(FunctionScopedVariable)
97+
rebuilt : SymbolId(2): SymbolFlags(Function)
98+
99+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-arguments-of-async-function-call/input.js
100+
semantic error: Symbol flags mismatch for "_fn":
101+
after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable)
102+
rebuilt : SymbolId(2): SymbolFlags(Function)
103+
104+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-async-call-inside-parameters-of-function-inside-async-function/input.js
105+
semantic error: Symbol flags mismatch for "_f":
106+
after transform: SymbolId(3): SymbolFlags(FunctionScopedVariable)
107+
rebuilt : SymbolId(2): SymbolFlags(Function)
108+
109+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/await-inside-parenthesized-assign/input.js
110+
semantic error: Symbol flags mismatch for "_fn":
111+
after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable)
112+
rebuilt : SymbolId(2): SymbolFlags(Function)
113+
114+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/context-division-after-expression/input.js
115+
semantic error: Symbol flags mismatch for "fn":
116+
after transform: SymbolId(0): SymbolFlags(FunctionScopedVariable)
117+
rebuilt : SymbolId(2): SymbolFlags(Function)
118+
119+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/context-regex-after-statement/input.js
120+
semantic error: Symbol flags mismatch for "_fn":
121+
after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable)
122+
rebuilt : SymbolId(2): SymbolFlags(Function)
38123

39124
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/export/input.js
40125
semantic error: Symbol flags mismatch for "_foo":
41126
after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable)
42-
rebuilt : SymbolId(2): SymbolFlags(BlockScopedVariable | Function)
127+
rebuilt : SymbolId(2): SymbolFlags(Function)
43128
Symbol flags mismatch for "_bar":
44129
after transform: SymbolId(4): SymbolFlags(FunctionScopedVariable)
45-
rebuilt : SymbolId(4): SymbolFlags(BlockScopedVariable | Function)
130+
rebuilt : SymbolId(4): SymbolFlags(Function)
131+
132+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/object-default-params/input.js
133+
semantic error: Symbol flags mismatch for "b":
134+
after transform: SymbolId(4): SymbolFlags(FunctionScopedVariable)
135+
rebuilt : SymbolId(4): SymbolFlags(Function)
136+
137+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/valid-await-expr-using-in/input.js
138+
semantic error: Symbol flags mismatch for "_f":
139+
after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable)
140+
rebuilt : SymbolId(2): SymbolFlags(Function)
141+
142+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/valid-await-expr-using-instanceof/input.js
143+
semantic error: Symbol flags mismatch for "_f":
144+
after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable)
145+
rebuilt : SymbolId(2): SymbolFlags(Function)
146+
147+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2018/async-generators/for-await/input.js
148+
semantic error: Symbol flags mismatch for "_f":
149+
after transform: SymbolId(9): SymbolFlags(FunctionScopedVariable)
150+
rebuilt : SymbolId(3): SymbolFlags(Function)
151+
152+
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2018/async-generators/for-await-async-of/input.js
153+
semantic error: Symbol flags mismatch for "_f":
154+
after transform: SymbolId(8): SymbolFlags(FunctionScopedVariable)
155+
rebuilt : SymbolId(3): SymbolFlags(Function)
46156

47157
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-private-properties/await-in-private-property-in-params-of-async-arrow/input.js
48158
semantic error: Expected a semicolon or an implicit semicolon after a statement, but found none
@@ -63,20 +173,6 @@ Unexpected new.target expression
63173
Unexpected new.target expression
64174
Unexpected new.target expression
65175

66-
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-static-block/await-binding-in-function-in-static-block/input.js
67-
semantic error: Symbol flags mismatch for "f":
68-
after transform: SymbolId(1): SymbolFlags(BlockScopedVariable | Function)
69-
rebuilt : SymbolId(1): SymbolFlags(FunctionScopedVariable)
70-
Symbol flags mismatch for "f":
71-
after transform: SymbolId(2): SymbolFlags(BlockScopedVariable | Function)
72-
rebuilt : SymbolId(2): SymbolFlags(FunctionScopedVariable)
73-
Symbol flags mismatch for "f":
74-
after transform: SymbolId(4): SymbolFlags(BlockScopedVariable | Function)
75-
rebuilt : SymbolId(4): SymbolFlags(FunctionScopedVariable)
76-
Symbol flags mismatch for "f":
77-
after transform: SymbolId(6): SymbolFlags(BlockScopedVariable | Function)
78-
rebuilt : SymbolId(6): SymbolFlags(FunctionScopedVariable)
79-
80176
tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-static-block/await-binding-in-initializer-in-static-block/input.js
81177
semantic error: Unexpected token
82178

@@ -1789,8 +1885,8 @@ semantic error: Scope children mismatch:
17891885
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
17901886
rebuilt : ScopeId(0): [ScopeId(1)]
17911887
Symbol flags mismatch for "A":
1792-
after transform: SymbolId(0): SymbolFlags(BlockScopedVariable | Function | Interface)
1793-
rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable | Function)
1888+
after transform: SymbolId(0): SymbolFlags(Function | Interface)
1889+
rebuilt : SymbolId(0): SymbolFlags(Function)
17941890
Symbol redeclarations mismatch for "A":
17951891
after transform: SymbolId(0): [Span { start: 26, end: 27 }]
17961892
rebuilt : SymbolId(0): []
@@ -1800,8 +1896,8 @@ semantic error: Scope children mismatch:
18001896
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
18011897
rebuilt : ScopeId(0): [ScopeId(1)]
18021898
Symbol flags mismatch for "A":
1803-
after transform: SymbolId(0): SymbolFlags(BlockScopedVariable | Function | TypeAlias)
1804-
rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable | Function)
1899+
after transform: SymbolId(0): SymbolFlags(Function | TypeAlias)
1900+
rebuilt : SymbolId(0): SymbolFlags(Function)
18051901
Symbol redeclarations mismatch for "A":
18061902
after transform: SymbolId(0): [Span { start: 21, end: 22 }]
18071903
rebuilt : SymbolId(0): []
@@ -2035,8 +2131,8 @@ semantic error: Scope children mismatch:
20352131
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
20362132
rebuilt : ScopeId(0): [ScopeId(1)]
20372133
Symbol flags mismatch for "A":
2038-
after transform: SymbolId(0): SymbolFlags(BlockScopedVariable | Function | Interface)
2039-
rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable | Function)
2134+
after transform: SymbolId(0): SymbolFlags(Function | Interface)
2135+
rebuilt : SymbolId(0): SymbolFlags(Function)
20402136
Symbol span mismatch for "A":
20412137
after transform: SymbolId(0): Span { start: 10, end: 11 }
20422138
rebuilt : SymbolId(0): Span { start: 24, end: 25 }
@@ -2107,8 +2203,8 @@ semantic error: Scope children mismatch:
21072203
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
21082204
rebuilt : ScopeId(0): [ScopeId(1)]
21092205
Symbol flags mismatch for "A":
2110-
after transform: SymbolId(0): SymbolFlags(BlockScopedVariable | Function | TypeAlias)
2111-
rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable | Function)
2206+
after transform: SymbolId(0): SymbolFlags(Function | TypeAlias)
2207+
rebuilt : SymbolId(0): SymbolFlags(Function)
21122208
Symbol span mismatch for "A":
21132209
after transform: SymbolId(0): Span { start: 5, end: 6 }
21142210
rebuilt : SymbolId(0): Span { start: 26, end: 27 }

tasks/coverage/snapshots/semantic_misc.snap

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
semantic_misc Summary:
22
AST Parsed : 30/30 (100.00%)
3-
Positive Passed: 18/30 (60.00%)
3+
Positive Passed: 17/30 (56.67%)
44
tasks/coverage/misc/pass/oxc-1288.ts
55
semantic error: Bindings mismatch:
66
after transform: ScopeId(0): ["from"]
@@ -11,6 +11,11 @@ semantic error: Bindings mismatch:
1111
after transform: ScopeId(0): ["infer", "target", "type"]
1212
rebuilt : ScopeId(0): []
1313

14+
tasks/coverage/misc/pass/oxc-1740.tsx
15+
semantic error: Symbol flags mismatch for "render":
16+
after transform: SymbolId(5): SymbolFlags(FunctionScopedVariable)
17+
rebuilt : SymbolId(6): SymbolFlags(Function)
18+
1419
tasks/coverage/misc/pass/oxc-2087.ts
1520
semantic error: Bindings mismatch:
1621
after transform: ScopeId(0): ["Helpers"]
@@ -103,9 +108,18 @@ rebuilt : SymbolId(26): [ReferenceId(16)]
103108
Symbol reference IDs mismatch for "TestWorkingCopyBackupTracker":
104109
after transform: SymbolId(39): [ReferenceId(42), ReferenceId(74), ReferenceId(154), ReferenceId(215)]
105110
rebuilt : SymbolId(34): [ReferenceId(65), ReferenceId(216)]
111+
Symbol flags mismatch for "_createTracker":
112+
after transform: SymbolId(136): SymbolFlags(FunctionScopedVariable)
113+
rebuilt : SymbolId(49): SymbolFlags(Function)
114+
Symbol flags mismatch for "_untitledBackupTest":
115+
after transform: SymbolId(139): SymbolFlags(FunctionScopedVariable)
116+
rebuilt : SymbolId(56): SymbolFlags(Function)
106117
Symbol scope ID mismatch for "_untitledTextModel$te":
107118
after transform: SymbolId(138): ScopeId(14)
108119
rebuilt : SymbolId(63): ScopeId(20)
120+
Symbol flags mismatch for "_restoreBackupsInit":
121+
after transform: SymbolId(140): SymbolFlags(FunctionScopedVariable)
122+
rebuilt : SymbolId(73): SymbolFlags(Function)
109123
Unresolved reference IDs mismatch for "Promise":
110124
after transform: [ReferenceId(36), ReferenceId(39), ReferenceId(82), ReferenceId(114), ReferenceId(153), ReferenceId(282)]
111125
rebuilt : [ReferenceId(289)]

0 commit comments

Comments
 (0)