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

欢迎!有关如何使用该页面的更多信息,请查看关于页面。

0
ClojureScript
{code:title=mylib.js}
mylib = { abc: 3 }


{code:title=co.edn}
{:foreign-libs [{:file "mylib.js"
                 :provides ["my-lib"]
                 :global-exports {my-lib mylib}}]}


重现


$ clj -m cljs.main -co co.edn -r
ClojureScript 1.10.339
cljs.user=> (require 'my-lib)

cljs.user=> my-lib/abc
TypeError: Cannot read property 'abc' of undefined
     (<NO_SOURCE_FILE>)
cljs.user=> (require 'my-lib)

cljs.user=> my-lib/abc
3


在 Node 和 Nashorn REPL 中不会出现这种情况。

7 条回答

0

评论者:mfikes

问题是浏览器要求是异步的(至少在 REPL 中),因此设置全局导出的代码与加载代码抢跑了。

CLJS-2854-0.patch 通过有条件地排队代码(在浏览器 REPL 中)并在加载队列清空后执行它来探索解决这个问题(尚未包括测试等)。

0

评论者:mfikes

CLJS-2854-1.patch 引入了一种机制,允许 REPL 指示它们是否有排队的后加载活动的方式,浏览器 REPL 参与了这个机制。使用的名称可以进行清理,特别是如果这导致了公用的 API,REPL 可以使用它。

0

评论者:mfikes

使用以下代码

`
(ns foo.core
(:require my-lib))

(def x my-lib/abc)
`

该补丁可以解决这个问题

`
$ clj -m cljs.main -co co.edn -r
cljs.user=> (require 'foo.core)

cljs.user=> foo.core/x
3
`

0

评论者:dnolen

为了更清楚地说明问题 - 问题是 REPL 中的 (require ...) 形式隐式地位于 cljs.user 中,这意味着直接对包含全局导出的库进行的要求将发生竞态,因为该库的导出映射紧随该库的 (goog.require),但那将是异步加载,因此不会工作。这不会影响传递情况。

0

评论者:mfikes

CLJS-2854-2.patch 通过简单地使用超时尝试避免竞态,试图保持编译器代码中的逻辑。

0

评论者:mfikes

CLJS-2854-2.patch 已不再适用。

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