面向 Web 开发人员版本 - 最后更新于 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
例如,一些用户代理可能希望持久化表单控件的值。
持久化表单控件值的那些用户代理鼓励同时持久化其方向性(元素的 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
的 来源 设置为此值的来源。我们将其存储在这里,因为它在遍历期间恢复这些 Document
时也会使用,因为它们是在本地重建的,没有访问网络。它还用于比较 会话历史条目 被 重新填充 之前和之后的来源。如果来源发生变化,则 可导航目标名称 将被清除。
一个 关于基准 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
可以随时间代表多个 会话历史条目,因为许多连续的 会话历史条目 可以共享相同的 文档状态,如上所述。
为了维护单个真相来源,对 可遍历可导航对象 的 会话历史条目 的所有修改都需要同步。由于会话历史受所有后代 可导航对象 的影响,因此受多个 事件循环 的影响,因此这一点尤其重要。为了实现这一点,我们使用了 会话历史遍历并行队列 结构。
一个 会话历史遍历并行队列 与 并行队列 非常相似。它有一个 算法集,一个 有序集。
一个会话历史遍历并行队列的算法集中的项目要么是算法步骤,要么是同步导航步骤,同步导航步骤是涉及目标可导航(一个可导航)的特定算法步骤。
要将会话历史遍历步骤附加到给定算法步骤steps的可遍历可导航traversable(一个可遍历可导航),将steps附加到traversable的会话历史遍历队列的算法集。
要将涉及可导航targetNavigable(一个可导航)的会话历史同步导航步骤附加到可遍历可导航traversable(一个可遍历可导航),将steps作为针对目标可导航targetNavigable的同步导航步骤附加到traversable的会话历史遍历队列的算法集。
要启动新的会话历史遍历并行队列
令sessionHistoryTraversalQueue为新的会话历史遍历并行队列。
并行运行以下步骤
返回sessionHistoryTraversalQueue。
本节包含我们在整个标准中操作会话历史时执行的各种杂项操作。了解它们功能的最佳方法是查看它们的调用位置。
要 获取会话历史条目 的一个 可导航 navigable
令 traversable 为 navigable 的 可遍历可导航。
如果 navigable 是 traversable,则返回 traversable 的 会话历史条目。
对于 traversable 的每个 会话历史条目 的 entry,追加 entry 的 文档状态 到 docStates。
对于每个 docState 的 docStates
断言:未达到此步骤。
要 为导航 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
要 获取所有已使用历史步骤,它们是 可遍历可导航 traversable 的一部分
例如,跟随超链接、表单提交 以及 window.open()
和 location.assign()
方法都可能导致导航。
在我们能够深入 导航算法 本身之前,我们需要建立它使用的几个重要结构。
源快照参数 结构 用于捕获启动导航的 Document
的数据。它在导航开始时进行快照,并在整个导航的生命周期中使用。它具有以下 项目
要快照源快照参数,给定一个Document
sourceDocument,返回一个新的源快照参数,其中
The 目标快照参数 结构用于捕获从要导航的可导航对象中获取的数据。与源快照参数类似,它在导航开始时进行快照,并在整个导航生命周期内使用。它具有以下项
要快照目标快照参数,给定一个可导航对象 targetNavigable,返回一个新的目标快照参数,其中沙箱标志设置为确定创建沙箱标志的结果,给定targetNavigable的活动浏览上下文和targetNavigable的容器。
导航过程的很大一部分都与确定如何创建一个新的Document
有关,这最终在创建和初始化Document
对象算法中发生。该算法的参数通过一个导航参数 结构进行跟踪,该结构具有以下项
Document
的算法,一旦它被创建Document
保留Document
Document
Document
实施Document
NavigationTimingType
,用于创建新的Document
的导航计时条目Document
的关于基本 URL一旦创建了导航参数结构,本标准不会改变其任何项。它们只传递到其他算法。
一个导航 ID是在导航过程中生成的 UUID 字符串。它用于与WebDriver BiDi规范进行交互,以及跟踪正在进行的导航。[WEBDRIVERBIDI]
在Document
创建之后,相关的可遍历的可导航对象的会话历史记录会得到更新。NavigationHistoryBehavior
枚举用于指示对导航算法所需的会话历史记录更新类型。它以下列之一
push
"replace
"auto
"push
" 或 "replace
"。通常它会变成"push
",但在某些情况下它会变成"replace
"。一个历史处理行为是一个NavigationHistoryBehavior
,它既是"push
",又是"replace
",即,它已经从任何初始的"auto
"值中解析出来。
导航必须是替换,给定一个URL url 和一个Document
document,如果以下任何一项为真
url的方案是"javascript
";或
document的是初始about:blank
为真。
平台的各个部分跟踪用户是否参与导航。一个用户导航参与是以下之一
browser UI
"activation
"none
"为了在某些调用站点方便起见,用户导航参与,对于一个Event
event,定义如下
要导航一个可导航对象 navigable 到一个URL url,使用一个Document
sourceDocument,并使用可选的POST 资源、字符串或 null documentResource(默认值为 null)、可选的响应或 null response(默认值为 null)、可选的布尔值exceptionsEnabled(默认值为 false)、可选的NavigationHistoryBehavior
historyHandling(默认值为"auto
")、可选的序列化状态或 null navigationAPIState(默认值为 null)、可选的条目列表或 null formDataEntryList(默认值为 null)、可选的推荐人策略 referrerPolicy(默认为空字符串)以及可选的用户导航参与 userInvolvement(默认值为"none
")
如果 formDataEntryList 不为空,则将 cspNavigationType 设置为 "form-submission
";否则设置为 "other
"。
将 sourceSnapshotParams 设置为 快照源快照参数 的结果,该结果基于 sourceDocument。
将 initiatorOriginSnapshot 设置为 sourceDocument 的 来源。
将 initiatorBaseURLSnapshot 设置为 sourceDocument 的 文档基准 URL。
如果 sourceDocument 的 节点可导航 在给定 sourceSnapshotParams 的情况下,不被沙盒允许导航 navigable,则
如果 exceptionsEnabled 为 true,则抛出一个 "SecurityError
" 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 设置为 "replace
"。
如果 navigable 的 父级 不为空,则将 navigable 的 是否延迟 load
事件 设置为 true。
将 targetBrowsingContext 设置为 navigable 的 活动浏览上下文。
将 targetSnapshotParams 设置为 快照目标快照参数 的结果,该结果基于 navigable。
调用 WebDriver BiDi 导航已开始,使用 targetBrowsingContext 和一个新的 WebDriver BiDi 导航状态,其 ID 为 navigationId,状态 为 "待定
",URL 为 url。
如果 navigable 的 正在进行的导航 为 "traversal
",则
调用 WebDriver BiDi 导航失败,使用 targetBrowsingContext 和一个新的 WebDriver BiDi 导航状态,其 ID 为 navigationId,状态 为 "已取消
",URL 为 url。
返回。
设置正在进行的导航,针对 navigable,设置为 navigationId。
这将导致 navigable 的其他正在进行的导航中止,因为在导航的某些点,对 正在进行的导航 的更改会导致进一步的工作被放弃。
如果 url 的 方案 为 "javascript
",则
排队一个全局任务,在 导航和遍历任务源 上,针对 navigable 的 活动窗口,导航到 javascript:
URL,在给定 navigable、url、historyHandling、initiatorOriginSnapshot 和 cspNavigationType 的情况下。
返回。
如果以下所有条件都为真
userInvolvement 不为 "浏览器 UI
";
navigable 的 活动文档 的 是否为初始 about:blank
为 false;并且
则
将 navigation 设置为 navigable 的 活动窗口 的 导航 API。
如果 documentResource 是 POST 资源,则将 entryListForFiring 设置为 formDataEntryList;否则设置为 null。
如果 navigationAPIState 不为空,则将 navigationAPIStateForFiring 设置为 navigationAPIState;否则设置为 StructuredSerializeForStorage(undefined)。
将 continue 设置为 在 navigation 上触发 push/replace/reload navigate
事件 的结果,其中 navigationType 设置为 historyHandling,isSameDocument 设置为 false,userInvolvement 设置为 userInvolvement,formDataEntryList 设置为 entryListForFiring,destinationURL 设置为 url,navigationAPIState 设置为 navigationAPIStateForFiring。
如果 continue 为 false,则返回。
如果导航的 userInvolvement 为 "浏览器 UI
",或由 跨源域 sourceDocument 发起,则有可能触发 navigate
事件,如果它们经过了之前的 导航到片段 路径。
并行 执行以下步骤
将 unloadPromptCanceled 设置为 检查是否取消卸载 的结果,该结果针对 navigable 的 活动文档 的 包含的子级可导航。
如果 unloadPromptCanceled 为 true,或者 navigable 的 正在进行的导航 不再是 navigationId,则
使用 targetBrowsingContext 调用 WebDriver BiDi 导航失败,以及一个新的 WebDriver BiDi 导航状态,其 id 为 navigationId,状态 为 "已取消
",URL 为 url。
中止这些步骤。
在给定 navigable 的 活动窗口 上,在 导航和遍历任务源 上 排队一个全局任务,以 中止一个文档及其后代,给定 navigable 的 活动文档。
如果 url 匹配 about:blank
或为 about:srcdoc
,则
令 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,其中 allowPOST 设置为 true,完成步骤 设置为以下步骤
将 追加会话历史遍历步骤 追加到 navigable 的 可遍历对象,以 完成跨文档导航,给定 navigable、historyHandling 和 historyEntry。
虽然通常的跨文档导航情况会首先尝试使用 Document
填充会话历史条目,但所有未被中止的导航最终都会调用以下算法之一。
要 完成跨文档导航,给定一个 可导航对象 navigable、历史处理行为 historyHandling 和 会话历史条目 historyEntry
将 navigable 的 是否延迟 load
事件 设置为 false。
如果 historyEntry 的 文档 为 null,则返回。
这意味着 尝试填充历史条目的文档 最终没有创建文档,例如,导航被后续导航取消、出现 204 无内容响应等。
如果以下所有条件都为真
navigable 的 父级 为 null;
如果 historyHandling 为 "替换
",则令 entryToReplace 为 navigable 的 活动会话历史条目,否则为 null。
令 traversable 为 navigable 的 可遍历导航对象。
令 targetStep 为 null。
令 targetEntries 为对 navigable 获取会话历史条目 的结果。
如果 entryToReplace 为 null,则
对 traversable 清除前向会话历史。
将 targetStep 设置为 traversable 的 当前会话历史步骤 + 1。
将 historyEntry 的 步骤 设置为 targetStep。
将 historyEntry 追加 到 targetEntries。
否则
对 traversable 应用推送/替换历史步骤 targetStep,给定 historyHandling。
javascript:
URL 特殊情况
URL 在问题跟踪器上拥有一个 专用标签,用于记录其规范中出现的各种问题。javascript:
要 导航到 javascript:
URL,给定一个 可导航对象 targetNavigable、一个 URL url、一个 历史处理行为 historyHandling、一个 来源 initiatorOrigin 和一个字符串 cspNavigationType
设置正在进行的导航,使 targetNavigable 的值为 null。
令 request 为一个新的 请求,其 URL 为 url。
这是一个为下一步处理而创建的合成 请求。它永远不会命中网络。
如果 内容安全策略是否应阻止类型为的导航请求? 给定 request 和 cspNavigationType 为 "Blocked
",则返回。 [CSP]
令 newDocument 为给定 targetNavigable、url 和 initiatorOrigin 评估 javascript:
URL 的结果。
如果 newDocument 为 null,则返回。
在这种情况下,一些 JavaScript 代码已执行,但没有创建新的 Document
,因此我们将不执行导航。
令 entryToReplace 为 targetNavigable 的 活动会话历史记录条目。
令 oldDocState 为 entryToReplace 的 文档状态。
令 documentState 为一个新的 文档状态,其中包含
令 historyEntry 为一个新的 会话历史记录条目,其中包含
对于 URL,我们不使用 url,即 navigate 算法调用的实际 javascript:
URL。这意味着 javascript:
URL 永远不会存储在会话历史记录中,因此永远无法导航到它们。
追加会话历史记录遍历步骤 到 targetNavigable 的 可遍历,以 完成跨文档导航,其中 targetNavigable、historyHandling 和 historyEntry。
给定 可导航 targetNavigable、URL url 和 来源 newDocumentOrigin 评估 javascript:
URL
令 urlString 为对 url 运行 URL 序列化器 的结果。
令 encodedScriptSource 为从 urlString 中删除前导 "javascript:
" 的结果。
令 settings 为 targetNavigable 的 活动文档 的 相关设置对象。
令 baseURL 为 settings 的 API 基地址。
令 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 导航到片段
令 navigation 为 navigable 的 活动窗口 的 导航 API。
令 destinationNavigationAPIState 为 navigable 的 活动会话历史记录条目 的 导航 API 状态。
如果 navigationAPIState 非空,则将 destinationNavigationAPIState 设置为 navigationAPIState。
令 continue 为在 navigation 上 触发 push/replace/reload navigate
事件 的结果,其中 navigationType 设置为 historyHandling,isSameDocument 设置为 true,userInvolvement 设置为 userInvolvement,destinationURL 设置为 url,navigationAPIState 设置为 destinationNavigationAPIState。
如果 continue 为 false,则返回。
令 historyEntry 为一个新的 会话历史记录条目,其中包含
对于使用 navigation.navigate()
执行的导航,由 state
选项提供的 value 用于新的 导航 API 状态。(如果该选项没有提供 value,则会将其设置为 undefined 的序列化。)对于其他片段导航,包括用户发起的导航,导航 API 状态 会从上一个条目中继承。
经典历史 API 状态 永远不会继承。
如果 historyHandling 为 "replace
",则令 entryToReplace 为 navigable 的 活动会话历史记录条目;否则为 null。
令 history 为 navigable 的 活动文档 的 历史记录对象。
令 scriptHistoryIndex 为 history 的 索引。
令 scriptHistoryLength 为 history 的 长度。
如果 historyHandling 为 "push
",则
将 history 的 状态 设置为 null。
将 scriptHistoryIndex 加 1。
将 scriptHistoryLength 设置为 scriptHistoryIndex + 1。
将 navigable 的 活动会话历史记录条目 设置为 historyEntry。
更新文档以应用历史记录步骤,其中 navigable 的 活动文档、historyEntry、true、scriptHistoryIndex、scriptHistoryLength 和 historyHandling。
单个片段导航将导致该算法被调用两次:一次同步调用,在此会设置最佳猜测值 scriptHistoryIndex 和 scriptHistoryLength,将 history.state
设为 null,并触发各种事件;一次异步调用,在此会设置索引和长度的最终值,history.state
保持不变,不会触发任何事件。
如果滚动失败,因为 Document
是新的,并且相关的 ID 尚未解析,那么对 更新文档以应用历史步骤 的第二次异步调用将负责滚动。
设 traversable 为 navigable 的 可遍历导航器。
将涉及 navigable 的以下 附加到会话历史同步导航步骤 到 traversable 中。
根据 traversable、navigable、historyEntry、entryToReplace 和 historyHandling,完成一次同文档导航。
使用 navigable 的 活动浏览上下文 和一个新的 WebDriver BiDi 导航状态,其 id 为 navigationId,url 为 url,以及 status 为 "complete
",来调用 WebDriver BiDi 片段导航。
根据一个 可遍历导航器 traversable,一个 导航器 targetNavigable,一个 会话历史条目 targetEntry,一个 会话历史条目 或 null entryToReplace,以及一个 历史处理行为 historyHandling,来 完成一次同文档导航。
这同时被 片段导航 和 URL 和历史更新步骤 使用,它们是会话历史的唯一同步更新。由于是同步的,这些算法是在 顶级可遍历器 的 会话历史遍历队列 之外执行的。这使它们与 顶级可遍历器 的 当前会话历史步骤 不同步,因此该算法用于解决由于竞争条件导致的冲突。
如果 targetNavigable 的 活动会话历史条目 不是 targetEntry,则返回。
令 targetStep 为 null。
设 targetEntries 为 获取会话历史条目 的结果,针对 targetNavigable。
如果 entryToReplace 为 null,则
清除 traversable 的前向会话历史。
将 targetStep 设置为 traversable 的 当前会话历史步骤 + 1。
将 targetEntry 的 步骤 设置为 targetStep。
将 targetEntry 追加 到 targetEntries 中。
否则
根据 historyHandling,将 应用推送/替换历史步骤 targetStep 到 traversable 中。
即使对于 "替换
" 导航,也执行此操作,因为它解决了跨多个同步导航的竞争条件。
尝试创建非提取方案文档 的输入是 非提取方案导航参数 结构。它是 导航参数 的轻量级版本,只包含与非 提取方案 导航情况相关的参数。它具有以下 项目
可能用于在用户界面提示中确认外部软件包调用的 来源
这与 文档状态 的 发起者来源 略有不同,因为 非提取方案导航参数 的 发起者来源 遵循重定向,直至重定向链中的最后一个 提取方案 URL,该链以非 提取方案 URL 结束。
Document
的导航计时条目 的 NavigationTimingType
如果 url 要使用不会影响 navigable 的机制进行处理,例如,因为 url 的 方案 是在外部处理的,那么
通过显示某种内联内容来处理 url,例如,因为指定的方案不是受支持的协议之一而显示的错误消息,或显示的内联提示,允许用户为给定方案选择 注册的处理程序。根据 navigable、navigationParams 的 id,以及 navigationParams 的 导航计时类型,返回 显示内联内容 的结果。
在使用注册的处理程序的情况下,将使用新的 URL 调用 导航。
根据 URL 或 响应 resource,导航器 navigable,沙箱标志集 sandboxFlags,布尔值 hasTransientActivation,以及 来源 initiatorOrigin,用户代理应该
如果以下所有条件都为真
navigable 不是 顶级可遍历器;
sandboxFlags 的 沙箱自定义协议导航浏览上下文标志 已设置;并且
sandboxFlags 的 沙箱顶级导航(具有用户激活)浏览上下文标志 已设置,或者 hasTransientActivation 为 false,
则返回,不调用外部软件包。
在 iframe 中导航到外部软件可能会被用户视为新弹出窗口或新的顶级导航。 这就是为什么只有在指定了 allow-popups
、allow-top-navigation
、allow-top-navigation-by-user-activation
或 allow-top-navigation-to-custom-protocols
之一的情况下,才允许在沙盒化 iframe
中进行导航。
在尝试降低此操作可能是试图利用目标软件的风险时,执行 resource 的适当移交。 例如,用户代理可能会提示用户确认是否允许 initiatorOrigin 调用有问题的外部软件。 特别是,如果 hasTransientActivation 为 false,那么用户代理不应在事先获得用户确认的情况下调用外部软件包。
例如,目标软件的 URL 处理程序中可能存在漏洞,敌对页面会试图通过欺骗用户点击链接来利用该漏洞。
导航过程的早期可能会有几种情况介入并使整个过程停止。 当多个 可导航对象 由于会话历史记录遍历而同时导航时,这尤其令人兴奋。
给定 源快照参数 sourceSnapshotParams,如果以下步骤返回 true,则 可导航对象 source 被 沙盒允许导航 到第二个 可导航对象 target。
如果 source 等于 target,则返回 true。
如果 source 是 target 的祖先,则返回 true。
如果 target 是 source 的祖先,则
如果 target 不是 顶级可遍历对象,则返回 true。
如果 sourceSnapshotParams 的 has transient activation 为 true,并且 sourceSnapshotParams 的 沙盒标志 的 带用户激活的沙盒顶级导航浏览上下文标志 已设置,则返回 false。
如果 sourceSnapshotParams 的 has transient activation 为 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
",则中止这些步骤。
设 navigation 为 traversable 的 活动窗口 的 导航 API。
设 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 为 在 document 的 相关全局对象 上触发名为 beforeunload
的事件 的结果,使用 BeforeUnloadEvent
,并将 cancelable
属性初始化为 true。
如果以下所有条件都为真
unloadPromptShown 为 false;
document 的 活动沙盒标志集 未设置其 沙盒模态标志;
document 的 相关全局对象 具有 粘性激活;
eventFiringResult 为 false,或 event 的 returnValue
属性不是空字符串;并且
显示卸载提示不太可能令人厌烦、具有欺骗性或毫无意义,
则
将 unloadPromptShown 设置为 true。
使用 document 的 相关全局对象、"beforeunload
" 和 "" 调用 WebDriver BiDi 用户提示已打开。
询问用户是否确认他们希望卸载文档,并在等待用户响应时 暂停。
显示给用户的消息不可自定义,而是由用户代理确定。 特别是,returnValue
属性的实际值被忽略。
如果用户未确认页面导航,则将 unloadPromptCanceled 设置为 true。
使用 document 的 相关全局对象 和 unloadPromptCanceled 为 false 时的 true 或 false 时的 false 调用 WebDriver BiDi 用户提示已关闭。
将 document 的 卸载计数器 减少 1。
返回 (unloadPromptShown、unloadPromptCanceled)。
要 设置可导航对象 的 可导航对象 navigable 为 newValue
如果 navigable 的 正在进行的导航 等于 newValue,则返回。
告知导航 API 关于中止导航,给定 navigable。
将 navigable 的 正在进行的导航 设置为 newValue。
要 重新加载 一个 可导航对象 navigable,给定一个可选的 序列化状态 或 null navigationAPIState(默认值为 null)和一个可选的 用户导航参与 userInvolvement(默认值为 "none
")
如果 userInvolvement 不是 "浏览器 UI
",则
将 navigation 设为 navigable 的 活动窗口 的 导航 API。
将 destinationNavigationAPIState 设为 navigable 的 活动会话历史记录条目 的 导航 API 状态。
如果 navigationAPIState 非空,则将 destinationNavigationAPIState 设置为 navigationAPIState。
将 continue 设为 在 navigation 上触发 push/replace/reload navigate
事件 的结果,其中 navigationType 设置为 "reload
",isSameDocument 设置为 false,userInvolvement 设置为 userInvolvement,destinationURL 设置为 navigable 的 活动会话历史记录条目 的 URL,以及 navigationAPIState 设置为 destinationNavigationAPIState。
如果 continue 为 false,则返回。
将 navigable 的 活动会话历史记录条目 的 文档状态 的 重新加载挂起 设置为 true。
将 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,但标准的各个其他部分也需要对 活动历史记录条目 进行更新,它们使用这些步骤来执行此操作。
给定一个 Document
document,一个 URL newURL,一个可选的 序列化状态 或 null serializedData(默认值为 null),以及一个可选的 历史记录处理行为 historyHandling(默认值为 "replace
"),URL 和历史记录更新步骤 为
将 navigable 设为 document 的 节点可导航对象。
将 activeEntry 设为 navigable 的 活动会话历史记录条目。
将 newEntry 设为一个新的 会话历史记录条目,其中包含
如果 document 的 is initial about:blank
为 true,则将 historyHandling 设置为 "replace
"。
这意味着对 初始 about:blank
Document
的 pushState()
调用行为类似于 replaceState()
调用。
将 entryToReplace 设为 activeEntry,如果 historyHandling 为 "replace
",否则为 null。
如果 historyHandling 为 "push
",则
递增 document 的 历史记录对象 的 index。
将 document 的 历史记录对象 的 length 设置为其 index + 1。
这些是用于立即同步访问的临时最佳猜测值。
如果 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(默认值为一个空算法)
断言:这正在并行运行。
令currentBrowsingContext为navigable的活动浏览上下文。
如果navigationParams为 null,则
如果documentResource为字符串,则将navigationParams设置为从 srcdoc 资源创建导航参数的结果,给定entry,navigable,targetSnapshotParams,navigationId和navTimingType。
否则,如果以下所有条件都为真
则将navigationParams设置为通过获取创建导航参数的结果,给定entry,navigable,sourceSnapshotParams,targetSnapshotParams,cspNavigationType,navigationId和navTimingType。
否则,如果entry的URL的方案不为获取方案,则将navigationParams设置为一个新的非获取方案导航参数,其中包含
要 从 srcdoc 资源创建导航参数,需要提供 会话历史记录条目 entry、可导航对象 navigable、目标快照参数 targetSnapshotParams、导航 ID(或 null)navigationId 以及 NavigationTimingType
navTimingType
令 response 为一个新的 响应,具有以下内容:
令 responseOrigin 为 确定来源 的结果,该结果基于 response 的 URL、targetSnapshotParams 的 沙箱标志 以及 entry 的 文档状态 的 来源。
令 coop 为一个新的 打开者策略。
令 coopEnforcementResult 为一个新的 打开者策略执行结果,其拥有
令 policyContainer 为 确定导航参数策略容器 的结果,该结果基于 response 的 URL、entry 的 文档状态 的 历史记录策略容器、null、navigable 的 容器文档 的 策略容器 以及 null。
返回一个新的 导航参数,具有以下内容:
此算法会修改 entry。
断言:这是在 并行 中运行的。
令 request 为一个新的 请求,具有以下内容:
如果 documentResource 为 POST 资源,则
如果 entry 的 文档状态 的 重新加载挂起 为 true,则将 request 的 重新加载导航标志 设置为 true。
如果 navigable 的 容器 非空
令 response 为 null。
令 responseOrigin 为 null。
令 fetchController 为 null。
令 coopEnforcementResult 为一个新的 打开者策略执行结果,其
令 finalSandboxFlags 为一个空的 沙盒标志集。
令 responsePolicyContainer 为 null。
令 responseCOOP 为一个新的 打开者策略。
令 locationURL 为 null。
令 currentURL 为 request 的 当前 URL。
令 commitEarlyHints 为 null。
当真时
如果 request 的 保留客户端 非空,且 currentURL 的 源 与 request 的 保留客户端 的 创建 URL 的 源 相同,则
如果 request 的 保留客户端 为 null,则
如果给定 request 和 cspNavigationType 为 "Blocked
" 的 是否应通过内容安全策略阻止类型为的导航请求? 的结果为 "Blocked
",则将 response 设置为一个 网络错误,并 退出循环。 [CSP]
将 response 设置为 null。
如果 fetchController 为 null,则将 fetchController 设置为 获取 request 的结果,其中 processEarlyHintsResponse 设置为下面定义的 processEarlyHintsResponse,processResponse 设置为下面定义的 processResponse,useParallelQueue 设置为真。
令 processEarlyHintsResponse 为以下算法,给定一个 响应 earlyResponse
如果 commitEarlyHints 为 null,则将 commitEarlyHints 设置为给定 earlyResponse 和 request 的 保留客户端 的 处理早期提示标头 的结果。
令 processResponse 为以下算法,给定一个 响应 fetchedResponse
将 response 设置为 fetchedResponse。
否则,对 fetchController 处理下一个手动重定向。
这将导致在我们的第一个循环迭代中调用我们上面提供的 processResponse,从而设置 response。
导航手动处理重定向,因为导航是网络平台中唯一关心重定向到 mailto:
URL 以及其他类似 URL 的地方。
等待 response 非空,或 navigable 的 正在进行的导航 更改为不再等于 navigationId。
如果发生后者,则 中止 fetchController,并返回。
否则,继续进行。
如果 request 的 主体 为 null,则将 entry 的 文档状态 的 资源 设置为 null。
获取会取消某些重定向的 主体。
将 responsePolicyContainer 设置为给定 response 和 request 的 保留客户端 的 从获取响应创建策略容器 的结果。
将 finalSandboxFlags 设置为 targetSnapshotParams 的 沙盒标志 和 responsePolicyContainer 的 CSP 列表 的 CSP 派生的沙盒标志 的 并集。
将 responseOrigin 设置为给定 response 的 URL、finalSandboxFlags 和 entry 的 文档状态 的 发起者源 的 确定源 的结果。
如果 response 是重定向,则 response 的 URL 将是导致重定向到 response 的 location URL 的 URL;它不会是 location URL 本身。
如果 navigable 是一个 顶级可遍历,则
将 responseCOOP 设置为给定 response 和 request 的 保留的客户端,获取 opener 策略的结果。
将 coopEnforcementResult 设置为给定 navigable 的 活动浏览上下文,response 的 URL,responseOrigin,responseCOOP,coopEnforcementResult 和 request 的 referrer,执行 response 的 opener 策略的结果。
如果 finalSandboxFlags 不为空,且 responseCOOP 的 值 不是 "unsafe-none
",则将 response 设置为一个合适的 网络错误,并 跳出循环.
这将导致一个网络错误,因为不能同时使用 opener 策略为 response 提供一个空白页面,并对导航到该 response 的结果进行沙盒化。
如果 response 不是一个 网络错误,navigable 是一个 子 navigable,且执行 跨域资源策略检查 的结果(使用 navigable 的 容器文档 的 源,navigable 的 容器文档 的 相关设置对象,request 的 目标,response 和 true)是 **被阻止**,则将 response 设置为一个 网络错误,并 跳出循环.
这里我们正在对 父 navigable 而不是 navigable 本身运行 跨域资源策略检查。这是因为我们关心嵌入内容相对于父上下文的同源性,而不是导航源。
将 locationURL 设置为给定 currentURL 的 片段,response 的 location URL.
如果 locationURL 是失败或 null,则 跳出循环.
将 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 中的条目共享的 文档状态 具有一个 null 的 文档,即 bfcache 并没有起作用。
现在考虑这种情况,我们向后遍历到步骤 2,但这一次当获取 /a
时,服务器使用一个指向 /c
的 `Location
` 标头进行响应。也就是说,locationURL 指向 /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,其 方案 不是一个 fetch 方案,则返回一个新的 非 fetch 方案导航参数,其中包含
此时,request 的 当前 URL 是重定向链中最后一个具有 fetch 方案 的 URL,在重定向到一个非 fetch 方案 URL 之前。它将作为导航到非 fetch 方案 URL 的发起者源被使用。
如果以下任何一项为真
则返回 null。
我们允许重定向到非 fetch 方案 URL,但重定向到非 HTTP(S) 的 fetch 方案 URL 将被视为网络错误。
设 resultPolicyContainer 为给定 response 的 URL、entry 的 文档状态 的 历史策略容器、sourceSnapshotParams 的 来源策略容器、null 和 responsePolicyContainer,确定导航参数策略容器 的结果。
如果 navigable 的 容器 是一个 iframe
,并且 response 的 计时允许通过标志 被设置,则将 容器 的 挂起的资源计时开始时间 设置为 null。
如果 iframe
被允许向资源计时报告,我们不需要运行其回退步骤,因为正常的报告将发生。
返回一个新的 导航参数,其中包含
如果一个元素的 Document
的 节点可导航 是一个 顶级可遍历,或者如果其 Document
的所有 祖先可导航 都有 活动文档,其 来源 与元素的 节点文档 的 来源 是 相同来源,则元素具有 浏览上下文范围来源。如果元素具有 浏览上下文范围来源,则其值为元素的 节点文档 的 来源。
此定义已损坏,需要调查以了解其意图表达的内容:请参阅 issue #4703。
要 加载文档,请执行以下步骤,并给定 导航参数 navigationParams、源快照参数 sourceSnapshotParams 和 来源 initiatorOrigin。它们返回一个 Document
或 null。
设 type 为 navigationParams 的 响应 的 计算类型。
如果用户代理已被配置为使用某些机制处理给定 type 的资源,而不是在 可导航 中呈现内容,则跳过此步骤。否则,如果 type 是以下类型之一
text/css
"text/plain
"text/vtt
"multipart/x-mixed-replace
"multipart/x-mixed-replace
文档 的结果,给定 navigationParams、sourceSnapshotParams 和 initiatorOrigin。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
时出现。对于导航,此工作通常在流程结束时进行;对于遍历,它是开始。
确保 可遍历 最终位于正确的会话历史步骤中特别复杂,因为它可能涉及跨可遍历的多个 可导航 后代进行协调,填充 它们,然后同步回来以确保每个人对结果都有相同的视图。同步相同的文档导航与跨文档导航混合在一起,以及网页如何拥有某些相对的定时期望,使得这一点更加复杂。
一个 更改可导航延续状态 用于在 应用历史步骤 算法期间存储信息,允许算法的一部分仅在其他部分完成之后继续。它是一个具有以下内容的 结构
Document
虽然对 可遍历可导航 的所有更新最终都在同一个 应用历史步骤 算法中,但每个可能的入口点都伴随着一些小的定制
要 更新可导航创建/销毁,给定一个 可遍历可导航 traversable
要 应用推送/替换历史步骤,给定一个非负整数 step 和一个 历史处理行为 historyHandling 到一个 可遍历可导航 traversable
返回 应用历史步骤 step 到 traversable 的结果,给定 false、null、null、null 和 historyHandling。
应用 push/replace 历史步骤 永远不会传递 源快照参数 或发起者 可导航对象 到 应用历史步骤。这是因为这些检查是在 导航 算法中的较早阶段完成的。
要将 应用重载历史步骤 应用于 可遍历可导航对象 traversable
令 step 为 traversable 的 当前会话历史步骤。
返回将 应用历史步骤 step 应用于 traversable(给定 true、null、null、null 和 "reload
")的结果。
应用重载历史步骤 永远不会传递 源快照参数 或发起者 可导航对象 到 应用历史步骤。这是因为重载始终被视为由 可导航对象 本身完成的,即使在像 parent.location.reload()
这样的情况下也是如此。
要将 应用遍历历史步骤 应用于给定的非负整数 step 和 可遍历可导航对象 traversable,以及 源快照参数 sourceSnapshotParams、可导航对象 initiatorToCheck 和 用户导航参与度 userInvolvement
返回将 应用历史步骤 step 应用于 traversable(给定 true、sourceSnapshotParams、initiatorToCheck、userInvolvement 和 "traverse
")的结果。
现在介绍算法本身。
要将 应用历史步骤 应用于给定的非负整数 step 和 可遍历可导航对象 traversable,以及布尔值 checkForCancelation、源快照参数-或-null sourceSnapshotParams、可导航对象-或-null initiatorToCheck、用户导航参与度-或-null userInvolvementForNavigateEvents 和 NavigationType
-或-null navigationType,请执行以下步骤。它们将返回 "initiator-disallowed
"、"canceled-by-beforeunload
"、"canceled-by-navigate
" 或 "applied
"。
令 targetStep 为给定 traversable 和 step 时,获取使用的步骤 的结果。
如果 initiatorToCheck 不是 null,则
断言:sourceSnapshotParams 不是 null。
对于 获取所有当前会话历史条目将发生更改或重载的可导航对象 的每个 navigable:如果 initiatorToCheck 未被沙箱 允许 通过沙箱 sourceSnapshotParams 导航 navigable,则返回 "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,则
如果 targetEntry 的 document 为 null,则将 navTimingType 设置为 "back_forward
";否则设置为 "reload
"。
将 targetSnapshotParams 设置为给定 navigable 的 快照目标快照参数 的结果。
将 potentiallyTargetSpecificSourceSnapshotParams 设置为 sourceSnapshotParams。
如果 potentiallyTargetSpecificSourceSnapshotParams 为 null,则将其设置为给定 navigable 的 活动文档 的 快照源快照参数 的结果。
在这种情况下,没有明确的遍历/重新加载源。我们将这种情况视为 navigable 自行导航,但需要注意的是,targetEntry 的原始发起者的某些属性保留在 targetEntry 的 文档状态 中,例如 发起者来源 和 来源,这将适当地影响导航。
将 targetEntry 的 文档状态 的 reload pending 设置为 false。
将 allowPOST 设置为 targetEntry 的 文档状态 的 reload pending。
并行,尝试填充历史条目文档,对于 targetEntry,给定 navigable,potentiallyTargetSpecificSourceSnapshotParams,targetSnapshotParams,allowPOST 设置为 allowPOST,completionSteps 设置为在给定 navigable 的 活动窗口 的 导航和遍历任务源 上 排队一个全局任务 以运行 afterDocumentPopulated。
否则,立即运行 afterDocumentPopulated。
在这两种情况下,afterDocumentPopulated 为以下步骤
如果 targetEntry 的 document 为 null,则将 changingNavigableContinuation 的 update-only 设置为 true。
这意味着我们尝试填充文档,但无法做到,例如,由于服务器返回了 204。
这些类型的失败导航或遍历不会向 导航 API(例如,通过任何 导航 API 方法跟踪器 的 promise 或 navigateerror
事件)发出信号。这样做会泄漏有关跨来源情况下其他来源响应时间的信息,并且跨来源与同来源情况下的不同结果被认为过于混乱。
但是,实现可以使用此机会清除 navigation.transition.finished
promise 的任何 promise 处理程序,因为此时保证它们永远不会运行。而且,它们可能希望在 将警告报告到控制台 上,如果导航 API 的任何部分启动了这些导航,以便让 Web 开发人员清楚地了解为什么他们的 promise 永远不会解决,事件永远不会触发。
如果 targetEntry 的 document 的 来源 不是 oldOrigin,则将 targetEntry 的 经典历史 API 状态 设置为 StructuredSerializeForStorage(null)。
这会在来源发生变化时清除历史状态,而不是在没有发生重定向的情况下之前加载 targetEntry。这可能是由于 CSP 沙盒头部的更改而发生的。
如果以下所有条件都为真
将 changingNavigableContinuation 排队 到 changingNavigableContinuations 上。
此作业的其余部分将在该算法中 稍后运行。
将 navigablesThatMustWaitBeforeHandlingSyncNavigation 设置为一个空的 集合。
当 completedChangeJobs 不等于 totalChangeJobs 时
如果 traversable 的 正在运行的嵌套应用历史步骤 为 false,则
将 changingNavigableContinuation 设置为 从 changingNavigableContinuations 出队 的结果。
如果 changingNavigableContinuation 为 nothing,则 继续。
将 displayedDocument 设置为 changingNavigableContinuation 的 显示的文档。
将 targetEntry 设置为 changingNavigableContinuation 的 目标条目。
将 navigable 设置为 changingNavigableContinuation 的 可导航。
将 (scriptHistoryLength,scriptHistoryIndex) 设置为给定 traversable 和 targetStep 的 获取历史对象长度和索引 的结果。
这些值可能已自上次计算以来发生变化。
将 navigable 追加 到 navigablesThatMustWaitBeforeHandlingSyncNavigation 中。
一旦可导航在遍历中到达此点,额外排队的同步导航步骤很可能打算在此遍历之后发生,而不是之前发生,因此它们不再跳过队列。可以在这里找到更多详细信息。
将 entriesForNavigationAPI 设置为给定 navigable 和 targetStep 的 获取会话历史条目以供导航 API 使用 的结果。
如果 changingNavigableContinuation 的 update-only 为 true,或者 targetEntry 的 document 为 displayedDocument,则
这是同一个文档导航:我们继续进行,而不进行卸载。
否则
在这两种情况下,afterPotentialUnloads 为以下步骤
如果 changingNavigableContinuation 的 update-only 为 false,则 激活历史条目 targetEntry,用于 navigable。
将 updateDocument 设置为一个算法步骤,它执行给定 targetEntry 的 document,targetEntry,changingNavigableContinuation 的 update-only,scriptHistoryLength,scriptHistoryIndex,navigationType,entriesForNavigationAPI 和 displayedEntry 的 更新文档以进行历史步骤应用。
如果 targetEntry 的 document 等于 displayedDocument,则执行 updateDocument。
否则,在给定 targetEntry 的 document 的 相关全局对象 的 导航和遍历任务源 上 排队一个全局任务 以执行 updateDocument。
递增 completedChangeJobs。
将 totalNonchangingJobs 设置为 nonchangingNavigablesThatStillNeedUpdates 的 大小。
从这一步开始,会故意等待所有之前的操作完成,因为它们包括 处理同步导航,这也会发布任务来更新历史长度和索引。
令 completedNonchangingJobs 为 0。
令 (scriptHistoryLength, scriptHistoryIndex) 为 获取历史对象长度和索引 的结果,给定 traversable 和 targetStep。
对于 nonchangingNavigablesThatStillNeedUpdates 的每个 navigable,在给定 navigable 的 活动窗口 的 导航和遍历任务源 上 排队一个全局任务 来运行以下步骤
令 document 为 navigable 的 活动文档。
将 document 的 历史对象 的 索引 设置为 scriptHistoryIndex。
将 document 的 历史对象 的 长度 设置为 scriptHistoryLength。
将 completedNonchangingJobs 加 1。
等待 completedNonchangingJobs 等于 totalNonchangingJobs。
将 traversable 的 当前会话历史步骤 设置为 targetStep。
返回 "applied
"。
为了 为跨文档导航停用文档,给定一个 Document
displayedDocument,一个 用户导航参与度 userNavigationInvolvement,一个 会话历史条目 targetEntry,一个 NavigationType
navigationType,以及 afterPotentialUnloads,它是一个不接收参数的算法
令 navigable 为 displayedDocument 的 节点可导航。
令 potentiallyTriggerViewTransition 为 false。
如果 userNavigationInvolvement 为 "
",则令 isBrowserUINavigation 为 true;否则为 false。浏览器 UI
将 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
事件,给定一个 Document
displayedDocument,一个 会话历史条目 targetEntry,一个 NavigationType
navigationType,以及一个 ViewTransition
或 null viewTransition
令 navigation 为 displayedDocument 的 相关全局对象 的 导航 API。
令 activation 为 null。
如果以下所有条件都为真
则
令 destinationEntry 由 navigationType 的切换决定
将 activation 设置为在 displayedDocument 的 相关领域 中创建的新的 新 NavigationActivation
,具有以下内容:
这意味着在导航期间的跨源重定向将导致旧文档的 PageSwapEvent
中的 activation
为 null,除非新文档是从 bfcache 中恢复的。
触发 名为 pageswap
的事件,在 displayedDocument 的 相关全局对象 上,使用 PageSwapEvent
,其 activation
设置为 activation,其 viewTransition
设置为 viewTransition。
为了 激活历史条目 会话历史条目 entry,对于 可导航 navigable
令 newDocument 为 entry 的 文档。
断言:newDocument 的 是否为初始 about:blank
为 false,即我们从不遍历回 初始 about:blank
Document
,因为它在我们从它导航出去时总是会被 替换。
将 navigable 的 活动会话历史条目 设置为 entry。
为了 获取使用的步骤,给定一个 可遍历导航 traversable,以及一个非负整数 step,执行以下步骤。它们返回一个非负整数。
令 steps 为 获取在 traversable 内所有使用的历史步骤 的结果。
返回 steps 中小于或等于 step 的最大的 项。
为了 获取历史对象长度和索引,给定一个 可遍历导航 traversable,以及一个非负整数 step,执行以下步骤。它们返回一个包含两个非负整数的 元组。
令 steps 为 获取在 traversable 内所有使用的历史步骤 的结果。
令 scriptHistoryLength 为 steps 的 大小。
假设 step 已经通过 获取使用的步骤 进行调整。
令 scriptHistoryIndex 为 step 在 steps 中的索引。
返回 (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,要获取目标历史条目,执行以下步骤。它们返回一个会话历史条目。
要了解为什么获取目标历史条目 会返回步数 最大的且小于或等于输入步数的条目,请考虑以下Jake 图
0 | 1 | 2 | 3 | |
---|---|---|---|---|
顶部 | /t | /t#foo | ||
frames[0] | /i-0-a | /i-0-b |
对于输入步数 1,top
导航对象的步数 为 0 的 /t
条目是目标历史条目,而 frames[0]
导航对象的步数 为 1 的 /i-0-b
条目是目标历史条目
0 | 1 | 2 | 3 | |
---|---|---|---|---|
顶部 | /t | /t#foo | ||
frames[0] | /i-0-a | /i-0-b |
类似地,给定输入步数 3,我们得到步数 为 3 的 top
条目和步数 为 1 的 frames[0]
条目
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 的活动历史条目 可以同步更改,但新条目将始终具有相同的 Document
,因此访问 navigable 的文档 是可靠的。
否则,将 navigablesToCheck 扩展 为 navigable 的子导航对象。
将子导航对象 添加到 navigablesToCheck 表示这些导航对象也将被此循环检查。子导航对象 仅在 navigable 的活动文档 不会作为此遍历的一部分发生更改时才会被检查。
返回 results。
给定一个 Document
document、一个会话历史条目 entry、一个布尔值 doNotReactivate、整数 scriptHistoryLength 和 scriptHistoryIndex、NavigationType
-or-null navigationType、一个可选的列表,包含会话历史条目 entriesForNavigationAPI 以及一个可选的会话历史条目 previousEntryForActivation,要更新文档以应用历史步骤,执行以下步骤。
如果 document 的最新条目 为空,则令 documentIsNew 为真;否则为假。
如果 document 的最新条目 不是 entry,则令 documentsEntryChanged 为真;否则为假。
将 document 的 历史对象 的 索引 设置为 scriptHistoryIndex。
将 document 的 历史对象 的 长度 设置为 scriptHistoryLength。
令 navigation 为 history 的相关全局对象 的导航 API。
如果 documentsEntryChanged 为真,则
将 document 的最新条目 设置为 entry。
恢复历史对象状态,给定 document 和 entry。
如果 documentIsNew 为假,则
断言: navigationType 不为空。
更新同文档导航的导航 API 条目,给定 navigation、entry 以及 navigationType。
在 document 的相关全局对象 上触发 名为popstate
的事件,使用 PopStateEvent
,将state
属性初始化为 document 的历史对象 的状态,并将hasUAVisualTransition
初始化为真,如果用户代理执行了可视化转换来显示最新条目 的缓存渲染状态。
恢复持久状态,给定 entry。
如果 oldURL 的 片段 不等于 entry 的 URL 的 片段,则在 document 的 相关全局对象 上,在 DOM 操作任务源 上 排队一个全局任务,以 触发一个事件,名为 hashchange
,在 document 的 相关全局对象 上,使用 HashChangeEvent
,其中 oldURL
属性初始化为 oldURL 的 序列化,newURL
属性初始化为 entry 的 URL 的 序列化。
否则
如果以下所有条件都为真
previousEntryForActivation 已给定;
navigationType 非空;且
navigationType 为 “reload
” 或 previousEntryForActivation 的 文档 不是 document,
则
如果 navigation 的 激活 为 null,则将 navigation 的 激活 设置为 navigation 的 相关领域 中的新 NavigationActivation
对象。
令 previousEntryIndex 为 获取导航 API 条目索引 的结果,该索引在 navigation 中指向 previousEntryForActivation。
如果 previousEntryIndex 非负,则将 activation 的 旧条目 设置为 navigation 的 条目列表[previousEntryIndex]。
否则,如果以下所有条件都为真
navigationType 为 “replace
”;
previousEntryForActivation 的 文档 的 初始 about:blank
为 false,
则将 activation 的 旧条目 设置为 navigation 的 相关领域 中的新 NavigationHistoryEntry
,其 会话历史条目 为 previousEntryForActivation。
将 activation 的 新条目 设置为 navigation 的 当前条目。
将 activation 的 导航类型 设置为 navigationType。
如果 documentIsNew 为 true,则
尝试滚动到片段,针对 document。
此时,新创建的文档 document 可能会运行脚本。
否则,如果 documentsEntryChanged 为 false 且 doNotReactivate 为 false,则
documentsEntryChanged 可能为 false,原因有两个:要么我们正在从 bfcache 恢复,要么我们正在异步完成一个同步导航,该导航已经同步设置了 document 的 最新条目。参数 doNotReactivate 区分了这两种情况。
要 恢复历史对象状态,给定 Document
document 和 会话历史条目 entry
令 targetRealm 为 document 的 相关领域。
令 state 为 StructuredDeserialize(entry 的 经典历史 API 状态,targetRealm)。如果这抛出异常,则捕获它并令 state 为 null。
将 document 的 历史对象 的 状态 设置为 state。
要 激活 Document
document
令 window 为 document 的 相关全局对象。
将 document 的 浏览上下文 的 WindowProxy
的 [[Window]] 内部槽位值设置为 window。
排队 一个新的 VisibilityStateEntry
,其 可见性状态 为 document 的 可见性状态,其 时间戳 为零。
将 window 的 相关设置对象 的 执行就绪标志 设置为 true。
要 重新激活 Document
document,给定一个 会话历史条目 reactivatedEntry 和一个 列表,包含 会话历史条目 entriesForNavigationAPI
此算法更新 document,在它从 bfcache 中出来之后,即在它再次被设为 完全激活 之后。其他希望观察这种 完全激活 状态变化的规范被鼓励将步骤添加到此算法中,以便清楚地显示发生在变化影响下的事件的顺序。
遍历 document 中具有 “off
” 的 自动填充字段名称 的表单控件 formControl,为 formControl 调用 重置算法。
更新导航 API 条目以重新激活,给定 document 的 相关全局对象 的 导航 API、entriesForNavigationAPI 和 reactivatedEntry。
如果 document 的 当前文档就绪状态 为 "complete
",且 document 的 页面显示 标志为 false,则
要 尝试滚动到片段,针对 Document
document,执行以下步骤,并行 地
等待 实现定义的 一段时间。(这旨在允许用户代理在面对性能问题时优化用户体验。)
排队一个全局任务,在 document 的 相关全局对象 上,在 导航和遍历任务源 上,以运行以下步骤
要 使文档不可恢复,给定 Document
document 和一个字符串 reason
追加 details 到 document 的 bfcache 阻止详情。
将 document 的 可恢复 状态设置为 false。
给定Document
document,构建文档状态的未恢复原因
令 notRestoredReasonsForDocument 为一个新的未恢复原因。
将 notRestoredReasonsForDocument 的reasons 设置为document 的bfcache 阻塞细节 的克隆。
对于 document 的文档树子节点可导航 中的每一个 navigable
令 childDocument 为 navigable 的活动文档。
构建文档状态的未恢复原因 给定 childDocument。
追加 childDocument 的未恢复原因 到 notRestoredReasonsForDocument 的子节点。
将 document 的节点可导航 的活动会话历史条目 的文档状态 的未恢复原因 设置为 notRestoredReasonsForDocument。
给定顶级可遍历 topLevelTraversable,构建顶级可遍历及其后代的未恢复原因
构建文档状态的未恢复原因 给定 topLevelTraversable 的活动文档。
令 crossOriginDescendants 为一个空的列表。
令 crossOriginDescendantsPreventsBfcache 为 false。
对于 crossOriginDescendants 中的每一个 crossOriginNavigable
如果 crossOriginDescendantsPreventsBfcache 为 true,则使文档无法恢复 给定 topLevelTraversable 的活动文档 和 "masked
"。
一个Document
有一个布尔值已被显示,最初为 false。它用于确保pagereveal
事件对每个Document
的激活只触发一次(第一次渲染时触发一次,每次重新激活时触发一次)。
显示Document
document
如果 document 的已被显示 为 true,则返回。
将 document 的已被显示 设置为 true。
令 transition 为解析传入跨文档视图过渡 对 document 的结果。
触发 一个名为pagereveal
的事件,在 document 的相关全局对象 上,使用 PageRevealEvent
,其viewTransition
设置为 transition。
如果 transition 不是 null,则
准备运行脚本 给定 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 运行聚焦步骤,其中 Document
的视窗 作为备用目标。
将顺序焦点导航起点 移动到 target。
Document
的指示部分 是其URL 的片段 标识的部分,或者如果片段没有标识任何内容,则为 null。片段在映射到节点方面的语义由定义Document
使用的MIME 类型 的规范定义(例如,片段 的处理XML MIME 类型 是 RFC7303 的责任)。 [RFC7303]
每个Document
还有一个目标元素,它用于定义:target
伪类,并由上述算法更新。它最初为 null。
对于 HTML 文档 document,其 指示部分 是在给定 document 和 document 的 URL 的情况下, 选择指示部分 的结果。
要 选择指示部分,请给定一个 Document
document 和一个 URL url
令 fragment 为 url 的 片段。
如果 fragment 为空字符串,则返回特殊值 文档顶部。
令 potentialIndicatedElement 为在给定 document 和 fragment 的情况下 查找潜在的指示元素 的结果。
如果 potentialIndicatedElement 不为 null,则返回 potentialIndicatedElement。
令 fragmentBytes 为 百分比解码 fragment 的结果。
令 decodedFragment 为对 fragmentBytes 运行 无 BOM 的 UTF-8 解码 的结果。
将 potentialIndicatedElement 设置为在给定 document 和 decodedFragment 的情况下 查找潜在的指示元素 的结果。
如果 potentialIndicatedElement 不为 null,则返回 potentialIndicatedElement。
如果 decodedFragment 与字符串 top
ASCII 不区分大小写 匹配,则返回 文档顶部。
返回 null。
要 查找潜在的指示元素,请给定一个 Document
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 的 文档 及其呈现的其他方面,例如表单字段的值,这些值是用户代理先前记录在 entry 的 持久用户状态 中的。
这甚至可以包括更新 dir
属性的 textarea
元素或 input
元素,其 type
属性处于 文本、搜索、电话、URL 或 电子邮件 状态,如果持久状态包含此类控件中用户输入的方向。
在此过程中恢复表单控件的值不会触发任何 input
或 change
事件,但可以触发 与表单关联的自定义元素 的 formStateRestoreCallback
。
每个 Document
都有一个布尔值 用户已滚动,最初为 false。如果用户滚动文档,用户代理必须将该文档的 用户已滚动 设置为 true。
Document
document 的 可恢复的滚动区域 是 document 的 视窗,以及 document 的所有滚动区域,不包括任何 可导航容器。
子可导航 滚动恢复作为 可导航 的 Document
的 会话历史条目 状态恢复的一部分进行处理。
要 恢复滚动位置数据,请给定一个 会话历史条目 entry