动态标准 - 最后更新于 2024 年 9 月 12 日
欢迎来到龙之口。导航、会话历史以及通过该会话历史的遍历是本标准中最复杂的部分之一。
基本概念似乎并不难
你可以看到这里出现了一些交织的复杂性,比如遍历会导致导航(即对存储的 URL 进行网络获取),而导航必然需要与会话历史列表交互,以确保当它完成时,用户正在查看正确的内容。但真正的问题在于各种边缘情况和相互作用的 Web 平台功能。
子可导航对象(例如,包含在 iframe
中的那些)也可以导航和遍历,但这些导航需要线性化为 单个会话历史列表,因为用户只有一个用于整个 可遍历可导航对象(例如,浏览器选项卡)的后退/前进界面。
由于用户可以在会话历史中遍历超过一步(例如,按住后退按钮),因此当 子可导航对象 参与时,他们最终可能会同时遍历多个 可导航对象。这需要在所有参与的可导航对象之间同步,这可能涉及多个 事件循环,甚至 代理集群。
在导航期间,服务器可以使用 204 或 205 状态代码或带有 `Content-Disposition: attachment
` 头部进行响应,这会导致导航中止,并使 可导航对象 保留在其原始的 活动文档 上。(如果在遍历触发的导航期间发生这种情况,那就更糟糕了!)
各种其他 HTTP 头部,例如 `Location
`、`Refresh
`、`X-Frame-Options
` 以及内容安全策略的那些头部,要么影响 获取过程,要么影响 Document
创建过程,或者两者都有。`Cross-Origin-Opener-Policy
` 头部甚至会影响 浏览上下文选择和创建 过程!
某些导航(主要是 片段导航 和 单页应用程序导航)是同步的,这意味着 JavaScript 代码期望立即观察到导航的结果。然后,这需要与所有其他 可导航对象 在树中看到的会话历史视图同步,这可能会受到竞争条件的影响,并需要解决对会话历史的冲突视图。
该平台积累了各种令人兴奋的与导航相关的功能,需要特殊情况,例如 javascript:
URL、srcdoc
iframe
以及 beforeunload
事件。
在接下来的内容中,我们试图通过将这些复杂性适当地划分为标记部分和算法,并在可能的情况下提供适当的介绍性文字,来引导读者理解这些复杂性。但是,如果你想真正理解导航和会话历史,通常的建议 将是无价的。
步骤,一个非负整数或“pending
”,最初为“pending
”。
URL,一个 URL
文档状态,一个 文档状态。
经典历史 API 状态,它是 序列化状态,最初为 StructuredSerializeForStorage(null)。
导航 API 状态,它是 序列化状态,最初为 StructuredSerializeForStorage(undefined)。
导航 API 密钥,它是一个字符串,最初设置为 生成随机 UUID 的结果。
导航 API ID,它是一个字符串,最初设置为 生成随机 UUID 的结果。
持久化用户状态,它是 实现定义的,最初为 null
例如,某些用户代理可能希望持久化表单控件的值。
持久化表单控件值的 user-agent 鼓励也持久化其方向性(元素的 dir
属性的值)。这可以防止用户在最初以显式、非默认方向性输入值后,在历史遍历后出现值显示不正确的情况。
要获取 会话历史条目 的 文档,请返回其 文档状态 的 文档。
序列化状态 是对表示用户界面状态的对象进行序列化(通过 StructuredSerializeForStorage)的结果。我们有时非正式地称之为“状态对象”,它们是作者提供的表示用户界面状态的对象,或者反过来,是通过对序列化状态进行反序列化(通过 StructuredDeserialize)创建的对象。
页面可以通过 添加 序列化状态 到会话历史记录中。这些状态将在用户(或脚本)在历史记录中后退时被 反序列化 并 返回给脚本,从而使作者能够在单页面应用程序中使用“导航”隐喻。
序列化状态 用于两个主要目的:首先,将状态的预解析描述存储在 URL 中,以便在简单情况下,作者无需进行解析(尽管仍然需要解析来处理用户传递的 URL,因此这只是一个小的优化)。其次,作者可以存储不应存储在 URL 中的状态,因为该状态仅适用于当前的 Document
实例,如果打开新的 Document
,则需要重建该状态。
后者的一个例子是跟踪弹出 div
动画的精确坐标,以便如果用户后退,它可以动画到相同的位置。或者,它可以用来在数据缓存中保留一个指针,该数据将根据 URL 中的信息从服务器获取,以便在前后移动时,无需再次获取信息。
滚动恢复模式 指示用户代理在遍历到 条目 时是否应该恢复持久化滚动位置(如果有)。滚动恢复模式是以下之一
auto
"manual
"文档状态 持有 会话历史记录条目 中的状态,有关如何呈现和(如果需要)重新创建 Document
的信息。它具有
一个 文档,一个 Document
或 null,最初为 null。
一个 历史策略容器,一个 策略容器 或 null,最初为 null。
一个 请求来源,它是 "no-referrer
","client
" 或 URL,最初为 "client
"。
一个 发起者来源,它是一个 来源 或 null,最初为 null。
一个 来源,它是一个 来源 或 null,最初为 null。
这是我们为 "about:
" 方案的 Document
设置的 "about:
" 方案的 Document
的 来源。我们将其存储在这里,因为它也用于在遍历期间恢复这些 Document
,因为它们是在本地重建的,无需访问网络。它还用于比较 会话历史记录条目 被 重新填充 之前和之后的状态。如果来源发生变化,则 可导航目标名称 将被清除。
一个 about 基准 URL,它是一个 URL 或 null,最初为 null。
这将仅为 "about:
" 方案的 Document
填充,并将是这些 Document
的 备用基准 URL。它是发起者 Document
的 文档基准 URL 的快照。
一个 资源,一个字符串,POST 资源 或 null,最初为 null。
字符串被视为 HTML。它用于存储 iframe
srcdoc
文档 的源代码。
一个 重新加载待处理 布尔值,最初为 false。
一个 曾经填充过 布尔值,最初为 false。
一个 可导航目标名称 字符串,最初为空字符串。
一个 未恢复原因,一个 未恢复原因 或 null,最初为 null。
用户代理可以 销毁文档及其子文档,前提是 文档状态 的 文档 中的 文档 不为 null,只要 Document
未处于 完全活动状态。
除了此限制之外,本规范未指定用户代理何时应该销毁存储在 文档状态 中的 文档,还是将其保留在缓存中。
一个 POST 资源 具有
一个 请求主体,一个 字节序列 或失败。
这只能 并行 访问,因此无需将其存储在内存中。但是,它必须每次都返回相同的 字节序列。如果由于磁盘上的资源发生变化或无法再访问资源而无法做到这一点,则必须将其设置为失败。
一个 请求内容类型,它是 `application/x-www-form-urlencoded
`,`multipart/form-data
` 或 `text/plain
`。
一个 嵌套历史记录 具有
这将包含用于跨重新加载标识子可导航的方法。
会话历史记录中的几个连续条目可以共享同一个 文档状态。当通过正常的 导航 访问初始条目,并且通过 history.pushState()
添加后续条目时,就会发生这种情况。或者,它可以通过 导航到片段 来实现。
共享同一个 文档状态(因此仅表示特定文档的不同状态)的所有条目在构造时是连续的。
一个 Document
具有一个 最新条目,一个 会话历史记录条目 或 null。
这是最近由给定 Document
表示的条目。单个 Document
可以在一段时间内表示多个 会话历史记录条目,因为多个连续的 会话历史记录条目 可以共享同一个 文档状态,如上所述。
为了维护单一的事实来源,对 可遍历可导航 的 会话历史条目 的所有修改都需要同步。由于会话历史受到所有后代 可导航 的影响,因此受到多个 事件循环 的影响,因此这一点尤其重要。为了实现这一点,我们使用 会话历史遍历并行队列 结构。
会话历史遍历并行队列 与 并行队列 非常相似。它有一个 算法集,一个 有序集。
项 在一个 会话历史遍历并行队列 的 算法集 中,要么是算法步骤,要么是 同步导航步骤,它们是涉及 目标可导航(可导航)的一种特殊类型的算法步骤。
要 追加会话历史遍历步骤 到 可遍历可导航 traversable 给定算法步骤 steps,追加 steps 到 traversable 的 会话历史遍历队列 的 算法集。
要 追加会话历史同步导航步骤 涉及 可导航 targetNavigable 到 可遍历可导航 traversable 给定算法步骤 steps,追加 steps 作为 同步导航步骤 针对 目标可导航 targetNavigable 到 traversable 的 会话历史遍历队列 的 算法集。
要 启动新的会话历史遍历并行队列
令 sessionHistoryTraversalQueue 为一个新的 会话历史遍历并行队列。
并行 运行以下步骤
返回 sessionHistoryTraversalQueue。
本节包含我们在整个标准中操作会话历史记录时执行的各种操作。了解这些操作的功能的最佳方法是查看它们的调用点。
要获取可遍历对象的会话历史记录条目navigable
令 traversable 为 navigable 的可遍历的可遍历对象。
断言:这在 traversable 的会话历史记录遍历队列 中运行。
如果 navigable 是 traversable,则返回 traversable 的会话历史记录条目。
对于 traversable 的会话历史记录条目 中的每个 entry,追加 entry 的文档状态 到 docStates。
对于 docStates 中的每个 docState
断言:不会执行此步骤。
要为导航 API 获取可遍历对象的会话历史记录条目navigable,并提供一个整数 targetStep
令 rawEntries 为获取 navigable 的会话历史记录条目 的结果。
令 entriesForNavigationAPI 为一个新的空列表。
令 startingIndex 为 rawEntries 中会话历史记录条目 的索引,该条目具有小于或等于 targetStep 的最大步骤。
参见此示例,以了解为什么它是小于或等于 targetStep 的最大步骤。
追加 rawEntries[startingIndex] 到 entriesForNavigationAPI。
令 i 为 startingIndex − 1。
当 i > 0 时
将 i 设置为 startingIndex + 1。
当 i < rawEntries 的大小 时
返回 entriesForNavigationAPI。
要清除可遍历对象的正向会话历史记录navigable
断言:这在 navigable 的会话历史记录遍历队列 中运行。
令 step 为 navigable 的当前会话历史步骤。
对于 entryLists 中的每个 entryList
要获取可遍历对象中使用的所有历史记录步骤traversable
断言:这在 traversable 的会话历史记录遍历队列 中运行。
令 steps 为一个空的有序集合,其中包含非负整数。
对于 entryLists 中的每个 entryList
返回 steps,排序。
例如,点击超链接、提交表单 以及 window.open()
和 location.assign()
方法都可以导致页面导航。
在我们深入 导航算法 本身之前,我们需要建立几个重要的结构,它将使用这些结构。
源快照参数 结构 用于捕获从启动导航的 文档
中获取的数据。它在导航开始时进行快照,并在整个导航的生命周期中使用。它包含以下 项
要 快照源快照参数,给定一个 文档
sourceDocument,返回一个新的 源快照参数,其中包含以下内容:
目标快照参数 结构 用于捕获从被导航的 可导航对象 中获取的数据。与 源快照参数 一样,它在导航开始时进行快照,并在整个导航的生命周期中使用。它包含以下 项
要 快照目标快照参数,给定一个 可导航对象 targetNavigable,返回一个新的 目标快照参数,其 沙箱标志 设置为 确定创建沙箱标志 的结果,该结果基于 targetNavigable 的 活动浏览上下文 和 targetNavigable 的 容器。
导航过程的大部分内容都与确定如何创建一个新的 文档
有关,最终将在 创建和初始化 Document
对象 算法中进行。该算法的参数通过一个 导航参数 结构 进行跟踪,该结构包含以下 项
文档
,一旦它被创建文档
保留文档
文档
文档
强制执行文档
NavigationTimingType
,用于 创建新的 文档
的导航时序条目文档
的 关于基本 URL一旦创建了 导航参数 结构,本标准不会改变其任何 项。它们只被传递给其他算法。
一个 导航 ID 是在导航期间生成的 UUID 字符串。它用于与 WebDriver BiDi 规范交互,以及跟踪 正在进行的导航。 [WEBDRIVERBIDI]
在 文档
创建之后,相关 可遍历可导航对象 的 会话历史记录 会被更新。 NavigationHistoryBehavior
枚举用于向 导航 算法指示所需的会话历史记录更新类型。它可以是以下之一:
push
"replace
"auto
"push
" 或 "replace
"。通常它会变为 "push
",但在 某些情况下,它会变为 "replace
"。一个 历史记录处理行为 是一个 NavigationHistoryBehavior
,它要么是 "push
",要么是 "replace
",即,它已从任何初始 "auto
" 值解析出来。
导航必须替换,给定一个 URL url 和一个 文档
document,如果以下任何一个为 true:
url 的 方案 是 "javascript
";或
document 的 初始 about:blank
为 true。
平台的各个部分会跟踪用户是否参与导航。一个 用户导航参与 是以下之一
浏览器 UI
"激活
"无
"为了方便在某些调用站点使用,事件
event 的 用户导航参与 定义如下
要 导航 一个 可导航的 navigable 到一个 URL url,使用一个 文档
sourceDocument,带有一个可选的 POST 资源、字符串或 null documentResource(默认为 null),一个可选的 响应 或 null response(默认为 null),一个可选的布尔值 exceptionsEnabled(默认为 false),一个可选的 NavigationHistoryBehavior
historyHandling(默认为 "自动
"),一个可选的 序列化状态 或 null navigationAPIState(默认为 null),一个可选的 条目列表 或 null formDataEntryList(默认为 null),一个可选的 引用策略 referrerPolicy(默认为空字符串),以及一个可选的 用户导航参与 userInvolvement(默认为 "无
")
如果 formDataEntryList 不为 null,则设 cspNavigationType 为 "表单提交
";否则为 "其他
"。
设 sourceSnapshotParams 为根据 sourceDocument 调用 快照源快照参数 的结果。
设 initiatorOriginSnapshot 为 sourceDocument 的 来源。
设 initiatorBaseURLSnapshot 为 sourceDocument 的 文档基准 URL。
如果 sourceDocument 的 节点可导航的 未经沙盒允许 导航 navigable,则
如果 exceptionsEnabled 为 true,则抛出 "安全错误
" DOMException
。
返回。
设 navigationId 为根据 生成随机 UUID 的结果。 [WEBCRYPTO]
如果 周围代理 等于 navigable 的 活动文档 的 相关代理,则继续执行以下步骤。否则,在 navigable 的 活动窗口 中,根据 导航和遍历任务源 排队一个全局任务 来继续执行以下步骤。
如果 navigable 的 活动文档 的 卸载计数器 大于 0,则调用 WebDriver BiDi 导航失败,并使用一个 WebDriver BiDi 导航状态,其 id 为 navigationId,状态 为 "已取消
",URL 为 url,并返回。
设 container 为 navigable 的 容器。
如果 container 是一个 iframe
元素,并且根据 container 调用 将懒加载元素步骤 返回 true,则 停止观察懒加载元素的交叉点 container 并将 container 的 懒加载恢复步骤 设置为 null。
如果根据 url 和 navigable 的 活动文档 导航必须为替换,则将 historyHandling 设置为 "替换
"。
如果 navigable 的 父级 不为 null,则将 navigable 的 是否延迟 load
事件 设置为 true。
设 targetBrowsingContext 为 navigable 的 活动浏览上下文。
设 targetSnapshotParams 为根据 navigable 调用 快照目标快照参数 的结果。
调用 WebDriver BiDi 导航已启动,并使用 targetBrowsingContext 和一个新的 WebDriver BiDi 导航状态,其 id 为 navigationId,状态 为 "挂起
",URL 为 url。
如果 navigable 的 正在进行的导航 为 "遍历
",则
使用 targetBrowsingContext 调用 WebDriver BiDi 导航失败,并使用新的 WebDriver BiDi 导航状态,其 id 为 navigationId,状态 为 "已取消
",url 为 url。
返回。
将 navigable 的 正在进行的导航 设置为 navigationId。
这将导致 navigable 的其他正在进行的导航被中止,因为在导航的某些阶段,对 正在进行的导航 的更改将导致进一步的工作被放弃。
如果 url 的 方案 为 "javascript
",那么
在给定 navigable 的 活动窗口 上,针对 导航和遍历任务源 排队一个全局任务,以给定 navigable、url、historyHandling、initiatorOriginSnapshot 和 cspNavigationType 的 导航到 javascript:
URL。
返回。
如果以下条件全部为真
userInvolvement 不为 "浏览器 UI
";
navigable 的 活动文档 的 初始 about:blank
为 false;并且
则
如果 documentResource 是 POST 资源,则设 entryListForFiring 为 formDataEntryList;否则为 null。
如果 navigationAPIState 不为 null,则设 navigationAPIStateForFiring 为 navigationAPIState;否则为 StructuredSerializeForStorage(undefined)。
设 continue 为在 navigation 上以 导航类型 设置为 historyHandling、isSameDocument 设置为 false、用户参与度 设置为 userInvolvement、formDataEntryList 设置为 entryListForFiring、目标 URL 设置为 url 以及 navigationAPIState 设置为 navigationAPIStateForFiring 触发 push/replace/reload navigate
事件 的结果。
如果 continue 为 false,则返回。
如果导航通过较早的 导航到片段 路径,则具有 "浏览器 UI
" 的 userInvolvement 或由 跨源 的 sourceDocument 启动的导航可能会触发 navigate
事件。
并行运行以下步骤
设 unloadPromptCanceled 为针对 navigable 的 活动文档 的 包含的子级可导航对象 检查是否取消卸载 的结果。
如果 unloadPromptCanceled 为 true,或者 navigable 的 正在进行的导航 不再是 navigationId,则
使用 targetBrowsingContext 调用 WebDriver BiDi 导航失败,并使用新的 WebDriver BiDi 导航状态,其 id 为 navigationId,状态 为 "已取消
",url 为 url。
中止这些步骤。
在给定 navigable 的 活动窗口 上,针对 导航和遍历任务源 排队一个全局任务,以给定 navigable 的 活动文档 中止文档及其子级。
如果 url 匹配 about:blank
或为 about:srcdoc
,那么
将 documentState 的 来源 设置为 initiatorOriginSnapshot。
将 documentState 的 about 基本 URL 设置为 initiatorBaseURLSnapshot。
设 historyEntry 为新的 会话历史条目,其 URL 设置为 url,其 文档状态 设置为 documentState。
设 navigationParams 为 null。
如果 response 不为 null
设 policyContainer 为给定 响应 的 URL、null、sourceDocument 的 策略容器 的 克隆、navigable 的 容器文档 的 策略容器 以及 null 确定导航参数策略容器 的结果。
设 finalSandboxFlags 为 targetSnapshotParams 的 沙箱标志 与 policyContainer 的 CSP 列表 的 CSP 衍生的沙箱标志 的 并集。
设 responseOrigin 为给定 response 的 URL、finalSandboxFlags 以及 documentState 的 启动来源 确定来源 的结果。
设 coop 为新的 打开策略。
设 coopEnforcementResult 为新的 打开策略执行结果,具有
将 navigationParams 设置为新的 导航参数,具有
针对 historyEntry,给定 navigable、"导航
"、sourceSnapshotParams、targetSnapshotParams、navigationId、navigationParams、cspNavigationType 以及 允许 POST 设置为 true 以及 完成步骤 设置为以下步骤 尝试填充历史条目的文档。
虽然通常的跨文档导航案例将首先尝试使用 填充会话历史条目,其中包含一个 Document
,但所有未中止的导航最终都将调用以下算法之一。
要 完成跨文档导航,给定一个 可导航对象 navigable、一个 历史处理行为 historyHandling 和一个 会话历史条目 historyEntry
将 navigable 的 是否延迟 load
事件 设置为 false。
如果 historyEntry 的 document 为 null,则返回。
这意味着 尝试填充历史条目的 document 最终没有创建 document,例如,导航被后续导航取消,204 No Content 响应等等。
如果以下条件全部为真
navigable 的 父级 为 null;
historyEntry 的 document 的 浏览上下文 不是一个 辅助浏览上下文,其 打开者浏览上下文 不为 null;并且
historyEntry 的 document 的 起源 与 navigable 的 活动 document 的 起源 不相同,
则将 historyEntry 的 document 状态 的 可导航目标名称 设置为空字符串。
如果 historyHandling 为 "replace
",则令 entryToReplace 为 navigable 的 活动会话历史条目,否则为 null。
令 traversable 为 navigable 的 可遍历导航对象。
令 targetStep 为 null。
令 targetEntries 为 获取会话历史条目 用于 navigable 的结果。
如果 entryToReplace 为 null,则
将 targetStep 设置为 traversable 的 当前会话历史步骤 + 1。
将 historyEntry 的 步骤 设置为 targetStep。
追加 historyEntry 到 targetEntries。
否则
应用推送/替换历史步骤 targetStep 到 traversable,给定 historyHandling。
javascript:
URL 特殊情况javascript:
URL 在问题跟踪器中有一个 专用标签,记录了与它们规范相关的各种问题。
要 导航到 javascript:
URL,给定一个 可导航对象 targetNavigable、一个 URL url、一个 历史处理行为 historyHandling、一个 起源 initiatorOrigin 和一个字符串 cspNavigationType
设置 targetNavigable 的正在进行的导航 为 null。
如果 initiatorOrigin 与 targetNavigable 的 活动 document 的 起源 同源域,则返回。
令 request 为一个新的 请求,其 URL 为 url。
这是一个合成 请求,仅用于连接到下一步。它永远不会访问网络。
如果 应该通过内容安全策略阻止类型为的导航请求吗? 给定 request 和 cspNavigationType 为 "Blocked
",则返回。 [CSP]
令 newDocument 为 评估 javascript:
URL 给定 targetNavigable、url 和 initiatorOrigin 的结果。
如果 newDocument 为 null,则返回。
在这种情况下,一些 JavaScript 代码被执行,但没有创建新的 Document
,因此我们将不会执行导航。
令 entryToReplace 为 targetNavigable 的 活动会话历史条目。
令 oldDocState 为 entryToReplace 的 document 状态。
令 documentState 为一个新的 document 状态,其中
令 historyEntry 为一个新的 会话历史条目,其中
对于 URL,我们不使用 url,即 navigate 算法调用的实际 javascript:
URL。这意味着 javascript:
URL 永远不会存储在会话历史中,因此也永远无法遍历到。
追加会话历史遍历步骤 到 targetNavigable 的 可遍历导航对象,以 完成跨文档导航,其中包含 targetNavigable、historyHandling 和 historyEntry。
要 评估 javascript:
URL,给定一个 可导航对象 targetNavigable、一个 URL url 和一个 起源 newDocumentOrigin
令 urlString 为在 url 上运行 URL 序列化器 的结果。
令 encodedScriptSource 为从 urlString 中删除前导 "javascript:
" 的结果。
设 baseURL 为 settings 的 API 基础 URL。
设 script 为使用 scriptSource、settings、baseURL 和 默认脚本获取选项 创建经典脚本 的结果。
设 evaluationStatus 为 运行经典脚本 script 的结果。
设 result 为 null。
如果 evaluationStatus 是正常完成,并且 evaluationStatus.[[Value]] 是一个字符串,则将 result 设置为 evaluationStatus.[[Value]]。
否则,返回 null。
设 response 为一个新的 响应,其中包含
Content-Type
`, `text/html;charset=utf-8
`) »对 UTF-8 的编码意味着,一旦 HTML 解析器对响应主体进行解码,则不成对的 代理项 将无法进行往返。
设 finalSandboxFlags 为 policyContainer 的 CSP 列表 的 CSP 衍生的沙箱标志。
设 coopEnforcementResult 为一个新的 打开者策略执行结果,其中包含
设 navigationParams 为一个新的 导航参数,其中包含
返回使用 navigationParams 加载 HTML 文档 的结果。
要使用 可导航对象 navigable、URL url、历史处理行为 historyHandling、用户导航参与 userInvolvement、序列化状态-或-null navigationAPIState 和 导航 ID navigationId 导航到片段
设 destinationNavigationAPIState 为 navigable 的 活动会话历史条目 的 导航 API 状态。
如果 navigationAPIState 不为 null,则将 destinationNavigationAPIState 设置为 navigationAPIState。
设 continue 为 在 navigation 上触发 push/replace/reload navigate
事件 的结果,其中 navigationType 设置为 historyHandling,isSameDocument 设置为 true,userInvolvement 设置为 userInvolvement,destinationURL 设置为 url,navigationAPIState 设置为 destinationNavigationAPIState。
如果 continue 为 false,则返回。
设 historyEntry 为一个新的 会话历史条目,其中包含
对于使用 navigation.navigate()
执行的导航,state
选项提供的值将用于新的 导航 API 状态。(如果未为此选项提供值,则将其设置为 undefined 的序列化。)对于其他片段导航,包括用户启动的导航,导航 API 状态 将从前一个条目中继承。
经典历史 API 状态 永远不会被继承。
设 entryToReplace 为 navigable 的 活动会话历史条目(如果 historyHandling 为 "replace
",否则为 null)。
设 scriptHistoryIndex 为 history 的 索引。
设 scriptHistoryLength 为 history 的 长度。
如果 historyHandling 为 "push
",则
将 history 的 状态 设置为 null。
递增 scriptHistoryIndex。
将 scriptHistoryLength 设置为 scriptHistoryIndex + 1。
将 navigable 的 活动会话历史条目 设置为 historyEntry。
更新文档以进行历史步骤应用,其中包含 navigable 的 活动文档、historyEntry、true、scriptHistoryIndex、scriptHistoryLength 和 historyHandling。
由于单个片段导航,该算法将被调用两次:一次是同步调用,其中设置了最佳猜测值 scriptHistoryIndex 和 scriptHistoryLength,history.state
被设置为 null,并且触发了各种事件;另一次是异步调用,其中设置了索引和长度的最终值,history.state
保持不变,并且不会触发任何事件。
如果滚动失败,因为 文档
是新的,并且相关 ID 尚未解析,则第二次异步调用 更新文档以进行历史步骤应用 将负责滚动。
设 traversable 为 navigable 的 可遍历导航对象。
将涉及 navigable 的以下会话历史同步导航步骤 附加到 traversable
完成同一文档导航,其中包含 traversable、navigable、historyEntry、entryToReplace 和 historyHandling。
使用 navigable 的 活动浏览上下文 和一个新的 WebDriver BiDi 导航状态 调用 WebDriver BiDi 片段导航,该状态的 id 为 navigationId,url 为 url,status 为 "complete
"。
要使用 可遍历导航对象 traversable、可导航对象 targetNavigable、会话历史条目 targetEntry、会话历史条目-或-null entryToReplace 和 历史处理行为 historyHandling 完成同一文档导航
这被 片段导航 和 URL 和历史更新步骤 都使用,这是对会话历史的唯一同步更新。由于是同步的,这些算法是在 顶级可遍历对象 的 会话历史遍历队列 之外执行的。这使得它们与 顶级可遍历对象 的 当前会话历史步骤 不同步,因此该算法用于解决由于竞争条件造成的冲突。
如果 targetNavigable 的 活动会话历史条目 不是 targetEntry,则返回。
令 targetStep 为 null。
让 targetEntries 为 获取会话历史条目 针对 targetNavigable 的结果。
如果 entryToReplace 为 null,则
清除前向会话历史 traversable。
将 targetStep 设置为 traversable 的 当前会话历史步骤 + 1。
将 targetEntry 的 步骤 设置为 targetStep。
追加 targetEntry 到 targetEntries。
否则
应用 push/replace 历史步骤 targetStep 到 traversable 给定 historyHandling。
即使对于 "替换
" 导航,也会这样做,因为它可以解决多个同步导航之间的竞争条件。
对 尝试创建非 Fetch 方案文档 的输入是 非 Fetch 方案导航参数 结构。它是 导航参数 的轻量级版本,它只包含与非 Fetch 方案 导航案例相关的参数。它有以下 条目
一个 来源 可能用于用户界面提示,以确认调用外部软件包。
这与 文档状态 的 发起者来源 略有不同,因为 非 Fetch 方案导航参数 的 发起者来源 跟踪重定向到重定向链中的最后一个 Fetch 方案 URL,该链以非 Fetch 方案 URL 结束。
NavigationTimingType
用于 创建导航计时条目 用于新的 Document
如果 url 要使用不会影响 navigable 的机制处理,例如,因为 url 的 方案 由外部处理,那么
通过显示某种内联内容来处理 url,例如,因为指定的方案不是支持的协议之一,或者内联提示允许用户为给定的方案选择 注册的处理程序,从而显示错误消息。返回 显示内联内容 给定 navigable、navigationParams 的 id 以及 navigationParams 的 导航计时类型 的结果。
在使用注册的处理程序的情况下,导航 将使用新的 URL 调用。
要 移交到外部软件 给定 URL 或 响应 resource、可导航 navigable、沙盒标志集 sandboxFlags、布尔值 hasTransientActivation 以及 来源 initiatorOrigin,用户代理应该
如果以下条件全部为真
navigable 不是 顶级可遍历;
sandboxFlags 设置了它的 沙盒自定义协议导航浏览上下文标志;以及
sandboxFlags 设置了它的 沙盒顶级导航(使用用户激活)浏览上下文标志,或者 hasTransientActivation 为 false,
则返回,而不调用外部软件包。
在 iframe 内部的导航到外部软件,用户可能会将其视为新的弹出窗口或新的顶级导航。这就是它在沙盒 iframe
中被允许的原因,前提是指定了以下内容之一:allow-popups
、allow-top-navigation
、allow-top-navigation-by-user-activation
或者 allow-top-navigation-to-custom-protocols
。
执行 resource 的适当移交,同时尝试减轻此行为是尝试利用目标软件的风险。例如,用户代理可能会提示用户确认是否允许 initiatorOrigin 调用相关外部软件。特别是,如果 hasTransientActivation 为 false,那么用户代理在事先没有用户确认的情况下,不应调用外部软件包。
例如,目标软件的 URL 处理程序中可能存在漏洞,敌对页面会尝试通过欺骗用户点击链接来利用它。
在导航过程的早期,一些情况可能会介入并使整个过程停止。当多个 可导航 同时导航时,这可能特别令人兴奋,因为这可能是由于会话历史遍历造成的。
给定 源快照参数 sourceSnapshotParams,可导航 source 被 沙盒允许导航 第二个 可导航 target,如果以下步骤返回 true
如果 source 为 target,则返回 true。
如果 source 是 target 的祖先,则返回 true。
如果 target 是 source 的祖先,则
如果 target 不是 顶级可遍历,则返回 true。
如果 sourceSnapshotParams 的 具有瞬态激活 为 true,并且 sourceSnapshotParams 的 沙盒标志 的 沙盒顶级导航(使用用户激活)浏览上下文标志 被设置,则返回 false。
如果 sourceSnapshotParams 的 具有瞬态激活 为 false,并且 sourceSnapshotParams 的 沙盒标志 的 沙盒顶级导航(不使用用户激活)浏览上下文标志 被设置,则返回 false。
返回 true。
如果 target 是 顶级可遍历
如果 source 是 target 的 一个允许的沙盒导航器,则返回 true。
如果 sourceSnapshotParams 的 沙盒标志 的 沙盒导航浏览上下文标志 被设置,则返回 false。
返回 true。
如果 sourceSnapshotParams 的 沙盒标志 的 沙盒导航浏览上下文标志 被设置,则返回 false。
返回 true。
要检查是否取消卸载一个列表的可导航项navigablesThatNeedBeforeUnload,给定一个可选的可遍历可导航项traversable,一个可选的整数targetStep,以及一个可选的用户导航参与或空userInvolvementForNavigateEvent,运行以下步骤。它们返回 "canceled-by-beforeunload
"、"canceled-by-navigate
" 或 "continue
"。
让documentsToFireBeforeunload成为navigablesThatNeedBeforeUnload中每个项的活动文档。
让unloadPromptShown为 false。
让finalStatus为 "continue
"。
如果给定了traversable,那么
断言:targetStep 和 userInvolvementForNavigateEvent 被给出。
让targetEntry成为给定traversable 和 targetStep 的获取目标历史记录条目的结果。
如果targetEntry 不是traversable 的当前会话历史记录条目,并且targetEntry 的文档状态 的源 与traversable 的当前会话历史记录条目 的文档状态 的源 相同,那么
在这种情况下,我们将为traversable 触发navigate
事件。因为在某些情况下 它可能被取消,我们需要与其他遍历 navigate
事件 分开进行,这些事件将在稍后发生。
此外,因为我们希望beforeunload
事件在navigate
事件之前触发,这意味着我们需要为traversable 触发beforeunload
(如果适用),而不是在下面的documentsToFireBeforeunload 循环中进行。
断言:userInvolvementForNavigateEvent 不为空。
让eventsFired 为 false。
让needsBeforeunload 为 true,如果navigablesThatNeedBeforeUnload 包含traversable;否则为 false。
如果needsBeforeunload 为 true,那么从documentsToFireBeforeunload 中删除traversable 的活动文档。
在全局任务队列中排队,在给定traversable 的活动窗口 的导航和遍历任务源 上执行以下步骤
如果needsBeforeunload 为 true,那么
让 (unloadPromptShownForThisDocument,unloadPromptCanceledByThisDocument) 成为运行给定traversable 的活动文档 和 false 的触发 beforeunload
的步骤 的结果。
如果unloadPromptShownForThisDocument 为 true,那么将unloadPromptShown 设置为 true。
如果unloadPromptCanceledByThisDocument 为 true,那么将finalStatus 设置为 "canceled-by-beforeunload
"。
如果finalStatus 为 "canceled-by-beforeunload
",那么中止这些步骤。
让navigateEventResult 成为在给定targetEntry 和 userInvolvementForNavigateEvent 的navigation 上触发遍历 navigate
事件 的结果。
如果navigateEventResult 为 false,那么将finalStatus 设置为 "canceled-by-navigate
"。
将eventsFired 设置为 true。
等待eventsFired 为 true。
如果finalStatus 不是 "continue
",那么返回finalStatus。
让totalTasks 成为documentsThatNeedBeforeunload 的大小。
让completedTasks 为 0。
对于 documents 的每个document,在全局任务队列中排队,在给定document 的相关全局对象 的导航和遍历任务源 上运行以下步骤
让 (unloadPromptShownForThisDocument,unloadPromptCanceledByThisDocument) 成为运行给定document 和 unloadPromptShown 的触发 beforeunload
的步骤 的结果。
如果unloadPromptShownForThisDocument 为 true,那么将unloadPromptShown 设置为 true。
如果unloadPromptCanceledByThisDocument 为 true,那么将finalStatus 设置为 "canceled-by-beforeunload
"。
将completedTasks 加 1。
等待completedTasks 等于totalTasks。
返回finalStatus。
给定一个Document
document 和一个布尔值unloadPromptShown 的触发 beforeunload
的步骤 为
让unloadPromptCanceled 为 false。
将document 的卸载计数器 加 1。
让eventFiringResult 成为触发事件 的结果,该事件名为beforeunload
,在document 的相关全局对象 上,使用BeforeUnloadEvent
,可取消
属性初始化为 true。
如果以下条件全部为真
unloadPromptShown 为 false;
eventFiringResult 为 false,或者event 的returnValue
属性不是空字符串;并且
显示卸载提示不太可能令人讨厌、欺骗性或无意义,
则
将unloadPromptShown 设置为 true。
使用document 的相关全局对象、"beforeunload
" 和 "" 调用WebDriver BiDi 用户提示打开。
询问用户是否确认他们希望卸载该文档,并在等待用户响应时暂停。
显示给用户的消息不可自定义,而是由用户代理决定。特别是,returnValue
属性的实际值会被忽略。
如果用户没有确认页面导航,那么将unloadPromptCanceled 设置为 true。
使用document 的相关全局对象,以及如果unloadPromptCanceled 为 false 则为 true,否则为 false 调用WebDriver BiDi 用户提示关闭。
将document 的卸载计数器 减 1。
返回 (unloadPromptShown,unloadPromptCanceled)。
要为一个可导航项navigable 将正在进行的导航 设置为newValue
如果navigable 的正在进行的导航 等于newValue,那么返回。
通知导航 API 关于中止导航,给定navigable。
将navigable 的正在进行的导航 设置为newValue。
要重新加载一个可导航项navigable,给定一个可选的序列化状态或空navigationAPIState(默认 null)和一个可选的用户导航参与userInvolvement(默认 "无
")
如果userInvolvement 不是 "浏览器 UI
",那么
让destinationNavigationAPIState 成为navigable 的活动会话历史记录条目 的导航 API 状态。
如果 navigationAPIState 不为 null,则将 destinationNavigationAPIState 设置为 navigationAPIState。
令 continue 为在 navigation 上 触发 push/replace/reload navigate
事件 的结果,其中 navigationType 设置为 "reload
",isSameDocument 设置为 false,userInvolvement 设置为 userInvolvement,destinationURL 设置为 navigable 的 活动会话历史条目 的 URL,以及 navigationAPIState 设置为 destinationNavigationAPIState。
如果 continue 为 false,则返回。
令 traversable 为 navigable 的 可遍历的导航对象。
将以下会话历史遍历步骤 附加到 traversable。
将重新加载历史步骤 应用于 traversable。
为了 按增量遍历历史,给定一个 可遍历的导航对象 traversable,一个整数 delta,以及一个可选的 Document
sourceDocument
令 sourceSnapshotParams 和 initiatorToCheck 为 null。
令 userInvolvement 为 "浏览器 UI
"。
如果给定了 sourceDocument,则
将以下会话历史遍历步骤 附加到 traversable。
令 allSteps 为 traversable 的 获取所有使用过的历史步骤 的结果。
令 currentStepIndex 为 traversable 的 当前会话历史步骤 在 allSteps 中的索引。
令 targetStepIndex 为 currentStepIndex 加上 delta。
如果 allSteps[targetStepIndex] 不存在,则中止这些步骤。
应用遍历历史步骤 allSteps[targetStepIndex] 到 traversable,给定 sourceSnapshotParams,initiatorToCheck 和 userInvolvement。
除了 navigate 算法之外,会话历史条目 可以通过一种额外的机制来推送或替换,即 URL 和历史更新步骤。这些步骤的最著名的调用者是 history.replaceState()
和 history.pushState()
API,但标准的各个其他部分也需要对 活动历史条目 进行更新,它们使用这些步骤来执行此操作。
URL 和历史更新步骤,给定一个 Document
document,一个 URL newURL,一个可选的 序列化状态-或-null serializedData(默认值为 null),以及一个可选的 历史处理行为 historyHandling(默认值为 "replace
"),分别是
令 navigable 为 document 的 节点导航对象。
令 activeEntry 为 navigable 的 活动会话历史条目。
令 newEntry 为一个新的 会话历史条目,其包含
如果 document 的 初始 about:blank
为 true,则将 historyHandling 设置为 "replace
"。
这意味着 pushState()
在 初始 about:blank
Document
上的行为与 replaceState()
调用相同。
令 entryToReplace 为 activeEntry,如果 historyHandling 为 "replace
",否则为 null。
如果 historyHandling 为 "push
",则
这些是用于立即同步访问的临时最佳猜测值。
如果 serializedData 不为 null,则 恢复历史对象状态,给定 document 和 newEntry。
将 document 的 URL 设置为 newURL。
由于这不是 导航 也不是 历史遍历,因此它不会导致 hashchange
事件被触发。
将 document 的 最新条目 设置为 newEntry。
将 navigable 的 活动会话历史条目 设置为 newEntry。
更新相同文档导航的导航 API 条目,给定 document 的 相关全局对象 的 导航 API,newEntry 和 historyHandling。
令 traversable 为 navigable 的 可遍历的导航对象。
将以下涉及 navigable 的会话历史同步导航步骤 附加到 traversable。
完成相同文档导航,给定 traversable,navigable,newEntry,entryToReplace 和 historyHandling。
尽管 片段导航 和 URL 和历史更新步骤 都执行同步历史更新,但只有片段导航包含对 更新文档以应用历史步骤 的同步调用。相反,URL 和历史更新步骤 在上述算法中执行一些选择的更新,省略其他更新。这在一定程度上是一个不幸的历史事故,通常会导致 Web 开发人员对这种不一致感到沮丧。例如,这意味着 popstate
事件会针对片段导航触发,但不会针对 history.pushState()
调用触发。
如 概述 中所述,导航 和 遍历 都涉及创建 会话历史条目,然后尝试填充其 document 成员,以便它可以在 导航对象 内部呈现。
这涉及以下几种方式之一:使用 已给定的响应;使用 会话历史条目 中存储的 srcdoc 资源;或 获取。该过程有几种失败模式,这些模式可能会导致什么也不做(使 导航对象 停留在当前 活动 Document
上)或可能导致使用 错误文档 填充 会话历史条目。
为了尝试填充历史条目文档,针对一个会话历史条目 entry,给定一个可导航对象 navigable,一个NavigationTimingType
navTimingType,一个源快照参数 sourceSnapshotParams,一个目标快照参数 targetSnapshotParams,一个可选的导航ID 或 null navigationId(默认为 null),一个可选的导航参数 或 null navigationParams(默认为 null),一个可选的字符串 cspNavigationType(默认为 "other
"),一个可选的布尔值allowPOST(默认为 false),以及可选的算法步骤completionSteps(默认为空算法)。
断言:如果 navigationParams 不为 null,则 navigationParams 的 响应 不为 null。
设 currentBrowsingContext 为 navigable 的 活动浏览上下文。
如果 navigationParams 为 null,则
如果 documentResource 是一个字符串,则将 navigationParams 设置为根据 entry、navigable、targetSnapshotParams、navigationId 和 navTimingType 从 srcdoc 资源创建导航参数 的结果。
否则,如果以下所有条件都为真
documentResource 为 null,或 allowPOST 为 true 且 documentResource 的 请求体 不为失败,
则将 navigationParams 设置为根据 entry、navigable、sourceSnapshotParams、targetSnapshotParams、cspNavigationType、navigationId 和 navTimingType 通过获取创建导航参数 的结果。
否则,如果 entry 的 URL 的 方案 不是一个获取方案,则将 navigationParams 设置为一个新的非获取方案导航参数,其包含以下内容:
为了 从 srcdoc 资源创建导航参数,需要一个 会话历史记录项 entry,一个 可导航对象 navigable,一个 目标快照参数 targetSnapshotParams,一个 导航 ID 或 null navigationId,以及一个 NavigationTimingType
navTimingType
令 response 为新的 响应,其具有
about:srcdoc
Content-Type
`, `text/html
`) »令 responseOrigin 为使用 response 的 URL、targetSnapshotParams 的 沙盒标志 和 entry 的 文档状态 的 来源 执行 确定来源 的结果。
令 coop 为新的 开启策略。
令 coopEnforcementResult 为新的 开启策略执行结果,其具有
令 policyContainer 为使用 response 的 URL、entry 的 文档状态 的 历史记录策略容器、null、navigable 的 容器文档 的 策略容器 和 null 执行 确定导航参数策略容器 的结果。
返回新的 导航参数,其具有
此算法修改了 entry。
令 request 为新的 请求,其具有
如果 documentResource 是 POST 资源,则
如果 entry 的 文档状态 的 重新加载挂起 为 true,则将 request 的 重新加载导航标志 设置为 true。
否则,如果 entry 的 文档状态 的 已填充 为 true,则将 request 的 历史记录导航标志 设置为 true。
如果 sourceSnapshotParams 的 has transient activation 为真,则将 request 的 user-activation 设置为真。
如果 navigable 的 container 不为空
如果 navigable 的 container 有一个 browsing context scope origin,则将 request 的 origin 设置为该 browsing context scope origin。
将 request 的 destination 设置为 navigable 的 container 的 local name。
如果 sourceSnapshotParams 的 fetch client 是 navigable 的 container document 的 relevant settings object,则将 request 的 initiator type 设置为 navigable 的 container 的 local name。
这确保只有容器触发的导航会被报告给资源计时。
设 response 为空。
设 responseOrigin 为空。
设 fetchController 为空。
设 coopEnforcementResult 为一个新的 opener policy enforcement result,包含
设 finalSandboxFlags 为一个空 sandboxing flag set。
设 responsePolicyContainer 为空。
设 responseCOOP 为一个新的 opener policy。
设 locationURL 为空。
设 currentURL 为 request 的 current URL。
设 commitEarlyHints 为空。
当 true 时
如果 request 的 reserved client 不为空,且 currentURL 的 origin 不与 request 的 reserved client 的 creation URL 的 origin 为 same,则
对 request 的 reserved client 运行 environment discarding steps。
将 request 的 reserved client 设置为空。
将 commitEarlyHints 设置为空。
来自 early hint headers 的预加载链接在 same origin 重定向后保留在预加载缓存中,但在跨域重定向时会被丢弃。
如果 request 的 reserved client 为空,则
设 topLevelCreationURL 为 currentURL。
设 topLevelOrigin 为空。
如果 navigable 不是一个 top-level traversable,则
设 parentEnvironment 为 navigable 的 parent 的 active document 的 relevant settings object。
将 topLevelCreationURL 设置为 parentEnvironment 的 top-level creation URL。
将 topLevelOrigin 设置为 parentEnvironment 的 top-level origin。
将 request 的 reserved client 设置为一个新的 environment,其 id 为一个唯一的不可见字符串,target browsing context 为 navigable 的 active browsing context,creation URL 为 currentURL,top-level creation URL 为 topLevelCreationURL,top-level origin 为 topLevelOrigin。
创建的 environment 的 active service worker 在 Handle Fetch 算法中进行 fetch 时设置,如果请求 URL 匹配服务工作者注册。 [SW]
如果 should navigation request of type be blocked by Content Security Policy? 给定 request 和 cspNavigationType 为 "Blocked
" 的结果为 "Blocked
",则将 response 设置为一个 network error 并 break。 [CSP]
将 response 设置为空。
如果 fetchController 为空,则将 fetchController 设置为 fetching request 的结果,其中 processEarlyHintsResponse 设置为下面定义的 processEarlyHintsResponse,processResponse 设置为下面定义的 processResponse,useParallelQueue 设置为 true。
设 processEarlyHintsResponse 为以下给定一个 response earlyResponse 的算法
如果 commitEarlyHints 为空,则将 commitEarlyHints 设置为给定 earlyResponse 和 request 的 reserved client 的 processing early hint headers 的结果。
设 processResponse 为以下给定一个 response fetchedResponse 的算法
将 response 设置为 fetchedResponse。
否则,对 fetchController process the next manual redirect。
这将在我们第一次循环迭代中调用我们提供的 processResponse,从而设置 response。
导航手动处理重定向,因为导航是 Web 平台中唯一关心重定向到 mailto:
URL 等的地方。
等待 response 不为空,或者 navigable 的 ongoing navigation 更改为不再等于 navigationId。
如果后一种情况发生,则 abort fetchController,并返回。
否则,继续执行。
如果 request 的 body 为空,则将 entry 的 document state 的 resource 设置为空。
Fetch 为特定重定向取消设置 body。
将 responsePolicyContainer 设置为给定 response 和 request 的 reserved client 的 creating a policy container from a fetch response 的结果。
将 finalSandboxFlags 设置为 targetSnapshotParams 的 sandboxing flags 和 responsePolicyContainer 的 CSP list 的 CSP-derived sandboxing flags 的 union。
将 responseOrigin 设置为给定 response 的 URL,finalSandboxFlags 和 entry 的 document state 的 initiator origin 的 determining the origin 的结果。
如果 response 是重定向,那么 response 的 URL 将是导致重定向到 response 的 位置 URL 的 URL;它不会是 位置 URL 本身。
如果 navigable 是一个 顶级可遍历对象,那么
将 responseCOOP 设置为 获取打开者策略 的结果,该策略基于 response 和 request 的 保留的客户端。
将 coopEnforcementResult 设置为 执行响应的打开者策略 的结果,该策略基于 navigable 的 活动浏览上下文、response 的 URL、responseOrigin、responseCOOP、coopEnforcementResult 和 request 的 推荐来源。
如果 finalSandboxFlags 不为空且 responseCOOP 的 值 不是 "unsafe-none
",则将 response 设置为适当的 网络错误 并 中断。
这会导致网络错误,因为不能同时使用打开者策略提供干净的状态到响应并对导航到该响应的结果进行沙盒化。
如果 response 不是一个 网络错误,navigable 是一个 子可导航对象,并且执行 跨域资源策略检查 的结果,该检查基于 navigable 的 容器文档 的 来源、navigable 的 容器文档 的 相关设置对象、request 的 目标、response 和 true 是 **被阻止** 的,则将 response 设置为 网络错误 并 中断。
这里我们针对 父可导航对象 而不是 navigable 本身运行 跨域资源策略检查。这是因为我们关注的是嵌入内容与父上下文之间的同源性,而不是导航源。
将 locationURL 设置为 response 的 位置 URL,该 URL 基于 currentURL 的 片段。
如果 locationURL 是失败或空值,则 中断。
将 entry 的 经典历史 API 状态 设置为 StructuredSerializeForStorage(null)。
令 oldDocState 为 entry 的 文档状态。
将 entry 的 文档状态 设置为新的 文档状态,其中包含
对于导航情况,只有 entry 引用了 oldDocState,该状态是在 导航算法早期创建的。因此,对于导航,这在功能上只是对 entry 的 文档状态 的更新。对于遍历情况,相邻的 会话历史条目 也可能引用 oldDocState,在这种情况下,即使我们更新了 entry 的 文档状态,它们也会继续引用它。
oldDocState 的 历史策略容器 在遍历情况下仅在填充它之后才会不为空,这发生在导航到一个 需要将策略容器存储在历史记录中 的 URL 时。
设置由以下 Jake 图 给出
0 | 1 | 2 | 3 | |
---|---|---|---|---|
顶部 | /a | /a#foo | /a#bar | /b |
还假设步骤 0、1 和 2 中条目共享的 文档状态 具有一个空值的 文档,即 bfcache 并不起作用。
现在考虑我们遍历回步骤 2 的场景,但这次在获取 /a
时,服务器使用一个指向 /c
的
标头进行响应。也就是说,locationURL 指向 Location
/c
,因此我们到达了此步骤,而不是 中断 循环。
在这种情况下,我们替换了占据步骤 2 的 会话历史条目 的 文档状态,但我们 **没有** 替换占据步骤 0 和 1 的条目的文档状态。由此产生的 Jake 图 如下所示
0 | 1 | 2 | 3 | |
---|---|---|---|---|
顶部 | /a | /a#foo | /c#bar | /b |
注意,即使我们最终回到了原始 URL 的重定向链中,我们也会执行此替换,例如,如果 /c
本身有一个指向 /a
的
标头。这种情况最终会像这样Location
0 | 1 | 2 | 3 | |
---|---|---|---|---|
顶部 | /a | /a#foo | /a#bar | /b |
如果 locationURL 的 方案 不是一个 HTTP(S) 方案,那么
将 currentURL 设置为 locationURL。
将 entry 的 URL 设置为 currentURL。
如果 locationURL 是一个 URL,其 方案 不是 获取方案,则返回新的 非获取方案导航参数,其中包含
此时,request 的 当前 URL 是重定向链中最后一个具有 获取 方案 的 URL,它在重定向到非 获取方案 URL 之前。正是这个 URL 的 来源 将用作导航到非 获取方案 URL 的启动来源。
如果以下任何条件为真
则返回 null。
令 resultPolicyContainer 为使用 response 的 URL、entry 的 文档状态 的 历史策略容器、sourceSnapshotParams 的 源策略容器、null 和 responsePolicyContainer 执行 确定导航参数策略容器 的结果。
如果 navigable 的 容器 是一个 iframe
,并且 response 的 时间允许传递标志 已设置,则将 容器 的 待处理资源计时开始时间 设置为 null。
如果 iframe
被允许报告资源计时,则我们无需运行其回退步骤,因为正常的报告将照常进行。
返回一个新的 导航参数,其包含以下内容:
如果元素的 Document
的 节点可导航对象 是一个 顶级可遍历对象,或者如果其 Document
的所有 祖先可导航对象 都有 活动文档,且这些文档的 起源 与元素的 节点文档 的 起源 相同,则元素具有 浏览上下文范围起源。如果元素具有 浏览上下文范围起源,则其值为元素的 节点文档 的 起源。
此定义存在问题,需要调查以了解其本意表达的内容:请查看 issue #4703。
要 加载文档,请根据给定的 导航参数 navigationParams、源快照参数 sourceSnapshotParams 和 起源 initiatorOrigin 执行以下步骤。它们将返回一个 Document
或 null。
如果用户代理已配置为使用某种机制处理给定 type 的资源,而不是在 可导航对象 中呈现内容,则跳过此步骤。否则,如果 type 是以下类型之一:
text/css
"text/plain
"text/vtt
"multipart/x-mixed-replace
"multipart/x-mixed-replace
文档 的结果。application/pdf
"text/pdf
"否则,继续执行。
一个 明确支持的 XML MIME 类型 是一个 XML MIME 类型,用户代理已配置为使用外部应用程序来呈现其内容,或者用户代理为此类型制定了专用处理规则。例如,具有内置 Atom 订阅阅读器的网页浏览器被认为明确支持 application/atom+xml
MIME 类型。
一个 明确支持的 JSON MIME 类型 是一个 JSON MIME 类型,用户代理已配置为使用外部应用程序来呈现其内容,或者用户代理为此类型制定了专用处理规则。
在这两种情况下,外部应用程序或用户代理将 直接在 navigationParams 的 可导航对象 中显示内容(例如,以本地方式呈现内容或显示错误消息,因为未支持指定的类型),或 将内容移交给外部软件。这两种情况都将在下面的步骤中发生。
否则,文档的 type 将导致资源不会影响 navigationParams 的 可导航对象(例如,因为资源将被移交给外部应用程序,或者因为它是一种未知类型,将被 作为下载处理)。将内容移交给外部软件,使用 navigationParams 的 响应、navigationParams 的 可导航对象、navigationParams 的 最终沙箱标志集、sourceSnapshotParams 的 是否具有瞬态激活 和 initiatorOrigin。
返回 null。
对于导航和遍历,一旦我们了解了在会话历史中要前往的目的地,大部分工作都将集中在将该概念应用于 可遍历可导航对象 和相关 Document
上。对于导航,这项工作通常在流程的最后阶段进行;对于遍历,则是流程的开始。
确保一个可遍历对象最终处于正确的会话历史步骤,这尤其复杂,因为它可能涉及协调多个可导航对象,这些对象是可遍历对象的子孙节点,并行填充它们,然后同步以确保每个人对结果都有相同的视图。由于存在同步的同文档导航与跨文档导航混合在一起,以及网页已经有了某些相对的计时期望,所以这种情况更加复杂。
一个更改可导航延续状态用于在应用历史步骤算法期间存储信息,允许算法的一部分仅在其他部分完成之后才能继续。它是一个结构体,包含以下内容:
文档
尽管对可遍历可导航对象的所有更新最终都将出现在同一个应用历史步骤算法中,但每个可能的入口点都有一些小的定制。
为了更新可导航对象创建/销毁,给定一个可遍历可导航对象traversable
为了应用推入/替换历史步骤,给定一个非负整数step和一个历史处理行为historyHandling到一个可遍历可导航对象traversable
返回应用历史步骤step到traversable的结果,给定false、null、null、null和historyHandling。
应用推入/替换历史步骤从未将源快照参数或发起者可导航对象传递给应用历史步骤。这是因为这些检查是在导航算法的早期完成的。
为了应用重载历史步骤,给定一个可遍历可导航对象traversable
应用重载历史步骤从未将源快照参数或发起者可导航对象传递给应用历史步骤。这是因为重载始终被视为由可导航对象本身完成,即使在像parent.location.reload()
这样的情况下也是如此。
为了应用遍历历史步骤,给定一个非负整数step到一个可遍历可导航对象traversable,以及源快照参数sourceSnapshotParams、可导航对象initiatorToCheck和用户导航参与userInvolvement
现在来看看算法本身。
为了应用历史步骤,给定一个非负整数step到一个可遍历可导航对象traversable,以及布尔值checkForCancelation、源快照参数或nullsourceSnapshotParams、可导航对象或nullinitiatorToCheck、用户导航参与或nulluserInvolvementForNavigateEvents,以及NavigationType
或nullnavigationType,执行以下步骤。它们返回"initiator-disallowed
"、"canceled-by-beforeunload
"、"canceled-by-navigate
"或"applied
"。
令targetStep为获取使用的步骤的结果,给定traversable和step。
如果initiatorToCheck不是null,则
断言:sourceSnapshotParams不是null。
对于navigable的每个获取所有当前会话历史条目将更改或重载的可导航对象:如果initiatorToCheck不是被沙盒允许导航navigable,给定sourceSnapshotParams,则返回"initiator-disallowed
"。
令navigablesCrossingDocuments为获取所有可能经历跨文档遍历的可导航对象的结果,给定traversable和targetStep。
如果checkForCancelation为true,并且检查是否取消卸载的结果,给定navigablesCrossingDocuments、traversable、targetStep和userInvolvementForNavigateEvents,不是"continue
",则返回该结果。
令changingNavigables为获取所有当前会话历史条目将更改或重载的可导航对象的结果,给定traversable和targetStep。
令nonchangingNavigablesThatStillNeedUpdates为获取所有仅需要历史对象长度/索引更新的可导航对象的结果,给定traversable和targetStep。
对于changingNavigables的每个navigable
令totalChangeJobs为changingNavigables的大小。
令completedChangeJobs为0。
令changingNavigableContinuations为一个空的队列,包含更改可导航延续状态。
此队列用于将对changingNavigables的操作分成两部分。具体来说,changingNavigableContinuations保存了第二部分的数据。
对于changingNavigables的每个navigable,在全局任务队列中添加一个任务到navigable的活动窗口的导航和遍历任务源,以运行以下步骤:
这组步骤被分成两部分,以便在文档卸载之前处理同步导航。状态保存在changingNavigableContinuations中,用于第二部分。
令displayedEntry为navigable的活动会话历史条目。
令targetEntry为navigable的当前会话历史条目。
令changingNavigableContinuation为一个更改可导航延续状态,包含以下内容:
如果displayedEntry为targetEntry,并且targetEntry的文档状态的重载挂起为false,则
根据navigationType进行切换
如果 targetEntry 的 文档 为 null,或 targetEntry 的 文档状态 的 重载挂起 为 true,则
令 navTimingType 为 "back_forward
" 如果 targetEntry 的 文档 为 null;否则为 "reload
"。
令 targetSnapshotParams 为 快照目标快照参数 给定 navigable 的结果。
令 potentiallyTargetSpecificSourceSnapshotParams 为 sourceSnapshotParams。
如果 potentiallyTargetSpecificSourceSnapshotParams 为 null,则将其设置为 快照源快照参数 给定 navigable 的 活动文档 的结果。
在这种情况下,没有明确的遍历/重载来源。我们将这种情况视为 navigable 自行导航,但要注意,targetEntry 的原始发起者的某些属性会保留在 targetEntry 的 文档状态 中,例如 发起者源 和 引用来源,这将适当地影响导航。
并行,尝试填充历史记录条目的文档 对于 targetEntry,给定 navigable,potentiallyTargetSpecificSourceSnapshotParams,targetSnapshotParams,其中 allowPOST 设置为 allowPOST 且 completionSteps 设置为 在全局任务源上排队 给定 navigable 的 活动窗口 以运行 afterDocumentPopulated。
否则,立即运行 afterDocumentPopulated。
在这两种情况下,令 afterDocumentPopulated 为以下步骤
如果 targetEntry 的 文档 为 null,则将 changingNavigableContinuation 的 仅更新 设置为 true。
这意味着我们尝试填充文档,但无法做到,例如,由于服务器返回了 204。
这些类型的失败导航或遍历不会被发送到 导航 API(例如,通过任何 导航 API 方法跟踪器 的承诺,或 navigateerror
事件)。这样做会泄露有关来自其他源的响应时间的敏感信息,在跨源情况下,在跨源与同源情况下提供不同的结果被认为过于混乱。
但是,实现可以使用此机会来清除 navigation.transition.finished
承诺的任何承诺处理程序,因为它们保证此时永远不会运行。而且,他们可能希望 向控制台报告警告,如果导航 API 的任何部分启动了这些导航,以使 Web 开发人员清楚地了解为什么他们的承诺永远不会解决,并且事件永远不会触发。
如果 targetEntry 的 文档 的 源 不等于 oldOrigin,则将 targetEntry 的 经典历史 API 状态 设置为 StructuredSerializeForStorage(null)。
这会在源发生更改时清除历史记录状态,而不会发生重定向,而之前会加载 targetEntry。这可能是由于 CSP 沙箱标题的更改造成的。
如果以下条件全部为真
navigable 的 父级 为 null;
将 changingNavigableContinuation 排队 到 changingNavigableContinuations 上。
此作业的其余部分 稍后运行 在此算法中。
令 navigablesThatMustWaitBeforeHandlingSyncNavigation 为一个空的 集合。
当 completedChangeJobs 不等于 totalChangeJobs 时
如果 traversable 的 正在运行嵌套应用历史记录步骤 为 false,则
令 changingNavigableContinuation 为 从 changingNavigableContinuations 出队 的结果。
如果 changingNavigableContinuation 为空,则 继续。
令 displayedDocument 为 changingNavigableContinuation 的 显示文档。
令 targetEntry 为 changingNavigableContinuation 的 目标条目。
令 navigable 为 changingNavigableContinuation 的 可导航。
令 (scriptHistoryLength,scriptHistoryIndex) 为 获取历史记录对象长度和索引 给定 traversable 和 targetStep 的结果。
这些值可能已在上次计算后发生更改。
追加 navigable 到 navigablesThatMustWaitBeforeHandlingSyncNavigation。
一旦可导航已到达遍历中的此位置,额外排队的同步导航步骤很可能旨在在此遍历之后而不是之前发生,因此它们不再跳过队列。 此处可以找到更多详细信息。
令 entriesForNavigationAPI 为 获取导航 API 的会话历史条目 给定 navigable 和 targetStep 的结果。
如果 changingNavigableContinuation 的 仅更新 为 true,或 targetEntry 的 文档 为 displayedDocument,那么
这是一个同文档导航:我们无需卸载。
否则
在这两种情况下,令 afterPotentialUnloads 为以下步骤
如果 changingNavigableContinuation 的 仅更新 为 false,那么 激活历史条目 targetEntry 为 navigable。
令 updateDocument 为一个算法步骤,它执行 更新文档以应用历史步骤 给定 targetEntry 的 文档,targetEntry,changingNavigableContinuation 的 仅更新,scriptHistoryLength,scriptHistoryIndex,navigationType,entriesForNavigationAPI 和 displayedEntry。
如果 targetEntry 的 文档 等于 displayedDocument,那么执行 updateDocument。
否则,在全局任务队列中 在 导航和遍历任务源 给定 targetEntry 的 文档 的 相关全局对象 上执行 updateDocument。
递增 completedChangeJobs。
令 totalNonchangingJobs 为 nonchangingNavigablesThatStillNeedUpdates 的 大小。
从这一步开始,故意等待所有先前的操作完成,因为它们包括 处理同步导航,这也会发布任务来更新历史长度和索引。
令 completedNonchangingJobs 为 0。
令 (scriptHistoryLength,scriptHistoryIndex) 为 获取历史对象长度和索引 给定 traversable 和 targetStep 的结果。
对于 nonchangingNavigablesThatStillNeedUpdates 的每个 navigable,在全局任务队列中 在 导航和遍历任务源 给定 navigable 的 活动窗口 上运行以下步骤
等待 completedNonchangingJobs 等于 totalNonchangingJobs。
设置 traversable 的 当前会话历史步骤 为 targetStep。
返回 "applied
"。
要 停用跨文档导航的文档 给定一个 文档
displayedDocument,一个 用户导航参与 userNavigationInvolvement,一个 会话历史条目 targetEntry,一个 NavigationType
navigationType 和 afterPotentialUnloads,这是一个接收无参数的算法
令 navigable 为 displayedDocument 的 节点可导航。
令 potentiallyTriggerViewTransition 为 false。
令 isBrowserUINavigation 为 true,如果 userNavigationInvolvement 为 "浏览器 UI
";否则为 false。
设置 potentiallyTriggerViewTransition 为调用 导航是否可以触发跨文档视图转换? 给定 displayedDocument,targetEntry 的 文档,navigationType 和 isBrowserUINavigation 的结果。
如果 potentiallyTriggerViewTransition 为 false,那么
令 firePageSwapBeforeUnload 为以下步骤
触发 pageswap
事件 给定 displayedDocument,targetEntry,navigationType 和 null。
设置正在进行的导航 为 navigable 到 null。
这允许 navigable 的新的 导航 开始,而在遍历期间它们被阻止了。
卸载文档及其后代 给定 displayedDocument,targetEntry 的 文档,afterPotentialUnloads 和 firePageSwapBeforeUnload。
否则,在全局任务队列中 在 导航和遍历任务源 给定 navigable 的 活动窗口 上运行以下步骤
令 proceedWithNavigationAfterViewTransitionCapture 为以下步骤
令 viewTransition 为 设置跨文档视图转换 给定 displayedDocument,targetEntry 的 文档,navigationType 和 proceedWithNavigationAfterViewTransitionCapture 的结果。
触发 pageswap
事件 给定 displayedDocument,targetEntry,navigationType 和 viewTransition。
如果 viewTransition 为 null,那么运行 proceedWithNavigationAfterViewTransitionCapture。
在视图转换开始的情况下,视图转换算法负责调用 proceedWithNavigationAfterViewTransitionCapture。
要 触发 pageswap
事件 给定一个 文档
displayedDocument,一个 会话历史条目 targetEntry,一个 NavigationType
navigationType 和一个 ViewTransition
或 null viewTransition
令 activation 为 null。
如果以下条件全部为真
则
令 destinationEntry 通过切换 navigationType 来确定
设置 activation 为在 displayedDocument 的 相关领域 中创建的 新的 NavigationActivation
,具有
这意味着,在导航期间跨域重定向会导致旧文档的activation
为空,除非新文档是从bfcache恢复的。
在displayedDocument的相关全局对象上触发一个名为pageswap
的事件,使用PageSwapEvent
,将其activation
设置为activation,并将viewTransition
设置为viewTransition。
要为可导航navigable 激活历史条目会话历史条目entry
让newDocument成为entry的文档。
断言:newDocument的初始about:blank
为假,即,我们永远不会遍历回初始about:blank
文档
,因为它在我们离开它时总是会被替换。
将navigable的活动会话历史条目设置为entry。
激活newDocument。
要获取使用的步骤,给定一个可遍历的可导航traversable和一个非负整数step,执行以下步骤。它们返回一个非负整数。
让steps成为获取traversable中所有已使用的历史步骤的结果。
返回steps中小于或等于step的项目的最大值。
要获取历史对象长度和索引,给定一个可遍历的可导航traversable和一个非负整数step,执行以下步骤。它们返回两个非负整数的元组。
让steps成为获取traversable中所有已使用的历史步骤的结果。
让scriptHistoryLength成为steps的大小。
假设step已通过获取使用的步骤进行了调整。
让scriptHistoryIndex成为steps中step的索引。
返回(scriptHistoryLength,scriptHistoryIndex)。
要获取当前会话历史条目将更改或重新加载的所有可导航,给定一个可遍历的可导航traversable和一个非负整数targetStep,执行以下步骤。它们返回一个可导航的列表。
让results成为一个空的列表。
让navigablesToCheck成为« traversable »。
此列表在下面的循环中扩展。
对于navigablesToCheck中的每个navigable
让targetEntry成为获取给定navigable和targetStep的目标历史条目的结果。
如果targetEntry不是navigable的当前会话历史条目或targetEntry的文档状态的重新加载挂起为真,那么追加navigable到results。
如果targetEntry的文档是navigable的文档,并且targetEntry的文档状态的重新加载挂起为假,那么扩展navigablesToCheck,包括navigable的子可导航。
将子可导航添加到navigablesToCheck意味着这些可导航也将由此循环检查。只有在navigable的活动文档不会作为此遍历的一部分更改时,才会检查子可导航。
返回results。
要获取只需要历史对象长度/索引更新的所有可导航,给定一个可遍历的可导航traversable和一个非负整数targetStep,执行以下步骤。它们返回一个可导航的列表。
其他可导航可能不会受到遍历的影响。例如,如果响应是 204,当前活动的文档将保持不变。此外,在 204 之后“后退”将更改当前会话历史条目,但活动会话历史条目已经正确。
让results成为一个空的列表。
让navigablesToCheck成为« traversable »。
此列表在下面的循环中扩展。
对于navigablesToCheck中的每个navigable
返回results。
要获取目标历史条目,给定一个可导航navigable和一个非负整数step,执行以下步骤。它们返回一个会话历史条目。
让entries成为获取navigable的会话历史条目的结果。
要了解为什么获取目标历史条目返回具有小于或等于输入步骤的最大步骤的条目,请考虑以下Jake 图
0 | 1 | 2 | 3 | |
---|---|---|---|---|
顶部 | /t | /t#foo | ||
frames[0] | /i-0-a | /i-0-b |
对于输入步骤 1,top
可导航的目标历史条目是/t
条目,其步骤为 0,而frames[0]
可导航的目标历史条目是/i-0-b
条目,其步骤为 1
0 | 1 | 2 | 3 | |
---|---|---|---|---|
顶部 | /t | /t#foo | ||
frames[0] | /i-0-a | /i-0-b |
类似地,给定输入步骤 3,我们得到top
条目,其步骤为 3,以及frames[0]
条目,其步骤为 1
0 | 1 | 2 | 3 | |
---|---|---|---|---|
顶部 | /t | /t#foo | ||
frames[0] | /i-0-a | /i-0-b |
要获取可能经历跨文档遍历的所有可导航,给定一个可遍历的可导航traversable和一个非负整数targetStep,执行以下步骤。它们返回一个可导航的列表。
从traversable的会话历史遍历队列的角度来看,这些文档是targetStep所描述的遍历过程中进行跨文档遍历的候选者。如果它们目标文档的状态码是 HTTP 204 无内容,则它们不会经历跨文档遍历。
令 results 为一个空的 列表。
让navigablesToCheck成为« traversable »。
此列表在下面的循环中扩展。
对于每个 navigablesToCheck 中的 navigable
令 targetEntry 为给定 navigable 和 targetStep 的 获取目标历史条目 的结果。
如果 targetEntry 的 文档 不是 navigable 的 文档 或者 targetEntry 的 文档状态 的 重载待定 为真,则将 navigable 追加 到 results 中。
虽然 navigable 的 活动历史条目 可以同步改变,新的条目将始终具有相同的 文档
,因此访问 navigable 的 文档 是可靠的。
否则,将 navigable 的 子导航 扩展 到 navigablesToCheck 中。
将 子导航 添加到 navigablesToCheck 中意味着这些导航也将由此循环检查。仅当 navigable 的 活动文档 不会在此遍历过程中改变时才会检查 子导航。
返回results。
为了 更新用于历史步骤应用的文档,给定一个 文档
document,一个 会话历史条目 entry,一个布尔值 doNotReactivate,整数 scriptHistoryLength 和 scriptHistoryIndex,NavigationType
-或-null navigationType,一个可选的 列表,其中包含 会话历史条目 entriesForNavigationAPI,以及一个可选的 会话历史条目 previousEntryForActivation
如果 document 的 最新条目 为 null,则令 documentIsNew 为真;否则为假。
如果 document 的 最新条目 不是 entry,则令 documentsEntryChanged 为真;否则为假。
如果 documentsEntryChanged 为真,则
将 document 的 最新条目 设置为 entry。
给定 document 和 entry,恢复历史对象状态。
如果 documentIsNew 为假,则
断言: navigationType 不为 null。
给定 navigation,entry 和 navigationType,更新用于相同文档导航的导航 API 条目。
在 document 的 相关全局对象 上 触发一个名为 popstate
的事件,使用 PopStateEvent
,其中 state
属性初始化为 document 的 历史对象 的 state,并且 hasUAVisualTransition
初始化为真,如果用户代理执行了一个可视化转换,以显示 最新条目 的已缓存渲染状态。
给定 entry,恢复持久化状态。
如果 oldURL 的 片段 不等于 entry 的 URL 的 片段,则在 document 的 相关全局对象 上,在 DOM 操作任务源 上 排队一个全局任务,以便 触发一个名为 hashchange
的事件,使用 HashChangeEvent
,其中 oldURL
属性初始化为 oldURL 的 序列化,并且 newURL
属性初始化为 entry 的 URL 的 序列化。
否则
断言: entriesForNavigationAPI 已给出。
给定 entry,恢复持久化状态。
给定 navigation,entriesForNavigationAPI 和 entry,初始化用于新文档的导航 API 条目。
如果以下所有条件都为真
previousEntryForActivation 已给出;
navigationType 不为 null;并且
navigationType 为 "reload
" 或者 previousEntryForActivation 的 文档 不是 document,
则
如果 navigation 的 激活 为 null,则将 navigation 的 激活 设置为 navigation 的 相关领域 中的一个新的 NavigationActivation
对象。
令 previousEntryIndex 为在 navigation 中 获取导航 API 条目索引 的 previousEntryForActivation 的结果。
如果 previousEntryIndex 非负,则将 activation 的 旧条目 设置为 navigation 的 条目列表[previousEntryIndex]。
否则,如果以下所有条件都为真
navigationType 为 "replace
";
previousEntryForActivation 的 文档 的 初始 about:blank
为假,
则将 activation 的 旧条目 设置为 navigation 的 相关领域 中的一个新的 NavigationHistoryEntry
,其 会话历史条目 为 previousEntryForActivation。
将 activation 的 导航类型 设置为 navigationType。
如果 documentIsNew 为真,则
针对 document,尝试滚动到片段。
此时,脚本可能会针对新创建的文档 document 运行。
否则,如果 documentsEntryChanged 为假并且 doNotReactivate 为假,则
documentsEntryChanged 可能由于两种原因而为假:要么我们正在从 bfcache 中恢复,要么我们正在异步完成一个同步导航,该导航已同步设置了 document 的 最新条目。参数 doNotReactivate 区分了这两种情况。
为了 恢复历史对象状态,给定一个 文档
document 和一个 会话历史条目 entry
令 targetRealm 为 document 的 相关领域。
令 state 为 StructuredDeserialize(entry 的 经典历史 API 状态,targetRealm)。如果这引发了异常,则捕获它并令 state 为 null。
为了 激活 一个 文档
document
令 window 为 document 的 相关全局对象。
将 document 的 浏览上下文 的 WindowProxy
的 [[Window]] 内部槽值设置为 window。
排队一个新的VisibilityStateEntry
,其可见性状态为document的可见性状态,其时间戳为零。
为了重新激活一个Document
document,给定一个会话历史记录条目reactivatedEntry和一个列表的会话历史记录条目entriesForNavigationAPI
此算法在document从bfcache中退出后更新document,即在document再次变为完全激活后。鼓励希望监视对完全激活状态更改的其他规范将步骤添加到此算法中,以便更改导致的事件顺序清晰。
对于document中具有自动填充字段名称为“off
”的每个formControl,调用formControl的重置算法。
如果document的挂起的计时器句柄不为空
更新重新激活的导航 API 条目,给定document的相关全局对象的导航 API、entriesForNavigationAPI和reactivatedEntry。
为了尝试滚动到片段,给定一个Document
document,执行以下步骤并行
等待实现定义的时间量。(目的是允许用户代理在性能问题的情况下优化用户体验。)
为了使文档不可恢复,给定一个Document
document和一个字符串reason
将details追加到document的bfcache 阻止详细信息。
将document的可恢复状态设置为假。
为了为文档状态构建未恢复原因,给定Document
document
让notRestoredReasonsForDocument为一个新的未恢复原因。
将notRestoredReasonsForDocument的reasons设置为document的bfcache 阻止详细信息的克隆。
对于document的文档树子级可导航中的每个navigable
让childDocument为navigable的活动文档。
为文档状态构建未恢复原因,给定childDocument。
将childDocument的未恢复原因追加到notRestoredReasonsForDocument的children。
将document的节点可导航的活动会话历史记录条目的文档状态的未恢复原因设置为notRestoredReasonsForDocument。
为了为顶级可遍历及其后代构建未恢复原因,给定顶级可遍历topLevelTraversable
为文档状态构建未恢复原因,给定topLevelTraversable的活动文档。
让crossOriginDescendants为一个空的列表。
让crossOriginDescendantsPreventsBfcache为假。
对于crossOriginDescendants中的每个crossOriginNavigable
如果 crossOriginDescendantsPreventsBfcache 为 true,则 使文档无法恢复,给定 topLevelTraversable 的 活动文档 和 "遮罩
"。
一个 文档
具有一个布尔值 已被显示,初始值为 false。它用于确保 pagereveal
事件为每个 文档
的激活触发一次(在首次渲染时触发一次,以及在每个 重新激活 时触发一次)。
要 显示 一个 文档
document
如果 document 的 已被显示 为 true,则返回。
将 document 的 已被显示 设置为 true。
令 transition 为 解析入站跨文档视图转换 的结果,针对 document。
触发一个事件,名为 pagereveal
,在 document 的 相关全局对象 上,使用 PageRevealEvent
,其 viewTransition
设置为 transition。
如果 transition 不为空,则
准备运行脚本,给定 document。
激活 transition。
清理运行脚本后的操作,给定 document。
激活视图转换可能会解析/拒绝承诺,因此通过用准备/清理包裹激活,我们确保这些承诺在下一个渲染步骤之前得到处理。
虽然 pagereveal
гарантированно будет вызываться во время первого шага обновления рендеринга, который отображает обновленную версию страницы, пользовательские агенты могут свободно отображать кэшированный кадр страницы, прежде чем вызывать его. Это предотвращает задержку представления такого кэшированного кадра из-за наличия обработчика pagereveal
.
要 滚动到片段,给定一个 文档
document
否则,如果 document 的 指示部分 为 文档顶部,则
将 document 的 目标元素 设置为 null。
滚动到文档开头,针对 document。 [CSSOMVIEW]
返回。
否则
令 target 为 document 的 指示部分。
将 document 的 目标元素 设置为 target。
运行 祖先详细信息显示算法,针对 target。
运行
,针对 target。滚动 target 到视图中,其中 behavior 设置为 "auto",block 设置为 "start",inline 设置为 "nearest"。 [CSSOMVIEW]
将 顺序焦点导航起点 移动到 target。
一个 文档
的 指示部分 是其 URL 的 片段 所标识的部分,或者如果片段未标识任何内容,则为 null。片段在映射到节点方面的语义由定义 文档
使用的 MIME 类型 的规范定义(例如,处理 片段 针对 XML MIME 类型 是 RFC7303 的职责)。 [RFC7303]
每个 文档
还具有一个 目标元素,它用于定义 :target
伪类,并通过上述算法更新。它最初为 null。
对于一个 HTML 文档 document,其 指示部分 是 选择指示部分 的结果,给定 document 和 document 的 URL。
要 选择指示部分,给定一个 文档
document 和一个 URL url
令 fragment 为 url 的 片段。
如果 fragment 为空字符串,则返回特殊值 文档顶部。
令 potentialIndicatedElement 为 查找潜在的指示元素 的结果,给定 document 和 fragment。
如果 potentialIndicatedElement 不为空,则返回 potentialIndicatedElement。
令 fragmentBytes 为 百分比解码 fragment 的结果。
令 decodedFragment 为在 fragmentBytes 上运行 UTF-8 解码(无 BOM) 的结果。
将 potentialIndicatedElement 设置为 查找潜在的指示元素 的结果,给定 document 和 decodedFragment。
如果 potentialIndicatedElement 不为空,则返回 potentialIndicatedElement。
如果 decodedFragment 与字符串 top
ASCII 不区分大小写 匹配,则返回 文档顶部。
返回 null。
要 查找潜在的指示元素,给定一个 文档
document 和一个字符串 fragment,运行以下步骤
如果在文档树中存在一个元素,其 根节点 为 document,且其 ID 等于 fragment,则返回在 树序 中的第一个此类元素。
如果在文档树中存在一个 a
元素,其 根节点 为 document,且其具有一个 name
属性,其值为 fragment,则返回在 树序 中的第一个此类元素。
返回 null。
要 保存持久状态 到一个 会话历史条目 entry
可选地,更新 entry 的 持久用户状态,以反映用户代理希望持久化的任何状态,例如表单字段的值。
要 恢复持久状态 从一个 会话历史条目 entry
如果 entry 的 滚动恢复模式 为 "auto
",并且 entry 的 文档 的 相关全局对象 的 导航 API 的 在正在进行的导航期间抑制正常滚动恢复 为 false,则 恢复滚动位置数据,给定 entry。
用户代理不恢复滚动位置并不意味着滚动位置将保留在任何特定值(例如(0,0))。实际滚动位置取决于导航类型和用户代理的特定缓存策略。因此,Web 应用程序不能假设任何特定的滚动位置,而是被敦促将其设置为他们想要的值。
如果 在进行中的导航期间抑制正常滚动恢复 为 true,则 恢复滚动位置数据 可能会在稍后某个时间点作为 完成 相关 NavigateEvent
的一部分,或者通过 navigateEvent.scroll()
方法调用发生。
可选地,更新 entry 的其他方面 document 及其渲染,例如表单字段的值,用户代理之前已记录在 entry 的 持久用户状态 中。
这甚至可以包括更新 dir
属性的 textarea
元素或 input
元素,其 type
属性处于 文本、搜索、电话、URL 或 电子邮件 状态,如果持久状态包含此类控件中用户输入的方向性。
作为此过程的一部分恢复表单控件的值不会触发任何 input
或 change
事件,但可以触发 与表单关联的自定义元素 的 formStateRestoreCallback
。
每个 Document
都有一个布尔值 用户滚动过,最初为 false。如果用户滚动文档,用户代理必须将其文档的 用户滚动过 设置为 true。
Document
document 的 可恢复滚动区域 是 document 的 视窗,以及所有 document 的可滚动区域,除了任何 可导航容器。
子可导航 滚动恢复作为这些 可导航 的 Document
的 会话历史条目 的状态恢复的一部分处理。
要 恢复滚动位置数据,给定 会话历史条目 entry