From e5614576832b8dca4925e016d27df2c9ec4de92c Mon Sep 17 00:00:00 2001 From: Tzvi Melamed Date: Thu, 1 Feb 2024 00:27:20 -0500 Subject: [PATCH] feat(semantic): track cfg index per ast node (#2210) This allows looking up a cfg index from an ast node in a semantics return. This allows later passes to better make use of the cfg. --- .../src/rules/eslint/getter_return.rs | 4 +- crates/oxc_semantic/examples/simple.rs | 2 + crates/oxc_semantic/src/builder.rs | 30 ++- crates/oxc_semantic/src/control_flow.rs | 212 +++--------------- crates/oxc_semantic/src/lib.rs | 5 +- crates/oxc_semantic/src/node.rs | 13 +- crates/oxc_semantic/src/pg.rs | 21 +- ...fg__cfg_files@class_extend_super.js-2.snap | 9 +- .../cfg__cfg_files@class_extend_super.js.snap | 6 +- ...eturn_obj_expr_with_computed_key.js-2.snap | 9 +- ..._return_obj_expr_with_computed_key.js.snap | 6 +- .../cfg__cfg_files@if_else.js-2.snap | 27 ++- .../snapshots/cfg__cfg_files@if_else.js.snap | 22 +- ...fg__cfg_files@labelled_try_break.js-2.snap | 39 ++-- .../cfg__cfg_files@labelled_try_break.js.snap | 20 +- ...ember_access_with_numbered_index.js-2.snap | 10 +- ...@member_access_with_numbered_index.js.snap | 12 +- ...s@member_access_with_unreachable.js-2.snap | 10 +- ...les@member_access_with_unreachable.js.snap | 12 +- ...ested_computed_member_expression.js-2.snap | 9 +- ...@nested_computed_member_expression.js.snap | 6 +- .../cfg__cfg_files@private_in.js-2.snap | 9 +- .../cfg__cfg_files@private_in.js.snap | 6 +- .../cfg__cfg_files@simple_spread.js-2.snap | 9 +- .../cfg__cfg_files@simple_spread.js.snap | 6 +- ...fg__cfg_files@spread_in_a_spread.js-2.snap | 9 +- .../cfg__cfg_files@spread_in_a_spread.js.snap | 6 +- .../cfg__cfg_files@switch_statement.js-2.snap | 53 ++--- .../cfg__cfg_files@switch_statement.js.snap | 22 +- .../cfg__cfg_files@two_functions.js-2.snap | 18 +- .../cfg__cfg_files@two_functions.js.snap | 16 +- .../snapshots/cfg__cfg_files@while.js-2.snap | 18 +- .../snapshots/cfg__cfg_files@while.js.snap | 14 +- 33 files changed, 318 insertions(+), 352 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/getter_return.rs b/crates/oxc_linter/src/rules/eslint/getter_return.rs index 66f680411..a9dd12519 100644 --- a/crates/oxc_linter/src/rules/eslint/getter_return.rs +++ b/crates/oxc_linter/src/rules/eslint/getter_return.rs @@ -154,7 +154,7 @@ impl GetterReturn { let output = neighbors_filtered_by_edge_weight( &cfg.graph, - cfg.function_to_node_ix[&node.id()], + node.cfg_ix(), &|edge| match edge { EdgeType::Normal => None, // We don't need to handle backedges because we would have already visited @@ -178,7 +178,7 @@ impl GetterReturn { // previous such as [`no_this_before_super`] we would want to observe this value. &mut |basic_block_id, _state_going_into_this_rule| { // Scan through the values in this basic block. - for entry in &cfg.basic_blocks[*basic_block_id] { + for entry in cfg.basic_block_by_index(*basic_block_id) { match entry { // If the element is an assignment. // diff --git a/crates/oxc_semantic/examples/simple.rs b/crates/oxc_semantic/examples/simple.rs index 7f7e29c0f..e3ed731be 100644 --- a/crates/oxc_semantic/examples/simple.rs +++ b/crates/oxc_semantic/examples/simple.rs @@ -21,6 +21,8 @@ fn main() { let ret = Parser::new(&allocator, &source_text, source_type).parse(); let program = allocator.alloc(ret.program); + println!("{:#?}", &program); + let semantic = SemanticBuilder::new(&source_text, source_type) .with_check_syntax_error(true) .with_trivias(ret.trivias) diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 451438037..bb218423a 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -209,7 +209,7 @@ impl<'a> SemanticBuilder<'a> { if self.jsdoc.retrieve_jsdoc_comment(kind) { flags |= NodeFlags::JSDoc; } - let ast_node = AstNode::new(kind, self.current_scope_id, flags); + let ast_node = AstNode::new(kind, self.current_scope_id, self.cfg.current_node_ix, flags); let parent_node_id = if matches!(kind, AstKind::Program(_)) { None } else { Some(self.current_node_id) }; self.current_node_id = self.nodes.add_node(ast_node, parent_node_id); @@ -1012,6 +1012,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { /* cfg */ /* cfg - put unreachable after return */ + let _ = self.cfg.new_basic_block(); self.cfg.put_unreachable(); self.cfg.after_statement( @@ -1164,7 +1165,6 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { let before_try_stmt_graph_ix = self.cfg.current_node_ix; let catch_block_graph_ix = self.cfg.new_basic_block(); - let catch_block_basic_block_id = self.cfg.current_basic_block; // every statement created with this active adds an edge from that node to this // catch block node // @@ -1186,7 +1186,6 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { let optional_catch_block_graph_ix = if let Some(handler) = &stmt.handler { /* cfg */ self.cfg.current_node_ix = catch_block_graph_ix; - self.cfg.current_basic_block = catch_block_basic_block_id; /* cfg */ self.visit_catch_clause(handler); @@ -1417,14 +1416,19 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { } flags }); - self.enter_node(kind); /* cfg */ let preserved = self.cfg.preserve_expression_state(); let before_function_graph_ix = self.cfg.current_node_ix; let function_graph_ix = self.cfg.new_basic_block_for_function(); - self.cfg.function_to_node_ix.insert(self.current_node_id, function_graph_ix); + /* cfg */ + + // We add a new basic block to the cfg before entering the node + // so that the correct cfg_ix is associated with the ast node. + self.enter_node(kind); + + /* cfg */ self.cfg.add_edge(before_function_graph_ix, function_graph_ix, EdgeType::NewFunction); /* cfg */ @@ -1510,17 +1514,20 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { fn visit_arrow_expression(&mut self, expr: &ArrowExpression<'a>) { let kind = AstKind::ArrowExpression(self.alloc(expr)); self.enter_scope(ScopeFlags::Function | ScopeFlags::Arrow); + + /* cfg */ + let preserved = self.cfg.preserve_expression_state(); + let current_node_ix = self.cfg.current_node_ix; + let function_graph_ix = self.cfg.new_basic_block_for_function(); + /* cfg */ + + // We add a new basic block to the cfg before entering the node + // so that the correct cfg_ix is associated with the ast node. self.enter_node(kind); self.visit_formal_parameters(&expr.params); /* cfg */ - let preserved = self.cfg.preserve_expression_state(); - - let current_basic_block_ix = self.cfg.current_basic_block; - let current_node_ix = self.cfg.current_node_ix; - let function_graph_ix = self.cfg.new_basic_block_for_function(); - self.cfg.function_to_node_ix.insert(self.current_node_id, function_graph_ix); self.cfg.add_edge(current_node_ix, function_graph_ix, EdgeType::NewFunction); if expr.expression { self.cfg.store_assignments_into_this_array.push(vec![]); @@ -1531,7 +1538,6 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { /* cfg */ self.cfg.restore_expression_state(preserved); - self.cfg.current_basic_block = current_basic_block_ix; self.cfg.current_node_ix = current_node_ix; // self.cfg.put_x_in_register(AssignmentValue::Function(self.current_node_id)); /* cfg */ diff --git a/crates/oxc_semantic/src/control_flow.rs b/crates/oxc_semantic/src/control_flow.rs index 27c179bed..8a612a3af 100644 --- a/crates/oxc_semantic/src/control_flow.rs +++ b/crates/oxc_semantic/src/control_flow.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use oxc_span::Atom; use oxc_syntax::operator::{ AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator, @@ -117,13 +115,13 @@ pub enum EdgeType { NewFunction, } +#[derive(Debug, Default)] pub struct ControlFlowGraph { pub basic_blocks: Vec>, // note: this should only land in the big box for all things that take arguments // ie: callexpression, arrayexpression, etc // todo: add assert that it is used every time? pub use_this_register: Option, - pub current_basic_block: usize, pub next_free_register: u32, pub store_assignments_into_this_array: Vec>, pub store_final_assignments_into_this_array: Vec>, @@ -144,41 +142,31 @@ pub struct ControlFlowGraph { pub next_label: Option, pub label_to_ast_node_ix: Vec<(Atom, AstNodeId)>, pub ast_node_to_break_continue: Vec<(AstNodeId, usize, Option)>, - pub function_to_node_ix: HashMap, pub after_throw_block: Option, } -impl Default for ControlFlowGraph { - fn default() -> Self { - Self::new() - } -} - impl ControlFlowGraph { pub fn new() -> Self { - Self { - basic_blocks: Vec::new(), - use_this_register: None, - current_basic_block: 0, - next_free_register: 0, - store_assignments_into_this_array: Vec::new(), - store_final_assignments_into_this_array: Vec::new(), - spread_indices: Vec::new(), - should_save_stores_for_patching: false, - saved_stores: Vec::new(), - saved_store: None, - graph: Graph::default(), - // todo: invalid state - current_node_ix: NodeIndex::default(), - basic_blocks_with_breaks: Vec::new(), - basic_blocks_with_continues: Vec::new(), - switch_case_conditions: Vec::new(), - next_label: None, - label_to_ast_node_ix: Vec::new(), - ast_node_to_break_continue: Vec::new(), - function_to_node_ix: HashMap::new(), - after_throw_block: None, - } + Self::default() + } + + /// # Panics + pub fn basic_block_by_index(&self, index: NodeIndex) -> &Vec { + let idx = + *self.graph.node_weight(index).expect("expected a valid node index in self.graph"); + self.basic_blocks.get(idx).expect("expected a valid node index in self.basic_blocks") + } + + /// # Panics + pub fn basic_block_by_index_mut(&mut self, index: NodeIndex) -> &mut Vec { + let idx = + *self.graph.node_weight(index).expect("expected a valid node index in self.graph"); + self.basic_blocks.get_mut(idx).expect("expected a valid node index in self.basic_blocks") + } + + /// # Panics + pub fn current_basic_block(&mut self) -> &mut Vec { + self.basic_block_by_index_mut(self.current_node_ix) } #[must_use] @@ -187,7 +175,6 @@ impl ControlFlowGraph { let basic_block_id = self.basic_blocks.len() - 1; let graph_index = self.graph.add_node(basic_block_id); self.current_node_ix = graph_index; - self.current_basic_block = basic_block_id; // todo: get smarter about what can throw, ie: return can't throw but it's expression can if let Some(after_throw_block) = self.after_throw_block { @@ -200,10 +187,8 @@ impl ControlFlowGraph { #[must_use] pub fn new_basic_block(&mut self) -> NodeIndex { self.basic_blocks.push(Vec::new()); - let basic_block_id = self.basic_blocks.len() - 1; - let graph_index = self.graph.add_node(basic_block_id); + let graph_index = self.graph.add_node(self.basic_blocks.len() - 1); self.current_node_ix = graph_index; - self.current_basic_block = basic_block_id; // todo: get smarter about what can throw, ie: return can't throw but it's expression can if let Some(after_throw_block) = self.after_throw_block { @@ -224,6 +209,7 @@ impl ControlFlowGraph { register } + /// # Panics pub fn put_x_in_register(&mut self, asmt_value: AssignmentValue) { let register = self.use_this_register.take().unwrap_or_else(|| self.new_register()); @@ -237,7 +223,7 @@ impl ControlFlowGraph { saved_store.0.push(basic_block_element); saved_store.1 = Some(register); } else { - self.basic_blocks[self.current_basic_block].push(basic_block_element); + self.current_basic_block().push(basic_block_element); } // used for storing the object base for MemberExpressions if let Some(arr) = self.store_assignments_into_this_array.last_mut() { @@ -249,166 +235,21 @@ impl ControlFlowGraph { } } - // pub fn put_callee_with_arguments_in_register( - // &mut self, - // expression_ast_node_id: AstNodeId, - // callee_node_index: Register, - // call_type: CallType, - // arguments: Vec, - // ) { - // let call_expression = AssignmentValue::CalleeWithArguments( - // CalleeWithArgumentsAssignmentValue { - // id: expression_ast_node_id, - // callee: callee_node_index, - // arguments, - // spreads: self - // .spread_indices - // .pop() - // .expect("expected there to be atleast one vec in the spread_indices"), - // call_type, - // } - // .into(), - // ); - - // self.put_x_in_register(call_expression); - // } - - // pub fn put_collection_in_register( - // &mut self, - // collection_ast_node_id: AstNodeId, - // collection_type: CollectionType, - // elements: Vec, - // ) { - // let array = AssignmentValue::Collection( - // CollectionAssignmentValue { - // id: collection_ast_node_id, - // elements, - // spreads: self - // .spread_indices - // .pop() - // .expect("expected there to be a corresponding spread_indices for an array"), - // collection_type, - // } - // .into(), - // ); - - // self.put_x_in_register(array); - // } - - // pub fn put_constant_in_register(&mut self, constant_ast_node_id: AstNodeId) { - // self.put_x_in_register(AssignmentValue::Constant(constant_ast_node_id)); - // } - - // pub fn put_reference_in_register(&mut self, constant_ast_node_id: AstNodeId) { - // self.put_x_in_register(AssignmentValue::Reference(constant_ast_node_id)); - // } - pub fn put_throw(&mut self, throw_expr: Register) { - self.basic_blocks[self.current_basic_block].push(BasicBlockElement::Throw(throw_expr)); + self.current_basic_block().push(BasicBlockElement::Throw(throw_expr)); } pub fn put_unreachable(&mut self) { let current_node_ix = self.current_node_ix; let basic_block_with_unreachable_graph_ix = self.new_basic_block(); self.add_edge(current_node_ix, basic_block_with_unreachable_graph_ix, EdgeType::Normal); - self.basic_blocks[self.current_basic_block].push(BasicBlockElement::Unreachable); + self.current_basic_block().push(BasicBlockElement::Unreachable); } pub fn put_undefined(&mut self) { self.put_x_in_register(AssignmentValue::ImplicitUndefined); } - // pub fn visit_computed_member_expression( - // &mut self, - // expr: &ComputedMemberExpression, - // ast_node_id: AstNodeId, - // ) { - // let basic_block = &mut self.basic_blocks[self.current_basic_block]; - // let removed = self.saved_stores.pop(); - // if let Some((saved_nodes, Some(last_register))) = removed { - // if self.should_save_stores_for_patching { - // let saved_store = self.saved_stores.last_mut().expect( - // "expected a saved_store if self.should_save_stores_for_patching is true", - // ); - // saved_store.0.extend(saved_nodes); - // saved_store.1 = Some(last_register); - // } else { - // basic_block.extend(saved_nodes); - // } - - // let accessed_on = { - // let asmts = self - // .store_assignments_into_this_array - // .pop() - // .expect("expected store_assignments_into_this_array to have an element"); - // debug_assert!(!asmts.is_empty(), "there should be at least the object base here"); - // asmts[asmts.len() - 1] - // }; - - // self.put_x_in_register(AssignmentValue::ObjectPropertyAccess( - // ObjectPropertyAccessAssignmentValue { - // id: ast_node_id, - // access_by: ObjectPropertyAccessBy::Expression(last_register), - // optional: expr.optional, - // access_on: accessed_on, - // } - // .into(), - // )); - // } else { - // panic!("No saved_node_indices in self.saved_stores") - // } - // } - - // pub fn visit_static_member_expression( - // &mut self, - // expr: &StaticMemberExpression, - // ast_node_id: AstNodeId, - // ) { - // let accessed_on = { - // let asmts = self - // .store_assignments_into_this_array - // .pop() - // .expect("expected store_assignments_into_this_array to have an element"); - // debug_assert!(!asmts.is_empty(), "there should be at least the object base here"); - // asmts[asmts.len() - 1] - // }; - - // self.put_x_in_register(AssignmentValue::ObjectPropertyAccess( - // ObjectPropertyAccessAssignmentValue { - // id: ast_node_id, - // access_by: ObjectPropertyAccessBy::Property(expr.property.name.clone()), // todo: should we be cloning here? - // optional: expr.optional, - // access_on: accessed_on, - // } - // .into(), - // )); - // } - - // pub fn visit_private_field_expression( - // &mut self, - // expr: &PrivateFieldExpression, - // ast_node_id: AstNodeId, - // ) { - // let accessed_on = { - // let asmts = self - // .store_assignments_into_this_array - // .pop() - // .expect("expected store_assignments_into_this_array to have an element"); - // debug_assert!(!asmts.is_empty(), "there should be at least the object base here"); - // asmts[asmts.len() - 1] - // }; - - // self.put_x_in_register(AssignmentValue::ObjectPropertyAccess( - // ObjectPropertyAccessAssignmentValue { - // id: ast_node_id, - // access_by: ObjectPropertyAccessBy::PrivateProperty(expr.field.name.clone()), // todo: should we be cloning here? - // optional: expr.optional, - // access_on: accessed_on, - // } - // .into(), - // )); - // } - #[must_use] pub fn preserve_expression_state(&mut self) -> PreservedExpressionState { let use_this_register = self.use_this_register.take(); @@ -471,6 +312,7 @@ impl ControlFlowGraph { pss } + /// # Panics pub fn after_statement( &mut self, preserved_state: &PreservedStatementState, diff --git a/crates/oxc_semantic/src/lib.rs b/crates/oxc_semantic/src/lib.rs index 21939cfa5..28f325ac4 100644 --- a/crates/oxc_semantic/src/lib.rs +++ b/crates/oxc_semantic/src/lib.rs @@ -19,7 +19,6 @@ pub use petgraph; pub use builder::{SemanticBuilder, SemanticBuilderReturn}; use class::ClassTable; -use control_flow::ControlFlowGraph; pub use jsdoc::{JSDoc, JSDocComment, JSDocTag}; use oxc_ast::{ast::IdentifierReference, AstKind, TriviasMap}; use oxc_span::SourceType; @@ -34,8 +33,8 @@ pub use crate::{ builder::VariableInfo, control_flow::{ print_basic_block, AssignmentValue, BasicBlockElement, BinaryAssignmentValue, BinaryOp, - CallType, CalleeWithArgumentsAssignmentValue, CollectionAssignmentValue, EdgeType, - ObjectPropertyAccessAssignmentValue, Register, UnaryExpressioneAssignmentValue, + CallType, CalleeWithArgumentsAssignmentValue, CollectionAssignmentValue, ControlFlowGraph, + EdgeType, ObjectPropertyAccessAssignmentValue, Register, UnaryExpressioneAssignmentValue, UpdateAssignmentValue, }, node::{AstNode, AstNodeId, AstNodes}, diff --git a/crates/oxc_semantic/src/node.rs b/crates/oxc_semantic/src/node.rs index 0849231ad..77987d9fc 100644 --- a/crates/oxc_semantic/src/node.rs +++ b/crates/oxc_semantic/src/node.rs @@ -1,3 +1,5 @@ +use petgraph::stable_graph::NodeIndex; + use oxc_ast::AstKind; use oxc_index::IndexVec; @@ -15,18 +17,25 @@ pub struct AstNode<'a> { /// Associated Scope (initialized by binding) scope_id: ScopeId, + /// Associated NodeIndex in CFG (initialized by control_flow) + cfg_ix: NodeIndex, + flags: NodeFlags, } impl<'a> AstNode<'a> { - pub fn new(kind: AstKind<'a>, scope_id: ScopeId, flags: NodeFlags) -> Self { - Self { id: AstNodeId::new(0), kind, scope_id, flags } + pub fn new(kind: AstKind<'a>, scope_id: ScopeId, cfg_ix: NodeIndex, flags: NodeFlags) -> Self { + Self { id: AstNodeId::new(0), kind, cfg_ix, scope_id, flags } } pub fn id(&self) -> AstNodeId { self.id } + pub fn cfg_ix(&self) -> NodeIndex { + self.cfg_ix + } + pub fn kind(&self) -> AstKind<'a> { self.kind } diff --git a/crates/oxc_semantic/src/pg.rs b/crates/oxc_semantic/src/pg.rs index 7ba7df2fd..1fb9e3b3a 100644 --- a/crates/oxc_semantic/src/pg.rs +++ b/crates/oxc_semantic/src/pg.rs @@ -19,14 +19,13 @@ pub fn neighbors_filtered_by_edge_weight< ) -> Vec where F: Fn(&EdgeWeight) -> Option, - G: FnMut(&NodeWeight, State) -> (State, bool), + G: FnMut(&NodeIndex, State) -> (State, bool), { let mut q = vec![]; let mut final_states = vec![]; // for initial node - let (new_state, keep_walking_this_path) = - visitor(graph.node_weight(node).unwrap(), Default::default()); + let (new_state, keep_walking_this_path) = visitor(&node, Default::default()); // if we will continue walking push this node if keep_walking_this_path { q.push((node, new_state)); @@ -42,7 +41,7 @@ where } else { let opposite_dir_of_edge_graph_ix = edge.target(); let (new_state, keep_walking_this_path) = - visitor(graph.node_weight(opposite_dir_of_edge_graph_ix).unwrap(), state); + visitor(&opposite_dir_of_edge_graph_ix, state); if keep_walking_this_path { q.push((opposite_dir_of_edge_graph_ix, new_state)); } else { @@ -65,13 +64,13 @@ pub fn replicate_tree_to_leaves( start_at: NodeIndex, cfg: &mut ControlFlowGraph, ) -> HashMap { - fn duplicate_graph_node(basic_block_id: usize, cfg: &mut ControlFlowGraph) -> NodeIndex { + fn duplicate_graph_node(basic_block_id: NodeIndex, cfg: &mut ControlFlowGraph) -> NodeIndex { let new_basic_block_graph_ix = cfg.new_basic_block(); // todo: what's a better way to do this? - for i in 0..cfg.basic_blocks[basic_block_id].len() { - let item = cfg.basic_blocks[basic_block_id][i].clone(); - cfg.basic_blocks[cfg.current_basic_block].push(item); + let items = cfg.basic_block_by_index(basic_block_id).clone(); + for item in items { + cfg.current_basic_block().push(item); } // todo: should we add the functions copied here to the function_to_node_ix? @@ -80,12 +79,11 @@ pub fn replicate_tree_to_leaves( } let preserved_graph_ix = cfg.current_node_ix; - let preserved_bb = cfg.current_basic_block; let mut old_to_new: HashMap = HashMap::default(); let mut q = vec![]; - let new_graph_start_ix = duplicate_graph_node(*cfg.graph.node_weight(start_at).unwrap(), cfg); + let new_graph_start_ix = duplicate_graph_node(start_at, cfg); old_to_new.insert(start_at, new_graph_start_ix); q.push((new_graph_start_ix, start_at)); let mut edges_finished_already = HashSet::new(); @@ -108,7 +106,7 @@ pub fn replicate_tree_to_leaves( let new_graph_ix = if old_to_new.contains_key(&to) { old_to_new[&to] } else { - let new_graph_ix = duplicate_graph_node(*cfg.graph.node_weight(to).unwrap(), cfg); + let new_graph_ix = duplicate_graph_node(to, cfg); old_to_new.insert(node.1, new_graph_start_ix); new_graph_ix }; @@ -119,7 +117,6 @@ pub fn replicate_tree_to_leaves( } } - cfg.current_basic_block = preserved_bb; cfg.current_node_ix = preserved_graph_ix; old_to_new } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js-2.snap index 16f724245..4b899c6a9 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js-2.snap @@ -6,10 +6,11 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/class_extend_super.js digraph { 0 [ label = ""] 1 [ label = "$return = "] - 2 [ label = "Unreachable()"] - 3 [ label = ""] + 2 [ label = ""] + 3 [ label = "Unreachable()"] + 4 [ label = ""] 0 -> 1 [ ] - 1 -> 2 [ ] - 0 -> 3 [ ] + 2 -> 3 [ ] + 0 -> 4 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js.snap index 004891520..d82dbc18a 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js.snap @@ -12,9 +12,13 @@ bb1: { } bb2: { - Unreachable() + } bb3: { + Unreachable() +} + +bb4: { } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js-2.snap index e0df97d7d..50fddee87 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js-2.snap @@ -6,10 +6,11 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/fn_return_obj_expr_with_compu digraph { 0 [ label = ""] 1 [ label = "$return = "] - 2 [ label = "Unreachable()"] - 3 [ label = ""] + 2 [ label = ""] + 3 [ label = "Unreachable()"] + 4 [ label = ""] 0 -> 1 [ ] - 1 -> 2 [ ] - 0 -> 3 [ ] + 2 -> 3 [ ] + 0 -> 4 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js.snap index d65431921..2847d50e7 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js.snap @@ -12,9 +12,13 @@ bb1: { } bb2: { - Unreachable() + } bb3: { + Unreachable() +} + +bb4: { } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_else.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_else.js-2.snap index 8d520a365..bd56990c1 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_else.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_else.js-2.snap @@ -7,22 +7,25 @@ digraph { 0 [ label = ""] 1 [ label = ""] 2 [ label = "$return = "] - 3 [ label = "Unreachable()"] - 4 [ label = "$return = "] - 5 [ label = "Unreachable()"] + 3 [ label = ""] + 4 [ label = "Unreachable()"] + 5 [ label = "$return = "] 6 [ label = ""] - 7 [ label = "Unreachable()\n$return = "] - 8 [ label = "Unreachable()"] - 9 [ label = ""] + 7 [ label = "Unreachable()"] + 8 [ label = ""] + 9 [ label = "Unreachable()\n$return = "] + 10 [ label = ""] + 11 [ label = "Unreachable()"] + 12 [ label = ""] 0 -> 1 [ ] - 2 -> 3 [ ] - 4 -> 5 [ ] + 3 -> 4 [ ] 6 -> 7 [ ] - 3 -> 6 [ ] + 8 -> 9 [ ] + 4 -> 8 [ ] 1 -> 2 [ ] - 1 -> 4 [ ] - 5 -> 6 [ ] + 1 -> 5 [ ] 7 -> 8 [ ] - 0 -> 9 [ ] + 10 -> 11 [ ] + 0 -> 12 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_else.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_else.js.snap index ae8fc3a33..67df1a869 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_else.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_else.js.snap @@ -16,15 +16,15 @@ bb2: { } bb3: { - Unreachable() + } bb4: { - $return = + Unreachable() } bb5: { - Unreachable() + $return = } bb6: { @@ -33,13 +33,25 @@ bb6: { bb7: { Unreachable() - $return = } bb8: { - Unreachable() + } bb9: { + Unreachable() + $return = +} + +bb10: { + +} + +bb11: { + Unreachable() +} + +bb12: { } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labelled_try_break.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labelled_try_break.js-2.snap index 62d1a622b..21e5c3e07 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labelled_try_break.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labelled_try_break.js-2.snap @@ -8,30 +8,33 @@ digraph { 1 [ label = ""] 2 [ label = ""] 3 [ label = "$return = "] - 4 [ label = "Unreachable()"] + 4 [ label = ""] 5 [ label = "Unreachable()"] - 6 [ label = ""] - 7 [ label = "Unreachable()"] - 8 [ label = "$return = "] - 9 [ label = ""] - 10 [ label = "Unreachable()"] + 6 [ label = "Unreachable()"] + 7 [ label = ""] + 8 [ label = "Unreachable()"] + 9 [ label = "$return = "] + 10 [ label = ""] 11 [ label = "Unreachable()"] 12 [ label = ""] + 13 [ label = "Unreachable()"] + 14 [ label = ""] 0 -> 1 [ ] 3 -> 2 [ ] 4 -> 2 [ ] - 3 -> 4 [ ] - 2 -> 5 [ ] - 6 -> 7 [ ] - 1 -> 3 [ ] - 9 -> 10 [ ] - 4 -> 6 [ ] + 5 -> 2 [ ] + 4 -> 5 [ ] + 2 -> 6 [ ] 7 -> 8 [ ] - 4 -> 2 [ ] - 2 -> 9 [ ] - 1 -> 9 [ ] - 6 -> 8 [ ] - 8 -> 11 [ ] - 0 -> 12 [ ] + 1 -> 3 [ ] + 10 -> 11 [ ] + 5 -> 7 [ ] + 8 -> 9 [ ] + 5 -> 2 [ ] + 2 -> 10 [ ] + 1 -> 10 [ ] + 7 -> 9 [ ] + 12 -> 13 [ ] + 0 -> 14 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labelled_try_break.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labelled_try_break.js.snap index 20ff1f90f..3b345cb5d 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labelled_try_break.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labelled_try_break.js.snap @@ -20,7 +20,7 @@ bb3: { } bb4: { - Unreachable() + } bb5: { @@ -28,23 +28,23 @@ bb5: { } bb6: { - + Unreachable() } bb7: { - Unreachable() + } bb8: { - $return = + Unreachable() } bb9: { - + $return = } bb10: { - Unreachable() + } bb11: { @@ -54,3 +54,11 @@ bb11: { bb12: { } + +bb13: { + Unreachable() +} + +bb14: { + +} diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_numbered_index.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_numbered_index.js-2.snap index 999845368..1ba4b8b3e 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_numbered_index.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_numbered_index.js-2.snap @@ -6,12 +6,14 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/member_access_with_numbered_i digraph { 0 [ label = ""] 1 [ label = "$return = "] - 2 [ label = "Unreachable()\n$return = "] - 3 [ label = "Unreachable()"] + 2 [ label = ""] + 3 [ label = "Unreachable()\n$return = "] 4 [ label = ""] + 5 [ label = "Unreachable()"] + 6 [ label = ""] 0 -> 1 [ ] - 1 -> 2 [ ] 2 -> 3 [ ] - 0 -> 4 [ ] + 4 -> 5 [ ] + 0 -> 6 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_numbered_index.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_numbered_index.js.snap index ec6c1330a..564b69c84 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_numbered_index.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_numbered_index.js.snap @@ -12,14 +12,22 @@ bb1: { } bb2: { - Unreachable() - $return = + } bb3: { Unreachable() + $return = } bb4: { } + +bb5: { + Unreachable() +} + +bb6: { + +} diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_unreachable.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_unreachable.js-2.snap index d31a72368..71920669c 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_unreachable.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_unreachable.js-2.snap @@ -6,12 +6,14 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/member_access_with_unreachabl digraph { 0 [ label = ""] 1 [ label = "$return = "] - 2 [ label = "Unreachable()\n$return = "] - 3 [ label = "Unreachable()"] + 2 [ label = ""] + 3 [ label = "Unreachable()\n$return = "] 4 [ label = ""] + 5 [ label = "Unreachable()"] + 6 [ label = ""] 0 -> 1 [ ] - 1 -> 2 [ ] 2 -> 3 [ ] - 0 -> 4 [ ] + 4 -> 5 [ ] + 0 -> 6 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_unreachable.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_unreachable.js.snap index 37fbbbc1d..25c0d27bd 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_unreachable.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@member_access_with_unreachable.js.snap @@ -12,14 +12,22 @@ bb1: { } bb2: { - Unreachable() - $return = + } bb3: { Unreachable() + $return = } bb4: { } + +bb5: { + Unreachable() +} + +bb6: { + +} diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@nested_computed_member_expression.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@nested_computed_member_expression.js-2.snap index 73afd2454..37045aa19 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@nested_computed_member_expression.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@nested_computed_member_expression.js-2.snap @@ -6,10 +6,11 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/nested_computed_member_expres digraph { 0 [ label = ""] 1 [ label = "$return = "] - 2 [ label = "Unreachable()"] - 3 [ label = ""] + 2 [ label = ""] + 3 [ label = "Unreachable()"] + 4 [ label = ""] 0 -> 1 [ ] - 1 -> 2 [ ] - 0 -> 3 [ ] + 2 -> 3 [ ] + 0 -> 4 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@nested_computed_member_expression.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@nested_computed_member_expression.js.snap index 871a5eb99..5e34f05d3 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@nested_computed_member_expression.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@nested_computed_member_expression.js.snap @@ -12,9 +12,13 @@ bb1: { } bb2: { - Unreachable() + } bb3: { + Unreachable() +} + +bb4: { } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@private_in.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@private_in.js-2.snap index a70a2be3d..fe6f808a5 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@private_in.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@private_in.js-2.snap @@ -6,10 +6,11 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/private_in.js digraph { 0 [ label = ""] 1 [ label = "$return = "] - 2 [ label = "Unreachable()"] - 3 [ label = ""] + 2 [ label = ""] + 3 [ label = "Unreachable()"] + 4 [ label = ""] 0 -> 1 [ ] - 1 -> 2 [ ] - 0 -> 3 [ ] + 2 -> 3 [ ] + 0 -> 4 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@private_in.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@private_in.js.snap index 4eb2d1569..da60938bf 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@private_in.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@private_in.js.snap @@ -12,9 +12,13 @@ bb1: { } bb2: { - Unreachable() + } bb3: { + Unreachable() +} + +bb4: { } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@simple_spread.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@simple_spread.js-2.snap index 1785be513..4782f9dd7 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@simple_spread.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@simple_spread.js-2.snap @@ -6,10 +6,11 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/simple_spread.js digraph { 0 [ label = ""] 1 [ label = "$return = "] - 2 [ label = "Unreachable()"] - 3 [ label = ""] + 2 [ label = ""] + 3 [ label = "Unreachable()"] + 4 [ label = ""] 0 -> 1 [ ] - 1 -> 2 [ ] - 0 -> 3 [ ] + 2 -> 3 [ ] + 0 -> 4 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@simple_spread.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@simple_spread.js.snap index de13c7f51..b8a8fab03 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@simple_spread.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@simple_spread.js.snap @@ -12,9 +12,13 @@ bb1: { } bb2: { - Unreachable() + } bb3: { + Unreachable() +} + +bb4: { } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@spread_in_a_spread.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@spread_in_a_spread.js-2.snap index 0383e5d8f..e4c5a71b1 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@spread_in_a_spread.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@spread_in_a_spread.js-2.snap @@ -6,10 +6,11 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/spread_in_a_spread.js digraph { 0 [ label = ""] 1 [ label = "$return = "] - 2 [ label = "Unreachable()"] - 3 [ label = ""] + 2 [ label = ""] + 3 [ label = "Unreachable()"] + 4 [ label = ""] 0 -> 1 [ ] - 1 -> 2 [ ] - 0 -> 3 [ ] + 2 -> 3 [ ] + 0 -> 4 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@spread_in_a_spread.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@spread_in_a_spread.js.snap index d74d0300a..2123f4d2b 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@spread_in_a_spread.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@spread_in_a_spread.js.snap @@ -12,9 +12,13 @@ bb1: { } bb2: { - Unreachable() + } bb3: { + Unreachable() +} + +bb4: { } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@switch_statement.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@switch_statement.js-2.snap index e6e527b82..c8559aaee 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@switch_statement.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@switch_statement.js-2.snap @@ -16,14 +16,17 @@ digraph { 9 [ label = "Unreachable()"] 10 [ label = ""] 11 [ label = "$return = "] - 12 [ label = "Unreachable()"] - 13 [ label = ""] + 12 [ label = ""] + 13 [ label = "Unreachable()"] 14 [ label = ""] 15 [ label = ""] - 16 [ label = "$return = "] - 17 [ label = "Unreachable()\n$return = "] - 18 [ label = "Unreachable()"] - 19 [ label = ""] + 16 [ label = ""] + 17 [ label = "$return = "] + 18 [ label = ""] + 19 [ label = "Unreachable()\n$return = "] + 20 [ label = ""] + 21 [ label = "Unreachable()"] + 22 [ label = ""] 0 -> 1 [ ] 2 -> 3 [ ] 3 -> 4 [ ] @@ -33,38 +36,38 @@ digraph { 8 -> 9 [ ] 8 -> 9 [ ] 10 -> 11 [ ] - 11 -> 12 [ ] - 13 -> 14 [ ] - 15 -> 16 [ ] + 12 -> 13 [ ] + 14 -> 15 [ ] 16 -> 17 [ ] + 18 -> 19 [ ] 2 -> 5 [ ] 2 -> 7 [ ] 2 -> 10 [ ] - 2 -> 13 [ ] - 2 -> 15 [ ] + 2 -> 14 [ ] + 2 -> 16 [ ] 4 -> 5 [ ] 1 -> 2 [ ] 5 -> 7 [ ] 5 -> 10 [ ] - 5 -> 13 [ ] - 5 -> 15 [ ] + 5 -> 14 [ ] + 5 -> 16 [ ] 6 -> 7 [ ] 1 -> 5 [ ] 7 -> 10 [ ] - 7 -> 13 [ ] - 7 -> 15 [ ] + 7 -> 14 [ ] + 7 -> 16 [ ] 9 -> 10 [ ] 1 -> 7 [ ] - 10 -> 13 [ ] - 10 -> 15 [ ] - 12 -> 13 [ ] + 10 -> 14 [ ] + 10 -> 16 [ ] + 13 -> 14 [ ] 1 -> 10 [ ] - 13 -> 15 [ ] - 14 -> 15 [ ] - 1 -> 13 [ ] - 1 -> 15 [ ] - 15 -> 17 [ ] - 17 -> 18 [ ] - 0 -> 19 [ ] + 14 -> 16 [ ] + 15 -> 16 [ ] + 1 -> 14 [ ] + 1 -> 16 [ ] + 16 -> 19 [ ] + 20 -> 21 [ ] + 0 -> 22 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@switch_statement.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@switch_statement.js.snap index 5be3016a7..5d690743a 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@switch_statement.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@switch_statement.js.snap @@ -52,11 +52,11 @@ bb11: { } bb12: { - Unreachable() + } bb13: { - + Unreachable() } bb14: { @@ -68,18 +68,30 @@ bb15: { } bb16: { - $return = + } bb17: { - Unreachable() $return = } bb18: { - Unreachable() + } bb19: { + Unreachable() + $return = +} + +bb20: { + +} + +bb21: { + Unreachable() +} + +bb22: { } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@two_functions.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@two_functions.js-2.snap index f4af1e0c7..ba7be2ca3 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@two_functions.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@two_functions.js-2.snap @@ -6,16 +6,18 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/two_functions.js digraph { 0 [ label = ""] 1 [ label = "$return = "] - 2 [ label = "Unreachable()"] - 3 [ label = ""] - 4 [ label = "$return = "] - 5 [ label = "Unreachable()"] + 2 [ label = ""] + 3 [ label = "Unreachable()"] + 4 [ label = ""] + 5 [ label = "$return = "] 6 [ label = ""] + 7 [ label = "Unreachable()"] + 8 [ label = ""] 0 -> 1 [ ] - 1 -> 2 [ ] - 0 -> 3 [ ] - 3 -> 4 [ ] + 2 -> 3 [ ] + 0 -> 4 [ ] 4 -> 5 [ ] - 3 -> 6 [ ] + 6 -> 7 [ ] + 4 -> 8 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@two_functions.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@two_functions.js.snap index c259c2e58..26a514245 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@two_functions.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@two_functions.js.snap @@ -12,21 +12,29 @@ bb1: { } bb2: { - Unreachable() + } bb3: { - + Unreachable() } bb4: { - $return = + } bb5: { - Unreachable() + $return = } bb6: { } + +bb7: { + Unreachable() +} + +bb8: { + +} diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@while.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@while.js-2.snap index a2a21c525..958fdb16e 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@while.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@while.js-2.snap @@ -8,18 +8,20 @@ digraph { 1 [ label = ""] 2 [ label = ""] 3 [ label = "$return = "] - 4 [ label = "Unreachable()"] - 5 [ label = "$return = "] - 6 [ label = "Unreachable()"] + 4 [ label = ""] + 5 [ label = "Unreachable()"] + 6 [ label = "$return = "] 7 [ label = ""] + 8 [ label = "Unreachable()"] + 9 [ label = ""] 0 -> 1 [ ] - 3 -> 4 [ ] + 4 -> 5 [ ] 1 -> 2 [ ] 2 -> 3 [ ] - 3 -> 5 [ ] + 3 -> 6 [ ] 3 -> 2 [ ] - 2 -> 5 [ ] - 5 -> 6 [ ] - 0 -> 7 [ ] + 2 -> 6 [ ] + 7 -> 8 [ ] + 0 -> 9 [ ] } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@while.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@while.js.snap index 50a8ee7b8..496c594f5 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@while.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@while.js.snap @@ -20,17 +20,25 @@ bb3: { } bb4: { - Unreachable() + } bb5: { - $return = + Unreachable() } bb6: { - Unreachable() + $return = } bb7: { } + +bb8: { + Unreachable() +} + +bb9: { + +}