Standard way with for `@JSExportTopLevel` when Exporting under a namespace in `scala-js 1.x.x`

Viewed 75

I have two classes with the same name A having different package one as: -

xxx.yyy.v1.A

and second as:-

xxx.yyy.v2.A

I have to use @JSExportTopLevel in scala-js (1.1.1).

What is the standard way of accomplishing this?

Previously in scala-js (0.6.x), I used something like this: -

@JSExportTopLevel("xxx.yyy.v1.A")

and

@JSExporttopLevel("xxx.yyy.v2.A")

but with scala-js (1.1.1 ), it is now removed. Exporting under a namespace (deprecated)

Note:- I am facing this issue in scala-js upgrade 0.6.x -> 1.x.x

My configuration: -

scala -> 2.13.3, jvm -> 14, sbt -> 1.3.13, scala-js -> 1.x.x

1 Answers

Exporting under a namespace was deprecated in Scala.js 0.6.26 and eventually removed in 1.x because such exports do not correspond to anything in terms of ECMAScript module exports. The compiler had to jump through non-standard hoops to make them appear to work.

As the release notes of 0.6.26, linked above, explain, the replacement is to explicitly construct a JS object that will hold those namespaces and the values to export. In your case:

object JSNamespacesExports {
  @JSExportTopLevel("xxx")
  val xxx = new js.Object {
    val yyy = new js.Object {
      val v1 = new js.Object {
        val A = _root_.xxx.yyy.v1.A
      }

      val v2 = new js.Object {
        val A = _root_.xxx.yyy.v2.A
      }
    }
  }
}

(_root_. is used to force resolving xxx as a top-level Scala package, instead of the val xxx that is in scope.)

With this encoding, you explicitly choose how you want xxx to appear, as seen from JavaScript. This is more transparent than the opaque, half-baked implementation that Scala.js 0.6.x was using.

Related