zh CN Error Handling - chiba233/yume-dsl-token-walker GitHub Wiki
错误怎么上报、解释器提供什么安全保证、以及如何在不停止迭代的情况下观察错误。
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,包含 start 和
end,每个都有 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 的 type === "text" 但 value 不是字符串,解释器抛出 "traversal" 错误,而不是静默产出垃圾。
导出的 flattenText() 函数是独立工具——它不会经过 onError。只有在 interpretTokens / interpretTokensAsync
内部产生的错误才会被 onError 观察到。
如果你直接调 flattenText(value) 并且遇到循环引用,它直接抛出,没有任何观察者。