Re: [whatwg/fetch] Deferred fetching (PR #1647)

@annevk commented on this pull request.

I think this is very close. If anyone has any final comments please make them this week. I'll work with Noam to get this merged early next week.

> +   <li>
+    <p>The user agent should wait until any of the following conditions is met:
+
+    <ul class=brief>
+     <li><p>At least <var>activateAfter</var> milliseconds have passed.
+
+     <li><p>The user agent has a reason to believe that it is about to lose the opportunity to
+     execute scripts, e.g., when the browser is moved to the background, or when
+     <var>request</var>'s <a for=request>window</a> is a {{Window}} whose
+     <a>associated document</a> had a "<code>hidden</code>" <a for=Document>visibility state</a> for
+     a long period of time.
+    </ul>
+
+   <li><p><a data-lt="process a deferred fetch">Process</a> <var>deferredRecord</var>.
+  </ol>
+ </li>

```suggestion
```

> +  </ol>
+ </li>
+
+ <li><p>Return <var>deferredRecord</var>.
+</ol>
+</div>
+
+<div algorithm>
+<p>To compute the <dfn>total request length</dfn> of a <a for=/>request</a> <var>request</var>:
+
+<ol>
+ <li><p>Let <var>totalRequestLength</var> be the <a for=string>length</a> of <var>request</var>'s
+ <a for=request>URL</a>, <a lt="URL serializer">serialized</a> with
+ [=URL serializer/exclude fragment=] set to true.
+
+ <li><p>Increment <var>totalRequestLength</var> by the  <a for=string>length</a> of

```suggestion
 <li><p>Increment <var>totalRequestLength</var> by the <a for=string>length</a> of
```

> +
+   <li><p><a data-lt="process a deferred fetch">Process</a> <var>deferredRecord</var>.
+  </ol>
+ </li>
+
+ <li><p>Return <var>deferredRecord</var>.
+</ol>
+</div>
+
+<div algorithm>
+<p>To compute the <dfn>total request length</dfn> of a <a for=/>request</a> <var>request</var>:
+
+<ol>
+ <li><p>Let <var>totalRequestLength</var> be the <a for=string>length</a> of <var>request</var>'s
+ <a for=request>URL</a>, <a lt="URL serializer">serialized</a> with
+ [=URL serializer/exclude fragment=] set to true.

I don't think this will get the correct formatting. It needs to use `<i><a>` iirc.

> +cross-origin nested documents, each reserving 8 kibibytes.
+
+<p>The top-level <a for=/>document</a>, and subsequently its nested documents, can control how much
+of their quota is delegates to cross-origin child documents, using permissions policy. By default,
+the "{{PermissionsPolicy/deferred-fetch-minimal}}" policy is enabled for any origin, while
+"{{PermissionsPolicy/deferred-fetch}}" is enabled for the top-level document's origin only. By
+relaxing the "{{PermissionsPolicy/deferred-fetch}}" policy for particular origins and nested
+documents, the top-level document can allocate 64 kibibytes to those nested documents. Similarly, by
+restricting the "{{PermissionsPolicy/deferred-fetch-minimal}}" policy for a particular origin or
+nested document, the document can prevent the document from reserving the 8 kibibytes it would
+receive by default. By disabling the "{{PermissionsPolicy/deferred-fetch-minimal}}" policy for the
+top-level document itself, the entire 128 kibibytes delegated quota is collected back into the main
+pool of 640 kibibytes.
+
+<p>Out of the allocated quota for a <a for=/>document</a>, only 64 kibibytes can be used
+concurrently for the same reporting origin (the <a for=/>request</a>'s <a for=request>URL</a>'

```suggestion
concurrently for the same reporting origin (the <a for=/>request</a>'s <a for=request>URL</a>'s
```

> +
+<p>The top-level <a for=/>document</a>, and subsequently its nested documents, can control how much
+of their quota is delegates to cross-origin child documents, using permissions policy. By default,
+the "{{PermissionsPolicy/deferred-fetch-minimal}}" policy is enabled for any origin, while
+"{{PermissionsPolicy/deferred-fetch}}" is enabled for the top-level document's origin only. By
+relaxing the "{{PermissionsPolicy/deferred-fetch}}" policy for particular origins and nested
+documents, the top-level document can allocate 64 kibibytes to those nested documents. Similarly, by
+restricting the "{{PermissionsPolicy/deferred-fetch-minimal}}" policy for a particular origin or
+nested document, the document can prevent the document from reserving the 8 kibibytes it would
+receive by default. By disabling the "{{PermissionsPolicy/deferred-fetch-minimal}}" policy for the
+top-level document itself, the entire 128 kibibytes delegated quota is collected back into the main
+pool of 640 kibibytes.
+
+<p>Out of the allocated quota for a <a for=/>document</a>, only 64 kibibytes can be used
+concurrently for the same reporting origin (the <a for=/>request</a>'s <a for=request>URL</a>'
+<a for=url>origin</a>). This prevents a situation where particular 3rd party libraries would reserve

```suggestion
<a for=url>origin</a>). This prevents a situation where particular third-party libraries would reserve
```

> +  fetchLater("https://origin.example.com", {method: "POST", body: body_exceeding_64_kb});
+  fetchLater(a_62_kb_url /* with a 3kb referrer */);
+</code></pre>
+
+<p>In the following sequence, the first two requests would succeed, but the third one would throw.
+That's because the overall 640 kibibytes quota was not exceeded in the first two calls, however the
+3rd request exceeds the reporting-origin quota for <code>https://a.example.com</code>, and would
+throw.
+<pre><code class=lang-javascript>
+  fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
+  fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
+  fetchLater("https://a.example.com");
+</code></pre>
+
+<p>Same-origin nested documents share the quota of their parent. However, cross-origin or
+cross-agent iframes only receive 8kb of quota by default. So in the following example, the first 3

```suggestion
cross-agent iframes only receive 8kb of quota by default. So in the following example, the first three
```

> + <li><p>Let <var>controlDocument</var> be <var>container</var>'s <a>node document</a>'s
+ <a>deferred-fetch control document</a>.
+
+ <li><p>If the <a data-lt="define an inherited policy for feature in container">inherited policy</a>
+ for "{{PermissionsPolicy/deferred-fetch}}", <var>container</var> and <var>originToNavigateTo</var>
+ is <code>Enabled</code>, and the <a>available deferred-fetch quota</a> for
+ <var>controlDocument</var> is equal or greater than
+ <a for="reserved deferred-fetch quota">normal quota</a>, then set <var>container</var>'s
+ <a>reserved deferred-fetch quota</a> to <a for="reserved deferred-fetch quota">normal quota</a> and
+ return.
+
+ <li>
+  <p>If all of the following conditions are true:
+
+  <ul class=brief>
+   <li><p><var>controlDocument</var>'s <a>node navigable</a> is a <a for=/>top-level traversable</a>

```suggestion
   <li><p><var>controlDocument</var>'s <a>node navigable</a> is a <a for=/>top-level traversable</a>;
```

> +   <li><p>The <a data-lt="define an inherited policy for feature in container">inherited policy</a>
+   for "{{PermissionsPolicy/deferred-fetch-minimal}}", <var>container</var> and
+   <var>originToNavigateTo</var> is <code>Enabled</code>

```suggestion
   <li><p>the <a data-lt="define an inherited policy for feature in container">inherited policy</a>
   for "{{PermissionsPolicy/deferred-fetch-minimal}}", <var>container</var> and
   <var>originToNavigateTo</var> is <code>Enabled</code>; and
```
I don't like `Enabled` as an output. That's not Infra. Can you file an upstream issue?

> +   <li><p>The <a for=list>size</a> of <var>controlDocument</var>'s <a>node navigable</a>'s
+   <a>descendant navigables</a>, <a for=list data-lt=remove>removing</a> any <a for=/>navigable</a>
+   whose <a>navigable container</a>'s <a>reserved deferred-fetch quota</a> is not
+   <a for="reserved deferred-fetch quota">minimal quota</a>, is less than
+   <a>quota reserved for <code>deferred-fetch-minimal</code></a> /
+   <a for="reserved deferred-fetch quota">minimal quota</a>.

```suggestion
   <li><p>the <a for=list>size</a> of <var>controlDocument</var>'s <a>node navigable</a>'s
   <a>descendant navigables</a>, <a for=list data-lt=remove>removing</a> any <a for=/>navigable</a>
   whose <a>navigable container</a>'s <a>reserved deferred-fetch quota</a> is not
   <a for="reserved deferred-fetch quota">minimal quota</a>, is less than
   <a>quota reserved for <code>deferred-fetch-minimal</code></a> /
   <a for="reserved deferred-fetch quota">minimal quota</a>,
```

> + <li><p>If <var>document</var>' <a>node navigable</a>'s <a>container document</a> is null or a
+ <a for=/>document</a> whose <a for=Document>origin</a> is not <a>same origin</a> with
+ <var>document</var>, return <var>document</var>; Otherwise return the
+ <a>deferred-fetch control document</a> given <var>document</var>' <a>node navigable</a>'s
+ <a>container document</a>.

```suggestion
 <li><p>If <var>document</var>' <a>node navigable</a>'s <a>container document</a> is null or a
 <a for=/>document</a> whose <a for=Document>origin</a> is not <a>same origin</a> with
 <var>document</var>, then return <var>document</var>; otherwise, return the
 <a>deferred-fetch control document</a> given <var>document</var>'s <a>node navigable</a>'s
 <a>container document</a>.
```

> @@ -8576,6 +9058,135 @@ with a <var>promise</var>, <var>request</var>, <var>responseObject</var>, and an
 </ol>
 </div>
 
+<p>A {{FetchLaterResult}} has an associated <dfn for=FetchLaterResult>activated getter steps</dfn>,
+which is an algorithm returning a boolean.
+
+<div algorithm>
+<p>The <dfn attribute for=FetchLaterResult><code>activated</code></dfn> getter steps are to return
+the result of running <a>this</a>'s <a for=FetchLaterResult>activated getter steps</a>.
+</div>
+
+<div algorithm="dom-fetch-later">
+<p>The
+<dfn id=dom-global-fetch-later method for=Window><code>fetchLater(<var>input</var>, <var>init</var>)</code></dfn>

```suggestion
<dfn method for=Window><code>fetchLater(<var>input</var>, <var>init</var>)</code></dfn>
```

>  
 <pre class=idl>
 partial interface mixin WindowOrWorkerGlobalScope {
   [NewObject] Promise&lt;Response> fetch(RequestInfo input, optional RequestInit init = {});
 };
+
+
+dictionary DeferredRequestInit : RequestInit {
+  DOMHighResTimeStamp activateAfter;
+};
+
+[Exposed=Window]
+interface FetchLaterResult {
+  readonly attribute boolean activated;
+};
+
+partial interface mixin Window {

```suggestion
partial interface Window {
```
I don't understand why this would be a mixin.

> + <li><p>If <var>request</var>'s <a for=request>window</a>'s <a>associated document</a> is not a
+ <a>fully active</a> <a for=/>document</a>, then throw a {{TypeError}}.

```suggestion
 <li><p>If <var>request</var>'s <a for=request>window</a>'s <a>associated document</a> is not
 <a>fully active</a>, then throw a {{TypeError}}.
```

-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/fetch/pull/1647#pullrequestreview-2753295603
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/fetch/pull/1647/review/2753295603@github.com>

Received on Wednesday, 9 April 2025 12:40:36 UTC