Participants

Luke Warlow, Alex Christensen, Guohui Deng, Yoav Weiss, Nic Jansma, Chengzhong Wu, Giacomo Zecchini, Mike Henniger, Noam Helfman, Nazim Can Altinova,  Joone hur, Jase Williams, Philip Tellis, Carine Bournez, Michal Mocny, Leon Brocard

Admin

Minutes

Fix 126: Add targetIdentifier to PerformanceEventTiming (ET # 126)

Michal: A long standing feature request. When you interact with an event target, the act of running the event handler can modify the DOM and sometimes removes the node from the DOM

… By the time the performance observer fires, the node is no longer there

… It’s been a persistent request to add a string that serializes the event target

… Iterating on a spec change and a Chromium prototype

… LoAF added a very similar feature. Script attribution data has metadata about the invoker

… We’ll reuse the same string format for both. Move some of the specs around

… We also want to slightly change the format for LoAF (images with src attribute and no ID had format issues)

… 2 PSAs: expect this feature soon, and fixing LoAF attribution a bit

Fetch: Add a mechanism to fetch to track progress (fetch # 1843)

Luke: fetch() replaced XHR a decade ago, but there’s missing functionality - we can’t track progress of requests and responses.

… main usecase people want is tracking the uploads

… Looked into it and it looks like it’s not challenging technically to introduce this functionality

… Current thinking is that it would be an option on the fetch call itself - a “monitor” parameter that would give you an object you can add event listeners to

… Some question about if it should be a progress event, or if it should be tracked elsewhere

.. You can use that to do all the upload tracking XHR has

… Response tracking is a bit more complex because XHR buffers the response, where fetch() exposes the stream

… There’s an idea of wrapping the response stream in an identity stream that forwards things internally and enables us to keep track

… Built on fetch() rather than Request/Response

… Corresponds to other APIs that have “tracking progress” design

Yoav: Fetch-call specific, where I know feature request on ResourceTiming was for a general detection of any fetches have started

… Traditional use-case for that was around client-side implementations of TTI and detecting idle time on the network

… If it is, it would be great to think through the design and tackle it, or expand later on to cover general fetches or fetch calls

Michal: How form uploads would track progress?  Does it initiate a fetch?  Would it help w/ that use-case?

… A file-selector, then native upload.  Semantically valid and best-case way to implement this.

Luke: Form submission can navigate the page so no JS execution happening at that time

Michal: You can intercept and not have it navigate

Philip: The form can also submit to a different target and not replace the current page

Nic: One use case is TTI and detecting idle time. Boomerang does that today.

… We also use fetch and XHR wrapping for SPA soft navigation tracking, to try and determine “end time” of soft navigation

… Being able to observe all fetches would be helpful

… For this in particular, it’s useful for a first party use-case, but less useful for a third party (a RUM script) that wants to monitor fetches initiated by other scripts. Today we wrap fetch and XHR API, and we wouldn’t be able to use this proposal to stop doing that

… Would be to great to have a global observer

… As an example, there are multiple Akamai scripts that wrap fetch and XHR, and other 3Ps do that as well. Multiple wrappings are not a recipe for a good time

… An observer would be very useful

NoamR: I wanted to say that for the observer usecase, you don’t want progress on every single upload buffer. This API is for first party upload tracking. You can do that in a service worker, but that’s harder

… If we wanted to do this, we should see what’s missing in service workers

NoamH: A couple of comments on this. It’s supposed to provide a solution similar to XHR. Also wanted to point out a similar usecase - monitor the download of the HTML page as it arrives in multiple chunks. Currently we have to add JS snippets to different parts of the page. Last question - is it still a common practice to use upload forms? I’ve seen people do that in a separate navigation..

Luke: Differences from XHR - you should be able to do everything here. The main differences would be in API design

Yoav: There's a good point from NoamR that this is a different use-case (upload tracking vs. detecting silence over network vs. keeping track of different buffers that HTML took to download)

… Maybe they should be addressed by different API shapes?

… Can we have a unified spec / infrastructure / implementation that would hook into the Fetch algorithm and do all of the things we would want to do

… In which case, this group will not bug you about addressing use-cases, but if we could build a unified hook, we could build on top of your work to address this group's use-cases

Luke: That makes sense.  API designed to match other APIs like this.

… Currently it is fairly rooted in Fetch JavaScript call itself, Fetch already provides a lot of hooks

… What XHR is using to do Upload and Download progress tracking

… Wrapping response stream is something we can design in such a way that it's outside the Fetch call itself

… Some of these callbacks we provide into these hooks, we can generalize somewhat

… For non-JS fetches, one thing worth keeping in mind, many will happen in context where JS can't run while they're happening

… Downside because it means you can't get access to that data, but they may be designed such that JS won't be running at that time

Yoav: Basic shape I have in mind is an Observer pattern, like PerformanceObserver, the JavaScript will run in an async way.  Not parallel to when resource did the thing we want to observe, but has a timestamp

… Sufficient for our use-cases

NoamH: Comment NoamR made on ServiceWorker, I think it would address my use-case of streaming of navigation

… However in most cases, it would be excluded with Static Routing, so I don't know if it would intercept the fetch in that case

Yoav: Service Workers are hard to pull-off for a third-party

… Not as practical for use-cases we're talking about

Luke: Feedback on PR https://github.com/whatwg/fetch/pull/1843 

Async Context continued

Chengzhong: Want to continue the discussion on AsyncContext

…  might be interesting to talk about events. We use context of when the event was fired - the dispatching context.

… In TaskAttribution we want to observe when the task is being terminated, where AsyncContext doesn’t give you that option

… If people want to observe that they need to build their own termination semantics. Would be interesting to see how the task attribution termination can work with asyncContext

… Also found a bug in the softNavigation spec when a promise is rejected - may make sense for softnavigations to follow what asyncContext did

Michal: So for the softNavigation spec, it’s pretty old and gone through several iterations since. It was changed quite a bit to be more like asyncContext. It’s likely that the spec is wrong

.. We want to match the asyncContext semantics

Chengzhong: contexts are not propagated across agents so aren’t serialized. So the propagation through messagePorts may be tricky.

Michal: It’s same-agent message ports, and even there it’s constrained

Chengzhong: not propagating the context across agents would be great

Michal: As a principle it’d be nice to decouple this from the soft navigation spec

… When it comes to event listeners of certain types, TODO

… So we don’t have to change the context

Andreu: that’s the goal - have an internal asyncContext variable and change the variable before certain calls

… For messagePorts in particular I looked into it. It’s tricky as you can transfer messages between ports, and it’s hard to know when to remove that memory

… So thinking to only propagate if neither of the messageports have been transferred, guaranteeing same agent

… Sometimes you can have sync cross-origin communication e.g. focus blur if there’s no site isolation or if you land in the same process

… Current thinking you would explicitly clear the context in those cases

… Simpler if there’s no propagation at all, but there can also be simplicity in allowing it some cases

Yoav: Regarding events, if we look on an event-by-event basis, there could be differences in the desired outcome in turns of propagated context.  For soft navigations, if we take FCP, the work it's doing in context of Task Attribution, should be registered whoever the FCP event, and not what triggered the FCP.

… FCP doesn't have a context besides who registered it.  Other PerformanceObservers, UserTiming for example, you have registration context and dispatching context, those are typically dictated by registration and not by dispatch context.

… Dispatching added a new Mark, work that follows is script that registered the thing wanted to happen

… How does this work layed on async context

Michal: Let's say a click on a button triggers some event.  Event registered earlier, and is what will update change (route change)

… We want interaction to be part of that journey so we can attribute to soft nav

… Whereas developer of route handler might want original registration semantics

… But you can think about it; We wrap when firing, but we'll restore context of all variables to API

… Hidden value that no one has access to for browser, we'd fork it, variables restore their registration time.  We could have a different value

… We'd need to know whether the interaction lead to that event happening

… I think we could support both use-cases

… Start by restoring original context, we'd override value before forking the code

… I think some of that happening for scheduler already

… At least most recently that's how we decided we could square that different of opinion happening

Jase: I struggle for use-cases on registration side.  PerformanceObserver for FCP… I think it could be more useful for events triggered by event listeners.  I don't see registration eating those events as much.

… I can't picture people needing to go back to the PerformanceObserver registration as much.  Seems like a weaker use-case than dispatch to me

Michal: How would a developer write their code?  Save some value into a variable (context)

… The moment I register some continuation I also save some local state

… Then my callback is called or continued, I want my local state to read it back

… Interaction shouldn't overwrite my storage

… Path that got there is unique, separate state off to the side

Yoav: Looking from Async Context use-case, I want to be able to track perf and attribute runtime to actors, if I have UserTiming, script that registers event that does a ton of work, then that gets blamed for calling mark/measure

… Feels like there's some attribution issues there

Andreu: Feedback from Mozilla concerned about implicit propagation that would cause memory leaks in the wild

… Register event, no one ever calls removeEventListener()

… If it's a single event listener, that could be handled specially

Yoav: My feedback is that concerns about memory leaks should lead to different designs, not different semantics

… Shouldn't be reason we're pointing at wrong actor and attribution

Michal: For our use-case we've been thinking of having an internal variable(s) that might have different semantics

… We override values when there's a better value to set

… Should the foundation API be more flexible?

… I wonder if interactions aren't unique to web platform, where knowing the current active interaction, that could be exposed as a variable

… Maybe not general calls, but a performance API, you could ask for the internal variable value

… I don't know how many other cases on the web, on the web, new input that forks pathway on site seems interesting and important

… Other perf APIs could hook into that to adjust attribution