From e3171a079443f5c1305e93ed6a2fb98f21c489ba Mon Sep 17 00:00:00 2001 From: rzvxa Date: Fri, 10 May 2024 14:54:52 +0330 Subject: [PATCH] improvement(semantic): add explicit break block element. --- .../oxc_linter/src/rules/eslint/getter_return.rs | 2 ++ crates/oxc_semantic/src/builder.rs | 14 +++++++++++++- crates/oxc_semantic/src/control_flow.rs | 12 ++++++++++++ ...es@break_from_a_label_in_global_scope.js-2.snap | 3 +-- ...iles@break_from_a_label_in_global_scope.js.snap | 1 + .../cfg__cfg_files@do_while_break.js-2.snap | 5 ++--- .../cfg__cfg_files@do_while_break.js.snap | 2 ++ .../cfg__cfg_files@if_stmt_in_for_in.js-2.snap | 3 +-- .../cfg__cfg_files@if_stmt_in_for_in.js.snap | 1 + .../cfg__cfg_files@labeled_block_break.js-2.snap | 3 +-- .../cfg__cfg_files@labeled_block_break.js.snap | 1 + .../cfg__cfg_files@labelled_try_break.js-2.snap | 5 ++--- .../cfg__cfg_files@labelled_try_break.js.snap | 2 ++ .../cfg__cfg_files@switch_statement.js-2.snap | 5 ++--- .../cfg__cfg_files@switch_statement.js.snap | 2 ++ 15 files changed, 45 insertions(+), 16 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/getter_return.rs b/crates/oxc_linter/src/rules/eslint/getter_return.rs index dd35cac022bbf..cc09e70b84e96 100644 --- a/crates/oxc_linter/src/rules/eslint/getter_return.rs +++ b/crates/oxc_linter/src/rules/eslint/getter_return.rs @@ -288,6 +288,8 @@ impl GetterReturn { return (DefinitelyReturnsOrThrowsOrUnreachable::Yes, false); } + // Ignore irrelevant elements. + BasicBlockElement::Break(_) => {} } } diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 5cd30a8b51379..40ea2ceccb5fb 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -489,14 +489,25 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { fn visit_break_statement(&mut self, stmt: &BreakStatement<'a>) { let kind = AstKind::BreakStatement(self.alloc(stmt)); self.enter_node(kind); + let maybe_label = stmt.label.as_ref(); /* cfg */ let statement_state = self .cfg .before_statement(self.current_node_id, StatementControlFlowType::DoesNotUseContinue); + let break_label = maybe_label.and_then(|_| { + let reg = Some(self.cfg.new_register()); + self.cfg.use_this_register = reg; + reg + }); /* cfg */ - if let Some(break_target) = &stmt.label { + if let Some(break_target) = maybe_label { + /* cfg */ + let break_label = self.cfg.new_register(); + self.cfg.use_this_register = Some(break_label); + /* cfg */ + self.visit_label_identifier(break_target); /* cfg */ @@ -527,6 +538,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { } self.cfg.put_unreachable(); + self.cfg.put_break(break_label); self.cfg.after_statement( &statement_state, self.current_node_id, diff --git a/crates/oxc_semantic/src/control_flow.rs b/crates/oxc_semantic/src/control_flow.rs index be23ec9bc6e3d..ab8b94aa07c5e 100644 --- a/crates/oxc_semantic/src/control_flow.rs +++ b/crates/oxc_semantic/src/control_flow.rs @@ -106,6 +106,7 @@ pub enum BasicBlockElement { Unreachable, Assignment(Register, AssignmentValue), Throw(Register), + Break(Option), } #[derive(Debug, Clone)] @@ -239,6 +240,10 @@ impl ControlFlowGraph { self.current_basic_block().push(BasicBlockElement::Throw(throw_expr)); } + pub fn put_break(&mut self, label: Option) { + self.current_basic_block().push(BasicBlockElement::Break(label)); + } + 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(); @@ -380,6 +385,13 @@ pub fn print_basic_block(basic_block_elements: &Vec) -> Strin BasicBlockElement::Throw(reg) => { output.push_str(&format!("throw {}\n", print_register(*reg))); } + + BasicBlockElement::Break(Some(reg)) => { + output.push_str(&format!("break {}\n", print_register(*reg))); + } + BasicBlockElement::Break(None) => { + output.push_str("break"); + } BasicBlockElement::Assignment(to, with) => { output.push_str(&format!("{} = ", print_register(*to))); diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js-2.snap index acba8fb312f21..1ce0b92f256aa 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js-2.snap @@ -5,8 +5,7 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/break_from_a_label_in_global_ --- digraph { 0 [ label = ""] - 1 [ label = "Unreachable()"] + 1 [ label = "Unreachable()\nbreak $0"] 0 -> 1 [ ] 0 -> 1 [ ] } - diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js.snap index 790a58e296a72..4dcff99f855c7 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js.snap @@ -9,4 +9,5 @@ bb0: { bb1: { Unreachable() + break $0 } diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@do_while_break.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@do_while_break.js-2.snap index 735052fb75e8a..1901e131241c0 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@do_while_break.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@do_while_break.js-2.snap @@ -9,13 +9,13 @@ digraph { 2 [ label = ""] 3 [ label = ""] 4 [ label = ""] - 5 [ label = "Unreachable()"] + 5 [ label = "Unreachable()\nbreak"] 6 [ label = ""] 7 [ label = ""] 8 [ label = "Unreachable()"] 9 [ label = ""] 10 [ label = ""] - 11 [ label = "Unreachable()"] + 11 [ label = "Unreachable()\nbreak"] 12 [ label = ""] 13 [ label = ""] 14 [ label = ""] @@ -41,4 +41,3 @@ digraph { 13 -> 14 [ ] 0 -> 15 [ ] } - diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@do_while_break.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@do_while_break.js.snap index d35d3d8e3d6e1..789e91d945317 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@do_while_break.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@do_while_break.js.snap @@ -25,6 +25,7 @@ bb4: { bb5: { Unreachable() + break } bb6: { @@ -49,6 +50,7 @@ bb10: { bb11: { Unreachable() + break } bb12: { diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_stmt_in_for_in.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_stmt_in_for_in.js-2.snap index efbf85d01b7b8..489faca8ed5b4 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_stmt_in_for_in.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_stmt_in_for_in.js-2.snap @@ -10,7 +10,7 @@ digraph { 3 [ label = ""] 4 [ label = ""] 5 [ label = ""] - 6 [ label = "Unreachable()"] + 6 [ label = "Unreachable()\nbreak"] 7 [ label = ""] 8 [ label = ""] 9 [ label = "Unreachable()"] @@ -42,4 +42,3 @@ digraph { 9 -> 3 [ ] 0 -> 15 [ ] } - diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_stmt_in_for_in.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_stmt_in_for_in.js.snap index b87d5badbf460..1b5e0fc854784 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_stmt_in_for_in.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_stmt_in_for_in.js.snap @@ -29,6 +29,7 @@ bb5: { bb6: { Unreachable() + break } bb7: { diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labeled_block_break.js-2.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labeled_block_break.js-2.snap index 0bef73f3d42d0..579a8eb81b609 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labeled_block_break.js-2.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labeled_block_break.js-2.snap @@ -8,7 +8,7 @@ digraph { 1 [ label = ""] 2 [ label = ""] 3 [ label = ""] - 4 [ label = "Unreachable()"] + 4 [ label = "Unreachable()\nbreak $0"] 5 [ label = ""] 6 [ label = ""] 0 -> 1 [ ] @@ -21,4 +21,3 @@ digraph { 3 -> 5 [ ] 5 -> 6 [ ] } - diff --git a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labeled_block_break.js.snap b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labeled_block_break.js.snap index 18cef6ababb14..5894ba9fe1437 100644 --- a/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labeled_block_break.js.snap +++ b/crates/oxc_semantic/tests/snapshots/cfg__cfg_files@labeled_block_break.js.snap @@ -21,6 +21,7 @@ bb3: { bb4: { Unreachable() + break $0 } bb5: { 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 362cd92384cea..70309e2b92550 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 @@ -10,10 +10,10 @@ digraph { 3 [ label = ""] 4 [ label = ""] 5 [ label = "Unreachable()"] - 6 [ label = "Unreachable()"] + 6 [ label = "Unreachable()\nbreak $0"] 7 [ label = "Unreachable()"] 8 [ label = ""] - 9 [ label = "Unreachable()"] + 9 [ label = "Unreachable()\nbreak $2"] 10 [ label = "$return = "] 11 [ label = ""] 12 [ label = "Unreachable()"] @@ -35,4 +35,3 @@ digraph { 11 -> 12 [ ] 0 -> 13 [ ] } - 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 ee495a6d05dfd..44bde54935801 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 @@ -29,6 +29,7 @@ bb5: { bb6: { Unreachable() + break $0 } bb7: { @@ -41,6 +42,7 @@ bb8: { bb9: { Unreachable() + break $2 } bb10: { 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 c8559aaee5ce8..2593bc1b8d47f 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 @@ -8,12 +8,12 @@ digraph { 1 [ label = ""] 2 [ label = ""] 3 [ label = ""] - 4 [ label = "Unreachable()"] + 4 [ label = "Unreachable()\nbreak"] 5 [ label = ""] 6 [ label = ""] 7 [ label = ""] 8 [ label = ""] - 9 [ label = "Unreachable()"] + 9 [ label = "Unreachable()\nbreak"] 10 [ label = ""] 11 [ label = "$return = "] 12 [ label = ""] @@ -70,4 +70,3 @@ digraph { 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 5d690743a3ef4..29d240a1ac7a7 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 @@ -21,6 +21,7 @@ bb3: { bb4: { Unreachable() + break } bb5: { @@ -41,6 +42,7 @@ bb8: { bb9: { Unreachable() + break } bb10: {