-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Document render blocking with a <link rel=expect> element #9970
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 19 commits
4cd42e8
44f212a
e03fe95
745e1ff
8469cc6
6400b52
e053141
13f8fd6
d70a7a0
0a7f0ae
d701641
ab0a4fb
8ab3a90
3d81086
4eb3251
ec278ec
f2f7071
3f1e9ac
a0ab1dd
435c97c
c1652a8
1bacd54
dc919fa
b89e0ad
80bf0d3
6a9d5b2
f5bae82
53f8aa5
c88bce2
ac5a66f
d7bc03a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1789,6 +1789,10 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute | |
<li><p><span>Reset the form owner</span> of the <span>form-associated element</span>.</p></li> | ||
</ol> | ||
</li> | ||
|
||
<li><p>If <var>insertedNode</var> is an <code>Element</code> whose not on the | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<span>stack of open elements</span> of an <span>HTML parser</span>, then | ||
<span>unblock on expected element</span> given <var>insertedNode</var>.</p></li> | ||
</ol> | ||
|
||
<p>The <span data-x="concept-node-remove-ext">removing steps</span> for the HTML Standard, given | ||
|
@@ -2449,6 +2453,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute | |
<li>The <dfn data-x-href="https://url.spec.whatwg.org/#concept-urlencoded"><code>application/x-www-form-urlencoded</code></dfn> format</li> | ||
<li>The <dfn data-x-href="https://url.spec.whatwg.org/#concept-urlencoded-serializer"><code>application/x-www-form-urlencoded</code> serializer</dfn></li> | ||
<li><dfn data-x-href="https://url.spec.whatwg.org/#is-special">is special</dfn></li> | ||
<li><dfn data-x-href="https://url.spec.whatwg.org/#url-fragment-string">URL-fragment string</dfn></li> | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</ul> | ||
|
||
<p>A number of schemes and protocols are referenced by this specification also:</p> | ||
|
@@ -15133,6 +15138,7 @@ interface <dfn interface>HTMLLinkElement</dfn> : <span>HTMLElement</span> { | |
data-x="concept-supported-tokens">supported tokens</span> are | ||
<code data-x="rel-alternate">alternate</code>, | ||
<code data-x="rel-dns-prefetch">dns-prefetch</code>, | ||
<code data-x="rel-expect">expect</code>, | ||
<code data-x="rel-icon">icon</code>, | ||
<code data-x="rel-manifest">manifest</code>, | ||
<code data-x="rel-modulepreload">modulepreload</code>, | ||
|
@@ -24576,6 +24582,11 @@ document.body.appendChild(wbr);</code></pre> | |
<dd><p>These are links to other resources that are generally exposed to the user by the user | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
agent so that the user can cause the user agent to <span>navigate</span> to those resources, e.g. | ||
to visit them in a browser or download them.</p></dd> | ||
|
||
<dt><dfn data-x="Internal resource link" export>Internal resource link</dfn></dt> | ||
|
||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<dd><p>These are links to resources within the current document, used to give those resources | ||
special meaning or behavior.</p></dd> | ||
</dl> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<p>For <code>link</code> elements with an <code data-x="attr-link-href">href</code> attribute and a | ||
|
@@ -25856,6 +25867,15 @@ document.body.appendChild(wbr);</code></pre> | |
<td>Specifies that the user agent should preemptively perform DNS resolution for the target resource's <span>origin</span>.</td> | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</tr> | ||
|
||
<tr> | ||
<td><code data-x="rel-expect">expect</code></td> | ||
<td><span>Internal resource link</span></td> | ||
<td colspan="2"><em>not allowed</em></td> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<td class="no"> · </td> | ||
<td class="no"> · </td> | ||
<td>Expect an element with the target ID to appear in the current document.</td> | ||
</tr> | ||
|
||
<tr> | ||
<td><code data-x="rel-external">external</code></td> | ||
<td><em>not allowed</em></td> | ||
|
@@ -26315,6 +26335,117 @@ document.body.appendChild(wbr);</code></pre> | |
</ol> | ||
|
||
|
||
<h5>Link type "<dfn attr-value for="link/rel"><code data-x="rel-expect">expect</code></dfn>"</h5> | ||
|
||
<p>The <code data-x="rel-expect">expect</code> keyword may be used with <code>link</code> | ||
elements.</p> | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<p>The <code data-x="rel-expect">expect</code> keyword indicates that an element with a certain | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<span data-x="concept-id">ID</span> is expected in this document, and the link might | ||
<span>block rendering</span> until that element's closing tag is parsed.</p> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<p>There is no default type for resources given by the <code data-x="rel-expect">expect</code> | ||
keyword.</p> | ||
|
||
<p>Whenever the following conditions occur for an <code data-x="rel-expect">expect</code> | ||
<code>link</code> element <var>el</var>:</p> | ||
|
||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<ul> | ||
<li><p><var>el</var>'s <code data-x="attr-link-href">href</code> attribute is | ||
changed;</p></li> | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<li><p>The environment changed and <var>el</var> has a <code | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From implementation perspective, this may be hard to realize because we need to know which environment can change to satisfy or not satisfy a media value. We also need to be future proof about this. Is there a precedence in the spec for re-checking media attribute if the environment changes? IMHO the ideal think would be to define specific points at which the media attribute is checked (e.g. for rel=expect, when the link element is parsed/encountered) and make the decision whether it applies at that time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's how all existing media attributes work? E.g. viewport width media queries, dark mode... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not different from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm trying to find a place where that's spelled out in the spec, do you have a link? The best I can find in rel=stylesheet fetch setup steps is
The only other place I can see is in https://html.spec.whatwg.org/#processing-the-media-attribute (which btw, needs to updated in this PR):
This is a bit ambiguous. One can read that as "check if media matches the environment when you're about to apply the resource". I'm not sure the interpretation of "anytime environment changes, recheck all media attributes" is clear here. What is the correct reading of this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Likewise here, the only relevant text I can find is in https://html.spec.whatwg.org/#link-type-preload
This says
not when the environment itself changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed it as a requirement and added a note instead There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this is just a victim of the general under-specification of link processing, indeed.. I don't understand the new note though. The normative text says that when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The note is about the environment changing without media changing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For stylesheets, the handling of environment changes for the CSSOM View defines when the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm unsure where this discussion leaves us but I personally am content with what's currently written because this area feels like an existing problem. @zcorpan, if you have any concerns or concrete suggestions, please let us know. |
||
data-x="attr-link-media">media</code> attribute; or</p></li> | ||
|
||
<li><p><var>el</var>'s <code data-x="attr-link-media">media</code> attribute changed.</p></li> | ||
</ul> | ||
|
||
<p>perform the following steps:</p> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<ol> | ||
<li> | ||
<p>If all of the following are true:</p> | ||
|
||
<ul> | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<li><p><var>el</var> is <span>browsing-context connected</span>;</p></li> | ||
|
||
<li><p><var>el</var>'s <code data-x="attr-link-rel">rel</code> attribute | ||
contains <code data-x="rel-expect">expect</code>;</p></li> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<li><p><var>el</var>'s <code data-x="attr-link-media">media</code> attribute | ||
<span>matches the environment</span>; and</p></li> | ||
|
||
<li><p>the <span>expected ID fragment</span> for <var>el</var> is not null.</p> | ||
</ul> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<p>then <span>block rendering</span> on <var>el</var>.</p> | ||
</li> | ||
|
||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<li><p>Otherwise, <span>unblock rendering</span> on <var>el</var>.</p></li> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</ol> | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<p>To retrieve the <dfn>expected ID fragment</dfn> of an <span | ||
data-x="rel-expect">expect</span> <code>link</code> element <var>el</var>, run these steps: | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<ol> | ||
<li><p>Let <var>url</var> be the result of <span>encoding-parsing a URL</span> given | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<var>el</var>'s <code data-x="attr-link-href">href</code> attribute's value, relative to | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<var>el</var>'s <span>node document</span>.</p></li> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<li><p>If <span>node document</span>'s <span data-x="concept-document-url">URL</span> does | ||
not <span data-x="concept-url-equals">equal</span> <var>url</var> with <i | ||
data-x="url equals exclude fragments">exclude fragments</i> set to true, then return | ||
null.</p></li> | ||
|
||
<li><p>If <var>url</var>'s <span | ||
data-x="concept-url-fragment">fragment</span> is the empty string, return null.</p></li> | ||
|
||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<li><p>Return <var>fragment</var>.</p></li> | ||
</ol> | ||
|
||
<p>To <dfn>unblock on expected element</dfn> <var>el</var>:</p> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<ol> | ||
<li> | ||
<p><span data-x="list iterate">For each</span> <code | ||
data-x="rel-expect">expect</code> <code>link</code> element <var>link</var> in | ||
<var>doc</var>'s <span>render-blocking element set</span>:</p> | ||
|
||
<ol> | ||
<li><p>Let <var>fragment</var> be the <span>expected ID fragment</span> for | ||
<var>link</var>.</p></li> | ||
|
||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<li><p><span>Assert</span>: <var>fragment</var> is not null.</p></li> | ||
|
||
<li> | ||
<p>If any of the following are true:</p> | ||
|
||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<ul> | ||
<li><p><var>el</var> is the <span>document element</span></p></li> | ||
|
||
<li><p><var>fragment</var> is <var>el</var>'s <span | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
data-x="concept-id">ID</span>;</p></li> | ||
|
||
<li><p>The result of <span data-x="decode indicator from fragment">decoding</span> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<var>fragment</var>is <var>el</var>'s <span data-x="concept-id">ID</span>; or</p></li> | ||
</ul> | ||
|
||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<p>then <span>unblock rendering</span> on <var>link</var>.</p> | ||
</ol> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</li> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</ol> | ||
|
||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<p>The following<span | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
data-x="concept-element-attributes-change-ext">attribute change steps</span>, given | ||
<var>element</var> and <var>localName</var> are used to ensure <span | ||
data-x="rel-expect">expect</span> <code>link</code> elements respond to dynamic <span | ||
data-x="attr-id">id</span> changes:</p> | ||
|
||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<ol> | ||
<li><p>If <var>localName</var> is <code data-x="attr-id">id</code>, and <var>element</var> is not | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
in a <span>stack of open elements</span> of an <span>HTML parser</span>, then | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<span>unblock on expected element</span> <var>element</var>.</p></li> | ||
</ol> | ||
|
||
<h5>Link type "<dfn attr-value for="a/rel,area/rel,form/rel"><code | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
data-x="rel-external">external</code></dfn>"</h5> | ||
<!-- fifth and sixth most used <a rel> value (sixth is "external nofollow") --> | ||
|
@@ -101891,11 +102022,8 @@ location.href = '#foo';</code></pre> | |
<li><p>If <var>potentialIndicatedElement</var> is not null, then return | ||
<var>potentialIndicatedElement</var>.</p></li> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Slightly better phrasing:
|
||
|
||
<li><p>Let <var>fragmentBytes</var> be the result of <span | ||
data-x="percent-decode">percent-decoding</span> <var>fragment</var>.</p></li> | ||
|
||
<li><p>Let <var>decodedFragment</var> be the result of running <span>UTF-8 decode without | ||
BOM</span> on <var>fragmentBytes</var>.</p></li> | ||
<li><p>Let <var>decodedFragment</var> be the result of <span | ||
data-x="decode indicator from fragment">decoding</span> <var>fragment</var>. | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<li><p>Set <var>potentialIndicatedElement</var> to the result of <span data-x="find a potential | ||
indicated element">finding a potential indicated element</span> given <var>document</var> and | ||
|
@@ -101910,6 +102038,17 @@ location.href = '#foo';</code></pre> | |
<li><p>Return null.</p></li> | ||
</ol> | ||
|
||
<p>To <dfn>decode indicator from fragment</dfn> given an <span>ASCII string</span> | ||
<var>fragment</var>, run these steps:</p> | ||
|
||
<ol> | ||
noamr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<li><p>Let <var>fragmentBytes</var> be the result of <span | ||
data-x="percent-decode">percent-decoding</span> <var>fragment</var>.</p></li> | ||
|
||
<li><p>Return result of running <span>UTF-8 decode without | ||
BOM</span> on <var>fragmentBytes</var>.</p></li> | ||
</ol> | ||
|
||
<p>To <dfn>find a potential indicated element</dfn> given a <code>Document</code> | ||
<var>document</var> and a string <var>fragment</var>, run these steps:</p> | ||
|
||
|
@@ -122316,6 +122455,9 @@ dictionary <dfn dictionary>StorageEventInit</dfn> : <span>EventInit</span> { | |
the <span>stack of open elements</span> has only one element in it (<span>fragment case</span>); | ||
otherwise, the <span>adjusted current node</span> is the <span>current node</span>.</p> | ||
|
||
<p>When the <span>current node</span> <var>el</var> is removed from the | ||
<span>stack of open elements</span>, <span>unblock on expected element</span> <var>el</var>.</p> | ||
|
||
<p>Elements in the <span>stack of open elements</span> fall into the following categories:</p> | ||
|
||
<dl> | ||
|
@@ -129161,6 +129303,8 @@ document.body.appendChild(text); | |
|
||
<li><p>Pop <em>all</em> the nodes off the <span>stack of open elements</span>.</p></li> | ||
|
||
<li><p><span>Unblock on expected element</span> given the <span>document element</span>.</p></li> | ||
domenic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<li><p>While the <span>list of scripts that will execute when the document has finished | ||
parsing</span> is not empty:</p> | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.