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

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

0
ClojureScript
嗨,各位,我在使用 1.10.439 版本时在导入外部库时遇到错误。

我的项目根据 https://script.clojure.org/guides/javascript-modules, 安装,但没有使用 leiningen。

所以,有 deps.edn,{{\{:deps {org.clojure/clojurescript \{:mvn/version "1.9.908"\}\}\}}}

{code:title=watch.clj}
(require '[cljs.build.api :as b])

(b/watch "src"
  {:output-to    "main.js"
   :output-dir   "out"
   :main         'hello-es6.core
   :target       :nodejs
   :foreign-libs [{:file "src"
                   :module-type :es6}] ;; 或 :commonjs / :amd
   :verbose      true})


然后我已经根据说明将这些 cljs 和 js 文件复制过来

src/
├── hello_es6
│   └── core.cljs
└── js
    └── hello.js


然后我可以执行 {{clj ./watch.clj}} (使用 clojure 1.9) 并正常工作,{{node main.js}} 打印出预期的消息。但如果我仅仅是将 deps.edn 更改为 {{\{:deps \{org.clojure/clojurescript \{:mvn/version "1.10.439"\}\}\}},它就会中断。首先,出现关于 clj-oss/module-deps 的错误,好吧,我本想使用 npm,所以我安装了它,然后在进行了一次清缓存和重新编译后,出现了以下错误:


$ node main.js
/Users/jb/src/hello-es6/out/hello_es6/core.js:28
return module$Users$jb$src$hello_es6$src$js$hello.sayHello();
                                                  ^

TypeError: module$Users$jb$src$hello_es6$src$js$hello.sayHello is not a function
    at Function.cljs$core$IFn$_invoke$arity$variadic (/Users/jb/src/hello-es6/out/hello_es6/core.js:28:51)
    at hello_es6$core$_main (/Users/jb/src/hello-es6/out/hello_es6/core.js:24:29)
    at Object.cljs$core$apply_to [as apply_to] (/Users/jb/src/hello-es6/out/cljs/core.js:12956:81)
    at Function.cljs$core$IFn$_invoke$arity$2 (/Users/jb/src/hello-es6/out/cljs/core.js:13400:18)
    at cljs$core$apply (/Users/jb/src/hello-es6/out/cljs/core.js:13358:24)
    at Object.<anonymous> (/Users/jb/src/hello-es6/out/AEF573C.js:10:17)
    at Module._compile (internal/modules/cjs/loader.js:722:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:733:10)
    at Module.load (internal/modules/cjs/loader.js:620:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:560:12)


添加 {{:npm-deps true}} 到编译器选项后,错误依然存在。

4 个答案

0

由:filipematossilva

嗨,按照您的步骤,我能够重现您所看到的问题。

实际上,在运行{{clj ./watch.clj}}时会有一条警告信息。

警告:在类路径上发现与库`js.hello`相关的JavaScript文件,但未包含相应的`goog.provide`声明:文件:/D:/sandbox/cljs/modules/src/js/hello.js

我在生成的JS文件中进行了修改,运行{{node ./main.js}},发现以下情况:
- {{./out/src/js/hello.js}}已加载
- {{main.js}}中的{{module$D_$sandbox$cljs$modules$src$js$hello}}已定义但为空对象
- 在{{./out/src/js/hello.js}}中修改{{module$D_$sandbox$cljs$modules$src$js$hello}}并不影响{{main.js}}
- 从{{./out/src/js/hello.js}}中移除{{var module$D_$sandbox$cljs$modules$src$js$hello={};}}可以使程序正常运行

所以,生成的{{./out/src/js/hello.js}}似乎 declaring a local variable that shadows the GCC namespace object,导致 local assignments 不使用实际的 namespace object。

0

由:filipematossilva

我对此进行了进一步的调查。应该覆盖这个功能的测试位于https://github.com/clojure/clojurescript/blob/master/src/test/clojure/cljs/build_api_tests.clj#L540-L563中。

但问题并没有在构建时出现,只有在运行时才会出现。我对那个测试的输出进行了修改,以不删除 out 和 node_modules 目录,并添加了以下构建选项

`

          :target       :nodejs
          :output-to "main.js"
          :main 'foreign-libs-cljs-2334.core

`

然后运行了测试,并用 node 运行了结果

kamik@RED-X1C6 MINGW64 /d/sandbox/cljs/clojurescript (master) $ node main.js mylib: #js {}

这个测试本意是打印一个导出函数的js库的内容,但打印了一个空对象。这与上面的复现相似。

为了检测这种失败,测试集需要也执行 node 或浏览器的输出。

据我所知,master 和{{1.10.516}}版本(最新版本)在这个情况下都生成了不可正常运行的代码。

但是,不清楚问题根源是什么。可能是 GCC 或其配置问题。

0

由:filipematossilva

https://github.com/clojure/clojurescript/blob/c4a5120294aa83b8f69d35ce10e5d03c951d99ea/.travis.yml#L24-L46中对此功能的测试,但该测试似乎没有失败 Travis(https://travis-ci.org/mfikes/clojurescript/builds/540710982#L2084)。我认为回归是意外引入的,因为它没有被 CI 失败。

0
参考:https://clojure.atlassian.net/browse/CLJS-2992(由 alex+import 报告)
...