@@ -2689,6 +2689,9 @@ functionality.
2689
2689
<p> A <a for=fetch>fetch group</a> holds an ordered list of
2690
2690
<dfn lt="fetch record" export for="fetch group" id=concept-fetch-record>fetch records</dfn> .
2691
2691
2692
+ <p> A <a for=fetch>fetch group</a> holds an ordered list of
2693
+ <dfn export for="fetch group" id=concept-defer=fetch-record>deferred fetch records</dfn> .
2694
+
2692
2695
<p> A <a for="fetch group">fetch record</a> has an associated
2693
2696
<dfn export for="fetch record" id=concept-fetch-record-request>request</dfn> (a
2694
2697
<a for=/>request</a> ).
@@ -2697,16 +2700,103 @@ functionality.
2697
2700
<dfn export for="fetch record" id=concept-fetch-record-fetch>controller</dfn> (a
2698
2701
<a for=/>fetch controller</a> or null).
2699
2702
2703
+ <p> A <dfn export>deferred fetch record</dfn> is a <a for=/>struct</a> used to maintain state needed
2704
+ to invoke a fetch at a later time, e.g. when a <code> Document</code> is unloaded or backgrounded. It
2705
+ has the following <a for=struct>items</a> :
2706
+
2707
+ <dl>
2708
+ <dt> <dfn export for="deferred fetch record">request</dfn>
2709
+ <dd> A <a for=/>request</a>
2710
+
2711
+ <dt> <dfn export for="deferred fetch record">background timeout</dfn> (default null)
2712
+ <dd> Null or a <a>duration</a>
2713
+
2714
+ <dt> <dfn export for="deferred fetch record">pending steps</dfn> (default null)
2715
+ <dt> <dfn export for="deferred fetch record">invoked callback</dfn> (default null)
2716
+ <dd> Null or an algortihm accepting nothing
2717
+
2718
+ <dt> <dfn export for="deferred fetch record">invoked</dfn> (default false)
2719
+ <dd> A boolean
2720
+ </dl>
2721
+
2722
+
2700
2723
<hr>
2701
2724
2702
- <p> When a <a for=fetch>fetch group</a> is
2703
- <dfn export for="fetch group" id=concept-fetch-group-terminate>terminated</dfn> , for each associated
2704
- <a for="fetch group">fetch record</a> whose <a for="fetch group">fetch record</a> 's
2705
- <a for="fetch record">controller</a> is non-null, and whose <a for="fetch record">request</a> 's
2706
- <a>done flag</a> is unset or <a for=request>keepalive</a> is false,
2707
- <a for="fetch controller">terminate</a> the <a for="fetch group">fetch record</a> 's
2708
- <a for="fetch record">controller</a> .
2725
+ <p> When a <a for=fetch>fetch group</a> <var> fetchGroup</var> is
2726
+ <dfn export for="fetch group" id=concept-fetch-group-terminate>terminated</dfn> :
2727
+
2728
+ <ol>
2729
+ <li>
2730
+ <p> <a for=list>For each</a> <a for="fetch group">deferred fetch record</a>
2731
+ <var> deferredRecord</var> in <var> fetchGroup</var> 's
2732
+ <a for="fetch group">deferred fetch records</a> whose <a for="deferred fetch record">invoked</a> is
2733
+ false:
2734
+
2735
+ <ol>
2736
+ <li><p> If <var> deferredRecord</var> 's <a for="deferred fetch record">pending steps</a> is not
2737
+ null then <a>abort</a> <var> deferredRecord</var> 's
2738
+ <a for="deferred fetch record">pending steps</a> .
2739
+
2740
+ <li><p> <a for=/>fetch</a> <var> deferredRecord</var> 's <a for="deferred fetch record">request</a> .
2741
+ </ol>
2742
+
2743
+ <li><p> For each associated <a for="fetch group">fetch record</a> <var> record</var> ,
2744
+ if <var> record</var> 's <a for="fetch record">controller</a> is non-null and
2745
+ <var> record</var> 's <a for="fetch record">request</a>' s <a>done flag</a> is unset or
2746
+ <a for=request>keepalive</a> is false, <a for="fetch controller">terminate</a> <var> record</var> 's
2747
+ <a for="fetch record">controller</a> .
2748
+ </ol>
2749
+
2750
+ <p> When a <a for=fetch>fetch group</a> <var> fetchGroup</var> is
2751
+ <dfn export for="fetch group" id=concept-fetch-group-activate>activated</dfn> :
2752
+ <a for=list>for each</a> <a for=/>deferred fetch record</a> <var> deferredRecord</var> in
2753
+ <var> fetchGroup</var> 's <a for="fetch group">deferred fetch records</a> :
2754
+
2755
+ <ol>
2756
+ <li>
2757
+ <p> If <var> deferredRecord</var> 's <a for="deferred fetch record">invoked</a> is true then:
2758
+ <ol>
2759
+ <li><p> If <var> deferredRecord</var> 's <a for="deferred fetch record">invoked callback</a> is not
2760
+ null then call <var> deferredRecord</var> 's <a for="deferred fetch record">invoked callback</a> .
2761
+
2762
+ <li><p> <a for=list>Remove</a> <var> deferredRecord</var> from <var> fetchGroup</var> 's
2763
+ <a for="fetch group">deferred fetch records</a> .
2764
+ </ol>
2765
+
2766
+ <li><p> Otherwise, if <var> deferredRecord</var> 's
2767
+ <a for="deferred fetch record">pending steps</a> is not null, then <a>abort</a>
2768
+ <var> deferredRecord</var> 's <a for="deferred fetch record">pending steps</a> and set
2769
+ <var> deferredRecord</var> 's <a for="deferred fetch record">pending steps</a> to null.
2770
+ </ol>
2771
+
2772
+ <p> When a <a for=fetch>fetch group</a> <var> fetchGroup</var> is
2773
+ <dfn export for="fetch group" id=concept-fetch-group-deactivate>deactivated</dfn> :
2709
2774
2775
+ <ol>
2776
+ <li>
2777
+ <p> <a for=list>For each</a> <a>deferred fetch record</a> <var> deferredRecord</var> in
2778
+ <var> fetchGroup</var> 's <a for="fetch group">deferred fetch records</a> whose
2779
+ <a for="deferred fetch record">background timeout</a> is not null: set <var> deferredRecord</var> 's
2780
+ <a for="deferred fetch record">pending steps</a> to running the following steps <a>in parallel</a> :
2781
+
2782
+ <ol>
2783
+ <li><p> Wait until <var> deferredRecord</var> 's
2784
+ <a for="deferred fetch record">background timeout</a> have passed.
2785
+
2786
+ <li>
2787
+ <p> <a>Queue a fetch task</a> to run the following steps with
2788
+ <a for="fetch record">request</a> 's <a for=request>client</a>' s
2789
+ <a for="environment settings object">global object</a> :
2790
+
2791
+ <ol>
2792
+ <li><p> <a for=/>Fetch</a> <var> record</var> 's <a for="fetch record">request</a> .
2793
+
2794
+ <li><p> Set <var> deferredRecord</var> <a for="deferred fetch record">invoked</a> to true.
2795
+ </ol>
2796
+ </li>
2797
+ </ol>
2798
+ </li>
2799
+ </ol>
2710
2800
2711
2801
<h3 id=resolving-domains>Resolving domains</h3>
2712
2802
@@ -8541,6 +8631,117 @@ fetch("https://www.example.com/")
8541
8631
8542
8632
8543
8633
8634
+ <h2 id=deferred-fetching>Deferred fetching</h2>
8635
+
8636
+ <p> Deferred fetches allow callers to request that a fetch is invoked at the latest possible moment,
8637
+ when a <a>fetch group</a> is <a for="fetch group">terminated</a> , or after a timeout after it is
8638
+ <a for="fetch group">deactivated</a> .
8639
+
8640
+ <h3 id="requesting-a-deferred-fetch">Requesting a deferred fetch</h3>
8641
+
8642
+ <div algorithm="request-a-deferred-fetch">
8643
+ <p> To <dfn>request a deferred fetch</dfn> given a
8644
+ <a for=/>request</a> <var> request</var> and a null-or-{{DOMHighResTimeStamp}}
8645
+ <var> backgroundTimeout</var> (default null):
8646
+
8647
+ <ol>
8648
+ <li><p> Assert: <var> request</var> 's <a for=request>client</a> is an
8649
+ <a>environment settings object</a> .
8650
+
8651
+ <li> Let <var> totalScheduledDeferredBytesForOrigin</var> be 0.
8652
+
8653
+ <li>
8654
+ <p> If <var> request</var> 's <a for=request>body</a> is not null then:
8655
+
8656
+ <ol>
8657
+ <li><p> If <var> request</var> 's
8658
+ <a for=request>body</a> 's <a for=body>length</a> is null, then throw a {{TypeError}} .
8659
+
8660
+ <li><p> Set <var> totalScheduledDeferredBytesForOrigin</var> to <var> request</var> 's
8661
+ <a for=request>body</a> 's <a for=body>length</a> .
8662
+ </ol>
8663
+ </li>
8664
+
8665
+ <li><p> <a for=list>For each</a> <a>deferred fetch record</a> <var> deferredRecord</var> in
8666
+ <var> request</var> 's <a for=request>client</a>' s <a for=fetch>fetch group</a> 's
8667
+ <a for="fetch group">deferred fetch records</a> : if <var> deferredRecord</var> 's
8668
+ <a for="deferred fetch record">request</a> 's <a for=request>body</a> is not null and
8669
+ <var> deferredRecord</var> 's <a for="deferred fetch record">request</a>' s <a for=request>URL</a> 's
8670
+ <a for=url>origin</a> is <a>same origin</a> with <var> request</var> 's <a for=request>URL</a>' s
8671
+ <a for=url>origin</a> , then increment <var> totalScheduledDeferredBytesForOrigin</var> by
8672
+ <var> deferredRecord</var> 's <a for="deferred fetch record">request</a>' s <a for=request>body</a> 's
8673
+ <a for=body>length</a> .
8674
+
8675
+ <li><p> If <var> totalScheduledDeferredBytesForOrigin</var> is greater than 64 kilobytes, then
8676
+ throw a {{QuotaExceededError}} .
8677
+
8678
+ <li><p> Let <var> deferredRecord</var> be a new <a>deferred fetch record</a> whose
8679
+ <a for="deferred fetch record">request</a> is <var> request</var> .
8680
+
8681
+ <li><p> Set <var> deferredRecord</var> 's <a for="deferred fetch record">background timeout</a> to
8682
+ <var> backgroundTimeout</var> .
8683
+
8684
+ <li><p> <a for=list>Append</a> <var> deferredRecord</var> to <var> request</var> 's
8685
+ <a for=request>client</a> 's <a for=fetch>fetch group</a>' s
8686
+ <a for="fetch group">deferred fetch records</a> .
8687
+
8688
+ <li><p> Return <var> deferredRecord</var> .
8689
+ </ol>
8690
+ </div>
8691
+
8692
+ <h3 id=request-deferred-fetch-method>RequestDeferredFetch method</h3>
8693
+
8694
+ <pre class=idl>
8695
+
8696
+ dictionary DeferredRequestInit : RequestInit {
8697
+ DOMHighResTimeStamp? backgroundTimeout;
8698
+ };
8699
+
8700
+ partial interface mixin WindowOrWorkerGlobalScope {
8701
+ [NewObject] Promise<Response> requestDeferredFetch(RequestInfo input, optional DeferredRequestInit init = {});
8702
+ };
8703
+ </pre>
8704
+
8705
+ <div algorithm="dom-requestdeferredfetch">
8706
+ <p> The
8707
+ <dfn id=dom-global-requestdeferredfetch method for=WindowOrWorkerGlobalScope><code>requestDeferredFetch(<var>input</var>, <var>init</var>)</code></dfn>
8708
+ method steps are:
8709
+
8710
+ <ol>
8711
+ <li><p> Let <var> promise</var> be a new promise.
8712
+
8713
+ <li><p> Let <var> requestObject</var> be the result of invoking the initial value of {{Request}} as
8714
+ constructor with <var> input</var> and <var> init</var> as arguments. If that threw an exception,
8715
+ <a for=/>reject</a> <var> promise</var> with that exception and return <var> promise</var> .
8716
+
8717
+ <li><p> If <var> requestObject</var> 's <a for=Request>signal</a> is <a for=AbortSignal>aborted</a> ,
8718
+ then <a for=/>reject</a> <var> promise</var> with <var> requestObject</var> 's
8719
+ <a for=Request>signal</a> 's <a for=AbortSignal>abort reason</a> and return <var> promise</var> .
8720
+
8721
+ <li><p> Let <var> request</var> be <var> requestObject</var> 's <a for=Request>request</a> .
8722
+
8723
+ <li><p> Let <var> backgroundTimeout</var> be null.
8724
+
8725
+ <li><p> If <var> init</var> is given and <var> init</var> ["<code>backgroundTimeout</code>"]
8726
+ <a for=map>exists</a> then set <var> backgroundTimeout</var> to
8727
+ <var> init</var> ["<code>backgroundTimeout</code>"] .
8728
+
8729
+ <li><p> If <var> backgroundTimeout</var> is not a {{DOMHighResTimeStamp}} then throw a {{TypeError}} .
8730
+
8731
+ <li><p> Let <var> deferredRecord</var> be the result of calling
8732
+ <a>request a deferred fetch</a> given <var> request</var> and <var> backgroundTimeout</var> . If that
8733
+ threw an exception, <a for=/>reject</a> <var> promise</var> with that exception and return
8734
+ <var> promise</var> .
8735
+
8736
+ <li><p> Set <var> deferredRecord</var> 's <a for="deferred fetch record">invoke callback</a> to
8737
+ <a for=/>resolve</a> <var> promise</var> .
8738
+
8739
+ <li><p> <a for=AbortSignal lt=add>Add the following abort steps</a> to <var> requestObject</var> 's
8740
+ <a for=Request>signal</a> : <a for=list>remove</a> <var> deferredRecord</var> from
8741
+ <var> request</var> 's <a for=request>client</a>' s <a for=fetch>fetch group</a> 's
8742
+ <a for="fetch group">deferred fetch records</a> .
8743
+ </ol>
8744
+
8544
8745
<h2 id=data-urls><code>data:</code> URLs</h2>
8545
8746
8546
8747
<p> For an informative description of <code> data:</code> URLs, see RFC 2397. This section replaces
0 commit comments