diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08cc7d8..98ceea2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,9 @@ jobs: - uses: VirtusLab/scala-cli-setup@9bc68588ab2d49dae03e5395a5f411e20914f97e with: jvm: "temurin:17" + - uses: actions/setup-node@v4 + with: + node-version: '22' - name: Test CLI run: ./mill -i 'tests.test' @@ -60,6 +63,9 @@ jobs: - uses: coursier/setup-action@v1.2.0-M3 with: jvm: temurin:17 + - uses: actions/setup-node@v4 + with: + node-version: '22' - run: | ./mill -i "native.writeNativeImageScript" generate.sh "" && \ ./generate.sh && \ @@ -98,6 +104,9 @@ jobs: - uses: coursier/setup-action@v1.2.0-M3 with: jvm: temurin:17 + - uses: actions/setup-node@v4 + with: + node-version: '22' - run: | ./mill -i "native-static.writeNativeImageScript" generate.sh "" && \ ./generate.sh && \ @@ -128,6 +137,9 @@ jobs: - uses: coursier/setup-action@v1.2.0-M3 with: jvm: temurin:17 + - uses: actions/setup-node@v4 + with: + node-version: '22' - run: | ./mill -i "native-mostly-static.writeNativeImageScript" generate.sh "" && \ ./generate.sh && \ diff --git a/cli/src/org/scalajs/cli/Scalajsld.scala b/cli/src/org/scalajs/cli/Scalajsld.scala index 4daac42..937588d 100644 --- a/cli/src/org/scalajs/cli/Scalajsld.scala +++ b/cli/src/org/scalajs/cli/Scalajsld.scala @@ -54,7 +54,8 @@ object Scalajsld { jsHeader: String = "", logLevel: Level = Level.Info, importMap: Option[File] = None, - longRunning: Boolean = false + longRunning: Boolean = false, + emitWasm: Boolean = false ) private def moduleInitializer( @@ -238,6 +239,9 @@ object Scalajsld { opt[Unit]("longRunning") .action { (_, c) => c.copy(longRunning = true) } .text("Run linking incrementally every time a line is printed to stdin") + opt[Unit]("emitWasm") + .action { (_, c) => c.copy(emitWasm = true) } + .text("If present, use the _experimental_ web assembly backend in the linker") opt[Unit]('d', "debug") .action { (_, c) => c.copy(logLevel = Level.Debug) } .text("Debug mode: Show full log") @@ -277,6 +281,7 @@ object Scalajsld { } } } + val allValidations = Seq(outputCheck, importMapCheck) allValidations.forall(_.isRight) match { case true => success @@ -284,6 +289,7 @@ object Scalajsld { } } + override def showUsageOnError = Some(true) } @@ -319,6 +325,7 @@ object Scalajsld { .withBatchMode(true) .withJSHeader(options.jsHeader) .withMinify(options.fullOpt) + .withExperimentalUseWebAssembly(options.emitWasm) val linker = StandardImpl.linker(config) val logger = new ScalaConsoleLogger(options.logLevel) @@ -347,6 +354,7 @@ object Scalajsld { logger ) case (None, Some(outputDir)) => + linker.link( irImportMappedFiles, moduleInitializers, diff --git a/tests/test/src/org/scalajs/cli/tests/Tests.scala b/tests/test/src/org/scalajs/cli/tests/Tests.scala index 8a4bc84..e61ea17 100644 --- a/tests/test/src/org/scalajs/cli/tests/Tests.scala +++ b/tests/test/src/org/scalajs/cli/tests/Tests.scala @@ -498,4 +498,64 @@ class Tests extends munit.FunSuite { val rawJs = os.read.lines(dir / "out" / "main.js") assert(rawJs(1).contains(substTo)) } + + + test("wasm flag emits wasm") { + val dir = os.temp.dir() + os.write( + dir / "foo.scala", + """object Foo { + | def main(args: Array[String]): Unit = { + | println("Hello") + | } + | + |} + |""".stripMargin + ) + + val scalaJsLibraryCp = getScalaJsLibraryCp(dir) + + os.makeDir.all(dir / "bin") + os.proc( + "cs", + "launch", + "scalac:2.13.15", + "--", + "-classpath", + scalaJsLibraryCp, + s"-Xplugin:${getScalaJsCompilerPlugin(dir)}", + "-d", + "bin", + "foo.scala" + ).call(cwd = dir, stdin = os.Inherit, stdout = os.Inherit) + + os.makeDir.all(dir / "out") + val res = os + .proc( + launcher, + "--stdlib", + scalaJsLibraryCp, + "-s", + "--emitWasm", + "--moduleKind", + "ESModule", + "--moduleSplitStyle", + "FewestModules", + "--outputDir", + "out", + "-mm", + "Foo.main", + "bin" + ) + .call(cwd = dir, mergeErrIntoOut = true) + + os.walk(dir).foreach(println) + val testSize = os.size(dir / "out" / "main.wasm") + val testMapSize = os.size(dir / "out" / "main.wasm.map") + assert(testSize > 0) + assert(testMapSize > 0) + + os.proc("node", "--experimental-wasm-exnref", "main.js").call(cwd = dir / "out", check = true, stdin = os.Inherit, stdout = os.Inherit, stderr = os.Inherit) + + } }