diff --git a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs index b71566da5..f14f1255e 100644 --- a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs +++ b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs @@ -9,7 +9,7 @@ use oxc_ast::{ JSXAttributeValue, JSXChild, JSXElement, JSXElementName, JSXExpression, JSXExpressionContainer, JSXFragment, JSXIdentifier, JSXOpeningElement, LogicalExpression, MemberExpression, ModuleExportName, NewExpression, ObjectExpression, ObjectPropertyKind, - ParenthesizedExpression, PrivateFieldExpression, Program, PropertyKey, + ParenthesizedExpression, PrivateFieldExpression, Program, PropertyKey, SequenceExpression, SimpleAssignmentTarget, Statement, StaticMemberExpression, ThisExpression, UnaryExpression, VariableDeclarator, }, @@ -439,6 +439,7 @@ impl<'a> ListenerMap for BindingPattern<'a> { } BindingPatternKind::ObjectPattern(object) => { object.properties.iter().for_each(|prop| { + prop.key.report_effects(options); prop.value.report_effects(options); }); } @@ -533,6 +534,9 @@ impl<'a> ListenerMap for Expression<'a> { Self::UpdateExpression(expr) => { expr.argument.report_effects_when_assigned(options); } + Self::SequenceExpression(expr) => { + expr.get_value_and_report_effects(options); + } Self::ArrowFunctionExpression(_) | Self::FunctionExpression(_) | Self::Identifier(_) @@ -612,6 +616,7 @@ impl<'a> ListenerMap for Expression<'a> { Self::BinaryExpression(expr) => expr.get_value_and_report_effects(options), Self::ConditionalExpression(expr) => expr.get_value_and_report_effects(options), Self::LogicalExpression(expr) => expr.get_value_and_report_effects(options), + Self::SequenceExpression(expr) => expr.get_value_and_report_effects(options), _ => { self.report_effects(options); Value::Unknown @@ -636,6 +641,16 @@ fn defined_custom_report_effects_when_called(expr: &Expression) -> bool { ) } +impl<'a> ListenerMap for SequenceExpression<'a> { + fn get_value_and_report_effects(&self, options: &NodeListenerOptions) -> Value { + let mut val = Value::Unknown; + for expr in &self.expressions { + val = expr.get_value_and_report_effects(options); + } + val + } +} + impl<'a> ListenerMap for UnaryExpression<'a> { fn get_value_and_report_effects(&self, options: &NodeListenerOptions) -> Value { if self.operator == UnaryOperator::Delete { @@ -864,6 +879,9 @@ impl<'a> ListenerMap for JSXExpression<'a> { Self::UnaryExpression(expr) => { expr.get_value_and_report_effects(options); } + Self::SequenceExpression(expr) => { + expr.get_value_and_report_effects(options); + } Self::ArrowFunctionExpression(_) | Self::EmptyExpression(_) | Self::FunctionExpression(_) diff --git a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs index efebc1eb3..d3031074d 100644 --- a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs +++ b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs @@ -324,21 +324,21 @@ fn test() { "const x = new (function (){this.x = 1})()", "function x(){this.y = 1}; const z = new x()", "/*@__PURE__*/ new ext()", - // // ObjectExpression - // "const x = {y: ext}", - // r#"const x = {["y"]: ext}"#, - // "const x = {};x.y = ext", - // // ObjectPattern - // "const {x} = {}", - // "const {[ext]: x} = {}", - // // RestElement - // "const [...x] = []", - // // ReturnStatement - // "(()=>{return})()", - // "(()=>{return 1})()", - // // SequenceExpression - // "let x = 1; x++, x++", - // "if (ext, false) ext()", + // ObjectExpression + "const x = {y: ext}", + r#"const x = {["y"]: ext}"#, + "const x = {};x.y = ext", + // ObjectPattern + "const {x} = {}", + "const {[ext]: x} = {}", + // RestElement + "const [...x] = []", + // ReturnStatement + "(()=>{return})()", + "(()=>{return 1})()", + // SequenceExpression + "let x = 1; x++, x++", + "if (ext, false) ext()", // // SwitchCase // "switch(ext){case ext:const x = 1;break;default:}", // // SwitchStatement @@ -609,19 +609,19 @@ fn test() { // NewExpression "const x = new ext()", "new ext()", - // // ObjectExpression - // "const x = {y: ext()}", - // r#"const x = {["y"]: ext()}"#, - // "const x = {[ext()]: 1}", - // // ObjectPattern - // "const {[ext()]: x} = {}", - // // ReturnStatement - // "(()=>{return ext()})()", - // // SequenceExpression - // "ext(), 1", - // "1, ext()", - // "if (1, true) ext()", - // "if (1, ext) ext()", + // ObjectExpression + "const x = {y: ext()}", + r#"const x = {["y"]: ext()}"#, + "const x = {[ext()]: 1}", + // ObjectPattern + "const {[ext()]: x} = {}", + // ReturnStatement + "(()=>{return ext()})()", + // SequenceExpression + "ext(), 1", + "1, ext()", + "if (1, true) ext()", + "if (1, ext) ext()", // // Super when called // "class y {constructor(){ext()}}; class x extends y {constructor(){super()}}; const z = new x()", // "class y{}; class x extends y{constructor(){super(); super.test()}}; const z = new x()", diff --git a/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap b/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap index 667667134..ef32f319f 100644 --- a/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap +++ b/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap @@ -1016,6 +1016,60 @@ expression: no_side_effects_in_initialization · ─── ╰──── + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:15] + 1 │ const x = {y: ext()} + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:19] + 1 │ const x = {["y"]: ext()} + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:13] + 1 │ const x = {[ext()]: 1} + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:9] + 1 │ const {[ext()]: x} = {} + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:14] + 1 │ (()=>{return ext()})() + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:1] + 1 │ ext(), 1 + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:4] + 1 │ 1, ext() + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:14] + 1 │ if (1, true) ext() + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:13] + 1 │ if (1, ext) 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