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

@annevk commented on this pull request.



> +urlPrefix:https://w3c.github.io/webappsec-permissions-policy;spec:permissions-policy
+    type:dfn
+        url:is-feature-enabled;text:is feature enabled in document for origin?

This should be exported. Surprised it isn't already.

>  <p>A <a for=fetch>fetch group</a> holds an ordered list of
 <dfn lt="fetch record" export for="fetch group" id=concept-fetch-record>fetch records</dfn>.
 
+<p>A <a for=fetch>fetch group</a> holds a <a for=/>list</a> of
+<dfn export for="fetch group" id=concept-defer=fetch-record>deferred fetch records</dfn>.

Reword both of these as

> Y has associated X (a list of Z)

?

> -<a for="fetch record">controller</a>.
+<p>A <dfn export>deferred fetch record</dfn> is a <a for=/>struct</a> used to maintain state needed
+to invoke a fetch at a later time, e.g., when a <code>Document</code> object is unloaded or becomes
+not <a for=Document>fully active</a>. It has the following <a for=struct>items</a>:
+
+<dl>
+ <dt><dfn export for="deferred fetch record">request</dfn>
+ <dd>A <a for=/>request</a>.
+
+ <dt><dfn export for="deferred fetch record">invoke state</dfn> (default "<code>deferred</code>")
+ <dd>
+  <p>"<code>deferred</code>", "<code>aborted</code>", or "<code>activated</code>".
+
+  <p class=note>This value can be modified <a>in parallel</a>. There could be a race condition where
+  the <code>Document</code> object's <a for=/>event loop</a> might read it as
+  "<code>deferred</code>" at the same time that it is changed to "<code>activated</code>". UAs can

Don't abbreviate user agent.

> @@ -6653,6 +6689,153 @@ agent's <a>CORS-preflight cache</a> for which there is a <a>cache entry match</a
 </ol>
 </div>
 
+<h3 id=deferred-fetching>Deferred fetching</h3>
+
+<p>Deferred fetches allow callers to request that a fetch is invoked at the latest possible moment,
+i.e. when a <a>fetch group</a> is <a for="fetch group">terminated</a>, or after a timeout.

comma after i.e. too

> @@ -6653,6 +6689,153 @@ agent's <a>CORS-preflight cache</a> for which there is a <a>cache entry match</a
 </ol>
 </div>
 
+<h3 id=deferred-fetching>Deferred fetching</h3>
+
+<p>Deferred fetches allow callers to request that a fetch is invoked at the latest possible moment,
+i.e. when a <a>fetch group</a> is <a for="fetch group">terminated</a>, or after a timeout.
+
+<div algorithm="request-a-deferred-fetch">

"request a deferred fetch" (no hyphens)

But also is this needed? It seems there's only a single `<dfn>` here so we don't need to supply a name.

> + {{Document}}.
+
+ <li><p>Let <var>document</var> be <var>request</var>'s <a for=request>client</a>.
+
+ <li><p>If <var>request</var>'s <a for=request>URL</a>'s <a for=url>scheme</a> is not an
+ <a>HTTP(S) scheme</a>, then throw a {{TypeError}}.
+
+ <li><p>If <var>request</var>'s <a for=request>URL</a> is not a
+ [=potentially trustworthy url=], then throw a "{{SecurityError}}" {{DOMException}}.
+
+ <li><p>If the result of calling <a>is feature enabled in document for origin?</a> given
+ "<code>deferred-fetch</code>", <var>document</var>, and <var>request</var>'s
+ <a for=request>origin</a> is <code>Disabled</code>, then throw a {{NotAllowedError}}.
+
+ <li>
+  <p>If <var>request</var>'s <a for=request>body</a> is not null then:

```suggestion
  <p>If <var>request</var>'s <a for=request>body</a> is non-null:
```

> +
+    <p class=note>This disallows sending deferred fetches with a live {{ReadableStream}}.
+
+   <li><p>Let <var>totalScheduledDeferredBytesForTopLevelDocument</var> be
+   <var>request</var>'s <a for=request>body</a>'s <a for=body>length</a>.
+
+   <li><p>Let <var>totalScheduledDeferredBytesForOrigin</var> be <var>request</var>'s
+   <a for=request>body</a>'s <a for=body>length</a>.
+
+   <li>
+    <p><a for=list>For each</a> <var>navigable</var> of <var>document</var>'s
+    <a>node navigable</a>'s <a for=navigable>top-level traversable</a>'s
+    <a for=Document>inclusive descendant navigables</a>:
+
+    <p class=note>This algorithm asserts that this deferred fetch doesn't exceed two quotas: one for
+    the top-level document (640kb), and one for the reporting origin (64kb). The larger quota ensures

Don't abbreviate kb.

> +
+    <ol>
+     <li>
+      <p><a for=list>For each</a> <a>deferred fetch record</a> <var>deferredRecord</var> in
+      <var>navigable</var>'s <a>active document</a>'s <a for=fetch>fetch group</a>'s
+      <a for="fetch group">deferred fetch records</a>:</p>
+
+      <ol>
+       <li><p>Let <var>length</var> be <var>deferredRecord</var>'s
+       <a for="deferred fetch record">request</a>'s <a for=request>body</a>'s
+       <a for=body>length</a>.
+
+       <li><p>Increment <var>totalScheduledDeferredBytesForTopLevelDocument</var> by <var>length</var>.
+
+       <li><p>If <var>totalScheduledDeferredBytesForTopLevelDocument</var> is greater than 640
+       kilobytes, then throw a "{{QuotaExceededError}}" {{DOMException}}.

