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

欢迎!请访问关于页面以了解有关此如何工作的更多信息。

0
ClojureScript
影响:1.9.1033+

以下是这个最小化复现库:https://github.com/au-phiware/cljs-2818

h2. 问题描述

在 CLJS-2389 中更新 Closure 编译器之前,使用 {{export { x as y } from './x'}} 或 {{export { default as y } from './x'}} 语法的 ES6 模块可以正确编译。这种语法的其他形式,如 {{export { default } from './x'}}, 则不适用。

从 1.9.1033 开始,编译器不再发出 {{goog.require}} 语句,也不会在 {{cljs_deps.js}} 中发出一组完整的 {{goog.addDependency}} 语句。

h2. 重复问题的步骤

考虑以下源文件

{code:title=src/foo/core.cljs|language=clojure}
(ns foo.core (:require [hello :refer [helloGreet]]))                                 

(def ^:export sayHello
    (helloGreet "World"))

(sayHello)


{code:title=es6/hello.js|language=javascript}
export {
    default as helloGreet
} from "./greet";


{code:title=es6/greet.js|language=javascript}
export default function greet(m) {
    document.write("\nHello, " + m);
};


{code:title=build.clj|language=clojure}
(require 'cljs.build.api)

(cljs.build.api/build
  "src"
  {:main 'foo.core
   :output-to "target/main.js"
   :output-dir "target/main.out"
   :asset-path "main.out"
   :foreign-libs [{:file "es6/hello.js"
                   :provides ['hello]
                   :module-type :es6}]
   :verbose true
   :npm-deps {"@cljs-oss/module-deps" "*"}
   :install-deps true})


执行 {{cljs}}


java -cp cljs.jar:src clojure.main build.clj


h2. 预期结果

{{cljs}} 应正常退出并写入以下文件(大致如此)。

{code:title=target/main.out/cljs_deps.js|language=javascript}
goog.addDependency("base.js", ['goog'], []);
goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.Uri', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
goog.addDependency("../es6/greet.js", ['module$usr$src$es6$greet'], []);
goog.addDependency("../es6/hello.js", ['module$usr$src$es6$hello'], ['module$usr$src$es6$greet']);
goog.addDependency("../foo/core.js", ['foo.core'], ['cljs.core', 'module$usr$src$es6$hello']);


{code:title=target/main.out/es6/hello.js|language=javascript}
goog.provide("module$usr$src$es6$hello");
goog.require("module$usr$src$es6$greet");
module$usr$src$es6$hello.helloGreet=module$usr$src$es6$greet["default"]


h2. 实际结果

{{cljs_deps.js}} 缺少 {{es6/greet.js}} 依赖项

{code:title=target/main.out/cljs_deps.js|language=javascript}
goog.addDependency("base.js", ['goog'], []);
goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.Uri', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
goog.addDependency("../es6/hello.js", ['module$usr$src$es6$hello'], []);
goog.addDependency("../foo/core.js", ['foo.core'], ['cljs.core', 'module$usr$src$es6$hello']);


{{es6/hello.js}} 文件缺少 {{goog.requires}} 语句

{code:title=target/main.out/es6/hello.js|language=javascript}
goog.provide("module$usr$src$es6$hello");
var module$usr$src$es6$hello={get helloGreet(){return module$usr$src$es6$greet["default"]}}


并且浏览器控制台显示


>>>> 模块$usr$src$es6$hello.helloGreet
hello.js:2 未捕获的引用错误: module$usr$src$es6$greet 未定义
    在 hello.js:2 的 Object.get helloGreet [作为 helloGreet]
    在 <匿名>:1:65


h2. 尝试解决方案

明确将 {{:requires}} 选项添加到 {{es6/hello.js}} {{:foreign-libs}} 条目并不能解决这个问题(使用整个 {{es6}} 目录的条目或使用 npm 模块,例如 d3-scale)也不能。将 {{[greet]}} 添加到 {{foo.core}} 的 requires 也不能。

6 答案

0

评论由: phiware

这似乎是 Google Closure Compiler 的上游问题...

0

评论由: phiware

使用 gcc 将相同的 es6 代码编译出来了,使用命令 {{java -jar $JAR -O WHITESPACE_ONLY --js_output_file=/dev/stdout -W VERBOSE --module_resolution NODE greet.js hello.js}}。但当 cljs 调用 gcc 将 es6 代码转换成结果源代码时,缺少了 {{goog.require}} 语句...可能是 module_resolution 吗?

0

评论由: phiware

我发现 gcc 使用 {{-O BUNDLE --dependency_mode STRICT}} 无法产生 greet 依赖...这时我很困惑...

0

评论由: phiware

如果我将此补丁应用到 gcc,那么它将检测到 hello.js 的正确 requires

`
diff --git a/src/com/google/javascript/jscomp/CompilerInput.java b/src/com/google/javascript/jscomp/CompilerInput.java
index 62609562b..4e4d3e3dc 100644
--- a/src/com/google/javascript/jscomp/CompilerInput.java
+++ b/src/com/google/javascript/jscomp/CompilerInput.java
@@ -285,7 +285,7 @@ public class CompilerInput extends DependencyInfo.Base implements SourceAst {

 // If the code is a JsAst, then it was originally JS code, and is compatible with the
 // regex-based parsing of JsFileParser.
  • if (ast instanceof JsAst && JsFileParser.isSupported()) {
    • if (false && ast instanceof JsAst && JsFileParser.isSupported()) {
      // 查看源代码。
      // 注意:这里可以使用 getName() 而不是
      // getPathRelativeToClosureBase(),因为我们不使用
      `

但是现在 cljs 认为greet 应该命名为 {{"module$usr$src$greet"}},而不是 {{"module$usr$src$es6$greet"}},但这似乎也是一个 gcc 的错误。

0
0
参考资料:https://clojure.atlassian.net/browse/CLJS-2818(phiware报告)
...