背景:使用 cljs.spec.test.alpha/instrument
来仪器化 fdef
化函数。用一个不符合参数规范的输入调用其中一个函数。当前抛出的异常没有提供很多上下文。
- 异常消息包含 "缺少文件名" 和 "缺少行号",理想情况下这些应该包含违规调用的文件和行号
- 异常数据被编码为包含关于调用者的信息,但当前实现总是会在这里返回
nil
。
结果是,不符合 fdef 参数规范导致的失败没有留下任何关于调用的痕迹——它只告诉你哪个函数的规范没有被满足。
我开始进行调查,发现了一些问题,但没有完整的建议。我正在提供一个迄今为止的补丁,希望得到一些反馈,看看我是否应该继续调查。
到目前为止,我发现了以下内容
**目标**
被视为 "浏览器"
,而它注明在浏览器中的文档是 "默认值"
。第一个补丁已修复。
- 当尝试解析堆栈跟踪以查找调用者时,
host
包含端口号。第二个补丁已解决。
- 尝试解析堆栈跟踪时,使用
goog.userAgent.product
来确定浏览器,但它不可靠——例如,当 Chrome 处于响应式设计模式时,product/IPHONE
是正确的。这是不正确的,同时也是无用的,因为 cljs.spec.test.alpha
完全不识别 iPhone。因为用户代理只用于解析堆栈跟踪,所以我通过从堆栈跟踪中推断用户代理来修复了它。
find-caller
函数使用了错误的包名来查找 spec_checking_fn
。此外,它将点硬编码在包名中,而一些浏览器使用 $
。我在第四个补丁中修复了它。我还将创建错误的操作移出 conform!
匿名函数之外,因为在这里放置它会把 spec-checking-fn
从堆栈跟踪中删除。
使用这些补丁,调用者可以可靠地设置,尽管它似乎没有反映原始的调用位置。此外,抛出的异常仍然缺少文件名和行号。如果您对此感兴趣,我将很高兴继续调查,并添加一些测试。
附注:在我看来,从堆栈跟踪中推断用户代理的功能更合适地放在stacktrace.cljs中,我非常坚定地认为,在没有提供user-agent-product
的情况下,这应该是默认行为(而不是当前的:未修改地返回堆栈跟踪字符串)。如果对此感兴趣,我很乐意修复这个问题,并添加一些测试。请注意,当前的方法允许Safari采取Firefox的路线,效果出奇地好。
最后:如果我在一个地方放了很多东西,我很乐意按照指示拆分。