zh CN Error Handling - chiba233/yume-dsl-token-walker GitHub Wiki

错误处理与安全性

解释 API | 导出一览 | 首页

错误怎么上报、解释器提供什么安全保证、以及如何在不停止迭代的情况下观察错误。


onError——观察,不吞掉

InterpretRuleset.onError 在错误被抛出之前调用。它不会吞掉错误——onError 返回后错误仍然会被重新抛出。

用它来记录、上报、或收集错误,同时让错误继续传播:

import {createParser, createSimpleInlineHandlers} from "yume-dsl-rich-text";
import {interpretTokens, collectNodes} from "yume-dsl-token-walker";

const parser = createParser({
    handlers: createSimpleInlineHandlers(["bold"]),
    trackPositions: true,
});

const tokens = parser.parse("$$bold(hello)$$");

const errors: Error[] = [];

try {
    collectNodes(interpretTokens(tokens, {
        createText: (text) => text,
        interpret: (token) => {
            if (token.type === "bold") throw new Error("boom");
            return {type: "unhandled"};
        },
        onError: ({error, phase, token, position}) => {
            errors.push(error);
            if (position) {
                console.error(
                    `[${phase}] ${error.message} at line ${position.start.line}:${position.start.column}`,
                );
            }
        },
    }, undefined));
} catch {
    // errors[] 现在包含了观察到的错误
}

position 来自 token.position——上游 parser 启用 trackPositions: true 时才有。它是一个 SourceSpan,包含 startend,每个都有 offset(从 0 开始)、line(从 1 开始)、column(从 1 开始)。


错误阶段

通过 onError 上报的每个错误都有一个 phase 字段:

阶段 触发条件
"interpret" interpret() 抛出、onUnhandled 策略函数抛出、或 onUnhandled: "throw" 触发
"flatten" flattenText 失败(例如检测到循环引用)
"traversal" 结构性错误——text token 的 value 不是字符串,或检测到递归 token
"internal" 意外的内部状态(例如未知的 result 类型)

安全保证

自引用检测

如果 handler 把一个 token 通过 interpretChildren 喂回给自己,解释器会立即检测到并抛出——在炸栈之前。

内部用一个 WeakSet<TextToken> 追踪哪些 token 正在被解释。如果同一个 token 对象在自己的解释过程中再次出现,立即抛错。

循环引用检测

flattenText 按递归路径追踪已访问 token(不是全局追踪)。这意味着:

  • 共享引用是安全的——同一个 token 出现在多个分支里没问题
  • 真正的循环会抛出——如果 token 的 value 链条回到了自身,flattenText 抛出描述性错误

文本 token 校验

如果一个 token 的 type === "text"value 不是字符串,解释器抛出 "traversal" 错误,而不是静默产出垃圾。


边界说明

导出的 flattenText() 函数是独立工具——它不会经过 onError。只有在 interpretTokens / interpretTokensAsync 内部产生的错误才会被 onError 观察到。

如果你直接调 flattenText(value) 并且遇到循环引用,它直接抛出,没有任何观察者。

⚠️ **GitHub.com Fallback** ⚠️