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

欢迎!有关如何操作的更多信息,请参阅关于页面。

+1
ClojureScript
在运行时加载名称空间的顺序与用户代码中要求名称空间的顺序无关。这似乎影响所有优化级别。这意味着开发者不能依赖于在给定名称空间中首先运行具有副作用代码,然后再加载依赖于该副作用的另一个名称空间。

复现步骤

执行以下命令


clj --main cljs.main --compile-opts '{:target :nodejs :main a}' --compile a


将编译在{{a.cljs}}中定义的{{a}}名称空间。该名称空间通过ns宏的{{:require}}形式按字母顺序要求从{{b}}到{{g}}的名称空间。

编译后,请注意以下内容

在输出文件{{out/cljs_deps.js}}中为{{a.js}}的{{goog.addDependency}}调用以任意顺序包含其依赖项。例如,在我的机器上的一次运行中产生了以下结果:


goog.addDependency("../a.js", ['a'], ['cljs.core', 'e', 'c', 'g', 'b', 'd', 'f']);


通过运行编译代码{{node out/main.js}},给定的控制台输出表示运行时加载顺序与{{out/cljs_deps.js}}中反映的顺序相同。


{{e}}的主体

{{c}}的主体

{{g}}的主体

{{b}}的主体

{{d}}的主体

{{f}}的主体


分析

看起来有一些工作量确保编译时的顺序作为[CLJS-1453](
似乎给定ClojureScript文件的{{cljs_deps.js}}输出最终由{{cljs.compiler/emit-source}}的输出决定。那里的代码以与CLJS-1453之前在{{cljs.analyzer}}中使用的'ns'解析方法相同的方式删除重复的依赖项。

附带的补丁解决了我的近期用途中的问题,但我相信底层函数将`:uses`和`:requires`作为映射传递,因此可能还需要更多工作才能得到完整的解决方案。

11个答案

0

评论由:chancerussell 发表

为打扰到票据中的markdown表示法,我本以为可以在提交后清理。

0

评论由:mfikes 发表

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

0

评论由:thheller 发表

附件的补丁仍然使用{{deps}}映射,这只能保持插入顺序,直到达到数组映射阈值,一旦开始使用哈希映射,项就不再有序。在shadow-cljs中,我通过除通常的{{:requires}}映射外,还维护附加的{{:deps}}向量来处理这个问题。

0
_评论由:chancerussell_

这可能是最好的解决方案——我不想尝试修改现有代码中映射的类型。

我将在今晚查看这个问题——柳树编译器对CLJS-1453的补丁可能也存在同样的问题。

话虽如此,我很好奇当ns形式中同时包含:require和:use时,排序的语义应该是什么?
0

评论由:thheller 发表

看起来已经在分析器解析的'ns和'ns**中维护了{{:deps}}向量。只需在cljs.compiler/emit-source fn中用到这个向量,而不是取requires/uses映射的值。

0

评论由:chancerussell 发表

托马斯是对的,{{:deps}}向量确实存在,并且按预期顺序排列,因此我已经提交了一个使用该向量的新补丁。

一个问题是——当都存在时,{{cljs.core}} 和 {{cljs.core.constants}} 的顺序应该是什么?显然,之前的代码并没有保证顺序,但我想确保这是正确的。

(测试 test-cljs-1882-constants-table-is-sorted 似乎暗示 cljs.core 应该排在前面。)

0

评论由:mfikes 发表

2019年3月24日下午12:58的 CLJS-3056.patch 通过了CI和Canary测试(/)

0

评论由:dnolen 提出

{{cljs.core}} 必须在 {{cljs.core.constants}} 前面,因为如果没有定义关键字构造函数,{{cljs.core.constants}} 将无法工作。如果不是这种保证的顺序,我们将会听到很多关于失败的高级构建的抱怨。

0

评论由:chancerussell 发表

David,当你说“顺序肯定被保证”时,你是指只是 {{cljs.core}} 和 {{cljs.core.constants}},还是整个依赖项?当前的代码将 {{conj}} 添加到集合中,根据我所知,这并不保证维护任何顺序。

0

评论由:mfikes 发表

呼,我弄错了:CLJS-3056.patch 在 Windows CI 测试中失败(x)

特别是,它在 {{cljs-2077-test-loader}} 中引起堆栈溢出

错误在 (cljs-2077-test-loader) (core.clj:6077) 397未在断言中捕获的异常。 398预期值:nil 399实际值:java.lang.StackOverflowError: null 400 在 clojure.core$get_in.invokeStatic (core.clj:6077) 401 cljs.module_graph$deps_for.invokeStatic (module_graph.cljc:147) 402 cljs.module_graph$deps_for.invoke (module_graph.cljc:147) 403 clojure.lang.AFn.applyToHelper (AFn.java:160) 404 clojure.lang.AFn.applyTo (AFn.java:144) 405 clojure.core$apply.invokeStatic (core.clj:657) 406 clojure.core$memoize$fn__6665.doInvoke (core.clj:6288) 407 clojure.lang.RestFn.invoke (RestFn.java:436) 408 cljs.module_graph$deps_for$fn__7089.invoke (module_graph.cljc:151) 409 clojure.core$map$fn__5665.invoke (core.clj:2745) 410 clojure.lang.LazySeq.sval (LazySeq.java:40) 411 clojure.lang.LazySeq.seq (LazySeq.java:49) 412 clojure.lang.RT.seq (RT.java:528) 413 clojure.core$seq__5202.invokeStatic (core.clj:137) 414 clojure.core$apply.invokeStatic (core.clj:652) 415 clojure.core$mapcat.invokeStatic (core.clj:2775) 416 cljs.module_graph$deps_for.invokeStatic (module_graph.cljc:147) 417 cljs.module_graph$deps_for.invoke (module_graph.cljc:147) 418 clojure.lang.AFn.applyToHelper (AFn.java:160) 419 clojure.lang.AFn.applyTo (AFn.java:144) 420 clojure.core$apply.invokeStatic (core.clj:657)

CI构建: https://ci.appveyor.com/project/mfikes/clojurescript/builds/24478525

0
参考:[https://clojure.atlassian.net/browse/CLJS-3056](https://clojure.atlassian.net/browse/CLJS-3056) (由 chancerussell 报告)
...