@@ -2731,6 +2731,9 @@ functionality.
2731
2731
<p> A <a for=fetch>fetch group</a> holds an ordered list of
2732
2732
<dfn lt="fetch record" export for="fetch group" id=concept-fetch-record>fetch records</dfn> .
2733
2733
2734
+ <p> A <a for=fetch>fetch group</a> holds an ordered list of
2735
+ <dfn export for="fetch group" id=concept-defer=fetch-record>deferred fetch records</dfn> .
2736
+
2734
2737
<p> A <a for="fetch group">fetch record</a> has an associated
2735
2738
<dfn export for="fetch record" id=concept-fetch-record-request>request</dfn> (a
2736
2739
<a for=/>request</a> ).
@@ -2739,16 +2742,103 @@ functionality.
2739
2742
<dfn export for="fetch record" id=concept-fetch-record-fetch>controller</dfn> (a
2740
2743
<a for=/>fetch controller</a> or null).
2741
2744
2745
+ <p> A <dfn export>deferred fetch record</dfn> is a <a for=/>struct</a> used to maintain state needed
2746
+ to invoke a fetch at a later time, e.g. when a <code> Document</code> is unloaded or backgrounded. It
2747
+ has the following <a for=struct>items</a> :
2748
+
2749
+ <dl>
2750
+ <dt> <dfn export for="deferred fetch record">request</dfn>
2751
+ <dd> A <a for=/>request</a>
2752
+
2753
+ <dt> <dfn export for="deferred fetch record">background timeout</dfn> (default null)
2754
+ <dd> Null or a <a>duration</a>
2755
+
2756
+ <dt> <dfn export for="deferred fetch record">pending steps</dfn> (default null)
2757
+ <dt> <dfn export for="deferred fetch record">invoked callback</dfn> (default null)
2758
+ <dd> Null or an algortihm accepting nothing
2759
+
2760
+ <dt> <dfn export for="deferred fetch record">invoked</dfn> (default false)
2761
+ <dd> A boolean
2762
+ </dl>
2763
+
2764
+
2742
2765
<hr>
2743
2766
2744
- <p> When a <a for=fetch>fetch group</a> is
2745
- <dfn export for="fetch group" id=concept-fetch-group-terminate>terminated</dfn> , for each associated
2746
- <a for="fetch group">fetch record</a> whose <a for="fetch group">fetch record</a> 's
2747
- <a for="fetch record">controller</a> is non-null, and whose <a for="fetch record">request</a> 's
2748
- <a>done flag</a> is unset or <a for=request>keepalive</a> is false,
2749
- <a for="fetch controller">terminate</a> the <a for="fetch group">fetch record</a> 's
2750
- <a for="fetch record">controller</a> .
2767
+ <p> When a <a for=fetch>fetch group</a> <var> fetchGroup</var> is
2768
+ <dfn export for="fetch group" id=concept-fetch-group-terminate>terminated</dfn> :
2769
+
2770
+ <ol>
2771
+ <li>
2772
+ <p> <a for=list>For each</a> <a for="fetch group">deferred fetch record</a>
2773
+ <var> deferredRecord</var> in <var> fetchGroup</var> 's
2774
+ <a for="fetch group">deferred fetch records</a> whose <a for="deferred fetch record">invoked</a> is
2775
+ false:
2776
+
2777
+ <ol>
2778
+ <li><p> If <var> deferredRecord</var> 's <a for="deferred fetch record">pending steps</a> is not
2779
+ null then <a>abort</a> <var> deferredRecord</var> 's
2780
+ <a for="deferred fetch record">pending steps</a> .
2781
+
2782
+ <li><p> <a for=/>fetch</a> <var> deferredRecord</var> 's <a for="deferred fetch record">request</a> .
2783
+ </ol>
2784
+
2785
+ <li><p> For each associated <a for="fetch group">fetch record</a> <var> record</var> ,
2786
+ if <var> record</var> 's <a for="fetch record">controller</a> is non-null and
2787
+ <var> record</var> 's <a for="fetch record">request</a>' s <a>done flag</a> is unset or
2788
+ <a for=request>keepalive</a> is false, <a for="fetch controller">terminate</a> <var> record</var> 's
2789
+ <a for="fetch record">controller</a> .
2790
+ </ol>
2791
+
2792
+ <p> When a <a for=fetch>fetch group</a> <var> fetchGroup</var> is
2793
+ <dfn export for="fetch group" id=concept-fetch-group-activate>activated</dfn> :
2794
+ <a for=list>for each</a> <a for=/>deferred fetch record</a> <var> deferredRecord</var> in
2795
+ <var> fetchGroup</var> 's <a for="fetch group">deferred fetch records</a> :
2796
+
2797
+ <ol>
2798
+ <li>
2799
+ <p> If <var> deferredRecord</var> 's <a for="deferred fetch record">invoked</a> is true then:
2800
+ <ol>
2801
+ <li><p> If <var> deferredRecord</var> 's <a for="deferred fetch record">invoked callback</a> is not
2802
+ null then call <var> deferredRecord</var> 's <a for="deferred fetch record">invoked callback</a> .
2803
+
2804
+ <li><p> <a for=list>Remove</a> <var> deferredRecord</var> from <var> fetchGroup</var> 's
2805
+ <a for="fetch group">deferred fetch records</a> .
2806
+ </ol>
2807
+
2808
+ <li><p> Otherwise, if <var> deferredRecord</var> 's
2809
+ <a for="deferred fetch record">pending steps</a> is not null, then <a>abort</a>
2810
+ <var> deferredRecord</var> 's <a for="deferred fetch record">pending steps</a> and set
2811
+ <var> deferredRecord</var> 's <a for="deferred fetch record">pending steps</a> to null.
2812
+ </ol>
2813
+
2814
+ <p> When a <a for=fetch>fetch group</a> <var> fetchGroup</var> is
2815
+ <dfn export for="fetch group" id=concept-fetch-group-deactivate>deactivated</dfn> :
2751
2816
2817
+ <ol>
2818
+ <li>
2819
+ <p> <a for=list>For each</a> <a>deferred fetch record</a> <var> deferredRecord</var> in
2820
+ <var> fetchGroup</var> 's <a for="fetch group">deferred fetch records</a> whose
2821
+ <a for="deferred fetch record">background timeout</a> is not null: set <var> deferredRecord</var> 's
2822
+ <a for="deferred fetch record">pending steps</a> to running the following steps <a>in parallel</a> :
2823
+
2824
+ <ol>
2825
+ <li><p> Wait until <var> deferredRecord</var> 's
2826
+ <a for="deferred fetch record">background timeout</a> have passed.
2827
+
2828
+ <li>
2829
+ <p> <a>Queue a fetch task</a> to run the following steps with
2830
+ <a for="fetch record">request</a> 's <a for=request>client</a>' s
2831
+ <a for="environment settings object">global object</a> :
2832
+
2833
+ <ol>
2834
+ <li><p> <a for=/>Fetch</a> <var> record</var> 's <a for="fetch record">request</a> .
2835
+
2836
+ <li><p> Set <var> deferredRecord</var> <a for="deferred fetch record">invoked</a> to true.
2837
+ </ol>
2838
+ </li>
2839
+ </ol>
2840
+ </li>
2841
+ </ol>
2752
2842
2753
2843
<h3 id=resolving-domains>Resolving domains</h3>
2754
2844
@@ -8605,6 +8695,117 @@ fetch("https://www.example.com/")
8605
8695
8606
8696
8607
8697
8698
+ <h2 id=deferred-fetching>Deferred fetching</h2>
8699
+
8700
+ <p> Deferred fetches allow callers to request that a fetch is invoked at the latest possible moment,
8701
+ when a <a>fetch group</a> is <a for="fetch group">terminated</a> , or after a timeout after it is
8702
+ <a for="fetch group">deactivated</a> .
8703
+
8704
+ <h3 id="requesting-a-deferred-fetch">Requesting a deferred fetch</h3>
8705
+
8706
+ <div algorithm="request-a-deferred-fetch">
8707
+ <p> To <dfn>request a deferred fetch</dfn> given a
8708
+ <a for=/>request</a> <var> request</var> and a null-or-{{DOMHighResTimeStamp}}
8709
+ <var> backgroundTimeout</var> (default null):
8710
+
8711
+ <ol>
8712
+ <li><p> Assert: <var> request</var> 's <a for=request>client</a> is an
8713
+ <a>environment settings object</a> .
8714
+
8715
+ <li> Let <var> totalScheduledDeferredBytesForOrigin</var> be 0.
8716
+
8717
+ <li>
8718
+ <p> If <var> request</var> 's <a for=request>body</a> is not null then:
8719
+
8720
+ <ol>
8721
+ <li><p> If <var> request</var> 's
8722
+ <a for=request>body</a> 's <a for=body>length</a> is null, then throw a {{TypeError}} .
8723
+
8724
+ <li><p> Set <var> totalScheduledDeferredBytesForOrigin</var> to <var> request</var> 's
8725
+ <a for=request>body</a> 's <a for=body>length</a> .
8726
+ </ol>
8727
+ </li>
8728
+
8729
+ <li><p> <a for=list>For each</a> <a>deferred fetch record</a> <var> deferredRecord</var> in
8730
+ <var> request</var> 's <a for=request>client</a>' s <a for=fetch>fetch group</a> 's
8731
+ <a for="fetch group">deferred fetch records</a> : if <var> deferredRecord</var> 's
8732
+ <a for="deferred fetch record">request</a> 's <a for=request>body</a> is not null and
8733
+ <var> deferredRecord</var> 's <a for="deferred fetch record">request</a>' s <a for=request>URL</a> 's
8734
+ <a for=url>origin</a> is <a>same origin</a> with <var> request</var> 's <a for=request>URL</a>' s
8735
+ <a for=url>origin</a> , then increment <var> totalScheduledDeferredBytesForOrigin</var> by
8736
+ <var> deferredRecord</var> 's <a for="deferred fetch record">request</a>' s <a for=request>body</a> 's
8737
+ <a for=body>length</a> .
8738
+
8739
+ <li><p> If <var> totalScheduledDeferredBytesForOrigin</var> is greater than 64 kilobytes, then
8740
+ throw a {{QuotaExceededError}} .
8741
+
8742
+ <li><p> Let <var> deferredRecord</var> be a new <a>deferred fetch record</a> whose
8743
+ <a for="deferred fetch record">request</a> is <var> request</var> .
8744
+
8745
+ <li><p> Set <var> deferredRecord</var> 's <a for="deferred fetch record">background timeout</a> to
8746
+ <var> backgroundTimeout</var> .
8747
+
8748
+ <li><p> <a for=list>Append</a> <var> deferredRecord</var> to <var> request</var> 's
8749
+ <a for=request>client</a> 's <a for=fetch>fetch group</a>' s
8750
+ <a for="fetch group">deferred fetch records</a> .
8751
+
8752
+ <li><p> Return <var> deferredRecord</var> .
8753
+ </ol>
8754
+ </div>
8755
+
8756
+ <h3 id=request-deferred-fetch-method>RequestDeferredFetch method</h3>
8757
+
8758
+ <pre class=idl>
8759
+
8760
+ dictionary DeferredRequestInit : RequestInit {
8761
+ DOMHighResTimeStamp? backgroundTimeout;
8762
+ };
8763
+
8764
+ partial interface mixin WindowOrWorkerGlobalScope {
8765
+ [NewObject] Promise<Response> requestDeferredFetch(RequestInfo input, optional DeferredRequestInit init = {});
8766
+ };
8767
+ </pre>
8768
+
8769
+ <div algorithm="dom-requestdeferredfetch">
8770
+ <p> The
8771
+ <dfn id=dom-global-requestdeferredfetch method for=WindowOrWorkerGlobalScope><code>requestDeferredFetch(<var>input</var>, <var>init</var>)</code></dfn>
8772
+ method steps are:
8773
+
8774
+ <ol>
8775
+ <li><p> Let <var> promise</var> be a new promise.
8776
+
8777
+ <li><p> Let <var> requestObject</var> be the result of invoking the initial value of {{Request}} as
8778
+ constructor with <var> input</var> and <var> init</var> as arguments. If that threw an exception,
8779
+ <a for=/>reject</a> <var> promise</var> with that exception and return <var> promise</var> .
8780
+
8781
+ <li><p> If <var> requestObject</var> 's <a for=Request>signal</a> is <a for=AbortSignal>aborted</a> ,
8782
+ then <a for=/>reject</a> <var> promise</var> with <var> requestObject</var> 's
8783
+ <a for=Request>signal</a> 's <a for=AbortSignal>abort reason</a> and return <var> promise</var> .
8784
+
8785
+ <li><p> Let <var> request</var> be <var> requestObject</var> 's <a for=Request>request</a> .
8786
+
8787
+ <li><p> Let <var> backgroundTimeout</var> be null.
8788
+
8789
+ <li><p> If <var> init</var> is given and <var> init</var> ["<code>backgroundTimeout</code>"]
8790
+ <a for=map>exists</a> then set <var> backgroundTimeout</var> to
8791
+ <var> init</var> ["<code>backgroundTimeout</code>"] .
8792
+
8793
+ <li><p> If <var> backgroundTimeout</var> is not a {{DOMHighResTimeStamp}} then throw a {{TypeError}} .
8794
+
8795
+ <li><p> Let <var> deferredRecord</var> be the result of calling
8796
+ <a>request a deferred fetch</a> given <var> request</var> and <var> backgroundTimeout</var> . If that
8797
+ threw an exception, <a for=/>reject</a> <var> promise</var> with that exception and return
8798
+ <var> promise</var> .
8799
+
8800
+ <li><p> Set <var> deferredRecord</var> 's <a for="deferred fetch record">invoke callback</a> to
8801
+ <a for=/>resolve</a> <var> promise</var> .
8802
+
8803
+ <li><p> <a for=AbortSignal lt=add>Add the following abort steps</a> to <var> requestObject</var> 's
8804
+ <a for=Request>signal</a> : <a for=list>remove</a> <var> deferredRecord</var> from
8805
+ <var> request</var> 's <a for=request>client</a>' s <a for=fetch>fetch group</a> 's
8806
+ <a for="fetch group">deferred fetch records</a> .
8807
+ </ol>
8808
+
8608
8809
<h2 id=data-urls><code>data:</code> URLs</h2>
8609
8810
8610
8811
<p> For an informative description of <code> data:</code> URLs, see RFC 2397. This section replaces
0 commit comments