请分享您的想法,参加2024年Clojure状态调查!

欢迎!请查阅关于页面,了解更多有关此功能的信息。

0
ClojureScript

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

不幸的是,这与cljs-devtools(链接:1)不兼容。当我在尝试使用ExceptionInfo和新的支持打印deftype的cljs-devtools v0.8时,这个问题出现了。(链接: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本身中。

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

8 答案

0

评论者:thheller

为什么不在每个set!操作时都添加缺失的getBasiscljs$lang$typecljs$lang$ctorStr部分呢?

补丁看起来可能会搞乱高级编译,但这只是直觉,并没有经过验证,你是否也已经验证过?

0

评论者:darwin

我运行了ClojureScript测试,并假设也针对高级模式构建进行了运行。在开发过程中,当我的测试失败时,我看到有关压缩名称的错误信息。

这可能看起来像一个投机取巧的解决方案,但在我看来,原始代码也是一个投机取巧的解决方案。我的投机取巧的解决方案将与deftype实现的未来变化保持同步。我可以想象当触摸deftype时,人们可能会忘记更新这部分。

顺便说一下,还有一个相关的补丁即将推出,该补丁是与deftype和defrecord之间的不一致性相关。如果defrecord与deftype共享公共实现,那么这种情况是本可以避免的。

0

评论者:thheller

Closure通常会非常严格地处理重复定义的内容,但我想我的直觉是错误的,测试应该涵盖高级模式。

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

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

这只是我个人的2美分想法,重复使用{{deftype}}也有好处(就像你建议的那样)。

0

评论者:darwin

不幸的是,我无法找到任何评论或文档来解释我们那样进行js/Error继承的原因。

我将ExceptionInfo "修复" 的第一次尝试是简单地将其实现为一个普通的deftype。这_literal工作得很好_(对于我的测试)。然后我尝试在顶部重新实现原始行为,仅为此使其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
by

评论者:mfikes

已在 Patch Tender (i) 中添加 CLJS-1722.patch

0
by

评论者:mfikes

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

0
by
参考资料:https://clojure.atlassian.net/browse/CLJS-1722(由 darwin 汇报)
...