Report initiator url for resources fetched in event handler. [chromium/src : main]

38 views
Skip to first unread message

Guohui Deng (Gerrit)

unread,
Feb 6, 2026, 4:00:00 PM (5 days ago) Feb 6
to Kentaro Hara, Raphael Kubo da Costa, AyeAye, Michal Mocny, Scott Haseley, Chromium LUCI CQ, Menard, Alexis, chromium...@chromium.org, Olga Gerchikov, Nate Chapin, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, chikamu...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, jmedle...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, scheduler-...@chromium.org, web-schedulin...@chromium.org
Attention needed from Scott Haseley

Guohui Deng added 3 comments

File third_party/blink/renderer/core/dom/events/event_target.cc
Line 653, Patchset 4: // Currently, resource timing context is only propagated on the main thread.
Scott Haseley . resolved

This block and the one below should be flag-guarded.

We'll want to check the overhead of this too on speedometer (with the feature enabled. I sometimes create a separate dependent branch enabling the feature to test this). I'm not sure if you have access to pinpoint, but the instructions are https://chromium.googlesource.com/chromium/src/+/main/docs/speed/perf_trybots.md (although it's speedometer3 now, not too). I'm happy to kick off a job for this too. I _think_ this should be okay, but we'll want to evaluate.

Guohui Deng

Added flag guard. Sorry I forgot this again and thank you for your patience!

Regarding the test: I can sign in and open the "run a try job" page so it looks like I have access! I will try to start the test later and if I run into problems I will ask for help. 😊

Line 1091, Patchset 4: std::optional<scheduler::TaskAttributionTracker::TaskScope>
Scott Haseley . unresolved

Note: This is a divergence from task attribution, and I'm not sure if you want that or not in all cases.

This implements "registration" semantics, where context is captured during at event listener registration time. The alternative is "Dispatch" semantics follow execution flow, e.g. an event fires async because an a certain API was called, e.g. XHR. Sometimes these are the same, sometimes they're different. (see also https://github.com/tc39/proposal-async-context/blob/master/WEB-INTEGRATION.md#events)

Task Attribution has instrumented some events using dispatch context, e.g. XHR events, some filesystem events, postMessage/MessageChannel, etc. In those cases, you might be overwriting the context with a different value, and I'm not sure if that's what you'll want or not. One option is to use your approach as a fallback if the context isn't set.

Unfortunately how AsyncContext (and ultimately Task Attribution) will handle events is a WIP and a bit of a moving target, so I'm not sure how you'll want to handle that or what best fits this API. This is a bit of a unique situation (for soft navs too) where we're building a feature on top of something else that isn't stable, and could be worth discussion more offline about timelines, etc.

Guohui Deng

From the perspective of "initiator url" I much prefer propagating the "resource timing context" from script that sets up the handler, i.e., take the "context" at the "registration" (more details below). When I saw the planning of the AsyncContext I noticed they prefer propagating the "variables" along the script execution flow -- which makes sense for other applications of TaskAttribution(like soft navigation) and AsyncContext. I vaguely remembered I asked if asyncContext can accommodate this different propagating flow, and the answer was "yes with some extra work". So I hope this won't cause too much pain for you guys. If it adds too much work I will be happy to change. (maybe speaking with WebPerf WG too)

//////////////
The reason I prefer the current approach is that, the typical use case is that we "predict" the next resource fetch by previous resource that is fetched. In addition, the prediction is never reliable, because of the limitations that we have. (one noticeable limitation is that we can only pick up one script, instead of both the script that caused the event and the script that registered the handler). I think it's advantageous to report only "the script that registers the handler" because:

a) "registration script" would be expected to happen sooner. Typically, once the handler is registered, we can expect that the resource fetched in the handler can happen at any time.
b) "registration script" always exists. Events can result from user (and I would guess this is not a small portion) so that no "initiator" caused the event. Even if we make a "fallback" to report the "registering", then more different "initiator"s can be reported for the same resource and make the prediction more difficult. In addition, I prefer simpler definition.

What do you think?

