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