Propagate active ScriptOrModule with JobCallback Record S2
中文标题:使用 JobCallback 记录传播活动 ScriptOrModule
- 阶段: Stage 2
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案旨在统一活动 ScriptOrModule 的传播,使其在调用 promise.then 时确定,而不是在 HostEnqueuePromiseJob 时确定,从而避免暴露内部 [[PromiseState]]。它要求通过 promise 作业和 FinalizationRegistry 回调传播,与 HTML 现有的 HostMakeJobCallback 行为保持一致。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
ecma262#3195
这是 https://github.com/tc39/ecma262/pull/3195 的规范性更改的仓库。
状态:Stage 2
提案发起人:Chengzhong Wu (@legendecas)
动机
目标是避免通过宿主钩子要求向 Promise 处理器暴露内部插槽 [[PromiseState]],而是使用 promise.then(onFulfill, onRejection)。
ECMA262 HostEnqueuePromiseJob 定义宿主必须将其实现为:
- 在调用 HostEnqueuePromiseJob 时,让 scriptOrModule 为 GetActiveScriptOrModule()。如果 realm 不为 null,则每次调用 job 时,实现必须执行 实现定义 的步骤,使得 scriptOrModule 成为 job 调用时的 活动脚本或模块。
HostEnqueuePromiseJob 的时机取决于内部 Promise 的 [[PromiseState]]。而本动机期望 ActiveScriptOrModule 在调用 promise.then() 时被确定。
即在上面的例子中,调用点 (1) 处的 handler 的 ActiveScriptOrModule 应为“模块 A”,而调用点 (2) 处应为“模块 B”。
HTML 集成
HTML HostEnqueuePromiseJob 并不遵循 ecma262 的要求。
然而,HTML 规范定义活动的 ScriptOrModule 在调用 HostMakeJobCallback 时被保存,而不是在调用 HostEnqueuePromiseJob 时。这两个宿主钩子被连续地调用,且具有相同的活动脚本或模块。
这一更改也强制要求活动脚本通过 promise 作业和 FinalizationRegistry 清理回调进行传播。
例如,下面的示例使用了依赖于原始脚本的现任文档 URL 的 HTML API。
这种提议的行为在 HTML 规范中已经存在,因为 HTML 的 HostMakeJobCallback 已经传播了活动脚本。
提议的更改
查看 https://github.com/tc39/ecma262/pull/3195
实际实现状态的现实是:
- pending 在内部 iframe 中 resolve。
- f 是 iframe 的
setLocationHref。- outer: url 解析到外层页面。
- inner: url 解析到内部 iframe。
结论:
- ECMA-262 和 Safari 暴露了
[[PromiseState]]。 - Chrome/Firefox 不尊重
.then(f)等同于.then(v => f(v))。 - HTML 和提议的行为都不具有这些问题。
提议的更改还修复了 ecma262 HostEnqueuePromiseJob 和 HTML HostMakeJobCallback 之间的不一致要求。