File third_party/blink/renderer/core/dom/events/registered_event_listener.h
Line 40, Patchset 4:class RegisteredEventListener final
Scott Haseley . resolved

Is this needed for `NativeEventListener` as well as JS event listeners? Feels like `JSBasedEventListener` or `JSEventListener` might be a better place for this?

Guohui Deng

It should be indeed in `JSBasedEventListener`. I made changes accordingly.

Open in Gerrit

Related details

Attention is currently required from:
  • Scott Haseley
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: I1a9ade6c7b5ff27473e720181140b064f31a4ba7
Gerrit-Change-Number: 7520726
Gerrit-PatchSet: 5
Gerrit-Owner: Guohui Deng <guohu...@microsoft.com>
Gerrit-Reviewer: Guohui Deng <guohu...@microsoft.com>
Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
Gerrit-CC: Kentaro Hara <har...@chromium.org>
Gerrit-CC: Menard, Alexis <alexis...@intel.com>
Gerrit-CC: Michal Mocny <mmo...@chromium.org>
Gerrit-CC: Nate Chapin <jap...@chromium.org>
Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
Gerrit-Attention: Scott Haseley <shas...@chromium.org>
Gerrit-Comment-Date: Fri, 06 Feb 2026 20:59:49 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Scott Haseley <shas...@chromium.org>
satisfied_requirement
unsatisfied_requirement
open
diffy

Scott Haseley (Gerrit)

unread,
Feb 6, 2026, 4:54:58 PM (5 days ago) Feb 6
to Guohui Deng, Kentaro Hara, Raphael Kubo da Costa, AyeAye, Michal Mocny, Chromium LUCI CQ, Menard, Alexis, chromium...@chromium.org, Olga Gerchikov, Nate Chapin, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, chikamu...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, jmedle...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, scheduler-...@chromium.org, web-schedulin...@chromium.org
Attention needed from Guohui Deng

Scott Haseley added 3 comments

File third_party/blink/renderer/core/dom/events/event_target.cc
Line 653, Patchset 5 (Latest): if (RuntimeEnabledFeatures::ResourceTimingInitiatorEnabled()) {
Scott Haseley . unresolved

Can all of this move into JSBasedEventListener, i.e. the constructor?

Aside from improving encapsulation, I think it might be required anyway for event attributes, e.g. `onfoo` for event "foo", when changing the listener. E.g.

```
document.onfoo = listener1;

// ... sometime later ...

document.onfoo = listener2;
```

In that case, IIUC, we update the callback in the existing registered listener and don't go down this code path. https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/dom/events/event_target.cc;l=822-825;drc=976a71ef2a509d4391d814b52b9f4700fdf35789;bpv=1;bpt=1

Line 1091, Patchset 4: std::optional<scheduler::TaskAttributionTracker::TaskScope>
Scott Haseley . unresolved

Note: This is a divergence from task attribution, and I'm not sure if you want that or not in all cases.

This implements "registration" semantics, where context is captured during at event listener registration time. The alternative is "Dispatch" semantics follow execution flow, e.g. an event fires async because an a certain API was called, e.g. XHR. Sometimes these are the same, sometimes they're different. (see also https://github.com/tc39/proposal-async-context/blob/master/WEB-INTEGRATION.md#events)

Task Attribution has instrumented some events using dispatch context, e.g. XHR events, some filesystem events, postMessage/MessageChannel, etc. In those cases, you might be overwriting the context with a different value, and I'm not sure if that's what you'll want or not. One option is to use your approach as a fallback if the context isn't set.

Unfortunately how AsyncContext (and ultimately Task Attribution) will handle events is a WIP and a bit of a moving target, so I'm not sure how you'll want to handle that or what best fits this API. This is a bit of a unique situation (for soft navs too) where we're building a feature on top of something else that isn't stable, and could be worth discussion more offline about timelines, etc.

Guohui Deng

From the perspective of "initiator url" I much prefer propagating the "resource timing context" from script that sets up the handler, i.e., take the "context" at the "registration" (more details below). When I saw the planning of the AsyncContext I noticed they prefer propagating the "variables" along the script execution flow -- which makes sense for other applications of TaskAttribution(like soft navigation) and AsyncContext. I vaguely remembered I asked if asyncContext can accommodate this different propagating flow, and the answer was "yes with some extra work". So I hope this won't cause too much pain for you guys. If it adds too much work I will be happy to change. (maybe speaking with WebPerf WG too)

//////////////
The reason I prefer the current approach is that, the typical use case is that we "predict" the next resource fetch by previous resource that is fetched. In addition, the prediction is never reliable, because of the limitations that we have. (one noticeable limitation is that we can only pick up one script, instead of both the script that caused the event and the script that registered the handler). I think it's advantageous to report only "the script that registers the handler" because:

a) "registration script" would be expected to happen sooner. Typically, once the handler is registered, we can expect that the resource fetched in the handler can happen at any time.
b) "registration script" always exists. Events can result from user (and I would guess this is not a small portion) so that no "initiator" caused the event. Even if we make a "fallback" to report the "registering", then more different "initiator"s can be reported for the same resource and make the prediction more difficult. In addition, I prefer simpler definition.

