From b79f156ebfaa755b47e79189ab7c4b592185a4b7 Mon Sep 17 00:00:00 2001 From: Pierre Le Fevre Date: Fri, 27 Mar 2026 21:22:33 +0100 Subject: [PATCH] Review fixes: stopPropagation must prevent bubble phase entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two DOM spec compliance fixes: 1. Check is_propagation_stopped before entering bubble phase, so stopPropagation called during capture or at-target prevents bubbling. 2. Remove incorrect per-listener stopPropagation check in invoke_listeners. Per the DOM spec, stopPropagation does not prevent other listeners on the same node from firing — only stopImmediatePropagation does that. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/js/src/dom_bridge.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/js/src/dom_bridge.rs b/crates/js/src/dom_bridge.rs index eac948b..c687922 100644 --- a/crates/js/src/dom_bridge.rs +++ b/crates/js/src/dom_bridge.rs @@ -1941,7 +1941,7 @@ pub fn run_event_dispatch(vm: &mut Vm, target_idx: usize, event_ref: GcRef) -> V _ => false, }; - if bubbles { + if bubbles && !is_propagation_stopped(&vm.gc, event_ref) { set_builtin_prop(&mut vm.gc, event_ref, "eventPhase", Value::Number(3.0)); set_builtin_prop(&mut vm.gc, event_ref, EVENT_PHASE_KEY, Value::Number(3.0)); @@ -2069,10 +2069,6 @@ fn invoke_listeners( if is_immediate_stopped(&vm.gc, event_ref) { break; } - if is_propagation_stopped(&vm.gc, event_ref) && capture_only { - break; - } - // Set `this` to currentTarget for the callback. let old_this = vm.get_global("this").cloned(); vm.set_global("this", Value::Object(current_target_wrapper)); -- 2.51.2