From 3c021010c038b44fb2d46d9fae38402bd6ef0584 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Mon, 3 Feb 2025 14:16:57 +0900 Subject: [PATCH] Use source document for prefetch lookup In particular, any time we look up a prefetch record to use for a navigation request, we now look it up in (a snapshot of) the source document's list of prefetch records, instead of looking it up in the target navigable's active document's list of prefetch records. This impacts cases like allowing prefetches to fulfill navigations to target="_blank" links, and also all prerender cases (where the target navigable is a new prerender navigable). Fixes #261. Closes #267 by superseding it, although it is mostly a port of that PR updated on top of the current spec. Co-authored-by: Hiroshige Hayashizaki --- prefetch.bs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/prefetch.bs b/prefetch.bs index fd72b33..b1cab4a 100644 --- a/prefetch.bs +++ b/prefetch.bs @@ -242,12 +242,11 @@ The user agent may [=prefetch record/cancel and discard=] records from the [=Doc
- To find a matching complete prefetch record given a {{Document}} |document|, [=URL=] |url|, and [=sandboxing flag set=] |sandboxFlags|, perform the following steps. + To find a matching complete prefetch record given a [=source snapshot params=] |sourceSnapshotParams|, [=URL=] |url|, and [=sandboxing flag set=] |sandboxFlags|, perform the following steps. - 1. [=Assert=]: |document| is [=Document/fully active=]. 1. Let |exactRecord| be null. 1. Let |inexactRecord| be null. - 1. [=list/For each=] |record| of |document|'s [=Document/prefetch records=]: + 1. [=list/For each=] |record| of |sourceSnapshotParams|'s [=source snapshot params/prefetch records=]: 1. If |record|'s [=prefetch record/state=] is not "`completed`", then [=iteration/continue=]. 1. If |record|'s [=prefetch record/sandboxing flag set=] is empty and |sandboxFlags| is not empty, then [=iteration/continue=]. @@ -277,7 +276,7 @@ The user agent may [=prefetch record/cancel and discard=] records from the [=Doc
- To wait for a matching prefetch record given a {{Document}} |document|, [=URL=] |url|, and [=sandboxing flag set=] |sandboxFlags|, perform the following steps. + To wait for a matching prefetch record given a [=source snapshot params=] |sourceSnapshotParams|, [=URL=] |url|, and [=sandboxing flag set=] |sandboxFlags|, perform the following steps. 1. [=Assert=]: this is running [=in parallel=]. 1. Let |cutoffTime| be null. @@ -285,7 +284,7 @@ The user agent may [=prefetch record/cancel and discard=] records from the [=Doc 1. Let |completeRecord| be the result of [=finding a matching complete prefetch record=] given |document|, |url|, and |sandboxFlags|. 1. If |completeRecord| is not null, return |completeRecord|. 1. Let |potentialRecords| be an empty [=list=]. - 1. [=list/For each=] |record| of |document|'s [=Document/prefetch records=]: + 1. [=list/For each=] |record| of |sourceSnapshotParams|'s [=source snapshot params/prefetch records=]: 1. If all of the following are true, then [=list/append=] |record| to |potentialRecords|: * |record|'s [=prefetch record/state=] is "`ongoing`". * |record| [=prefetch record/is expected to match a URL=] given |url|. @@ -293,8 +292,8 @@ The user agent may [=prefetch record/cancel and discard=] records from the [=Doc * |record|'s [=prefetch record/expiry time=] is greater than the [=current high resolution time=] for the [=relevant global object=] of |document|. * |cutoffTime| is null or |record|'s [=prefetch record/start time=] is less than |cutoffTime|. 1. If |potentialRecords| [=list/is empty=], return null. - 1. Wait until the [=prefetch record/state=] of any element of |document|'s [=Document/prefetch records=] changes. - 1. If |cutoffTime| is null and any element of |potentialRecords| has a [=prefetch record/state=] that is not "`ongoing`", set |cutoffTime| to the [=current high resolution time=] for the [=relevant global object=] of |document|. + 1. Wait until the [=prefetch record/state=] of any element of |sourceSnapshotParams|'s [=source snapshot params/prefetch records=] changes. + 1. If |cutoffTime| is null and any element of |potentialRecords| has a [=prefetch record/state=] that is not "`ongoing`", set |cutoffTime| to the [=current high resolution time=] for |sourceSnapshotParams|'s [=source snapshot params/fetch client=]'s [=environment settings object/global object=].

The reasoning for setting the cutoff time *after* waiting for a prefetch record to finish is to allow for flexibility in selecting a prefetch to serve the navigation while still guaranteeing falling back to a non-prefetched navigation in the case of repeated prefetch failures. We allow blocking on prefetch attempts which started before we see an attempt fail, but we don't block on subsequent attempts. Notably, this approach: does not finalize the set of prefetches to block on at the start of the navigation; allows a prefetch which started and completed after the navigation started to serve the navigation; avoids the use of a fixed timeout, which would be arbitrary and detrimental to the use of prefetch with slower servers; and blocks on, at most, two nearly-consecutive prefetches before falling back to a conventional navigation.

@@ -388,6 +387,15 @@ Update all creation sites to supply an empty string, except for any in this docu
+Add an additional item to [=source snapshot params=] as follows: + +: prefetch records +:: a [=list=] of [=prefetch records=]. + +Modify the [=snapshot source snapshot params=] algorithm to set the return value's [=source snapshot params/prefetch records=] to a [=list/clone=] of sourceDocument's [=Document/prefetch records=]. + +
+
This is extracted from create navigation params by fetching.
@@ -475,7 +483,7 @@ Update all creation sites to supply an empty string, except for any in this docu 1. Let |request| be the result of [=creating a navigation request=] given entry, sourceSnapshotParams's [=source snapshot params/fetch client=], navigable's [=navigable/container=], and sourceSnapshotParams's [=source snapshot params/has transient activation=]. 1. Set |request|'s [=request/replaces client id=] to navigable's [=navigable/active document=]'s [=relevant settings object=]'s [=environment/id=]. - 1. Let |prefetchRecord| be the result of [=waiting for a matching prefetch record=] given navigable's [=navigable/active document=], entry's [=session history entry/URL=], and targetSnapshotParams's [=target snapshot params/sandboxing flags=]. + 1. Let |prefetchRecord| be the result of [=waiting for a matching prefetch record=] given sourceSnapshotParams, entry's [=session history entry/URL=], and targetSnapshotParams's [=target snapshot params/sandboxing flags=]. 1. If documentResource is null and |prefetchRecord| is not null: 1. Set navigationParams to the result of [=creating navigation params from a prefetch record=] given navigable, entry's [=session history entry/document state=], navigationId, navTimingType, request, |prefetchRecord|, targetSnapshotParams, and sourceSnapshotParams. 1. [=Copy prefetch cookies=] given |prefetchRecord|'s [=prefetch record/isolated partition key=] and navigationParams's [=navigation params/reserved environment=].