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

欢迎!请查看关于页面以了解更多关于如何使用本站的信息。

0
ClojureScript
大家好,我在使用1.10.439版本时,在require外部库时遇到了错误

我的项目设置根据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 不是函数
    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}} 中移除 {{var module$D_$sandbox$cljs$modules$src$js$hello={};}} 使程序正常运行

所以生成的 {{./out/src/js/hello.js}} 似乎声明了一个局部变量,它遮挡了 GCC 命名空间对象,这导致局部赋值不会使用真实的命名空间对象。

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 {}

此测试旨在打印导出函数的 JavaScript 库的内容,但打印了一个空对象。这与上面重现的情况类似。

为了检测此类失败,测试套件也需要以 node 或浏览器的形式执行输出。

据我所知,主分支和 {{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报告)
...