Skip to content

Commit

Permalink
fix(linter/tree-shaking): avoid recursive function stackoverflow (#4191)
Browse files Browse the repository at this point in the history
fixes: #4164
  • Loading branch information
mysteryven committed Jul 11, 2024
1 parent 6c49007 commit cc7e893
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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![
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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]
1function 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]
1function 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]
1function 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]
1function 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]
1function x(){ext = 1}; const y = new x(); y = new x(); y = new x()
Expand Down Expand Up @@ -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]
1const 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]
1const 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()
Expand Down Expand Up @@ -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) {
6a.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({})
Expand Down
6 changes: 6 additions & 0 deletions crates/oxc_linter/src/utils/tree_shaking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand All @@ -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),
Expand All @@ -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)]
Expand Down

0 comments on commit cc7e893

Please sign in to comment.