kibibytes*

> + <li><p>Set <var>request</var>'s <a for=request>keepalive</a> to true.
+
+ <li><p>Let <var>deferredRecord</var> be a new <a>deferred fetch record</a> whose
+ <a for="deferred fetch record">request</a> is <var>request</var>.
+
+ <li><p><a for=list>Append</a> <var>deferredRecord</var> to <var>request</var>'s
+ <a for=request>client</a>'s <a for=fetch>fetch group</a>'s
+ <a for="fetch group">deferred fetch records</a>.
+
+ <li>
+  <p>If <var>activateAfter</var> is not null, then run the following steps <a>in parallel</a>:</p>
+
+  <ol>
+   <li><p>The user agent should wait until <var>activateAfter</var> milliseconds have passed,
+   or until 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

comma after e.g. too

> +
+ <li><p><a for=list>Append</a> <var>deferredRecord</var> to <var>request</var>'s
+ <a for=request>client</a>'s <a for=fetch>fetch group</a>'s
+ <a for="fetch group">deferred fetch records</a>.
+
+ <li>
+  <p>If <var>activateAfter</var> is not null, then run the following steps <a>in parallel</a>:</p>
+
+  <ol>
+   <li><p>The user agent should wait until <var>activateAfter</var> milliseconds have passed,
+   or until 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>client</a> is a <code>Document</code> that had a "<code>hidden</code>"
+   <a for=Document>visibility state</a> for a long period of time.
+
+   <li><p>The user agent may wait for a further <a>implementation-defined</a> <a>duration</a>, e.g.

comma after e.g. too

> +   <a for=request>client</a> is a <code>Document</code> that had a "<code>hidden</code>"
+   <a for=Document>visibility state</a> for a long period of time.
+
+   <li><p>The user agent may wait for a further <a>implementation-defined</a> <a>duration</a>, e.g.
+   in order to batch several requests together or to wait until <a for=request>keepalive</a>
+   requests are complete.
+
+   <li><p><a>Process a deferred fetch</a> given <var>deferredRecord</var>.
+  </ol>
+ </li>
+
+ <li><p>Return <var>deferredRecord</var>.
+</ol>
+</div>
+
+<div algorithm="process-deferred-fetches">

No need for a name I think.

> +<p>To <dfn export>process deferred fetches</dfn> given a <a>fetch group</a> <var>fetchGroup</var>:
+
+<ol>
+ <li><p>Let <var>deferredFetchRecords</var> be <var>fetchGroup</var>'s
+ <a for="fetch group">deferred fetch records</a>.
+
+ <li><p>Let <var>fetchGroup</var>'s
+ <a for="fetch group">deferred fetch records</a> be « ».
+
+ <li><p><a for=list>For each</a> <a for="fetch group">deferred fetch record</a>
+ <var>deferredRecord</var> of <var>deferredFetchRecords</var>, <a>process a deferred fetch</a> given
+ <var>deferredRecord</var>.
+</ol>
+</div>
+
+<div algorithm="process-a-deferred-fetch">

No need for a name I think.

> +</ol>
+</div>
+
+<div algorithm="process-a-deferred-fetch">
+<p>To <dfn>process a deferred fetch</dfn> <var>deferredRecord</var>:
+<ol>
+ <li><p>If <var>deferredRecord</var>'s <a for="deferred fetch record">invoke state</a> is not
+ "<code>deferred</code>", then return.
+
+ <li><p>Set <var>deferredRecord</var>'s <a for="deferred fetch record">invoke state</a> to
+ "<code>activated</code>".
+
+ <li><p><a for=/>Fetch</a> <var>deferredRecord</var>'s
+ <a for="deferred fetch record">request</a>.
+</ol>
+</div>

Eating a newline before the `<h2>` here.

> +<pre class=idl>
+

Why these newlines?

> @@ -8505,6 +8688,75 @@ with a <var>promise</var>, <var>request</var>, <var>responseObject</var>, and an
 </ol>
 </div>
 
+<pre class=idl>
+
+dictionary DeferredRequestInit : RequestInit {
+  DOMHighResTimeStamp activateAfter;
+};
+
+[Exposed=Window]
+interface FetchLaterResult {
+  readonly attribute boolean activated;
+};
+
+partial interface mixin Window {
+  [NewObject] FetchLaterResult fetchLater(RequestInfo input, optional DeferredRequestInit init = {});

We should put this in the same IDL block `fetch()` is in.

> +<ol>
+ <li><p>Let <var>requestObject</var> be the result of invoking the initial value of {{Request}} as
+ constructor with <var>input</var> and <var>init</var> as arguments.
+
+ <li><p>If <var>requestObject</var>'s <a for=Request>signal</a> is <a for=AbortSignal>aborted</a>,
+ then throw <a for=Request>signal</a>'s <a for=AbortSignal>abort reason</a>.
+
+ <li><p>Let <var>request</var> be <var>requestObject</var>'s <a for=Request>request</a>.
+
+ <li><p>Let <var>activateAfter</var> be null.
+
+ <li><p>If <var>init</var> is given and <var>init</var>["<code>activateAfter</code>"]
+ <a for=map>exists</a>, then set <var>activateAfter</var> to
+ <var>init</var>["<code>activateAfter</code>"].
+
+ <li><p>If <var>activateAfter</var> is not a {{DOMHighResTimeStamp}}, then throw a {{TypeError}}.

How is this not enforced by IDL?

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

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

Received on Monday, 25 March 2024 15:45:00 UTC