@@ -6940,117 +6940,120 @@ concurrently for the same reporting origin (the <a for=/>request</a>'s <a for=re
69406940quota opportunistically, before they have data to send.
69416941
69426942<div class=example id=deferred-fetch-quota-examples>
6943- <p> Any of the following calls to <a method><code>fetchLater()</code></a> would throw due to
6944- the request itself exceeding the 64 kibibytes quota allocated to a reporting origin. Note that the
6945- size of the request includes the <a for=request>URL</a> itself, the <a for=request>body</a> , the
6946- <a for=request>header list</a> , and the <a for=request>referrer</a> .
6947- <pre><code class=lang-javascript>
6948- fetchLater(a_72_kb_url);
6949- fetchLater("https://origin.example.com", {headers: headers_exceeding_64kb});
6950- fetchLater(a_32_kb_url, {headers: headers_exceeding_32kb});
6951- fetchLater("https://origin.example.com", {method: "POST", body: body_exceeding_64_kb});
6952- fetchLater(a_62_kb_url /* with a 3kb referrer */);
6943+ <p> Any of the following calls to <a method><code>fetchLater()</code></a> would throw due to
6944+ the request itself exceeding the 64 kibibytes quota allocated to a reporting origin. Note that the
6945+ size of the request includes the <a for=request>URL</a> itself, the <a for=request>body</a> , the
6946+ <a for=request>header list</a> , and the <a for=request>referrer</a> .
6947+
6948+ <pre><code class=lang-javascript>
6949+ fetchLater(a_72_kb_url);
6950+ fetchLater("https://origin.example.com", {headers: headers_exceeding_64kb});
6951+ fetchLater(a_32_kb_url, {headers: headers_exceeding_32kb});
6952+ fetchLater("https://origin.example.com", {method: "POST", body: body_exceeding_64_kb});
6953+ fetchLater(a_62_kb_url /* with a 3kb referrer */);
69536954</code></pre>
69546955
6955- <p> In the following sequence, the first two requests would succeed, but the third one would throw.
6956- That's because the overall 640 kibibytes quota was not exceeded in the first two calls, however the
6957- 3rd request exceeds the reporting-origin quota for <code> https://a.example.com</code> , and would
6958- throw.
6959- <pre><code class=lang-javascript>
6960- fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
6961- fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
6962- fetchLater("https://a.example.com");
6956+ <p> In the following sequence, the first two requests would succeed, but the third one would throw.
6957+ That's because the overall 640 kibibytes quota was not exceeded in the first two calls, however the
6958+ 3rd request exceeds the reporting-origin quota for <code> https://a.example.com</code> , and would
6959+ throw.
6960+
6961+ <pre><code class=lang-javascript>
6962+ fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
6963+ fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
6964+ fetchLater("https://a.example.com");
69636965</code></pre>
69646966
6965- <p> Same-origin nested documents share the quota of their parent. However, cross-origin or
6966- cross-agent iframes only receive 8kb of quota by default. So in the following example, the first three
6967- calls would succeed and the last one would throw.
6968- <pre><code class=lang-javascript>
6969- // In main page
6970- fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
6967+ <p> Same-origin nested documents share the quota of their parent. However, cross-origin or
6968+ cross-agent iframes only receive 8kb of quota by default. So in the following example, the first
6969+ three calls would succeed and the last one would throw.
6970+
6971+ <pre><code class=lang-javascript>
6972+ // In main page
6973+ fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
69716974
6972- // In same-origin nested document
6973- fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
6975+ // In same-origin nested document
6976+ fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
69746977
6975- // In cross-origin nested document at https://fratop.example.com
6976- fetchLater("https://a.example.com", {body: a_5kb_body});
6977- fetchLater("https://a.example.com", {body: a_12kb_body});
6978+ // In cross-origin nested document at https://fratop.example.com
6979+ fetchLater("https://a.example.com", {body: a_5kb_body});
6980+ fetchLater("https://a.example.com", {body: a_12kb_body});
69786981</code></pre>
69796982
6983+ <p> To make the previous example not throw, the top-level document can delegate some of its quota
6984+ to <code> https://fratop.example.com</code> , for example by serving the following header:
6985+
6986+ <pre><code class=lang-http> Permissions-Policy: deferred-fetch=(self "https://fratop.example.com")</code></pre>
69806987
6981- <p> To make the previous example not throw, the top-level document can delegate some of its quota
6982- to <code> https://fratop.example.com</code> , for example by serving the following header:
6983- <pre><code class=lang-http> Permissions-Policy: deferred-fetch=(self "https://fratop.example.com")</code></pre>
6988+ <p> Each nested document reserves its own quota. So the following would work, because each frame
6989+ reserve 8 kibibytes:
69846990
6985- <p> Each nested document reserves its own quota. So the following would work, because each frame
6986- reserve 8 kibibytes:
6987- <pre><code class=lang-javascript>
6988- // In cross-origin nested document at https://fratop.example.com/frame-1
6989- fetchLater("https://a.example.com", {body: a_6kb_body});
6991+ <pre><code class=lang-javascript>
6992+ // In cross-origin nested document at https://fratop.example.com/frame-1
6993+ fetchLater("https://a.example.com", {body: a_6kb_body});
69906994
6991- // In cross-origin nested document at https://fratop.example.com/frame-2
6992- fetchLater("https://a.example.com", {body: a_6kb_body});
6995+ // In cross-origin nested document at https://fratop.example.com/frame-2
6996+ fetchLater("https://a.example.com", {body: a_6kb_body});
69936997</code></pre>
69946998
6995- <p> The following tree illustrates how quota is distributed to different nested documents in a tree:
6999+ <p> The following tree illustrates how quota is distributed to different nested documents in a tree:
69967000
6997- <ul>
6998- <li>
6999- <p><code> https://top.example.com</code> , with permissions policy set to
7000- <code> Permissions-policy: deferred-fetch=(self "https://ok.example.com")</code>
7001- <ul>
7002- <li>
7003- <p><code> https://top.example.com/frame</code> : shares quota with the top-level traversable, as
7004- they are same origin.
7001+ <ul>
7002+ <li>
7003+ <p><code> https://top.example.com</code> , with permissions policy set to
7004+ <code> Permissions-policy: deferred-fetch=(self "https://ok.example.com")</code>
7005+ <ul>
7006+ <li>
7007+ <p><code> https://top.example.com/frame</code> : shares quota with the top-level traversable, as
7008+ they are same origin.
70057009
7006- <ul><li><p><code> https://x.example.com</code> : receives 8 kibibytes.</ul>
7010+ <ul><li><p><code> https://x.example.com</code> : receives 8 kibibytes.</ul>
70077011
7008- <li>
7009- <p><code> https://x.example.com</code> : receives 8 kibibytes.
7010- <ul><li><p><code> https://top.example.com</code> : 0. Even though it's same origin with the
7011- top-level traversable, it does not automatically share its quota as they are separated by a
7012- cross-origin intermediary.</ul>
7012+ <li>
7013+ <p><code> https://x.example.com</code> : receives 8 kibibytes.
7014+ <ul><li><p><code> https://top.example.com</code> : 0. Even though it's same origin with the
7015+ top-level traversable, it does not automatically share its quota as they are separated by a
7016+ cross-origin intermediary.</ul>
70137017
7014- <li>
7015- <p><code> https://ok.example.com/good</code> : receives 64 kibibytes, granted via the
7016- "{{PermissionsPolicy/deferred-fetch}} " policy.
7018+ <li>
7019+ <p><code> https://ok.example.com/good</code> : receives 64 kibibytes, granted via the
7020+ "{{PermissionsPolicy/deferred-fetch}} " policy.
70177021
7018- <ul><li><p><code> https://x.example.com</code> : receives no quota. Only documents with the same
7019- origin as the top-level traversable can grant the 8 kibibytes based on the
7020- "{{PermissionsPolicy/deferred-fetch-minimal}} " policy.</ul>
7022+ <ul><li><p><code> https://x.example.com</code> : receives no quota. Only documents with the same
7023+ origin as the top-level traversable can grant the 8 kibibytes based on the
7024+ "{{PermissionsPolicy/deferred-fetch-minimal}} " policy.</ul>
70217025
7022- <li><p><code> https://ok.example.com/redirect</code> , navigated to
7023- <code> https://x.example.com</code> : receives no quota. The reserved 64 kibibytes for
7024- <code> https://ok.example.com</code> are not available for
7025- <code> https://x.example.com</code> .
7026+ <li><p><code> https://ok.example.com/redirect</code> , navigated to
7027+ <code> https://x.example.com</code> : receives no quota. The reserved 64 kibibytes for
7028+ <code> https://ok.example.com</code> are not available for
7029+ <code> https://x.example.com</code> .
70267030
7027- <li><p><code> https://ok.example.com/back</code> , navigated to
7028- <code> https://top.example.com</code> : shares quota with the top-level traversable, as they're
7029- same origin.
7030- </ul>
7031- </ul>
7031+ <li><p><code> https://ok.example.com/back</code> , navigated to
7032+ <code> https://top.example.com</code> : shares quota with the top-level traversable, as they're
7033+ same origin.
7034+ </ul>
7035+ </ul>
70327036
7033- <p> In the above example, the <a for=/>top-level traversable</a> and its <a>same origin</a>
7034- descendants share a quota of 384 kibibytes. That value is computed as such:
7035- <ul>
7036- <li><p> 640 kibibytes are initially granted to the <a for=/>top-level traversable</a> .
7037+ <p> In the above example, the <a for=/>top-level traversable</a> and its <a>same origin</a>
7038+ descendants share a quota of 384 kibibytes. That value is computed as such:
7039+ <ul>
7040+ <li><p> 640 kibibytes are initially granted to the <a for=/>top-level traversable</a> .
70377041
7038- <li><p> 128 kibibytes are reserved for the "{{PermissionsPolicy/deferred-fetch-minimal}} " policy.
7042+ <li><p> 128 kibibytes are reserved for the "{{PermissionsPolicy/deferred-fetch-minimal}} " policy.
70397043
7040- <li><p> 64 kibibytes are reserved for the container navigating to
7041- <code> https://ok.example/good</code> .
7044+ <li><p> 64 kibibytes are reserved for the container navigating to
7045+ <code> https://ok.example/good</code> .
70427046
7043- <li><p> 64 kibibytes are reserved for the container navigating to
7044- <code> https://ok.example/redirect</code> , and lost when it navigates away.
7047+ <li><p> 64 kibibytes are reserved for the container navigating to
7048+ <code> https://ok.example/redirect</code> , and lost when it navigates away.
70457049
7046- <li><code> https://ok.example.com/back</code> did not reserve 64 kibibytes, because it navigated
7047- back to <a for=/>top-level traversable</a> 's origin.
7050+ <li><code> https://ok.example.com/back</code> did not reserve 64 kibibytes, because it navigated
7051+ back to <a for=/>top-level traversable</a> 's origin.
70487052
7049- <li><p> 640 − 128 − 64 − 64 = 384 kibibytes.
7050- </ul>
7053+ <li><p> 640 − 128 − 64 − 64 = 384 kibibytes.
7054+ </ul>
70517055</div>
70527056
7053-
70547057<p> This specification defines a <a>policy-controlled feature</a> identified by the string
70557058"<dfn for=PermissionsPolicy enum-value>deferred-fetch</dfn> ". Its
70567059<a for="policy-controlled feature">default allowlist</a> is "<code> self</code> ".
@@ -9146,7 +9149,8 @@ method steps are:
91469149 <p> If <var> request</var> 's <a for=request>body</a> is not null, and <var>request</var>' s
91479150 <a for=request>body</a> <a for=body>length</a> is null, then throw a {{TypeError}} .
91489151
9149- <p class=note> Requests whose <a for=request>body</a> is a {{ReadableStream}} cannot be deferred.
9152+ <p class=note> Requests whose <a for=request>body</a> is a {{ReadableStream}} object cannot be
9153+ deferred.
91509154
91519155 <li><p> If the <a>available deferred-fetch quota</a> given <var> request</var> 's
91529156 <a for=request>client</a> and <var> request</var> 's <a for=request>URL</a>' s
@@ -9172,68 +9176,72 @@ method steps are:
91729176 <p> The following call would queue a request to be fetched when the document is terminated:
91739177
91749178 <pre><code class=lang-javascript>
9175- fetchLater("https://report.example.com", {
9176- method: "POST",
9177- body: JSON.stringify(myReport),
9178- headers: { "Content-Type": "application/json" }
9179- })</code></pre>
9179+ fetchLater("https://report.example.com", {
9180+ method: "POST",
9181+ body: JSON.stringify(myReport),
9182+ headers: { "Content-Type": "application/json" }
9183+ })
9184+ </code></pre>
91809185
91819186 <p> The following call would also queue this request after 5 seconds, and the returned value would
91829187 allow callers to observe if it was indeed activated. Note that the request is guaranteed to be
91839188 invoked, even in cases where the user agent throttles timers.
91849189
91859190 <pre><code class=lang-javascript>
9186- const result = fetchLater("https://report.example.com", {
9187- method: "POST",
9188- body: JSON.stringify(myReport),
9189- headers: { "Content-Type": "application/json" },
9190- activateAfter: 5000
9191- });
9191+ const result = fetchLater("https://report.example.com", {
9192+ method: "POST",
9193+ body: JSON.stringify(myReport),
9194+ headers: { "Content-Type": "application/json" },
9195+ activateAfter: 5000
9196+ });
91929197
9193- function check_if_fetched() {
9194- return result.activated;
9195- }</code></pre>
9198+ function check_if_fetched() {
9199+ return result.activated;
9200+ }
9201+ </code></pre>
91969202
91979203 <p> The {{FetchLaterResult}} object can be used together with an {{AbortSignal}} . For example:
91989204
91999205 <pre><code class=lang-javascript>
9200- let accumulated_events = [];
9201- let previous_result = null;
9202- const abort_signal = new AbortSignal();
9203- function accumulate_event(event) {
9204- if (previous_result) {
9205- if (previous_result.activated) {
9206- // The request is already activated, we can start from scratch.
9207- accumulated_events = [];
9208- } else {
9209- // Abort this request, and start a new one with all the events.
9210- signal.abort();
9211- }
9206+ let accumulated_events = [];
9207+ let previous_result = null;
9208+ const abort_signal = new AbortSignal();
9209+ function accumulate_event(event) {
9210+ if (previous_result) {
9211+ if (previous_result.activated) {
9212+ // The request is already activated, we can start from scratch.
9213+ accumulated_events = [];
9214+ } else {
9215+ // Abort this request, and start a new one with all the events.
9216+ signal.abort();
92129217 }
9218+ }
92139219
9214- accumulated_events.push(event);
9215- result = fetchLater("https://report.example.com", {
9216- method: "POST",
9217- body: JSON.stringify(accumulated_events),
9218- headers: { "Content-Type": "application/json" },
9219- activateAfter: 5000,
9220- abort_signal
9221- });
9222- }</code></pre>
9220+ accumulated_events.push(event);
9221+ result = fetchLater("https://report.example.com", {
9222+ method: "POST",
9223+ body: JSON.stringify(accumulated_events),
9224+ headers: { "Content-Type": "application/json" },
9225+ activateAfter: 5000,
9226+ abort_signal
9227+ });
9228+ }
9229+ </code></pre>
92239230
92249231 <p> Any of the following calls to <a method><code>fetchLater()</code></a> would throw:
92259232
92269233 <pre><code class=lang-javascript>
9227- // Only <a>potentially trustworthy URL</a> s are supported.
9228- fetchLater("http://untrusted.example.com");
9234+ // Only <a>potentially trustworthy URL</a> s are supported.
9235+ fetchLater("http://untrusted.example.com");
92299236
9230- // The length of the deferred request has to be known when.
9231- fetchLater("https://origin.example.com", {body: someDynamicStream});
9237+ // The length of the deferred request has to be known when.
9238+ fetchLater("https://origin.example.com", {body: someDynamicStream});
92329239
9233- // Deferred fetching only works on active windows.
9234- const detachedWindow = iframe.contentWindow;
9235- iframe.remove();
9236- detachedWindow.fetchLater("https://origin.example.com");</code></pre>
9240+ // Deferred fetching only works on active windows.
9241+ const detachedWindow = iframe.contentWindow;
9242+ iframe.remove();
9243+ detachedWindow.fetchLater("https://origin.example.com");
9244+ </code></pre>
92379245
92389246 <p> See <a href="#deferred-fetch-quota-examples">deferred fetch quota examples</a> for examples
92399247 portraying how the deferred-fetch quota works.
0 commit comments