What do you think?

Scott Haseley

w.r.t extra work, it's probably fine -- but long term it might depend on how AsyncContext gets implemented. Right now, we're setting up the context (for propagation) before dispatching the event, and you're hooking into a point after that, so it works. If we change this to also hook into events, we'll just have to make sure we get the ordering right.

---

I don't have a strong opinion on the feature itself, just want to make sure it's been thought through. But this should probably be documented in the explainer and discussed at WebPerfWG at some point (doesn't block this IMO).

Line 1102, Patchset 5 (Latest): if (RuntimeEnabledFeatures::ResourceTimingInitiatorEnabled()) {
Scott Haseley . unresolved

Similarly here, can this move into the js_based_event_listener? There's an `InvokeInternal()` method that runs to actually invoke the listener, and you could hook in there. You might need to create a helper method in the common base class to create the TaskScope.

Open in Gerrit

Related details

Attention is currently required from:
  • Guohui Deng
Gerrit-Attention: Guohui Deng <guohu...@microsoft.com>
Gerrit-Comment-Date: Fri, 06 Feb 2026 21:54:50 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Guohui Deng <guohu...@microsoft.com>
Comment-In-Reply-To: Scott Haseley <shas...@chromium.org>
satisfied_requirement
unsatisfied_requirement
open
diffy

Guohui Deng (Gerrit)

unread,
Feb 10, 2026, 12:06:36 PM (22 hours ago) Feb 10
to Kentaro Hara, Raphael Kubo da Costa, AyeAye, Michal Mocny, Scott Haseley, Chromium LUCI CQ, Menard, Alexis, chromium...@chromium.org, Olga Gerchikov, Nate Chapin, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, chikamu...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, jmedle...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, scheduler-...@chromium.org, web-schedulin...@chromium.org
Attention needed from Scott Haseley

Guohui Deng added 3 comments

File third_party/blink/renderer/core/dom/events/event_target.cc
Line 653, Patchset 5: if (RuntimeEnabledFeatures::ResourceTimingInitiatorEnabled()) {
Scott Haseley . resolved

Can all of this move into JSBasedEventListener, i.e. the constructor?

Aside from improving encapsulation, I think it might be required anyway for event attributes, e.g. `onfoo` for event "foo", when changing the listener. E.g.

```
document.onfoo = listener1;

// ... sometime later ...

document.onfoo = listener2;
```

In that case, IIUC, we update the callback in the existing registered listener and don't go down this code path. https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/dom/events/event_target.cc;l=822-825;drc=976a71ef2a509d4391d814b52b9f4700fdf35789;bpv=1;bpt=1

Guohui Deng

Done

Line 1091, Patchset 4: std::optional<scheduler::TaskAttributionTracker::TaskScope>
Scott Haseley . resolved

Note: This is a divergence from task attribution, and I'm not sure if you want that or not in all cases.

This implements "registration" semantics, where context is captured during at event listener registration time. The alternative is "Dispatch" semantics follow execution flow, e.g. an event fires async because an a certain API was called, e.g. XHR. Sometimes these are the same, sometimes they're different. (see also https://github.com/tc39/proposal-async-context/blob/master/WEB-INTEGRATION.md#events)

Task Attribution has instrumented some events using dispatch context, e.g. XHR events, some filesystem events, postMessage/MessageChannel, etc. In those cases, you might be overwriting the context with a different value, and I'm not sure if that's what you'll want or not. One option is to use your approach as a fallback if the context isn't set.

Unfortunately how AsyncContext (and ultimately Task Attribution) will handle events is a WIP and a bit of a moving target, so I'm not sure how you'll want to handle that or what best fits this API. This is a bit of a unique situation (for soft navs too) where we're building a feature on top of something else that isn't stable, and could be worth discussion more offline about timelines, etc.

Guohui Deng

From the perspective of "initiator url" I much prefer propagating the "resource timing context" from script that sets up the handler, i.e., take the "context" at the "registration" (more details below). When I saw the planning of the AsyncContext I noticed they prefer propagating the "variables" along the script execution flow -- which makes sense for other applications of TaskAttribution(like soft navigation) and AsyncContext. I vaguely remembered I asked if asyncContext can accommodate this different propagating flow, and the answer was "yes with some extra work". So I hope this won't cause too much pain for you guys. If it adds too much work I will be happy to change. (maybe speaking with WebPerf WG too)

//////////////
The reason I prefer the current approach is that, the typical use case is that we "predict" the next resource fetch by previous resource that is fetched. In addition, the prediction is never reliable, because of the limitations that we have. (one noticeable limitation is that we can only pick up one script, instead of both the script that caused the event and the script that registered the handler). I think it's advantageous to report only "the script that registers the handler" because:

a) "registration script" would be expected to happen sooner. Typically, once the handler is registered, we can expect that the resource fetched in the handler can happen at any time.
b) "registration script" always exists. Events can result from user (and I would guess this is not a small portion) so that no "initiator" caused the event. Even if we make a "fallback" to report the "registering", then more different "initiator"s can be reported for the same resource and make the prediction more difficult. In addition, I prefer simpler definition.

What do you think?

Scott Haseley

w.r.t extra work, it's probably fine -- but long term it might depend on how AsyncContext gets implemented. Right now, we're setting up the context (for propagation) before dispatching the event, and you're hooking into a point after that, so it works. If we change this to also hook into events, we'll just have to make sure we get the ordering right.

---

I don't have a strong opinion on the feature itself, just want to make sure it's been thought through. But this should probably be documented in the explainer and discussed at WebPerfWG at some point (doesn't block this IMO).

Guohui Deng

got it. I will take care of these. Thanks.

Line 1102, Patchset 5: if (RuntimeEnabledFeatures::ResourceTimingInitiatorEnabled()) {
Scott Haseley . resolved

Similarly here, can this move into the js_based_event_listener? There's an `InvokeInternal()` method that runs to actually invoke the listener, and you could hook in there. You might need to create a helper method in the common base class to create the TaskScope.

Guohui Deng

Done. As discussed, I moved the code to be besides "InvokeInternal()" and made additional tests for this.

Open in Gerrit

Related details

Attention is currently required from:
  • Scott Haseley
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • 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: I1a9ade6c7b5ff27473e720181140b064f31a4ba7
    Gerrit-Change-Number: 7520726
    Gerrit-PatchSet: 6
    Gerrit-Owner: Guohui Deng <guohu...@microsoft.com>
    Gerrit-Reviewer: Guohui Deng <guohu...@microsoft.com>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Kentaro Hara <har...@chromium.org>
    Gerrit-CC: Menard, Alexis <alexis...@intel.com>
    Gerrit-CC: Michal Mocny <mmo...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
    Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
    Gerrit-Attention: Scott Haseley <shas...@chromium.org>
    Gerrit-Comment-Date: Tue, 10 Feb 2026 17:06:26 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy
    Reply all
    Reply to author
    Forward
    0 new messages