mirror of
https://github.com/danbulant/oxc
synced 2026-05-20 04:38:54 +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));
|
let node = ctx.nodes().get_node(symbol_table.get_declaration(symbol_id));
|
||||||
node.report_effects_when_called(options);
|
node.report_effects_when_called(options);
|
||||||
}
|
}
|
||||||
|
|
@ -578,7 +577,6 @@ impl<'a> ListenerMap for Expression<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_effects_when_mutated(&self, options: &NodeListenerOptions) {
|
fn report_effects_when_mutated(&self, options: &NodeListenerOptions) {
|
||||||
#[allow(clippy::single_match)]
|
|
||||||
match self {
|
match self {
|
||||||
Self::Identifier(ident) => {
|
Self::Identifier(ident) => {
|
||||||
ident.report_effects_when_mutated(options);
|
ident.report_effects_when_mutated(options);
|
||||||
|
|
@ -1135,18 +1133,20 @@ impl<'a> ListenerMap for IdentifierReference<'a> {
|
||||||
|
|
||||||
let ctx = options.ctx;
|
let ctx = options.ctx;
|
||||||
if let Some(symbol_id) = get_symbol_id_of_variable(self, ctx) {
|
if let Some(symbol_id) = get_symbol_id_of_variable(self, ctx) {
|
||||||
let symbol_table = ctx.semantic().symbols();
|
if options.insert_called_node(symbol_id) {
|
||||||
for reference in symbol_table.get_resolved_references(symbol_id) {
|
let symbol_table = ctx.semantic().symbols();
|
||||||
if reference.is_write() {
|
for reference in symbol_table.get_resolved_references(symbol_id) {
|
||||||
let node_id = reference.node_id();
|
if reference.is_write() {
|
||||||
if let Some(expr) = get_write_expr(node_id, ctx) {
|
let node_id = reference.node_id();
|
||||||
expr.report_effects_when_called(options);
|
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 {
|
} else {
|
||||||
ctx.diagnostic(super::call_global(self.name.as_str(), self.span));
|
ctx.diagnostic(super::call_global(self.name.as_str(), self.span));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -503,6 +503,25 @@ fn test() {
|
||||||
"function* x(){yield ext}; x()",
|
"function* x(){yield ext}; x()",
|
||||||
// Supports TypeScript nodes
|
// Supports TypeScript nodes
|
||||||
"interface Blub {}",
|
"interface Blub {}",
|
||||||
|
"
|
||||||
|
function a() {
|
||||||
|
a
|
||||||
|
}
|
||||||
|
function b() {
|
||||||
|
b
|
||||||
|
}
|
||||||
|
export {
|
||||||
|
a,
|
||||||
|
b
|
||||||
|
}
|
||||||
|
",
|
||||||
|
"
|
||||||
|
const Comp = () => {
|
||||||
|
<div>
|
||||||
|
<Comp />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
",
|
||||||
];
|
];
|
||||||
|
|
||||||
let fail = vec![
|
let fail = vec![
|
||||||
|
|
@ -788,6 +807,16 @@ fn test() {
|
||||||
"function* x(){yield ext()}; x()",
|
"function* x(){yield ext()}; x()",
|
||||||
// YieldExpression when called
|
// YieldExpression when called
|
||||||
"function* x(){yield ext()}; x()",
|
"function* x(){yield ext()}; x()",
|
||||||
|
"
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
f();
|
||||||
|
} catch(e) {
|
||||||
|
a.map(v => v + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
",
|
||||||
];
|
];
|
||||||
|
|
||||||
// test options
|
// 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
|
⚠ 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]
|
╭─[no_side_effects_in_initialization.tsx:1:12]
|
||||||
1 │ function x(a){a.y = 1}; x(ext)
|
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`
|
⚠ 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]
|
╭─[no_side_effects_in_initialization.tsx:1:14]
|
||||||
1 │ function x(){ext = 1}; const y = new x(); y = new x(); y = new x()
|
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
|
⚠ 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]
|
╭─[no_side_effects_in_initialization.tsx:1:31]
|
||||||
1 │ const x = ()=>{}; const {y} = x(); y()
|
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
|
⚠ 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]
|
╭─[no_side_effects_in_initialization.tsx:1:1]
|
||||||
1 │ Object.freeze({})
|
1 │ Object.freeze({})
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ mod pure_functions;
|
||||||
|
|
||||||
pub struct NodeListenerOptions<'a, 'b> {
|
pub struct NodeListenerOptions<'a, 'b> {
|
||||||
pub checked_mutated_nodes: RefCell<FxHashSet<SymbolId>>,
|
pub checked_mutated_nodes: RefCell<FxHashSet<SymbolId>>,
|
||||||
|
pub checked_called_nodes: RefCell<FxHashSet<SymbolId>>,
|
||||||
pub ctx: &'b LintContext<'a>,
|
pub ctx: &'b LintContext<'a>,
|
||||||
pub has_valid_this: Cell<bool>,
|
pub has_valid_this: Cell<bool>,
|
||||||
pub called_with_new: 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 {
|
pub fn new(ctx: &'b LintContext<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
checked_mutated_nodes: RefCell::new(FxHashSet::default()),
|
checked_mutated_nodes: RefCell::new(FxHashSet::default()),
|
||||||
|
checked_called_nodes: RefCell::new(FxHashSet::default()),
|
||||||
ctx,
|
ctx,
|
||||||
has_valid_this: Cell::new(false),
|
has_valid_this: Cell::new(false),
|
||||||
called_with_new: 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 {
|
pub fn insert_mutated_node(&self, symbol_id: SymbolId) -> bool {
|
||||||
self.checked_mutated_nodes.borrow_mut().insert(symbol_id)
|
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)]
|
#[derive(Debug, Default, Clone)]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue