mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
fix(semantic): reference flags not correctly resolved when after an export stmt (#8134)
fixes https://github.com/oxc-project/oxc/issues/7879#issuecomment-2562574889
TLDR is curently here:
cdd121bfa4/crates/oxc_semantic/src/builder.rs (L2130-L2135)
`self.current_reference_flags.is_empty()` is not empty, which causes the current ref flags to be used (this is incorrect, we should be using a fresh version of reference flags). Buy setting ref flags to `None` on exit export node, this issue is avoided
`export` **BEFORE** the reference ( incorrect reference flags)
https://playground.oxc.rs/#eNpVjjuOwzAMRK8isElj7A/YxtttkVOkkR3aECCJBskkdgzdPZISG0ilGc3DcFbooQUXJmI1q/m3bJIZmII5fHx2lg9/p4hzTXWZsCL3N+RekB3qvRUxRyKDs2I8S61cEzRA0K7Al1geWaLaGVrlCzbgXdRNS08T7mYJHfnNKdsoA3GAdrBeMDUwWRbk3Jh1adn0jtYPUMsj5hOA8vP1/QuZ6OmMI5Yx2QQX3eCebLBx9K8FlYvK5I+ebiW9InckOX4uSOkBCrdvkw==
`export` **AFTER** the reference ( correct reference flags)
https://playground.oxc.rs/#eNpVjj2uwjAQhK9ibZMmen/Sa0JHwSlonLCJLNm70a6BhMh3xzEEQeUZz6fZWaCDBlwYWaJZzN6KSaYXDqb6+m6tVLsjHQmnknfeqpoDs8EpIp208Et6Q+I8Yum5ffTcqh3UwNAsIGdaH50p2gmaKGeswTuKm9aOR3yZObTsNxfFkvYsAZreesVUw2hFUXJj1mvLpl9o+YBoZcB8AlD/fn7/IRMdn3DAdUw2wZHr3YMNlgb/XFA4isL+4Pm6pheUljXHjwUp3QEtmnBd
this PR fixes this issue by resetting the reference flags after exising an export stmt
This commit is contained in:
parent
74572de625
commit
79af10070d
4 changed files with 70 additions and 13 deletions
|
|
@ -1517,6 +1517,14 @@ fn test() {
|
|||
// ",
|
||||
// None,
|
||||
// ),
|
||||
(
|
||||
"import { Bar } from './bar';
|
||||
export type { Baz } from './baz';
|
||||
|
||||
export class Foo extends Bar {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
|
|
|
|||
|
|
@ -1861,25 +1861,27 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
|
|||
self.visit_declaration(declaration);
|
||||
}
|
||||
|
||||
for specifier in &it.specifiers {
|
||||
// `export type { a }` or `export { type a }` -> `a` is a type reference
|
||||
if it.export_kind.is_type() || specifier.export_kind.is_type() {
|
||||
self.current_reference_flags = ReferenceFlags::Type;
|
||||
} else {
|
||||
// If the export specifier is not a explicit type export, we consider it as a potential
|
||||
// type and value reference. If it references to a value in the end, we would delete the
|
||||
// `ReferenceFlags::Type` flag in `fn resolve_references_for_current_scope`.
|
||||
self.current_reference_flags = ReferenceFlags::Read | ReferenceFlags::Type;
|
||||
}
|
||||
self.visit_export_specifier(specifier);
|
||||
}
|
||||
|
||||
if let Some(source) = &it.source {
|
||||
self.visit_string_literal(source);
|
||||
self.visit_export_specifiers(&it.specifiers);
|
||||
} else {
|
||||
for specifier in &it.specifiers {
|
||||
// `export type { a }` or `export { type a }` -> `a` is a type reference
|
||||
if it.export_kind.is_type() || specifier.export_kind.is_type() {
|
||||
self.current_reference_flags = ReferenceFlags::Type;
|
||||
} else {
|
||||
// If the export specifier is not a explicit type export, we consider it as a potential
|
||||
// type and value reference. If it references to a value in the end, we would delete the
|
||||
// `ReferenceFlags::Type` flag in `fn resolve_references_for_current_scope`.
|
||||
self.current_reference_flags = ReferenceFlags::Read | ReferenceFlags::Type;
|
||||
}
|
||||
self.visit_export_specifier(specifier);
|
||||
}
|
||||
}
|
||||
if let Some(with_clause) = &it.with_clause {
|
||||
self.visit_with_clause(with_clause);
|
||||
}
|
||||
|
||||
self.leave_node(kind);
|
||||
}
|
||||
|
||||
|
|
|
|||
43
crates/oxc_semantic/tests/fixtures/oxc/ts/issue-7879.snap
vendored
Normal file
43
crates/oxc_semantic/tests/fixtures/oxc/ts/issue-7879.snap
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
source: crates/oxc_semantic/tests/main.rs
|
||||
input_file: crates/oxc_semantic/tests/fixtures/oxc/ts/issue-7879.ts
|
||||
---
|
||||
[
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
"flags": "ScopeFlags(StrictMode)",
|
||||
"id": 1,
|
||||
"node": "Class(Foo)",
|
||||
"symbols": []
|
||||
}
|
||||
],
|
||||
"flags": "ScopeFlags(StrictMode | Top)",
|
||||
"id": 0,
|
||||
"node": "Program",
|
||||
"symbols": [
|
||||
{
|
||||
"flags": "SymbolFlags(Import)",
|
||||
"id": 0,
|
||||
"name": "Bar",
|
||||
"node": "ImportSpecifier(Bar)",
|
||||
"references": [
|
||||
{
|
||||
"flags": "ReferenceFlags(Read)",
|
||||
"id": 0,
|
||||
"name": "Bar",
|
||||
"node_id": 17
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"flags": "SymbolFlags(Class)",
|
||||
"id": 1,
|
||||
"name": "Foo",
|
||||
"node": "Class(Foo)",
|
||||
"references": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
4
crates/oxc_semantic/tests/fixtures/oxc/ts/issue-7879.ts
vendored
Normal file
4
crates/oxc_semantic/tests/fixtures/oxc/ts/issue-7879.ts
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import { Bar } from "./bar";
|
||||
export type { Baz } from "./baz";
|
||||
|
||||
export class Foo extends Bar {}
|
||||
Loading…
Reference in a new issue