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

欢迎!请访问关于页面了解更多关于它的工作方式的信息。

0
ClojureScript

目前 ExceptionInfo 以原始构造函数的形式实现,继承自 js/Error,并添加了一些临时的 JavaScript 级别补丁以满足一小部分 deftype 功能(主要针对打印)。

不幸的是,这与 cljs-devtools(链接:1)不相兼容。当我在 ExceptionInfo 和 cljs-devtools v0.8(新支持打印 deftype 的函数,链接:2)上实验时出现这个问题。ExceptionInfo 不包含 getBasis,cljs$lang白糖tor,cljs.lang$ctorStr 等类似机制。

我提出的补丁将 ExceptionInfo 实现为一个正确的 deftype,并进行了一些补丁以提供向后兼容性。我坚信我们不应该打破 ExceptionInfo 构造函数接受 3 个参数并在构造函数中动态生成其他字段的当前约定。

实现细节
1) 首先,我们将 ExceptionInfo 定义为正常的 deftype(以获取模板)
2) 然后我们记住 ExceptionInfo 在 ExceptionInfoTypeTemplate 中的引用
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! 调用时都添加缺少的 {{getBasis}}、{{cljs$lang$type}}、{{cljs$lang$ctorStr}} 块呢?

这个补丁看起来可能会弄乱高级编译,尽管这只是直觉,不是经过验证的,你验证过吗?

0

评论由:darwin 发表

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

这可能看起来像一个修补方案,但在我看来,原始代码也是一个修补方案。我的修补方案将随着 deftype 实现的未来更改保持最新。我可以想象人们会在触摸 deftype 时忘记更新这部分。

顺便说一下,还有一个补丁即将推出,涉及 deftype 和 defrecord 之间的差异。如果 defrecord 与 deftype共享通用实现,这本来可以避免。

0

评论由:thheller 发表

Closure 通常对其内容的重新定义非常严格,但我想我的直觉是错误的,测试应该覆盖高级模式。

我对此的看法是,{{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添加到Patch Tender (i)

0

评论者:mfikes

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

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