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

欢迎!请参阅关于页面,了解有关如何使用此功能的更多信息。

0 投票
ClojureScript
影响:1.9.1033+

您可以在以下最小化代码库中找到示例:https://github.com/au-phiware/cljs-2818

2. 问题描述

在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}}语句集。

2. 问题复现步骤

考虑以下源文件

{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


2. 预期结果

{{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"], [];
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"];


2. 实际结果

缺失{{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"]}}


此外,浏览器控制台显示


>>> module$usr$src$es6$hello.helloGreet
hello.js:2 未捕获的ReferenceError: module$usr$src$es6$greet没有定义
    在Object.get helloGreet [作为helloGreet] (hello.js:2)
    在 <匿名>:1:65


h2. 尝试修复问题

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

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 的 bug。

0 投票
0 投票
参考:https://clojure.atlassian.net/browse/CLJS-2818(由 phiware 提出)
...