请在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
by

评论者:filipematossilva

嗨,按照您的步骤,我可以重现您所看到的情况。

实际上在运行{{clj ./watch.clj}}时有一个警告。

WARNING: 标准库`js.hello`的classpath上发现了JavaScript文件,但没有包含相应的`goog.provide`声明:file:/D:/sandbox/cljs/modules/src/js/hello.js

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

因此,生成的{{./out/src/js/hello.js}}似乎声明了一个局部变量,它遮蔽了GCC命名空间对象,然后导致局部赋值没有使用实际的命名空间对象。

0
by

评论者:filipematossilva

对此进行了进一步的调查。有一个测试应该包含这个链接

但是问题只会在运行时出现,而不会在构建时出现。我修改了该测试的输出以不删除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
by

评论者: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 报告)
...