Error option limit S1
中文标题:错误选项 limit
提案概览
- 阶段: Stage 1
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
提案速览
该提案为所有内置 Error 构造函数引入了一个按错误实例的选项 limit,用于控制每个错误实例捕获的最大堆栈帧数。它解决了全局 Error.stackTraceLimit 的问题,如粒度粗、全局副作用和样板解决方案。
Note
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
ECMAScript 提案:错误选项 limit
状态
提案发起人:Ruben Bridgewater
作者:Ruben Bridgewater ruben@bridgewater.de
阶段:1
概述
本提案为每个错误引入了一个新的 Error 选项属性 limit,该属性指定了为该特定错误实例捕获的最大实现定义的堆栈帧数量。
limit是一个数值选项,使用 ToIntegerOrInfinity 解释。- 如果提供,局部
limit会覆盖任何全局堆栈跟踪限制(例如,V8 的Error.stackTraceLimit)仅针对该错误。 - 负值抛出 RangeError;
limit必须是非负整数、undefined或Infinity。 - 从概念上讲,这类似于在创建错误之前临时设置 V8 特定的
Error.stackTraceLimit,并在之后立即恢复,但没有任何全局副作用。
这提供了一种标准化的、跨引擎的方式来控制每个错误实例的堆栈深度,并避免操作影响无关错误的全局开关。
提议的 API
验证
- 如果提供了
options并且其limit属性值不是undefined,引擎计算n = ToIntegerOrInfinity(limit)。- 如果
n < 0,抛出RangeError。 - 否则,将
n记录在错误实例上。
- 如果
- 如果
limit是undefined或缺失,默认行为不变(如果存在全局限制,则应用全局限制)。
理由:局部限制更直观
- V8 中定义的全局
Error.stackTraceLimit粒度较粗,会影响所有错误,包括那些不需要更深堆栈的错误。 - 每个错误的
limit在关键处准确表达了意图,避免了意外的全局副作用。 - 局部限制总是覆盖该特定错误实例的全局限制,这符合开发者在定制诊断信息时的期望。
- 消除了仅为了构造一个错误而临时修改全局
Error.stackTraceLimit的样板模式。
为什么 V8 中定义的全局 Error.stackTraceLimit 容易出错
- 更改是进程范围且基于时间的,因此无关的错误可能继承错误的限制。
- “设置”和“重置”之间的代码可能同步抛出异常,跳过重置。
- 异步边界使得在
await期间很容易影响其他正在进行的任务。 - 人们有时只是忘记重置全局开关。
示例:
- 错误创建期间同步抛出异常会跳过重置
使用局部限制,没有全局修改:
- 异步危险:无关的错误使用您的临时限制
使用局部限制,只有预期的错误受到影响:
- 简单遗漏:忘记重置
每个错误的 limit 避免了整个类别的错误。
使用场景
- 性能敏感的热路径,只需要前几帧(例如,
limit: 2)以最小化开销。 - 针对特定错误类型或代码路径的聚焦深度调试(例如,
limit: 100或Infinity),而不改变其他错误的行为。 - 库和框架工具希望对其自身的诊断错误具有可预测的堆栈深度,而不全局影响用户代码。
实际中(先行实践)
开发者经常通过在创建错误之前临时更改全局 Error.stackTraceLimit 并在之后重置来模拟每个错误的控制。示例和参考:
- MDN:
Error.stackTraceLimit(记录了临时调整模式) —https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stackTraceLimit - Node.js 文档: Errors —
https://nodejs.org/api/errors.html - GitHub 代码搜索: “Error.stackTraceLimit = Infinity” —
https://github.com/search?q=%22Error.stackTraceLimit+%3D+Infinity%22&type=code - longjohn (异步堆栈跟踪) 设置非常高/Infinity 限制 —
https://github.com/mattinsler/longjohn - Mocha 完整跟踪选项 (“完整堆栈”的生态系统先例) —
https://mochajs.org/#--full-trace
这些表明开发者已经依赖每个错误或上下文本地的堆栈深度控制;标准化每个错误的 limit 消除了全局修改的需求。
语义
- 让
L为错误实例记录的limit,如果提供;否则为undefined。 - 当宿主为错误捕获堆栈时:
- 如果
L是undefined,应用宿主的默认/全局堆栈跟踪限制。 - 否则,仅对该错误应用
L作为限制。
- 如果
- 格式化以及任何其他宿主定义的堆栈处理保持不变。
stack frame 是实现定义的。
规范文本(大纲)
- 在每个接受选项参数的
Error(及子类)构造函数中:- 让
options为第二个(或对于AggregateError是第三个)参数。 - 如果
options不是undefined:- 让
limit为 ? Get(options, "limit"). - 如果
limit不是undefined:- 让
n为 ? ToIntegerOrInfinity(limit). - 如果
n < 0,抛出RangeError。 - 在错误实例的内部槽中记录
n,以供堆栈捕获时后续使用。
- 让
- 让
- 让
- 当为错误实例
E捕获堆栈时:- 让
S为在没有此选项时将为E捕获的帧序列。 - 让
n为E.[[StackTraceLimitOverride]],如果存在;否则为undefined。 - 应用堆栈长度限制:
- 如果
n是undefined,应用宿主的全局/默认限制。 - 否则,应用
n到S。
- 如果
- 照常从
S生成堆栈字符串。
- 让
查看完整规范草案:
非目标与边界情况
- 本提案不标准化堆栈字符串格式、源映射应用或异步堆栈合并。
- 如果
limit为0,除了错误标题(实现定义)外,错误不包含帧。 - 该选项是每个错误的,不影响其他错误或将来的堆栈捕获。
考虑的替代方案
- 继续使用全局
Error.stackTraceLimit。因缺乏精度、意外的全局副作用以及模拟每个错误控制所需的样板而被拒绝。 - 添加新的主机特定 API。已拒绝;标准化语言选项更具可移植性和互操作性。
结论
limit 提供了一种显式、局部的方式来控制每个错误的堆栈深度,符合开发者的期望,改善了人体工程学,避免了全局副作用,同时与生态系统实践保持一致。