@@ -3,7 +3,9 @@ use oxc_ast::{
3
3
AstKind ,
4
4
} ;
5
5
use oxc_macros:: declare_oxc_lint;
6
- use oxc_semantic:: { AstNodeId , AstNodes } ;
6
+ use oxc_semantic:: {
7
+ algo, petgraph:: visit:: Control , AstNodeId , AstNodes , BasicBlockId , EdgeType , InstructionKind ,
8
+ } ;
7
9
use oxc_span:: { Atom , CompactStr } ;
8
10
use oxc_syntax:: operator:: AssignmentOperator ;
9
11
@@ -236,13 +238,43 @@ impl Rule for RulesOfHooks {
236
238
return ctx. diagnostic ( diagnostics:: loop_hook ( span, hook_name) ) ;
237
239
}
238
240
239
- if semantic . cfg ( ) . has_conditional_path ( func_cfg_id, node_cfg_id) {
241
+ if has_conditional_path_accept_throw ( ctx , func_cfg_id, node_cfg_id) {
240
242
#[ allow( clippy:: needless_return) ]
241
243
return ctx. diagnostic ( diagnostics:: conditional_hook ( span, hook_name) ) ;
242
244
}
243
245
}
244
246
}
245
247
248
+ fn has_conditional_path_accept_throw (
249
+ ctx : & LintContext < ' _ > ,
250
+ from : BasicBlockId ,
251
+ to : BasicBlockId ,
252
+ ) -> bool {
253
+ let cfg = ctx. semantic ( ) . cfg ( ) ;
254
+ let graph = & cfg. graph ;
255
+ // All nodes should be able to reach the hook node, Otherwise we have a conditional/branching flow.
256
+ algo:: dijkstra ( graph, from, Some ( to) , |e| match e. weight ( ) {
257
+ EdgeType :: NewFunction => 1 ,
258
+ EdgeType :: Jump | EdgeType :: Unreachable | EdgeType :: Backedge | EdgeType :: Normal => 0 ,
259
+ } )
260
+ . into_iter ( )
261
+ . filter ( |( _, val) | * val == 0 )
262
+ . any ( |( f, _) | {
263
+ !cfg. is_reachabale_filtered ( f, to, |it| {
264
+ if cfg
265
+ . basic_block ( it)
266
+ . instructions ( )
267
+ . iter ( )
268
+ . any ( |i| matches ! ( i. kind, InstructionKind :: Throw ) )
269
+ {
270
+ Control :: Break ( true )
271
+ } else {
272
+ Control :: Continue
273
+ }
274
+ } )
275
+ } )
276
+ }
277
+
246
278
fn parent_func < ' a > ( nodes : & ' a AstNodes < ' a > , node : & AstNode ) -> Option < & ' a AstNode < ' a > > {
247
279
nodes. ancestors ( node. id ( ) ) . map ( |id| nodes. get_node ( id) ) . find ( |it| it. kind ( ) . is_function_like ( ) )
248
280
}
0 commit comments