Skip to content

Commit

Permalink
Define behavior of <link rel=preload> in detail
Browse files Browse the repository at this point in the history
A document keeps a list of preloaded resources, each with relevant parameters from the request, and the response once available.

Once a <link rel=preload> element starts fetching a resource, that entry is added, and once the response is fully loaded, the fetch consuming the resource receives the response.

See whatwg/fetch#590.
  • Loading branch information
noamr authored and mfreed7 committed Jun 3, 2022
1 parent b23d9fa commit 7cfb00a
Showing 1 changed file with 175 additions and 39 deletions.
214 changes: 175 additions & 39 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -2152,6 +2152,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li><dfn data-x-href="https://infra.spec.whatwg.org/#scalar-value">scalar value</dfn></li>
<li><dfn data-x-href="https://infra.spec.whatwg.org/#tuple">tuple</dfn></li>
<li><dfn data-x-href="https://infra.spec.whatwg.org/#noncharacter">noncharacter</dfn></li>
<li><dfn data-x-href="https://infra.spec.whatwg.org/#byte-sequence">byte sequence</dfn><li>
<li><dfn data-x-href="https://infra.spec.whatwg.org/#string">string</dfn>,
<dfn data-x-href="https://infra.spec.whatwg.org/#code-unit">code unit</dfn>,
<dfn data-x-href="https://infra.spec.whatwg.org/#string-length">length</dfn>, and
Expand Down Expand Up @@ -2487,7 +2488,10 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li>the <dfn data-x-href="https://fetch.spec.whatwg.org/#requestcredentials"><code>RequestCredentials</code></dfn> enumeration</li>
<li>the <dfn data-x-href="https://fetch.spec.whatwg.org/#requestdestination"><code>RequestDestination</code></dfn> enumeration</li>
<li>the <dfn data-x-href="https://fetch.spec.whatwg.org/#dom-global-fetch"><code>fetch()</code></dfn> method</li>
<li><dfn data-x-href="https://fetch.spec.whatwg.org/#finalize-and-report-timing">finalize and report timing</dfn></li>
<li><dfn data-x="serialize-a-response-url-for-reporting" data-x-href="https://fetch.spec.whatwg.org/#serialize-a-response-url-for-reporting">serialize a response URL for reporting</dfn></li>
<li><dfn data-x="body safely extract" data-x-href="https://fetch.spec.whatwg.org/#bodyinit-safely-extract">safely extracting a body</dfn></li>
<li><dfn data-x-href="https://fetch.spec.whatwg.org/#process-response-end-of-body">processResponseEndOfBody</dfn></li>
<li>
<dfn data-x="concept-response"
data-x-href="https://fetch.spec.whatwg.org/#concept-response">response</dfn> and its
Expand Down Expand Up @@ -14012,37 +14016,13 @@ interface <dfn interface>HTMLLinkElement</dfn> : <span>HTMLElement</span> {
<var>el</var>, is as follows:</p>

<ol>
<li><p>If <var>el</var>'s <code data-x="attr-link-href">href</code> attribute's value is the
empty string, then return.</p></li>

<li><p><span>Parse a URL</span> given <var>el</var>'s <code data-x="attr-link-href">href</code>
attribute, relative to <var>el</var>'s <span>node document</span>. If that fails, then return.
Otherwise, let <var>url</var> be the <span>resulting URL record</span>.</p></li>

<li><p>Let <var>corsAttributeState</var> be the current state of <var>el</var>'s <code
data-x="attr-link-crossorigin">crossorigin</code> content attribute.</p></li>
<li><p>Let <var>request</var> be the result of <span data-x="create a link element
request">creating a <code>link</code> element request</span> given <var>el</var>.</p></li>

<li><p>Let <var>request</var> be the result of <span
data-x="create a potential-CORS request">creating a potential-CORS request</span> given
<var>url</var>, the empty string, and <var>corsAttributeState</var>.</p></li>
<li><p>If <var>request</var> is null, then return.</p></li>

<li><p>Set <var>request</var>'s <span>synchronous flag</span>.</p></li>

<li><p>Set <var>request</var>'s <span data-x="concept-request-client">client</span> to
<var>el</var>'s <span>node document</span>'s <span>relevant settings object</span>.</p></li>

<li><p>Set <var>request</var>'s <span data-x="concept-request-nonce-metadata">cryptographic
nonce metadata</span> to the current value of <var>el</var>'s <span>[[CryptographicNonce]]</span>
internal slot.</p></li>

<li><p>Set <var>request</var>'s <span data-x="concept-request-integrity-metadata">integrity
metadata</span> to the current value of <var>el</var>'s <code
data-x="attr-link-integrity">integrity</code> content attribute.</p></li>

<li><p>Set <var>request</var>'s
<span data-x="concept-request-referrer-policy">referrer policy</span> to the current state of
<var>el</var>'s <code data-x="attr-link-referrerpolicy">referrerpolicy</code> attribute.</p></li>

<li><p>Run the <span>linked resource fetch setup steps</span>, given <var>el</var> and
<var>request</var>. If the result is false, then return.</p></li>

Expand Down Expand Up @@ -14082,6 +14062,43 @@ interface <dfn interface>HTMLLinkElement</dfn> : <span>HTMLElement</span> {
</li>
</ol>

<p>To <dfn data-x="create a link element request">create a <code>link</code> element request</dfn>
given a <code>link</code> element <var>el</var> and an optional string <var>destination</var>
(default the empty string):</p>

<ol>
<li><p>If <var>el</var>'s <code data-x="attr-link-href">href</code> attribute's value is the
empty string, then return null.</p></li>

<li><p><span>Parse a URL</span> given <var>el</var>'s <code data-x="attr-link-href">href</code>
attribute, relative to <var>el</var>'s <span>node document</span>. If that fails, then return
null. Otherwise, let <var>url</var> be the <span>resulting URL record</span>.</p></li>

<li><p>Let <var>corsAttributeState</var> be the current state of <var>el</var>'s <code
data-x="attr-link-crossorigin">crossorigin</code> content attribute.</p></li>

<li><p>Let <var>request</var> be the result of <span data-x="create a potential-CORS
request">creating a potential-CORS request</span> given <var>url</var>, <var>destination</var>,
and <var>corsAttributeState</var>.</p></li>

<li><p>Set <var>request</var>'s <span data-x="concept-request-client">client</span> to
<var>el</var>'s <span>node document</span>'s <span>relevant settings object</span>.</p></li>

<li><p>Set <var>request</var>'s <span data-x="concept-request-nonce-metadata">cryptographic
nonce metadata</span> to the current value of <var>el</var>'s
<span>[[CryptographicNonce]]</span> internal slot.</p></li>

<li><p>Set <var>request</var>'s <span data-x="concept-request-integrity-metadata">integrity
metadata</span> to the current value of <var>el</var>'s <code
data-x="attr-link-integrity">integrity</code> content attribute.</p></li>

<li><p>Set <var>request</var>'s <span data-x="concept-request-referrer-policy">referrer
policy</span> to the current state of <var>el</var>'s <code
data-x="attr-link-referrerpolicy">referrerpolicy</code> content attribute.</p></li>

<li><p>Return <var>request</var>.</p></li>
</ol>

<p>User agents may opt to only try to <span data-x="fetch and process the linked resource">fetch
and process</span> such resources when they are needed, instead of pro-actively fetching all the
<span data-x="external resource link">external resources</span> that are not applied.</p>
Expand Down Expand Up @@ -25428,34 +25445,102 @@ document.body.appendChild(wbr);</code></pre>
elements. This keyword creates an <span data-x="external resource link">external resource
link</span>. This keyword is <span>body-ok</span>.</p>

<p>The <code data-x="rel-preload">preload</code> keyword indicates that the user agent must
<p>The <code data-x="rel-preload">preload</code> keyword indicates that the user agent will
preemptively <span data-x="concept-fetch">fetch</span> and cache the specified resource according
to the <span data-x="concept-potential-destination">potential destination</span> given by the
<code data-x="attr-link-as">as</code> attribute (and the <span
data-x="concept-request-priority">priority</span> associated with the <span
data-x="concept-potential-destination-translate">corresponding</span> <span
data-x="concept-request-destination">destination</span>), as it is highly likely that the user
will require this resource for the current navigation. <span w-nodev>User agents must implement
the processing model of the <code data-x="rel-preload">preload</code> keyword described in
<cite>Preload</cite>, as well as in this specification's <span>fetch and process the linked
resource</span> algorithm.</span> <ref spec=PRELOAD></p>
will require this resource for the current navigation. <ref spec=PRELOAD></p>

<p>There is no default type for resources given by the <code data-x="rel-preload">preload</code>
keyword.</p>

<p>The <span>linked resource fetch setup steps</span> for this type of linked resource, given a
<code>link</code> element <var>el</var> and <span data-x="concept-request">request</span>
<var>request</var>, are:</p>
<p>A <code>Document</code> has a <dfn>map of preloaded resources</dfn>, which is a
<span>map</span>, initially empty.</p>

<p>A <dfn>preload key</dfn> is a <span>struct</span>. It has the following <span data-x="struct
item">items</span>:</p>

<dl>
<dt><dfn data-x="preload URL">URL</dfn>
<dd>A <span>URL</span>

<dt><dfn data-x="preload destination">destination</dfn>
<dt><dfn data-x="preload integrity metadata">integrity metadata</dfn>
<dd>A string

<dt><dfn data-x="preload mode">mode</dfn>
<dd>A <span data-x="concept-request-mode">request mode</span>, either
<code data-x="">same-origin</code>", "<code data-x="">cors</code>", or
"<code data-x="">no-cors</code>"

<dt><dfn data-x="preload credentials mode">credentials mode</dfn>
<dd>A <span data-x="concept-request-credentials-mode">credentials mode</span>
</dl>

<p>A <dfn>preload entry</dfn> is a <span>struct</span>. It has the following <span data-x="struct
item">items</span>:</p>

<dl>
<dt><dfn data-x="preload response">response</dfn>
<dd>Null or a <span data-x="concept-response">response</span>

<dt><dfn data-x="preload on response available">on response available</dfn>
<dd>Null, or an algorithm accepting a <span data-x="concept-response">response</span> or null
</dl>

<p>To <dfn export>consume a preloaded resource</dfn> for <code>Window</code> <var>window</var>,
given a <span>URL</span> <var>url</var>, a string <var>destination</var>, a string
<var>mode</var>, a string <var>credentialsMode</var>, a string <var>integrityMetadata</var>, and
<var>onResponseAvailable</var>, which is an algorithm accepting a <span
data-x="concept-response">response</span>:</p>

<ol>
<li><p>Let <var>key</var> be a <span>preload key</span> whose <span data-x="preload
URL">URL</span> is <var>url</var>, <span data-x="preload destination">destination</span> is
<var>destination</var>, <span data-x="preload integrity metadata">integrity metadata</span> is
<var>integrityMetadata</var>, <span data-x="preload mode">mode</span> is <var>mode</var>, and
<span data-x="preload credentials mode">credentials mode</span> is
<var>credentialsMode</var>.</p></li>

<li><p>Let <var>preloads</var> be <var>window</var>'s <span
data-x="concept-document-window">associated <code>Document</code></span>'s <span>map of
preloaded resources</span>.</p></li>

<li><p>If <var>key</var> does not <span data-x="map exists">exist</span> in <var>preloads</var>,
then return false.</p></li>

<li><p>Let <var>entry</var> be <var>preloads</var>[<var>key</var>].</p></li>

<li><p><span data-x="map remove">Remove</span> <var>preloads</var>[<var>key</var>].</p></li>

<li><p>If <var>entry</var> <span data-x="preload response">response</span> is null, then set
<var>entry</var>'s <span data-x="preload on response available">on response available</span> to
<var>onResponseAvailable</var>.</p></li>

<li><p>Otherwise, call <var>onResponseAvailable</var> with <var>entry</var>'s <span
data-x="preload response">response</span>.</p></li>

<li><p>Return true.</p></li>
</ol>

<p>The <span>fetch and process the linked resource</span> steps for this type of linked resource,
given a <code>link</code> element <var>el</var>, are:</p>

<ol>
<li><p>Let <var>as</var> be the current state of <var>el</var>'s <code
data-x="attr-link-as">as</code> attribute.</p></li>

<li><p>If <var>as</var> does not represent a state, return false.</p></li>

<li><p>Set <var>request</var>'s <span data-x="concept-request-destination">destination</span> to
the result of <span data-x="concept-potential-destination-translate">translating</span>
<var>as</var>.</p></li>
<li><p>Let <var>request</var> be the result of <span data-x="create a link element
request">creating a <code>link</code> element request</span> given <var>el</var> and the result
of <span data-x="concept-potential-destination-translate">translating</span>
<var>as</var>.<p></li>

<li><p>If <var>request</var> is null, then return.</p></li>

<li>
<p>If <var>as</var> is "<code data-x="">image</code>", then:</p>
Expand All @@ -25476,7 +25561,58 @@ document.body.appendChild(wbr);</code></pre>
</ol>
</li>

<li><p>Return true.</p></li>
<li><p>Let <var>preloadKey</var> be a <span>preload key</span> whose <span data-x="preload
URL">URL</span> is <var>request</var>'s <span data-x="concept-request-url">URL</span>, <span
data-x="preload destination">destination</span> is <var>request</var>'s <span
data-x="concept-request-destination">destination</span>, <span data-x="preload integrity
metadata">integrity metadata</span> is <var>request</var>'s <span
data-x="concept-request-integrity-metadata">integrity metadata</span>, <span data-x="preload
mode">mode</span> is <var>request</var>'s <span data-x="concept-request-mode">mode</span>, and
<span data-x="preload credentials mode">credentials mode</span> is <var>request</var>'s <span
data-x="concept-request-credentials-mode">credentials mode</span>.</p></li>

<li><p>Let <var>preloadEntry</var> be a new <span>preload entry</span>.</p></li>

<li><p><span data-x="map set">Set</span> <var>el</var>'s <span>node document</span>'s <span>map
of preloaded resources</span>[<var>preloadKey</var>] to <var>preloadEntry</var>.</p></li>

<li>
<p><span data-x="concept-fetch">Fetch</span> <var>request</var>, with <i
data-x="processResponseEndOfBody">processResponseEndOfBody</i> set to the following steps given
<span data-x="concept-response">response</span> <var>response</var> and null or <span>byte
sequence</span> <var>bytesOrNull</var>:</p>

<ol>
<li>
<p>If <var>bytesOrNull</var> is a <span>byte sequence</span>, then set <var>response</var>'s
<span data-x="concept-response-body">body</span> to the first return value of <span
data-x="body safely extract">safely extracting</span> <var>bytesOrNull</var>.</p>

<p class=note>By using <i data-x="processResponseEndOfBody">processResponseEndOfBody</i>, we
have <span data-x="body safely extract">extracted</span> the entire <span
data-x="concept-response-body">body</span>. This is necessary to ensure the preloader loads
the entire body from the network, regardless of whether the preload will be consumed (which
is uncertain at this point). This step then resets the request's body to a new body
containing the same bytes, so that other specifications can read from it at the time of
actual consumption, despite us having already done so once.</p>
</li>

<li><p>Otherwise, set <var>response</var> to a <span>network error</span>.</p></li>

<li><p><span>Finalize and report timing</span> with <var>response</var>, given <var>el</var>'s
<span>relevant global object</span> and "<code data-x="">link</code>".</p></li>

<li><p><span data-x="concept-event-fire">Fire an event</span> named <code
data-x="event-load">load</code> at <var>el</var>.</p></li>

<li><p>If <var>preloadEntry</var>'s <span data-x="preload on response available">on response
available</span> is null, then set <var>preloadEntry</var>'s <span data-x="preload
response">response</span> to <var>response</var>.</p></li>

<li><p>Otherwise, call <var>preloadEntry</var>'s <span data-x="preload on response
available">on response available</span> with <var>response</var>.</p></li>
</ol>
</li>
</ol>


Expand Down

0 comments on commit 7cfb00a

Please sign in to comment.