Clojure 2024状态调查!中分享你的想法。

欢迎!请查看关于页面以了解更多关于如何工作的信息。

0
ClojureScript

当前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

8 答案

0

评论由:thheller 发布

为什么不在每个 set! 调用时添加缺少的 {{getBasis}}、{{cljs$lang$type}}、{{cljs$lang$ctorStr}} 块呢?

补丁看起来可能会弄乱高级编译,但这只是直觉,还没有证实,你确认了吗?

0

评论由:darwin 发布

我运行了 ClojureScript 测试,并且我假设它们也适用于高级模式构建。在开发期间,当我的测试失败时,我看到了有关压缩名称的错误消息。

这可能看起来像是一个笨拙的解决方案,但据我所知,原始代码也有点笨拙。我的解决方案将随着 deftype 实现的未来变化保持最新。我可以想象到,当修改 deftype 时,人们会忘记更新这部分。

顺便说一下,还有一个与 deftype 和 defrecord 之间差异相关的补丁即将到来。如果 defrecord 与 deftype 共享相同的实现,那么这种情况本可以避免的。

0

评论由:thheller 发布

Closure 通常对重新定义内容非常严格,但我想我的直觉是错误的,测试应该涵盖高级(advanced)。

我对这个问题的问题是,{{deftype}} 是用于定义 Clojure 特定类型的。ExceptionInfo 不是,因为它继承自 Error,就像在 Clojure 中你不能有一个超类一样,你也不能在 CLJS 中这样做。所以如果我们将来要更改 {{deftype}},我们可能会以意想不到的方式破坏某些事物,这些事物只是重新使用了 {{deftype}},但实际上并不是 {{deftype}}。

是的,你必须做一些家务,但在处理继承时你不能强制执行 {{deftype}} 的规则。

只是我两分钱的想法,重新使用 {{deftype}} 也有好处(正如你所建议的)。

0

评论由:darwin 发布

不幸的是,我无法找到任何评论或文档解释为什么我们在那里进行 js/Error 继承。

我第一次尝试“修复”ExceptionInfo 是将它简单地实现为一个普通的 deftype。这效果很好(对我测试而言)。然后我尝试重新实现原始行为,只是为了使其完全兼容。

0

评论由:darwin 发布

仅添加一个激励性的截图

https://box.binaryage.com/CLJS-1722-example.png

那些黄色警告列出了通过gobject/extend调用被复制的属性。
扩展的日志条目是通过cljs-devtools v0.8.0新实现并记录的。
最后的日志条目是通过cljs-devtools v0.8.0(cljs-devtools不识别ExceptionInfo为CLJS类型,但检测到IPrintWithWriter并使用它来显示值)记录的老实现。

0

评论者:mfikes

将CLJS-1722.patch添加到修补程序之中(i)

0

评论者:mfikes

CLJS-1722.patch通过CI和Canary测试(/)

0
参考: https://clojure.atlassian.net/browse/CLJS-1722(由darwin报告)
...