[whatwg/dom] Capturing event listeners are called during bubbling phase for shadow hosts (#685)

We have a [bug report](https://webkit.org/b/174288) saying that WebKit fires event listeners with [*capture* flag](https://dom.spec.whatwg.org/#event-listener-capture) set to true during bubbling phase.

Consider the following DOM:
```js
const hostParent = document.createElement('section');
hostParent.id = 'hostParent';
hostParent.innerHTML = '<div id="host"></div>';
const host = hostParent.firstChild;
const shadowRoot = host.attachShadow({mode: 'closed'});
shadowRoot.innerHTML = '<p id="parent"><span id="target"></span></p>';
...
target.dispatchEvent(new CustomEvent('test', {detail: {}, bubbles: true, composed: true}));
```

Then the event listeners on target, parent, host, and hostParent are invoked in the following order on WebKit & Chrome:
 - hostParent, capturing, eventPhase: CAPTURING_PHASE
 - parent, capturing, eventPhase: CAPTURING_PHASE
 - target, capturing, eventPhase: AT_TARGET
 - target, non-capturing, eventPhase: AT_TARGET
 - parent, non-capturing, eventPhase: BUBBLING_PHASE
 - host, capturing, eventPhase: AT_TARGET
 - host, non-capturing, eventPhase: AT_TARGET
 - hostParent, non-capturing, eventPhase: BUBBLING_PHASE

As far as I can tell, the current behavior of WebKit & Chrome is in accordance with the latest DOM specification. What happens is that step 5 (event path construction) in [dispatching an event] (https://dom.spec.whatwg.org/#concept-event-dispatch) ends up appending an tuple/struct (we should probably stick with either term, btw) with *target* set to `null`. In step 14, we only invoke event listeners with capture flag set if *target* is `null`, meaning that shadow hosts' event listeners with capture flag set would NOT be called. Then in step 15, we set `eventPhase` to `AT_TARGET` and [invoke](https://dom.spec.whatwg.org/#concept-event-listener-invoke) event listeners. Because the concept [to inner invoke](https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke) an event listener doesn't skip event listeners with capture flag set to true when the event phase is AT_TARGET, we end up firing capturing event listeners during bubbling.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/685

Received on Thursday, 6 September 2018 04:57:27 UTC