mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 20:28:58 +00:00
fix(linter/tree-shaking): avoid recursive function stackoverflow (#4191)
fixes: #4164
This commit is contained in:
parent
6c49007b27
commit
cc7e893634
4 changed files with 54 additions and 59 deletions
|
|
@ -488,7 +488,6 @@ impl<'a> ListenerMap for BindingIdentifier<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
let symbol_table = ctx.semantic().symbols();
|
||||
let node = ctx.nodes().get_node(symbol_table.get_declaration(symbol_id));
|
||||
node.report_effects_when_called(options);
|
||||
}
|
||||
|
|
@ -578,7 +577,6 @@ impl<'a> ListenerMap for Expression<'a> {
|
|||
}
|
||||
|
||||
fn report_effects_when_mutated(&self, options: &NodeListenerOptions) {
|
||||
#[allow(clippy::single_match)]
|
||||
match self {
|
||||
Self::Identifier(ident) => {
|
||||
ident.report_effects_when_mutated(options);
|
||||
|
|
@ -1135,18 +1133,20 @@ impl<'a> ListenerMap for IdentifierReference<'a> {
|
|||
|
||||
let ctx = options.ctx;
|
||||
if let Some(symbol_id) = get_symbol_id_of_variable(self, ctx) {
|
||||
let symbol_table = ctx.semantic().symbols();
|
||||
for reference in symbol_table.get_resolved_references(symbol_id) {
|
||||
if reference.is_write() {
|
||||
let node_id = reference.node_id();
|
||||
if let Some(expr) = get_write_expr(node_id, ctx) {
|
||||
expr.report_effects_when_called(options);
|
||||
if options.insert_called_node(symbol_id) {
|
||||
let symbol_table = ctx.semantic().symbols();
|
||||
for reference in symbol_table.get_resolved_references(symbol_id) {
|
||||
if reference.is_write() {
|
||||
let node_id = reference.node_id();
|
||||
if let Some(expr) = get_write_expr(node_id, ctx) {
|
||||
expr.report_effects_when_called(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
let symbol_table = ctx.semantic().symbols();
|
||||
let node = ctx.nodes().get_node(symbol_table.get_declaration(symbol_id));
|
||||
node.report_effects_when_called(options);
|
||||
}
|
||||
let symbol_table = ctx.semantic().symbols();
|
||||
let node = ctx.nodes().get_node(symbol_table.get_declaration(symbol_id));
|
||||
node.report_effects_when_called(options);
|
||||
} else {
|
||||
ctx.diagnostic(super::call_global(self.name.as_str(), self.span));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -503,6 +503,25 @@ fn test() {
|
|||
"function* x(){yield ext}; x()",
|
||||
// Supports TypeScript nodes
|
||||
"interface Blub {}",
|
||||
"
|
||||
function a() {
|
||||
a
|
||||
}
|
||||
function b() {
|
||||
b
|
||||
}
|
||||
export {
|
||||
a,
|
||||
b
|
||||
}
|
||||
",
|
||||
"
|
||||
const Comp = () => {
|
||||
<div>
|
||||
<Comp />
|
||||
</div>
|
||||
}
|
||||
",
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
|
|
@ -788,6 +807,16 @@ fn test() {
|
|||
"function* x(){yield ext()}; x()",
|
||||
// YieldExpression when called
|
||||
"function* x(){yield ext()}; x()",
|
||||
"
|
||||
function f() {
|
||||
try {
|
||||
f();
|
||||
} catch(e) {
|
||||
a.map(v => v + 1);
|
||||
}
|
||||
}
|
||||
f();
|
||||
",
|
||||
];
|
||||
|
||||
// test options
|
||||
|
|
|
|||
|
|
@ -541,18 +541,6 @@ source: crates/oxc_linter/src/tester.rs
|
|||
· ─
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling function parameter
|
||||
╭─[no_side_effects_in_initialization.tsx:1:12]
|
||||
1 │ function x(a){a(); a(); a()}; x(ext)
|
||||
· ─
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling function parameter
|
||||
╭─[no_side_effects_in_initialization.tsx:1:12]
|
||||
1 │ function x(a){a(); a(); a()}; x(ext)
|
||||
· ─
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating function parameter
|
||||
╭─[no_side_effects_in_initialization.tsx:1:12]
|
||||
1 │ function x(a){a.y = 1}; x(ext)
|
||||
|
|
@ -583,30 +571,6 @@ source: crates/oxc_linter/src/tester.rs
|
|||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of assignment to `ext`
|
||||
╭─[no_side_effects_in_initialization.tsx:1:14]
|
||||
1 │ function x(){ext = 1}; x(); x(); x()
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of assignment to `ext`
|
||||
╭─[no_side_effects_in_initialization.tsx:1:14]
|
||||
1 │ function x(){ext = 1}; x(); x(); x()
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of assignment to `ext`
|
||||
╭─[no_side_effects_in_initialization.tsx:1:14]
|
||||
1 │ function x(){ext = 1}; const y = new x(); y = new x(); y = new x()
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of assignment to `ext`
|
||||
╭─[no_side_effects_in_initialization.tsx:1:14]
|
||||
1 │ function x(){ext = 1}; const y = new x(); y = new x(); y = new x()
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of assignment to `ext`
|
||||
╭─[no_side_effects_in_initialization.tsx:1:14]
|
||||
1 │ function x(){ext = 1}; const y = new x(); y = new x(); y = new x()
|
||||
|
|
@ -709,18 +673,6 @@ source: crates/oxc_linter/src/tester.rs
|
|||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of assignment to `ext`
|
||||
╭─[no_side_effects_in_initialization.tsx:1:16]
|
||||
1 │ const x = ()=>{ext = 1}; x(); x(); x()
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of assignment to `ext`
|
||||
╭─[no_side_effects_in_initialization.tsx:1:16]
|
||||
1 │ const x = ()=>{ext = 1}; x(); x(); x()
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling function return value
|
||||
╭─[no_side_effects_in_initialization.tsx:1:31]
|
||||
1 │ const x = ()=>{}; const {y} = x(); y()
|
||||
|
|
@ -1303,6 +1255,14 @@ source: crates/oxc_linter/src/tester.rs
|
|||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling member function
|
||||
╭─[no_side_effects_in_initialization.tsx:6:13]
|
||||
5 │ } catch(e) {
|
||||
6 │ a.map(v => v + 1);
|
||||
· ─────
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling member function
|
||||
╭─[no_side_effects_in_initialization.tsx:1:1]
|
||||
1 │ Object.freeze({})
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ mod pure_functions;
|
|||
|
||||
pub struct NodeListenerOptions<'a, 'b> {
|
||||
pub checked_mutated_nodes: RefCell<FxHashSet<SymbolId>>,
|
||||
pub checked_called_nodes: RefCell<FxHashSet<SymbolId>>,
|
||||
pub ctx: &'b LintContext<'a>,
|
||||
pub has_valid_this: Cell<bool>,
|
||||
pub called_with_new: Cell<bool>,
|
||||
|
|
@ -27,6 +28,7 @@ impl<'a, 'b> NodeListenerOptions<'a, 'b> {
|
|||
pub fn new(ctx: &'b LintContext<'a>) -> Self {
|
||||
Self {
|
||||
checked_mutated_nodes: RefCell::new(FxHashSet::default()),
|
||||
checked_called_nodes: RefCell::new(FxHashSet::default()),
|
||||
ctx,
|
||||
has_valid_this: Cell::new(false),
|
||||
called_with_new: Cell::new(false),
|
||||
|
|
@ -46,6 +48,10 @@ impl<'a, 'b> NodeListenerOptions<'a, 'b> {
|
|||
pub fn insert_mutated_node(&self, symbol_id: SymbolId) -> bool {
|
||||
self.checked_mutated_nodes.borrow_mut().insert(symbol_id)
|
||||
}
|
||||
|
||||
pub fn insert_called_node(&self, symbol_id: SymbolId) -> bool {
|
||||
self.checked_called_nodes.borrow_mut().insert(symbol_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
|
|
|||
Loading…
Reference in a new issue