feat(linter/tree-shaking): support SequenceExpression (#3154)

This commit is contained in:
Wang Wenzhe 2024-05-03 23:19:36 +08:00 committed by GitHub
parent 5c21b7f843
commit 8290421e72
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 101 additions and 29 deletions

View file

@ -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(_)

View file

@ -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()",

View file

@ -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