Retro-specifying fetch/performance
In the last year or so, my main task was to tackle some of the "specification technical debt" that had been accumulating over a few years, specifically at the crossroads of Fetch, performance APIs, and the HTML Standard.
Monkey patching and hand waving
When starting this work, the behaviors of some of the features relating to web performance were specified in the form of "monkey patching" — describing how another spec needs to be modified rather than modifying it; or "hand waving" — describing the expected behavior of a feature in general or vague terms.
These ways of specifying have an advantage at early stages of specification, and allow moving fast without requiring consensus prematurely.
However, as the specs mature and become widely used, these practices accumulate and come with a few costs.
Interoperability
Some details and flows may be too vaguely defined in the hand-waved description or monkey-patch. This, in turn, creates interoperability issues — one browser vendor may interpret a loosely defined phrase in some way, and another vendor in a different way.
Example: Resource Timing specified that loading images should result in a resource timing entry. However, it was not specified (or tested) whether those entries should be added before or after the image's load
event.
Bugs and security flaws
When having to spell out all the details of a previously loose spec, sometimes bugs and security/privacy flaws emerge. This has happened as part of this work more than once, for example in w3c/resource-timing#260: Resource Timing was exposing some of its properties for cross-origin resources, and by specifying it more rigorously we found that some properties that were exposed should actually be hidden.
The role of web platform tests
Of course, writing a few words into a standard doesn't fix interoperability issues or security flaws — it requires the two other pillars, tests and implementations. A big part of this debt-paying work involves adding missing coverage to web platform tests, and posting implementation bugs.
Work done so far
- The processing model of Resource Timing has been incorporated into Fetch, including many edge cases relating to service workers and network errors.
- The processing model of Navigation Timing has been incorporated into HTML.
- Page Visibility has been folded into HTML.
- The behavior of
<link rel=preload>
and how preloads are cached is now rigorously defined. timeOrigin
computation is defined in the HTML and Service Workers specs.- The deadline mechanism of
requestIdleCallback
is now clearly defined. - Patched multiple CSS specs to define how they fetch resources and report timing.
- Process
Link
headers.
Work in progress
- Additional work on
Link
headers. - Clearly defining
<link rel=prefetch>
— this is a bit tricky as browsers treat prefetch in different ways. - Rigorous specification for Server Timing.
- Define CSP interaction with preload.
- Specifying fetching range requests (for media).
- Finish the HTML integration for resource timing, which requires that all reporters of resource timing do so at the appropriate time.
- Specify early hint headers.
- Attempt to define the memory cache.
Retroactive consensus
Some of the features in question are already shipped, and vendors took liberties to interpret them in different ways. This raises a challenge of achieving retroactive consensus. Vendors might have good reasons to do things differently, but the differences make it difficult for web developers to write interoperable code. In the area of performance APIs, interoperability issues mean that performance measurements or hints might create different results across browsers.
Because the feature is already shipped, achieving consensus retroactively means that browser vendors would have to go back to their implementations and change things, which apart from the work involved could potentially make things suboptimal for some existing cases. Is interoperability worth it? That's a good question and the answer is dynamic.
A current example of this is the attempts to specify prefetch. It is a relatively old feature that is implemented differently across browsers and those two facts make it difficult to spec after the fact. Another bigger example is the discussion about navigation start time being the zero point, which is a cross-origin information leak, but where fixing it would have big implications.
What's next
The technical debt in the fetch/HTML/performance crossroads is a little smaller than before, but still far from being paid. Apart from the in-progress pull requests, some of the remaining debt is tracked here.
How you could help
Apart from the retroactive consensus challenge, an additional challenge is involving more people in the conversation. You can help by reading the issues in progress, forming opinions, finding flaws, posting what you find, proactively becoming involved. If you're not part of the conversation already and are curious, follow the links in this post, read, ask questions, and make suggestions. We'd love to hear from you!