请在2024 Clojure状态调查中分享您的想法!

欢迎!请参阅关于页面以了解更多有关其工作方式的信息。

0
ClojureScript

目前ExceptionInfo被实现为一个原始构造函数,它继承自js/Error,并通过一些非常规的javascript级别的补丁来满足deftype功能的一个小子集的(主要是为了打印)。

不幸的是,这并不与cljs-devtools(链接:1)很好地配合。这个问题在我开始尝试ExceptionInfo和cljs-devtools v0.8时浮出水面,它新支持打印deftype(链接: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实现移动到deftime本身。

(链接:1) https://github.com/binaryage/cljs-devtools/issues/23
(链接:2) https://github.com/binaryage/cljs-devtools/releases/tag/v0.8.0

8 答案

0

评论由:thheller做出

为什么不在每个{{getBasis}},{{cljs$lang:type}},{{cljs$lang$ctorStr}}上通过{{set!}}添加缺失的部分呢?

此补丁看起来可能会破坏高级编译,但这只是直觉,并没有得到验证,你知道吗?

0
by

评论者:darwin

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

这看起来可能像是一种蹩脚的解决方案,但在我看来,原始代码也是草率的。我的修补程序将跟上未来deftype实现的任何变化。我可以想象当触及deftype时,人们可能会忘记更新这一部分。

顺便一提,还有一个相关的修补程序即将推出,涉及deftype与defrecord之间的差异。如果defrecord与deftype共享相同的实现,这本来是可以避免的。

0
by

评论由:thheller做出

闭包通常对重新定义东西非常严格,但我猜我的直觉是错误的,测试应该涵盖高级模式。

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

是的,你必须做一些清理工作,但当你处理继承时,你不能强加{{deftype}}的规则。

只是我两分钱的意见,重用{{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 0.8.0 调用的旧实现(cljs-devtools 不能识别 ExceptionInfo 类型,但检测到 IPrintWithWriter 并用它来显示值)

0

评论者:mfikes

将 CLJS-1722.patch 添加到补丁仓库(i)

0

评论者:mfikes

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

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