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