当前ExceptionInfo被实现为一个原生构造函数,继承自js/Error,并添加一些临时的JavaScript级别的补丁以满足一些deftype功能的一小部分(主要是打印)。
不幸的是,这与cljs-devtools(link: 1)配合得不是很好。当我开始使用ExceptionInfo和(cljs-devtools v0.8)时,这个问题出现了,它是新支持打印deftypes(link: 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 - 但我们不在乎它)
这有效地为我们提供了具有重新定义的构造函数的适当工作的ExceptionInfo deftype,该构造函数包装了deftype的构造函数以提高向后兼容性。
我们还修补ExceptionInfo的原型以继承自js/Error,就像原始代码一样。
注意:随着deftype的有效工作,我们可以将IPrintWithWriter和toString实现移到deftype本身。
(link: 1) https://github.com/binaryage/cljs-devtools/issues/23
(link: 2) https://github.com/binaryage/cljs-devtools/releases/tag/v0.8.0