Skip to content

Capturing event listeners are called during bubbling phase for shadow hosts #685

Closed
@rniwa

Description

@rniwa

We have a bug report saying that WebKit fires event listeners with capture flag set to true during bubbling phase.

Consider the following DOM:

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 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 event listeners. Because the concept to 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions