[EventTiming] Enhance targetSelector with context-aware traversal [chromium/src : main]

0 views
Skip to first unread message

Mohamed Youns (Gerrit)

unread,
Feb 16, 2026, 10:05:03 AMFeb 16
to Chromium LUCI CQ, chromium...@chromium.org, blink-...@chromium.org, core-timi...@chromium.org, speed-metrics...@chromium.org

Mohamed Youns added 1 comment

Patchset-level comments
File-level comment, Patchset 1 (Latest):
Mohamed Youns . unresolved

I've implemented the traversal algorithm (checking ancestors for ID/Name/Alt/Src) as discussed.

I wanted to highlight two specific open questions:

1. **Feature Flag for New Attributes:** Should I put the new attribute checks (e.g., `name`, `alt`) behind the `EventTargetStringIdentifierUsesQuotesEnabled` flag, similar to how `src` is currently guarded? Or should they be enabled by default since this is a new feature? 2. **Handling Detached Nodes (The "Async" Issue):** There is a limitation with the current traversal logic when nodes are removed immediately from the DOM (e.g., `element.remove()` in a click handler).

  • The traversal relies on `current->parentNode()`. If the node is detached before `EventTargetToString` runs (which happens asynchronously for Event Timing), `parentNode()` returns `nullptr`.
  • The algorithm fails to find ancestors and falls back to just the target selector (e.g., `SPAN` instead of `DIV#card > SPAN`).
  • I've created a demo here: [https://jsbin.com/fixabuzeru/edit?html,output](https://jsbin.com/fixabuzeru/edit?html,output). If you uncomment `this.remove()` in `handleInteraction`, the parent context is lost. If you use `display: none`, it works correctly.
  • Is there a synchronous hook we should use instead?
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I84185c2fc148abaf706b6aa42cc73a9bbbfd164a
Gerrit-Change-Number: 7581314
Gerrit-PatchSet: 1
Gerrit-Owner: Mohamed Youns <mohame...@gmail.com>
Gerrit-Reviewer: Mohamed Youns <mohame...@gmail.com>
Gerrit-Comment-Date: Mon, 16 Feb 2026 15:04:47 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Mohamed Youns (Gerrit)

unread,
Mar 14, 2026, 1:40:52 PM (7 days ago) Mar 14
to AyeAye, Michal Mocny, Chromium LUCI CQ, chromium...@chromium.org, lighthouse-eng-extern...@google.com, blink-revie...@chromium.org, blink-...@chromium.org, core-timi...@chromium.org, speed-metrics...@chromium.org
Attention needed from Michal Mocny

Mohamed Youns added 1 comment

Patchset-level comments
Mohamed Youns . unresolved

I've implemented the traversal algorithm (checking ancestors for ID/Name/Alt/Src) as discussed.

I wanted to highlight two specific open questions:

1. **Feature Flag for New Attributes:** Should I put the new attribute checks (e.g., `name`, `alt`) behind the `EventTargetStringIdentifierUsesQuotesEnabled` flag, similar to how `src` is currently guarded? Or should they be enabled by default since this is a new feature? 2. **Handling Detached Nodes (The "Async" Issue):** There is a limitation with the current traversal logic when nodes are removed immediately from the DOM (e.g., `element.remove()` in a click handler).

  • The traversal relies on `current->parentNode()`. If the node is detached before `EventTargetToString` runs (which happens asynchronously for Event Timing), `parentNode()` returns `nullptr`.
  • The algorithm fails to find ancestors and falls back to just the target selector (e.g., `SPAN` instead of `DIV#card > SPAN`).
  • I've created a demo here: [https://jsbin.com/fixabuzeru/edit?html,output](https://jsbin.com/fixabuzeru/edit?html,output). If you uncomment `this.remove()` in `handleInteraction`, the parent context is lost. If you use `display: none`, it works correctly.
  • Is there a synchronous hook we should use instead?
Mohamed Youns

1. After the fix of the async issue with the event target https://chromium-review.googlesource.com/c/chromium/src/+/7617568, I think we are ready to update the WPT test
2. I updated the [demo](https://jsbin.com/daherucora/edit?html,output) as well to cover all uniqe cases
3. The WPT tests have been updated with the new use cases (e.g., SVG, shadow DOM)

Open in Gerrit

Related details

Attention is currently required from:
  • Michal Mocny
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I84185c2fc148abaf706b6aa42cc73a9bbbfd164a
Gerrit-Change-Number: 7581314
Gerrit-PatchSet: 7
Gerrit-Owner: Mohamed Youns <mohame...@gmail.com>
Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
Gerrit-Reviewer: Mohamed Youns <mohame...@gmail.com>
Gerrit-Attention: Michal Mocny <mmo...@chromium.org>
Gerrit-Comment-Date: Sat, 14 Mar 2026 17:40:31 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Mohamed Youns <mohame...@gmail.com>
satisfied_requirement
unsatisfied_requirement
open
diffy

Mohamed Youns (Gerrit)

unread,
Mar 14, 2026, 2:16:38 PM (7 days ago) Mar 14
to AyeAye, Michal Mocny, Chromium LUCI CQ, chromium...@chromium.org, lighthouse-eng-extern...@google.com, blink-revie...@chromium.org, blink-...@chromium.org, core-timi...@chromium.org, speed-metrics...@chromium.org
Attention needed from Michal Mocny

Mohamed Youns added 1 comment

File third_party/blink/web_tests/external/wpt/event-timing/target-selector.tentative.html
Line 112, Patchset 7 (Latest): // WebDriver would fail if there any intraction with the shadow DOM
await interactAndObserve('click', host, observerPromise);
Mohamed Youns . unresolved

@mmo...@chromium.org

A quick question about the Shadow DOM WPT test.

I tried to click the internal shadow button directly:

await interactAndObserve('click', btn, ...);

But testdriver.js fails locally with: "Error: element click intercepted error".

I changed it to click the Shadow Host instead:
await interactAndObserve('click', host, ...);

This works perfectly. A physical click on the host naturally reaches the inner button and bubbles up. This triggers C++ EventPath logic exactly like a real user interaction, proving that our code correctly stops at the ShadowRoot and returns "DIV#shadow-host".

Does this approach align with standard WPT practices, or is there a specific testdriver API I should use to click inside a Shadow DOM?

To see the issue in action

1. change await interactAndObserve('click', host, observerPromise); to await interactAndObserve('click', btn, observerPromise);

2. run `third_party/blink/tools/run_web_tests.py -t Default external/wpt/event-timing/target-selector.tentative.html`

Gerrit-Comment-Date: Sat, 14 Mar 2026 18:16:13 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Mohamed Youns (Gerrit)

unread,
Mar 15, 2026, 10:32:45 AM (7 days ago) Mar 15
to AyeAye, Michal Mocny, Chromium LUCI CQ, chromium...@chromium.org, lighthouse-eng-extern...@google.com, blink-revie...@chromium.org, blink-...@chromium.org, core-timi...@chromium.org, speed-metrics...@chromium.org
Attention needed from Michal Mocny

Mohamed Youns voted Commit-Queue+1

Commit-Queue+1
Open in Gerrit

Related details

Attention is currently required from:
  • Michal Mocny
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I84185c2fc148abaf706b6aa42cc73a9bbbfd164a
Gerrit-Change-Number: 7581314
Gerrit-PatchSet: 10
Gerrit-Owner: Mohamed Youns <mohame...@gmail.com>
Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
Gerrit-Reviewer: Mohamed Youns <mohame...@gmail.com>
Gerrit-Attention: Michal Mocny <mmo...@chromium.org>
Gerrit-Comment-Date: Sun, 15 Mar 2026 14:32:24 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
satisfied_requirement
unsatisfied_requirement
open
diffy

Michal Mocny (Gerrit)

unread,
Mar 16, 2026, 11:03:33 AM (6 days ago) Mar 16
to Mohamed Youns, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, lighthouse-eng-extern...@google.com, blink-revie...@chromium.org, blink-...@chromium.org, core-timi...@chromium.org, speed-metrics...@chromium.org
Attention needed from Mohamed Youns

Michal Mocny added 9 comments

Patchset-level comments
File-level comment, Patchset 10 (Latest):
Michal Mocny . resolved

I haven't finished review, just sending initial comments. Mostly:

  • may you please split the WPT into smaller files in a separate directory to make it easier to read each expectation?
  • the new implementation seems to change the helper that LoAF uses and this may changed specced behaviour. I would not change that function at all (see the comment at the top of the function).
  • some initial design feedback on the API design for the other parts.
Commit Message
Line 7, Patchset 10 (Latest):[EventTiming] Enhance targetSelector with context-aware traversal
Michal Mocny . unresolved

What is "context-aware traversal" ?

Line 9, Patchset 10 (Latest):This CL builds upon the EventPath integration in #7617568 to revamp the
Michal Mocny . unresolved

You can use crrev.com/c/7617568 to link this, the # syntax doesn't do anything special in most of the uis for chrome changelogs

Line 25, Patchset 10 (Latest):on classes for identification, only the first class is extracted and
appended (e.g., DIV.primary-card).
Michal Mocny . unresolved

Proposal: don't expose any className unless there is only a single unique className.

I don't know if there are use cases for 2 classNames, but I know that if there is a list of ~50 classNames on an element, using just the "first one" isn't that useful, either.

Line 28, Patchset 10 (Latest):3. The traversal algorithm strictly respects Web Component boundaries.
If the path hits a ShadowRoot, the internal collection is safely
Michal Mocny . unresolved

Is this a new key change? Or is this just part of how the event path works?

Line 33, Patchset 10 (Latest):4. Updates target-selector.tentative.html to enforce strict string
matching. Adds test coverage for name attributes, deep nesting limits,
SVG elements and Shadow DOM encapsulation boundaries.
Michal Mocny . unresolved

FYI If there are multiple different dom structures to test, its often better to create multiple distinct small test files.

It might even be useful to create a separate directory like: `event-timing/target-selector/tentative/*.html`

File third_party/blink/renderer/core/timing/timing_utils.cc
Line 23, Patchset 10 (Latest):String GetElementSelector(Element* element, bool* out_is_strong) {
Michal Mocny . unresolved

Nit: `bool*` is a sign of an imperfect design.

I think if you flip the order: return bool, accept `String&`, that already feels better.

---

But looking at the previous implementation, it basically did the following:

  • Get the EventPath and iterate all the nodes "bottom up"
  • Check if any given node is "strong" by checking if it has `HasID`
  • Convert each element to String, and append to a Vector
  • Concatenate the Vector in reverse to a string.

I wonder if you can just decouple the "is_string" check into its own little function, and replace where we used to hard-code the "HasId" check.

(I think that "strong" is just HasId || NameAttr || SrcAttr, although I would argue that having a singleton className is also strong)

Line 96, Patchset 10 (Latest):AtomicString EventTargetToString(EventTarget* target) {
Michal Mocny . unresolved

This code path is used by LoAF-- I haven't fully reviewed the changes but it looks like you changed the implementation here?

File third_party/blink/web_tests/external/wpt/event-timing/target-selector.tentative.html
Line 112, Patchset 7: // WebDriver would fail if there any intraction with the shadow DOM

await interactAndObserve('click', host, observerPromise);
Mohamed Youns . unresolved

@mmo...@chromium.org

A quick question about the Shadow DOM WPT test.

I tried to click the internal shadow button directly:

await interactAndObserve('click', btn, ...);

But testdriver.js fails locally with: "Error: element click intercepted error".

I changed it to click the Shadow Host instead:
await interactAndObserve('click', host, ...);

This works perfectly. A physical click on the host naturally reaches the inner button and bubbles up. This triggers C++ EventPath logic exactly like a real user interaction, proving that our code correctly stops at the ShadowRoot and returns "DIV#shadow-host".

Does this approach align with standard WPT practices, or is there a specific testdriver API I should use to click inside a Shadow DOM?

To see the issue in action

1. change await interactAndObserve('click', host, observerPromise); to await interactAndObserve('click', btn, observerPromise);

2. run `third_party/blink/tools/run_web_tests.py -t Default external/wpt/event-timing/target-selector.tentative.html`

Michal Mocny

I haven't tested `testdriver.js` for interacting with targets inside a closed shadow dom, and I don't see any mention of what is expected in the docs: https://web-platform-tests.org/writing-tests/testdriver.html#user-interaction

In general, I do think its common for web component based testing to simulate interactions with the host element, or with a specific co-ordinate that falls within the bounds of the host component-- so your solution is reasonable I think.

---

You might also want to search for existing interaction simulations inside the shadow-dom WPT suite in case there is a solution:

https://github.com/search?q=repo%3Aweb-platform-tests%2Fwpt+path%3A%2F%5Eshadow-dom%5C%2F%2F++click+closed&type=code

Open in Gerrit

Related details

Attention is currently required from:
  • Mohamed Youns
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I84185c2fc148abaf706b6aa42cc73a9bbbfd164a
Gerrit-Change-Number: 7581314
Gerrit-PatchSet: 10
Gerrit-Owner: Mohamed Youns <mohame...@gmail.com>
Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
Gerrit-Reviewer: Mohamed Youns <mohame...@gmail.com>
Gerrit-Attention: Mohamed Youns <mohame...@gmail.com>
Gerrit-Comment-Date: Mon, 16 Mar 2026 15:03:19 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Mohamed Youns <mohame...@gmail.com>
satisfied_requirement
unsatisfied_requirement
open
diffy

Mohamed Youns (Gerrit)

unread,
Mar 21, 2026, 12:14:06 PM (13 hours ago) Mar 21
to AyeAye, Michal Mocny, Chromium LUCI CQ, chromium...@chromium.org, lighthouse-eng-extern...@google.com, blink-revie...@chromium.org, blink-...@chromium.org, core-timi...@chromium.org, speed-metrics...@chromium.org
Attention needed from Michal Mocny

Mohamed Youns added 5 comments

Commit Message
Line 7, Patchset 10:[EventTiming] Enhance targetSelector with context-aware traversal
Michal Mocny . unresolved

What is "context-aware traversal" ?

Mohamed Youns

It's the term I used to describe the new selector logic (algorithm)

  • "Context-Aware" instead of looking at a generic target (like a <span>), the logic looks at its attributes (id, src, etc) to give it meaning/context
  • "Traversal" it traverses up (parent, grandparent) to find a new context if there is no one in the current element
Line 9, Patchset 10:This CL builds upon the EventPath integration in #7617568 to revamp the
Michal Mocny . resolved

You can use crrev.com/c/7617568 to link this, the # syntax doesn't do anything special in most of the uis for chrome changelogs

Mohamed Youns

Done

Line 25, Patchset 10:on classes for identification, only the first class is extracted and
appended (e.g., DIV.primary-card).
Michal Mocny . unresolved

Proposal: don't expose any className unless there is only a single unique className.

I don't know if there are use cases for 2 classNames, but I know that if there is a list of ~50 classNames on an element, using just the "first one" isn't that useful, either.

Mohamed Youns

Just to clarify your proposal, do you mean we should strictly check if element `ClassNames().size() == 1`, and if it has multiple classes (> 1 class), we ignore the class attribute entirely and continue traversing up?

Line 28, Patchset 10:3. The traversal algorithm strictly respects Web Component boundaries.

If the path hits a ShadowRoot, the internal collection is safely
Michal Mocny . unresolved

Is this a new key change? Or is this just part of how the event path works?

Mohamed Youns

The old logic didn't consider the shadow element; now it considers it and doesn't expose the context if any

Line 33, Patchset 10:4. Updates target-selector.tentative.html to enforce strict string

matching. Adds test coverage for name attributes, deep nesting limits,
SVG elements and Shadow DOM encapsulation boundaries.
Michal Mocny . resolved

FYI If there are multiple different dom structures to test, its often better to create multiple distinct small test files.

It might even be useful to create a separate directory like: `event-timing/target-selector/tentative/*.html`

Mohamed Youns

Done

Open in Gerrit

Related details

Attention is currently required from:
  • Michal Mocny
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I84185c2fc148abaf706b6aa42cc73a9bbbfd164a
Gerrit-Change-Number: 7581314
Gerrit-PatchSet: 13
Gerrit-Owner: Mohamed Youns <mohame...@gmail.com>
Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
Gerrit-Reviewer: Mohamed Youns <mohame...@gmail.com>
Gerrit-Attention: Michal Mocny <mmo...@chromium.org>
Gerrit-Comment-Date: Sat, 21 Mar 2026 16:13:47 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Michal Mocny <mmo...@chromium.org>
satisfied_requirement
unsatisfied_requirement
open
diffy
Reply all
Reply to author
Forward
0 new messages