- From: fergald <notifications@github.com>
- Date: Thu, 18 May 2023 00:28:01 -0700
- To: whatwg/fetch <fetch@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/fetch/pull/1647/review/1432133879@github.com>
@fergald commented on this pull request.
> @@ -8449,6 +8597,60 @@ with a <var>promise</var>, <var>request</var>, <var>responseObject</var>, and an
</div>
+<h3 id=fetch-later-method>FetchLater method</h3>
+
+<pre class=idl>
+
+dictionary DeferredRequestInit : RequestInit {
+ DOMHighResTimeStamp backgroundTimeout;
+};
+
+partial interface mixin WindowOrWorkerGlobalScope {
+ [NewObject] Promise<Response> fetchLater(RequestInfo input, optional DeferredRequestInit init = {});
Are we including the Response? I thought weren't.
> @@ -8449,6 +8597,60 @@ with a <var>promise</var>, <var>request</var>, <var>responseObject</var>, and an
</div>
+<h3 id=fetch-later-method>FetchLater method</h3>
+
+<pre class=idl>
+
+dictionary DeferredRequestInit : RequestInit {
+ DOMHighResTimeStamp backgroundTimeout;
+};
+
+partial interface mixin WindowOrWorkerGlobalScope {
+ [NewObject] Promise<Response> fetchLater(RequestInfo input, optional DeferredRequestInit init = {});
I think the Promise model has an unavoidable race caused by getting JS involved in delivering this state change information.
Here's the most direct way I can think of to trigger the issue
```js
let completed = false;
fetchLater(...).then(() => {completed = true});
addEventListener("pagehide", () => {
// This task will run first-thing after `pageshow`
setTimeout(() => {
if (!completed) {
doSomething();
}
}, 0);
});
```
Now let's say the fetch occurs while in BFCache. The first task to run on restore from BFCache will see complete as still `false` and will call `doSomething` incorrectly.
Even if we somehow make the tasks that run the promise resolves special so that they run first, you can recreate the same problem using 2 `fetchLater`s. One of the resolve callbacks must run first and would see the wrong value for the `completed` of the other fetch.
It might also be that any `pageshow` event handler will run before these callbacks. I can't find a clear answer to that. Document reactivation is [here](https://html.spec.whatwg.org/multipage/browsing-the-web.html#document-state:reactivate-a-document) but I'm not sure where the task queue is unfrozen.
This race was avoided in the original design because `isPending()` had access to the true state. It was all handled in native code which is allowed to execute while in BFCache - the timer expires, the renderer tells the browser to send and updates the pending state.
I think the only way to avoid this issue is to have an object that gives access to the state and update that object outside of JS.
--
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/fetch/pull/1647#pullrequestreview-1432133879
You are receiving this because you are subscribed to this thread.
Message ID: <whatwg/fetch/pull/1647/review/1432133879@github.com>
Received on Thursday, 18 May 2023 07:28:07 UTC