mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(linter/tree-shaking): check this in different environment (#2901)
This commit is contained in:
parent
acb6eb2573
commit
59869d0a96
3 changed files with 67 additions and 30 deletions
|
|
@ -26,7 +26,7 @@ pub struct NodeListenerOptions<'a, 'b> {
|
|||
checked_mutated_nodes: RefCell<FxHashSet<SymbolId>>,
|
||||
ctx: &'b LintContext<'a>,
|
||||
has_valid_this: Cell<bool>,
|
||||
call_with_new: Cell<bool>,
|
||||
called_with_new: Cell<bool>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> NodeListenerOptions<'a, 'b> {
|
||||
|
|
@ -41,7 +41,7 @@ impl<'a, 'b> NodeListenerOptions<'a, 'b> {
|
|||
checked_mutated_nodes: RefCell::new(FxHashSet::default()),
|
||||
ctx,
|
||||
has_valid_this: Cell::new(false),
|
||||
call_with_new: Cell::new(false),
|
||||
called_with_new: Cell::new(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -115,6 +115,12 @@ impl<'a> ListenerMap for AstNode<'a> {
|
|||
.ctx
|
||||
.diagnostic(NoSideEffectsDiagnostic::CallParameter(Span::new(start, end)));
|
||||
}
|
||||
AstKind::Function(function) => {
|
||||
let old_val = options.has_valid_this.get();
|
||||
options.has_valid_this.set(options.called_with_new.get());
|
||||
function.report_effects_when_called(options);
|
||||
options.has_valid_this.set(old_val);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -246,7 +252,10 @@ impl<'a> ListenerMap for Expression<'a> {
|
|||
expr.report_effects_when_called(options);
|
||||
}
|
||||
Self::FunctionExpression(expr) => {
|
||||
let old_val = options.has_valid_this.get();
|
||||
options.has_valid_this.set(options.called_with_new.get());
|
||||
expr.report_effects_when_called(options);
|
||||
options.has_valid_this.set(old_val);
|
||||
}
|
||||
Self::ArrowFunctionExpression(expr) => {
|
||||
expr.report_effects_when_called(options);
|
||||
|
|
@ -290,10 +299,10 @@ impl<'a> ListenerMap for NewExpression<'a> {
|
|||
return;
|
||||
}
|
||||
self.arguments.iter().for_each(|arg| arg.report_effects(options));
|
||||
let old_val = options.call_with_new.get();
|
||||
options.call_with_new.set(true);
|
||||
let old_val = options.called_with_new.get();
|
||||
options.called_with_new.set(true);
|
||||
self.callee.report_effects_when_called(options);
|
||||
options.call_with_new.set(old_val);
|
||||
options.called_with_new.set(old_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -318,22 +327,17 @@ impl<'a> ListenerMap for ParenthesizedExpression<'a> {
|
|||
impl<'a> ListenerMap for ArrowFunctionExpression<'a> {
|
||||
fn report_effects_when_called(&self, options: &NodeListenerOptions) {
|
||||
self.params.items.iter().for_each(|param| param.report_effects(options));
|
||||
let old_val = options.has_valid_this.get();
|
||||
options.has_valid_this.set(options.call_with_new.get());
|
||||
self.body.statements.iter().for_each(|stmt| stmt.report_effects(options));
|
||||
options.has_valid_this.set(old_val);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ListenerMap for Function<'a> {
|
||||
fn report_effects_when_called(&self, options: &NodeListenerOptions) {
|
||||
self.params.items.iter().for_each(|param| param.report_effects(options));
|
||||
let old_val = options.has_valid_this.get();
|
||||
options.has_valid_this.set(options.call_with_new.get());
|
||||
|
||||
if let Some(body) = &self.body {
|
||||
body.statements.iter().for_each(|stmt| stmt.report_effects(options));
|
||||
}
|
||||
options.has_valid_this.set(old_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -347,7 +351,10 @@ impl<'a> ListenerMap for CallExpression<'a> {
|
|||
fn report_effects(&self, options: &NodeListenerOptions) {
|
||||
self.arguments.iter().for_each(|arg| arg.report_effects(options));
|
||||
if defined_custom_report_effects_when_called(&self.callee) {
|
||||
let old_value = options.called_with_new.get();
|
||||
options.called_with_new.set(false);
|
||||
self.callee.report_effects_when_called(options);
|
||||
options.called_with_new.set(old_value);
|
||||
} else {
|
||||
// TODO: Not work now
|
||||
options.ctx.diagnostic(NoSideEffectsDiagnostic::Call(self.callee.span()));
|
||||
|
|
|
|||
|
|
@ -328,12 +328,12 @@ fn test() {
|
|||
// "const x = `Literal ${ext}`",
|
||||
// r#"const x = ()=>"a"; const y = `Literal ${x()}`"#,
|
||||
// // ThisExpression
|
||||
// "const y = this.x",
|
||||
"const y = this.x",
|
||||
// // ThisExpression when mutated
|
||||
// "const y = new (function (){this.x = 1})()",
|
||||
// "const y = new (function (){{this.x = 1}})()",
|
||||
// "const y = new (function (){(()=>{this.x = 1})()})()",
|
||||
// "function x(){this.y = 1}; const y = new x()",
|
||||
"const y = new (function (){this.x = 1})()",
|
||||
"const y = new (function (){{this.x = 1}})()",
|
||||
"const y = new (function (){(()=>{this.x = 1})()})()",
|
||||
"function x(){this.y = 1}; const y = new x()",
|
||||
// // TryStatement
|
||||
// "try {} catch (error) {}",
|
||||
// "try {} finally {}",
|
||||
|
|
@ -365,13 +365,13 @@ fn test() {
|
|||
];
|
||||
|
||||
let fail = vec![
|
||||
// // ArrayExpression
|
||||
// ArrayExpression
|
||||
"const x = [ext()]",
|
||||
"const x = [,,ext(),]",
|
||||
// // ArrayPattern
|
||||
// ArrayPattern
|
||||
"const [x = ext()] = []",
|
||||
"const [,x = ext(),] = []",
|
||||
// // ArrowFunctionExpression when called
|
||||
// ArrowFunctionExpression when called
|
||||
"(()=>{ext()})()",
|
||||
"(({a = ext()})=>{})()",
|
||||
"(a=>{a()})(ext)",
|
||||
|
|
@ -381,7 +381,7 @@ fn test() {
|
|||
"(a=>{const b = a;b.x = 1})(ext)",
|
||||
"((...a)=>{a.x = 1})(ext)",
|
||||
"(({a})=>{a.x = 1})(ext)",
|
||||
// // AssignmentExpression
|
||||
// AssignmentExpression
|
||||
"ext = 1",
|
||||
"ext += 1",
|
||||
"ext.x = 1",
|
||||
|
|
@ -399,12 +399,12 @@ fn test() {
|
|||
// "{ext()}",
|
||||
// "var x=()=>{};{var x=ext}x()",
|
||||
// "var x=ext;{x(); var x=()=>{}}",
|
||||
// // CallExpression
|
||||
// CallExpression
|
||||
"(()=>{})(ext(), 1)",
|
||||
"(()=>{})(1, ext())",
|
||||
// // CallExpression when called
|
||||
// CallExpression when called
|
||||
"const x = ()=>ext; const y = x(); y()",
|
||||
// // CallExpression when mutated
|
||||
// CallExpression when mutated
|
||||
"const x = ()=>ext; const y = x(); y.z = 1",
|
||||
// // CatchClause
|
||||
// "try {} catch (error) {ext()}",
|
||||
|
|
@ -580,7 +580,7 @@ fn test() {
|
|||
// "const x = {y: ext};delete x.y.z",
|
||||
// // MethodDefinition
|
||||
// "class x {static [ext()](){}}",
|
||||
// // NewExpression
|
||||
// NewExpression
|
||||
"const x = new ext()",
|
||||
"new ext()",
|
||||
// // ObjectExpression
|
||||
|
|
@ -612,12 +612,12 @@ fn test() {
|
|||
// "const x = ()=>{}; const y = x`${ext()}`",
|
||||
// // TemplateLiteral
|
||||
// "const x = `Literal ${ext()}`",
|
||||
// // ThisExpression when mutated
|
||||
// "this.x = 1",
|
||||
// "(()=>{this.x = 1})()",
|
||||
// "(function(){this.x = 1}())",
|
||||
// "const y = new (function (){(function(){this.x = 1}())})()",
|
||||
// "function x(){this.y = 1}; x()",
|
||||
// ThisExpression when mutated
|
||||
"this.x = 1",
|
||||
"(()=>{this.x = 1})()",
|
||||
"(function(){this.x = 1}())",
|
||||
"const y = new (function (){(function(){this.x = 1}())})()",
|
||||
"function x(){this.y = 1}; x()",
|
||||
// // ThrowStatement
|
||||
// r#"throw new Error("Hello Error")"#,
|
||||
// // TryStatement
|
||||
|
|
|
|||
|
|
@ -145,3 +145,33 @@ expression: no_side_effects_in_initialization
|
|||
1 │ new ext()
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating unknown this value
|
||||
╭─[no_side_effects_in_initialization.tsx:1:1]
|
||||
1 │ this.x = 1
|
||||
· ────
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating unknown this value
|
||||
╭─[no_side_effects_in_initialization.tsx:1:7]
|
||||
1 │ (()=>{this.x = 1})()
|
||||
· ────
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating unknown this value
|
||||
╭─[no_side_effects_in_initialization.tsx:1:13]
|
||||
1 │ (function(){this.x = 1}())
|
||||
· ────
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating unknown this value
|
||||
╭─[no_side_effects_in_initialization.tsx:1:40]
|
||||
1 │ const y = new (function (){(function(){this.x = 1}())})()
|
||||
· ────
|
||||
╰────
|
||||
|
||||
⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating unknown this value
|
||||
╭─[no_side_effects_in_initialization.tsx:1:14]
|
||||
1 │ function x(){this.y = 1}; x()
|
||||
· ────
|
||||
╰────
|
||||
|
|
|
|||
Loading…
Reference in a new issue