如何 return 从 scala.js 中的宏调用 require

how to return a require call from macro in scala.js

问题: 想要 return () => require(path) from macro

def gql(args: js.Any*): js.Function0[js.Any] = macro rqlMacroImpl
//impl
val generatedFilePath = ...
   c.Expr[js.Function0[js.Any]](q"""
        {
           import scala.scalajs.js
                      import scala.scalajs.js.annotation.JSImport

            val func:js.Function0[js.Any] = () => require($generatedFilePath)// I want to return require(...)
            func
        }
     """)

目前已尝试

//impl
    val generatedFilePath = ...
       c.Expr[js.Function0[js.Any]](q"""
            {
               import scala.scalajs.js
                          import scala.scalajs.js.annotation.JSImport
                @js.native
                @JSImport($generatedFilePath,JSImport.Default)
                object GQlImport extends js.Object
                val func:js.Function0[js.Any] = () => GQlImport
                func
            }
         """)

失败 Local native object/classes not allowed

解决方法:

使用 js.Dynamic.global.require(path) 并在 sbt 任务中将 $g.require( 替换为 require(

有更好的选择.. ?

不能那样做,因为@JSImport必须是顶层的,宏只能在非顶层的地方调用。

@JSImport 必须是顶级的原因是它 在语义上 不对应 require。相反,它对应于 ES2015 中的 import。当以 CommonJS 模块为目标时,他们 脱糖为 require,但这是一种特殊情况。 require 的动态使用不能用 ES2015 中的 import 来写,因此也不能用 @JSImport 来写。

现在您必须将 $g.require 调整为 require 的原因是另一个问题。过去的情况是,这只是 Node.js 以不符合规范的方式劫持 JavaScript,并且 Scala.js 不允许您访问它。现在事实证明,ES2015 使那个特殊的 require 东西变得有效,所以最终你将能够通过 https://github.com/scala-js/scala-js/issues/2800

在 Scala.js 中本地访问它