Error option framesAbove S1
中文标题:Error 选项 framesAbove
- 阶段: Stage 1
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案为 ECMAScript Error 构造函数引入了新的 framesAbove 选项,允许开发者指定一个函数,其最顶层调用(及其上方的所有帧)将从错误的堆栈跟踪中排除。它旨在移除样板包装帧,将当前存在于宿主特定 API(如 Node.js 的 Error.captureStackTrace)中的行为标准化。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
ECMAScript 提案:Error 选项 framesAbove
状态
Champion: Ruben Bridgewater
Author: Ruben Bridgewater ruben@bridgewater.de
阶段: 1
概述
本提案引入了新的 Error 选项属性 framesAbove,允许作者在捕获错误堆栈时排除特定的前导堆栈帧。
framesAbove接收一个方法(即可调用函数)。如果提供的值既不是方法也不是undefined,构造函数将抛出TypeError。- 当收集错误的堆栈跟踪时,所有位于所提供的函数最顶层调用之上的帧(包括该调用)都会从生成的堆栈跟踪中省略。
- 由于
framesAbove省略的帧不计入任何已定义的堆栈跟踪限制(例如,V8 中的Error.stackTraceLimit)。
此能力与长期存在的宿主特定设施(例如,Node.js/V8 的 Error.captureStackTrace 中的 constructorOpt 参数)相对应,同时提供标准化的、跨平台的选项,可用于所有 ECMAScript 内置 Error 子类的构造函数。
除了更易于使用的 API 和更好的堆栈限制处理外,它还使用更少的 CPU 周期,因为只评估一次堆栈帧而不是两次。
提议的 API
验证
- 如果提供了
options并且其framesAbove属性的值不是undefined且不可调用,则抛出TypeError。 - 如果
framesAbove是undefined或不存在,则默认行为不变。
动机
应用程序经常围绕用户代码创建小的包装工具。这些包装器出现在堆栈跟踪的顶部,为调试失败的开发人员提供的价值很小。作者当前依赖宿主特定 API 或后处理来移除这些帧。
framesAbove 在语言中标准化了这种行为:
- 提高错误堆栈中的信噪比。
- 在引擎之间提供确定性的行为。
- 避免依赖非标准 API 或脆弱的正则后处理。
语义
- 设 F 为
options.framesAbove的值。- 如果 F 是
undefined,则不执行任何特殊操作。 - 否则,如果 F 不可调用,则抛出
TypeError。 - 否则,记录 F 与新创建的错误实例关联,以便在堆栈收集期间使用。
- 如果 F 是
- 在收集错误的堆栈时:
- 从堆栈中最近的帧开始向下扫描,找到其关联函数为 F 的帧的最顶层出现。
- 省略该出现之上严格高于的所有帧,以及该出现本身。
- 仅对剩余的帧应用任何堆栈跟踪限制。由于
framesAbove省略的帧不计入限制。
- 如果 F 未出现在捕获的堆栈中,则堆栈不变(除了任何无关的平台行为和堆栈限制)。
- 如果 F 多次出现(例如,递归),则使用最顶层的出现。
注意:帧到关联函数的确切映射目前是宿主定义的。本提案使用引擎在堆栈跟踪帧中已经使用的相同关联。
示例
基本包装器移除
多次出现(最顶层获胜)
与堆栈跟踪限制的交互
详细语义
framesAbove是所有接受 options 袋的标准Error子类构造函数识别的选项。- 与
framesAbove关联的值:- 必须是可调用函数,或
undefined。 - 仅针对其提供该选项的错误进行考虑;它没有全局效果。
- 不改变消息、名称或 cause 语义。
- 必须是可调用函数,或
- 省略的帧:
- 不会出现在生成的堆栈字符串中。
- 不计入引擎应用的任何堆栈长度限制。
- 在应用任何限制或格式化之前,概念上被移除。
stack frame 是实现定义的。
与现有宿主行为的关系
许多宿主已经提供了移除帧的能力(例如,V8/Node 的 Error.captureStackTrace(target, constructorOpt))。framesAbove 提供了标准化的语言级行为,具有类似的意图:
- 可在不暴露宿主特定 API 的环境中工作。
- 为“最顶层调用”和“包含性省略”提供一致的语义。
宿主可以继续提供额外的设施;这些与 framesAbove 保持正交。
规范文本(大纲)
本节概述了规范性更改;精确措辞和集成点将在随附的规范文本中提供。
- 在每个接受 options 参数的
Error(及子类)构造函数中:- 让
options是第二个(对于AggregateError是第三个)参数。 - 如果
options不是undefined:- 让
framesAbove为 ? Get(options, "framesAbove"). - 如果
framesAbove不是undefined且 IsCallable(framesAbove) 为false,则抛出TypeError。
- 让
- 让
- 在错误实例初始化期间,将
framesAbove(可能是undefined)记录在错误的内部错误数据槽中,以便稍后在堆栈捕获期间使用。 - 在捕获错误实例 E 的堆栈时:
- 让
S为在无该选项的情况下本应为 E 捕获的帧序列。 - 如果 E.[[ErrorData]].[[FramesAboveFunction]] 是函数 F:
- 让
k为S中最小的索引(从最近帧的索引 0 开始计数),使得S[k]的关联函数是 F。 - 如果存在这样的
k,则将S替换为从索引k + 1到末尾的S切片。
- 让
- 对
S应用任何堆栈长度限制。 - 照常从
S生成堆栈字符串。
- 让
参见完整规范草案:
非目标与边缘情况
- 本提案不标准化堆栈字符串格式、源映射应用或异步堆栈拼接。
- 如果提供的函数从未出现在捕获的堆栈中,则不删除任何内容。
- 如果提供的值可调用但具有外部性(例如,Proxy 包装的函数),引擎使用其现有的帧到函数关联的概念。
- 该选项是针对每个错误的,不影响其他错误。
考虑的替代方案
- 继续依赖宿主特定 API(
Error.captureStackTrace)或后处理。由于缺乏可移植性到其他 JS 引擎、API 使用困难以及相关的 CPU 开销而被拒绝。 - 接受帧索引或哨兵而不是函数。由于脆弱性和跨调用路径缺乏组合性而被拒绝。
结论
framesAbove 提供了一种简单、明确的方法来从错误堆栈中移除无用的包装器帧,改善开发人员体验,同时与现有的宿主实践保持一致。通过标准化这种行为,生态系统获得了一个可移植、确定性的工具,用于生成更高信号的堆栈跟踪。