目前ExceptionInfo以原生构造函数的形式实现,从js/Error继承了部分专用的javascript级补丁,以满足deftype功能的一小部分需求(主要是用于打印)。
不幸的是,这与cljs-devtools(链接:1)不太兼容。当我和ExceptionInfo以及支持打印deftype的新功能v0.8的cljs-devtools(链接:2)一起玩耍时,出现了这个问题。ExceptionInfo不包含getBasis、cljs$lang$type、cljs$lang$ctorStr和类似机制。
我提出的补丁将ExceptionInfo实现为适当的deftype,并做了一些修补工作以提供向后兼容性。我非常确信我们不应该打破当前ExceptionInfo构造函数接受3个参数并在构造函数中现场合成其他字段的约定。
实现细节
1) 首先,我们将ExceptionInfo定义为一个正常的deftype(以获取模板)
2) 然后我们在ExceptionInfoTypeTemplate中记住对ExceptionInfo的引用
3) 然后我们用原生构造函数重新定义ExceptionInfo,该函数应该模仿原始行为(通过刮取新创建的js/Error实例,但调用ExceptionInfoTypeTemplate以进行适当的deftype初始化)
4) 然后我们将ExceptionInfoTypeTemplate中的键复制到ExceptionInfo
5) 然后将ExceptionInfo的原型设置为ExceptionInfoTypeTemplate的原型
6) 然后将ExceptionInfo原型的构造函数指向我们的重新定义的构造函数
7) 然后我们修补ExceptionInfo的原型以从js/Error继承(注意这也会覆盖ExceptionInfoTypeTemplate - 但我们对此不感兴趣)
这实际上使我们得到了一个具有重定构造函数的deftype来有效地工作,该构造函数会包装deftype的构造函数以提供向后兼容性。
我们还修补ExceptionInfo的原型以便以与原始代码相同的方式从js/Error继承。
注意:在有工作deftype的情况下,我们可以将IPrintWithWriter和toString实现移动到deftype本身。
(链接:1)https://github.com/binaryage/cljs-devtools/issues/23
(链接:2)https://github.com/binaryage/cljs-devtools/releases/tag/v0.8.0