fix(cfg): double resolution of labeled statements. (#4177)

Fixes #4173
This commit is contained in:
rzvxa 2024-07-11 01:39:28 +00:00
parent ca0b4fa08a
commit 7a059ab53a
2 changed files with 43 additions and 2 deletions

View file

@ -130,9 +130,12 @@ impl<'a, 'c> QueryCtx<'a, 'c> {
self.resolve_ctx(ctx);
// mark the upper label continue jump point the same as ours,
// mark the upper label continue jump point the same as ours if it isn't already assigned,
// NOTE: if it is already assigned there's a resolution before this context.
if let Some(jmp) = continue_jmp {
if let Some(label_ctx) = self.0.immediate_labeled_ctx() {
if let Some(label_ctx @ RefCtxCursor(Ctx { continue_jmp: None, .. })) =
self.0.immediate_labeled_ctx()
{
label_ctx.mark_continue(jmp);
}
}

View file

@ -0,0 +1,38 @@
use oxc_cfg::{ControlFlowGraphBuilder, CtxCursor};
use oxc_syntax::node::AstNodeId;
/// same as but just the skeleton
/// ```js
/// A: {
/// do {} while (a);
/// do {} while (b);
/// break A;
/// }
/// ```
#[test]
fn labeled_statement_with_multiple_loops_continue_and_break() {
const A: Option<&str> = Some("A");
let mut cfg = ControlFlowGraphBuilder::default();
cfg.attach_error_harness(oxc_cfg::ErrorEdgeKind::Implicit);
// labeled block start
let labeled = cfg.new_basic_block_normal();
cfg.ctx(A).default().allow_break().allow_continue();
// loop context 1
let c1 = cfg.new_basic_block_normal();
cfg.ctx(None).default().allow_break().allow_continue();
cfg.ctx(None).mark_break(c1).mark_continue(c1).resolve_with_upper_label();
// loop context 2
let c2 = cfg.new_basic_block_normal();
cfg.ctx(None).default().allow_break().allow_continue();
cfg.ctx(None).mark_break(c2).mark_continue(c2).resolve_with_upper_label();
cfg.append_break(AstNodeId::dummy(), A);
// labeled block end
cfg.ctx(A).mark_break(labeled).resolve();
cfg.build();
}