2024年Clojure调查问卷中分享您的想法!

欢迎!请参阅关于页面以获取有关如何使用本网站的更多信息。

0
ClojureScript

目前ExceptionInfo以原始构造函数的形式实现,继承自js/Error,并带有一些临时的JavaScript级别补丁以满足deftype功能的一小部分需求(主要是用于打印)。

不幸的是,这并不与cljs-devtools(link: 1)协同工作。当我开始使用ExceptionInfo和 cljs-devtools v0.8(新支持打印deftype(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,并使用定义类型的构造函数对重新定义的构造函数进行了包装,以实现向后兼容。
我们还修补了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
by

评论由:thheller 发布

为什么不在每个 set! 操作中简单地添加缺失的 {{getBasis}}, {{cljs$lang$type}}, {{cljs$lang$ctorStr}} 块呢?

这个补丁看起来可能会搞砸高级编译,但这只是一个直觉,并没有实际验证过,是这样吗?

0
by

评论由:darwin 发布

我运行了 clojurescript 测试,我假设他们也针对高级模式的构建运行。在开发期间,当我的测试失败时,我看到了有关最小化名称的错误信息。

这看起来可能是一个黑客解决方案,但在我看来,原始代码也是一个黑客解决方案。我的解决方案将与未来对 deftype 实现的任何更改保持同步。我可以想象,当触摸 deftype 时,人们可能会忘记更新这部分。

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

0
by

评论由:thheller 发布

Closure 大多数情况下对重新定义东西很严格,但我想我的直觉是错误的,测试应该涵盖高级模式。

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

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

这只是我的2便士的意见,重用 {{deftype}} 也具有优点(正如你建议的那样)。

0
by

评论由:darwin 发布

不幸的是,我无法查找任何评论或文档来解释我们为什么要在那里做 js/Error 继承的原因。

我第一次尝试“修复”ExceptionInfo 是简单地将它实现为一个普通的 deftype,这效果很好(对于我的测试)。然后我尝试在顶部重新实现原始行为,以便使其与100%兼容。

0
by

评论由: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报告)
...