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

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

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

问题是,浏览器 require 是异步的(至少在 REPL 中是),因此设置全局导出的代码会与加载代码竞争。

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

0

评论由:mfikes

CLJS-2854-1.patch 引入了一种机制,其中 REPL 可以指示它们是否有排队加载后活动的机制,并让浏览器 REPL 参与到这个机制中。使用的名称可能需要清理,特别是如果这导致了 publicly 可用的 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 (由mfikes报告)
...