如何在scala.js中从宏返回require调用

时间:2017-04-25 05:10:32

标签: scala macros scala.js

问题:想要返回()=>从宏

需要(路径)
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(

更好的选择..?

1 个答案:

答案 0 :(得分:1)

你不能这样做,因为@JSImport必须是顶级的,而宏只能在不是顶级的地方调用。

@JSImport必须是顶级的原因是在语义上与require对应。相反,它对应于ES2015中的import。当针对CommonJS模块时,他们 desugar 进入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中本地访问它。