From fdc5814617ef18d97673fd41ae945076d8af0847 Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sat, 2 Nov 2024 22:22:15 +0100 Subject: [PATCH 01/13] Emit wasm --- .../src/mill/scalajslib/ScalaJSModule.scala | 15 +++- .../scalajslib/worker/ScalaJSWorker.scala | 6 +- .../test/resources/wasm/src/app/App.scala | 10 +++ .../mill/scalajslib/EsModuleRemapTests.scala | 2 +- .../test/src/mill/scalajslib/WasmTests.scala | 87 +++++++++++++++++++ .../worker/api/ScalaJSWorkerApi.scala | 3 +- .../scalajslib/worker/ScalaJSWorkerImpl.scala | 19 +++- 7 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 scalajslib/test/resources/wasm/src/app/App.scala create mode 100644 scalajslib/test/src/mill/scalajslib/WasmTests.scala diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index 10b412d1741..0fc66f84cdb 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -140,7 +140,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => moduleSplitStyle = moduleSplitStyle(), outputPatterns = scalaJSOutputPatterns(), minify = scalaJSMinify(), - importMap = scalaJSImportMap() + importMap = scalaJSImportMap(), + emitWasm = emitWasm() ) } @@ -191,7 +192,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => moduleSplitStyle: ModuleSplitStyle, outputPatterns: OutputPatterns, minify: Boolean, - importMap: Seq[ESModuleImportMapping] + importMap: Seq[ESModuleImportMapping], + emitWasm: Boolean )(implicit ctx: mill.api.Ctx): Result[Report] = { val outputPath = ctx.dest @@ -212,7 +214,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => moduleSplitStyle = moduleSplitStyle, outputPatterns = outputPatterns, minify = minify, - importMap = importMap + importMap = importMap, + emitWasm ) } @@ -293,6 +296,9 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => /** Whether to emit a source map. */ def scalaJSSourceMap: T[Boolean] = Task { true } + /** Whether to emit WASM map. As of Nov 2024 scala JS wasm support is experimental */ + def emitWasm: T[Boolean] = Task { false } + /** Name patterns for output. */ def scalaJSOutputPatterns: T[OutputPatterns] = Task { OutputPatterns.Defaults } @@ -370,7 +376,8 @@ trait TestScalaJSModule extends ScalaJSModule with TestModule { moduleSplitStyle = moduleSplitStyle(), outputPatterns = scalaJSOutputPatterns(), minify = scalaJSMinify(), - importMap = scalaJSImportMap() + importMap = scalaJSImportMap(), + emitWasm = emitWasm() ) } diff --git a/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala b/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala index 321e0b55cf8..437ca0a6132 100644 --- a/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala +++ b/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala @@ -169,7 +169,8 @@ private[scalajslib] class ScalaJSWorker extends AutoCloseable { moduleSplitStyle: api.ModuleSplitStyle, outputPatterns: api.OutputPatterns, minify: Boolean, - importMap: Seq[api.ESModuleImportMapping] + importMap: Seq[api.ESModuleImportMapping], + emitWasm: Boolean )(implicit ctx: Ctx.Home): Result[api.Report] = { bridge(toolsClasspath).link( runClasspath = runClasspath.iterator.map(_.path.toNIO).toSeq, @@ -185,7 +186,8 @@ private[scalajslib] class ScalaJSWorker extends AutoCloseable { moduleSplitStyle = toWorkerApi(moduleSplitStyle), outputPatterns = toWorkerApi(outputPatterns), minify = minify, - importMap = importMap.map(toWorkerApi) + importMap = importMap.map(toWorkerApi), + emitWasm = emitWasm ) match { case Right(report) => Result.Success(fromWorkerApi(report)) case Left(message) => Result.Failure(message) diff --git a/scalajslib/test/resources/wasm/src/app/App.scala b/scalajslib/test/resources/wasm/src/app/App.scala new file mode 100644 index 00000000000..5bd4668058b --- /dev/null +++ b/scalajslib/test/resources/wasm/src/app/App.scala @@ -0,0 +1,10 @@ +package app + +import scala.scalajs.js +import scala.scalajs.js.annotation._ + +object App { + def main(args: Array[String]): Unit = { + println("hello, wasm!") + } +} diff --git a/scalajslib/test/src/mill/scalajslib/EsModuleRemapTests.scala b/scalajslib/test/src/mill/scalajslib/EsModuleRemapTests.scala index 488c051082e..be5119fa63d 100644 --- a/scalajslib/test/src/mill/scalajslib/EsModuleRemapTests.scala +++ b/scalajslib/test/src/mill/scalajslib/EsModuleRemapTests.scala @@ -65,7 +65,7 @@ object EsModuleRemapTests extends TestSuite { } test("should throw for older scalaJS versions") { - val evaluator = UnitTester(EsModuleRemap, millSourcePath) + val evaluator = UnitTester(OldJsModule, millSourcePath) val Left(Result.Exception(ex, _)) = evaluator(OldJsModule.fastLinkJS) val error = ex.getMessage assert(error == "scalaJSImportMap is not supported with Scala.js < 1.16.") diff --git a/scalajslib/test/src/mill/scalajslib/WasmTests.scala b/scalajslib/test/src/mill/scalajslib/WasmTests.scala new file mode 100644 index 00000000000..35189e36a18 --- /dev/null +++ b/scalajslib/test/src/mill/scalajslib/WasmTests.scala @@ -0,0 +1,87 @@ +package mill.scalajslib + +import mill.api.Result +import mill.define.Discover +import mill.testkit.UnitTester +import mill.testkit.TestBaseModule +import utest._ +import mill.scalajslib.api._ +import mill.T + +object WasmTests extends TestSuite { + val remapTo = "https://cdn.jsdelivr.net/gh/stdlib-js/array-base-linspace@esm/index.mjs" + + object Wasm extends TestBaseModule with ScalaJSModule { + override def scalaVersion = sys.props.getOrElse("TEST_SCALA_2_13_VERSION", ???) + + override def scalaJSVersion = "1.17.0" + + override def moduleKind = ModuleKind.ESModule + + override def moduleSplitStyle = ModuleSplitStyle.FewestModules + + override def emitWasm: T[Boolean] = true + + override lazy val millDiscover = { + import mill.main.TokenReaders.given + Discover[this.type] + } + } + + object OldWasmModule extends TestBaseModule with ScalaJSModule { + override def scalaVersion = sys.props.getOrElse("TEST_SCALA_2_13_VERSION", ???) + override def scalaJSVersion = "1.16.0" + + override def moduleKind = ModuleKind.ESModule + override def moduleSplitStyle = ModuleSplitStyle.FewestModules + + override def emitWasm: T[Boolean] = true + + override lazy val millDiscover = { + import mill.main.TokenReaders.given + Discover[this.type] + } + } + + val millSourcePath = os.Path(sys.env("MILL_TEST_RESOURCE_DIR")) / "wasm" + + val tests: Tests = Tests { + test("should emit wasm") { + val evaluator = UnitTester(Wasm, millSourcePath) + val Right(result) = + evaluator(Wasm.fastLinkJS) + val publicModules = result.value.publicModules.toSeq + val path = result.value.dest.path + val main = publicModules.head + assert(main.jsFileName == "main.js") + val mainPath = path / "main.js" + assert(os.exists(mainPath)) + val wasmPath = path / "main.wasm" + assert(os.exists(wasmPath)) + val wasmMapPath = path / "main.wasm.map" + assert(os.exists(wasmMapPath)) + } + + test("wasm is runnable") { + val evaluator = UnitTester(Wasm, millSourcePath) + val Right(result) = evaluator(Wasm.fastLinkJS) + val path = result.value.dest.path + os.proc("node", "--experimental-wasm-exnref", "main.js").call( + cwd = path, + check = true, + stdin = os.Inherit, + stdout = os.Inherit, + stderr = os.Inherit + ) + + } + + test("should throw for older scalaJS versions") { + val evaluator = UnitTester(OldWasmModule, millSourcePath) + val Left(Result.Exception(ex, _)) = evaluator(OldWasmModule.fastLinkJS) + val error = ex.getMessage + assert(error == "Emitting wasm is not supported with Scala.js < 1.17") + } + + } +} diff --git a/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala b/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala index b28a9358d8a..d4a60ae91ce 100644 --- a/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala +++ b/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala @@ -18,7 +18,8 @@ private[scalajslib] trait ScalaJSWorkerApi { moduleSplitStyle: ModuleSplitStyle, outputPatterns: OutputPatterns, minify: Boolean, - importMap: Seq[ESModuleImportMapping] + importMap: Seq[ESModuleImportMapping], + emitWasm: Boolean ): Either[String, Report] def run(config: JsEnvConfig, report: Report): Unit diff --git a/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala b/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala index d6f2164ff72..d7bf687edc5 100644 --- a/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala +++ b/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala @@ -37,7 +37,8 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { moduleSplitStyle: ModuleSplitStyle, outputPatterns: OutputPatterns, minify: Boolean, - dest: File + dest: File, + emitWasm: Boolean ) private def minorIsGreaterThanOrEqual(number: Int) = ScalaJSVersions.current match { case s"1.$n.$_" if n.toIntOption.exists(_ < number) => false @@ -153,7 +154,15 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { if (minorIsGreaterThanOrEqual(16)) withOutputPatterns.withMinify(input.minify) else withOutputPatterns - val linker = StandardImpl.clearableLinker(withMinify) + val withWasm = + (minorIsGreaterThanOrEqual(17), input.emitWasm) match { + case (_, false) => withMinify + case (true, true) => withMinify.withExperimentalUseWebAssembly(true) + case (false, true) => + throw new Exception("Emitting wasm is not supported with Scala.js < 1.17") + } + + val linker = StandardImpl.clearableLinker(withWasm) val irFileCacheCache = irFileCache.newCache (linker, irFileCacheCache) } @@ -180,7 +189,8 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { moduleSplitStyle: ModuleSplitStyle, outputPatterns: OutputPatterns, minify: Boolean, - importMap: Seq[ESModuleImportMapping] + importMap: Seq[ESModuleImportMapping], + emitWasm: Boolean ): Either[String, Report] = { // On Scala.js 1.2- we want to use the legacy mode either way since // the new mode is not supported and in tests we always use legacy = false @@ -195,7 +205,8 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { moduleSplitStyle = moduleSplitStyle, outputPatterns = outputPatterns, minify = minify, - dest = dest + dest = dest, + emitWasm = emitWasm )) val irContainersAndPathsFuture = PathIRContainer.fromClasspath(runClasspath) val testInitializer = From 1b302a31f5cfd7f827bd117abfcae30bc34deebd Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sat, 2 Nov 2024 22:42:58 +0100 Subject: [PATCH 02/13] . --- scalajslib/src/mill/scalajslib/ScalaJSModule.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index 0fc66f84cdb..824f41471f5 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -296,7 +296,7 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => /** Whether to emit a source map. */ def scalaJSSourceMap: T[Boolean] = Task { true } - /** Whether to emit WASM map. As of Nov 2024 scala JS wasm support is experimental */ + /** Whether to emit WASM. As of Nov 2024 scala JS wasm support is experimental */ def emitWasm: T[Boolean] = Task { false } /** Name patterns for output. */ From 1e3a47ded988c59c0c6dddcf0c434e63db658aa0 Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sat, 2 Nov 2024 22:43:51 +0100 Subject: [PATCH 03/13] . --- scalajslib/test/src/mill/scalajslib/EsModuleRemapTests.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scalajslib/test/src/mill/scalajslib/EsModuleRemapTests.scala b/scalajslib/test/src/mill/scalajslib/EsModuleRemapTests.scala index be5119fa63d..488c051082e 100644 --- a/scalajslib/test/src/mill/scalajslib/EsModuleRemapTests.scala +++ b/scalajslib/test/src/mill/scalajslib/EsModuleRemapTests.scala @@ -65,7 +65,7 @@ object EsModuleRemapTests extends TestSuite { } test("should throw for older scalaJS versions") { - val evaluator = UnitTester(OldJsModule, millSourcePath) + val evaluator = UnitTester(EsModuleRemap, millSourcePath) val Left(Result.Exception(ex, _)) = evaluator(OldJsModule.fastLinkJS) val error = ex.getMessage assert(error == "scalaJSImportMap is not supported with Scala.js < 1.16.") From 142836dbfa0f6e404b68677471b7046b18317ef9 Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 10:08:23 +0100 Subject: [PATCH 04/13] Node 22 --- .github/workflows/run-mill-action.yml | 5 +++++ scalajslib/src/mill/scalajslib/ScalaJSModule.scala | 6 +++--- scalajslib/test/src/mill/scalajslib/WasmTests.scala | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/run-mill-action.yml b/.github/workflows/run-mill-action.yml index 84f4cc75b72..1629231c138 100644 --- a/.github/workflows/run-mill-action.yml +++ b/.github/workflows/run-mill-action.yml @@ -58,6 +58,11 @@ jobs: java-version: ${{ inputs.java-version }} distribution: temurin + - uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Prepare git config run: | git config --global user.name "Mill GithHub Actions" diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index 824f41471f5..766a5d54e51 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -141,7 +141,7 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => outputPatterns = scalaJSOutputPatterns(), minify = scalaJSMinify(), importMap = scalaJSImportMap(), - emitWasm = emitWasm() + emitWasm = scalaJSEmitWasm() ) } @@ -297,7 +297,7 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => def scalaJSSourceMap: T[Boolean] = Task { true } /** Whether to emit WASM. As of Nov 2024 scala JS wasm support is experimental */ - def emitWasm: T[Boolean] = Task { false } + def scalaJSEmitWasm: T[Boolean] = Task { false } /** Name patterns for output. */ def scalaJSOutputPatterns: T[OutputPatterns] = Task { OutputPatterns.Defaults } @@ -377,7 +377,7 @@ trait TestScalaJSModule extends ScalaJSModule with TestModule { outputPatterns = scalaJSOutputPatterns(), minify = scalaJSMinify(), importMap = scalaJSImportMap(), - emitWasm = emitWasm() + emitWasm = scalaJSEmitWasm() ) } diff --git a/scalajslib/test/src/mill/scalajslib/WasmTests.scala b/scalajslib/test/src/mill/scalajslib/WasmTests.scala index 35189e36a18..effe7553a59 100644 --- a/scalajslib/test/src/mill/scalajslib/WasmTests.scala +++ b/scalajslib/test/src/mill/scalajslib/WasmTests.scala @@ -20,7 +20,7 @@ object WasmTests extends TestSuite { override def moduleSplitStyle = ModuleSplitStyle.FewestModules - override def emitWasm: T[Boolean] = true + override def scalaJSEmitWasm: T[Boolean] = true override lazy val millDiscover = { import mill.main.TokenReaders.given @@ -35,7 +35,7 @@ object WasmTests extends TestSuite { override def moduleKind = ModuleKind.ESModule override def moduleSplitStyle = ModuleSplitStyle.FewestModules - override def emitWasm: T[Boolean] = true + override def scalaJSEmitWasm: T[Boolean] = true override lazy val millDiscover = { import mill.main.TokenReaders.given From 249146aeb2507f414222b63e9e79a7fc87da34f5 Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 10:57:20 +0100 Subject: [PATCH 05/13] doc --- .../ROOT/pages/scalalib/web-examples.adoc | 6 ++- example/scalalib/web/8-wasm/build.mill | 49 +++++++++++++++++++ .../scalalib/web/8-wasm/wasm/src/hello.scala | 7 +++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 example/scalalib/web/8-wasm/build.mill create mode 100644 example/scalalib/web/8-wasm/wasm/src/hello.scala diff --git a/docs/modules/ROOT/pages/scalalib/web-examples.adoc b/docs/modules/ROOT/pages/scalalib/web-examples.adoc index 5ef5ece8807..f448f3b4bf8 100644 --- a/docs/modules/ROOT/pages/scalalib/web-examples.adoc +++ b/docs/modules/ROOT/pages/scalalib/web-examples.adoc @@ -35,4 +35,8 @@ include::partial$example/scalalib/web/6-cross-version-platform-publishing.adoc[] == Publishing Cross-Platform Scala Modules Alternative -include::partial$example/scalalib/web/7-cross-platform-version-publishing.adoc[] \ No newline at end of file +include::partial$example/scalalib/web/7-cross-platform-version-publishing.adoc[] + +== Scala.js WebAssembly Example + +include::partial$example/scalalib/web/8-wasm.adoc[] \ No newline at end of file diff --git a/example/scalalib/web/8-wasm/build.mill b/example/scalalib/web/8-wasm/build.mill new file mode 100644 index 00000000000..4d9bb204a68 --- /dev/null +++ b/example/scalalib/web/8-wasm/build.mill @@ -0,0 +1,49 @@ +package build +import mill._, scalalib._, scalajslib._ +import mill.scalajslib.api._ + + +object wasm extends ScalaJSModule { + override def scalaVersion = "3.3.4" + + override def scalaJSVersion = "1.17.0" + + override def moduleKind = ModuleKind.ESModule + + override def moduleSplitStyle = ModuleSplitStyle.FewestModules + + override def scalaJSEmitWasm = true +} + +// This build defines a single `ScalaJSModule` that uses the `WASM` backend of the scala JS linker. +// The release notes that introduced scalaJS wasm are here; +// https://www.scala-js.org/news/2024/09/28/announcing-scalajs-1.17.0/ +// and are worth reading. They include information such as the scala JS requirements to successful emit wasm, +// the flags needed to run in browser and the minimum node version (22) required to actually run the wasm output. +// +// You can check if you've emitted WASM by checking + +/** Usage + +> mill show wasm.fastLinkJS +[1/1] show +{ + ... + "dest": "... out/wasm/fastLinkJS.dest" +} + +> ls out/wasm/fastLinkJS.dest +__loader.js main.js main.wasm main.wasm.map + +> node out/foo/fullLinkJS.dest/main.js +Debugger listening on ws://127.0.0.1:57753/d17db228-5159-4e60-be1f-4cc47a396ddf +For help, see: https://nodejs.org/en/docs/inspector +Debugger attached. +hello wasm! + +*/ + +// Here we see that scala JS emits a single WASM module, as well as a loader and main.js file. +// `main.js` is the entry point of the program, and calls into the wasm module. + + diff --git a/example/scalalib/web/8-wasm/wasm/src/hello.scala b/example/scalalib/web/8-wasm/wasm/src/hello.scala new file mode 100644 index 00000000000..d8cbbc60ce5 --- /dev/null +++ b/example/scalalib/web/8-wasm/wasm/src/hello.scala @@ -0,0 +1,7 @@ +package hi + +object Foo { + def main(args: Array[String]): Unit = { + println("hello wasm!") + } +} From 1056a044927948bd2378b3920225a7a16dd49f01 Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 10:58:42 +0100 Subject: [PATCH 06/13] . --- example/scalalib/web/8-wasm/build.mill | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/example/scalalib/web/8-wasm/build.mill b/example/scalalib/web/8-wasm/build.mill index 4d9bb204a68..59702f946bc 100644 --- a/example/scalalib/web/8-wasm/build.mill +++ b/example/scalalib/web/8-wasm/build.mill @@ -18,10 +18,8 @@ object wasm extends ScalaJSModule { // This build defines a single `ScalaJSModule` that uses the `WASM` backend of the scala JS linker. // The release notes that introduced scalaJS wasm are here; // https://www.scala-js.org/news/2024/09/28/announcing-scalajs-1.17.0/ -// and are worth reading. They include information such as the scala JS requirements to successful emit wasm, +// and are worth reading. They include information such as the scala JS requirements to successfully emit wasm, // the flags needed to run in browser and the minimum node version (22) required to actually run the wasm output. -// -// You can check if you've emitted WASM by checking /** Usage From e88fca732007b8ac9a3aa300ad987bd213884c89 Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 12:24:14 +0100 Subject: [PATCH 07/13] rename vars --- example/scalalib/web/8-wasm/build.mill | 2 +- scalajslib/src/mill/scalajslib/ScalaJSModule.scala | 10 +++++----- .../src/mill/scalajslib/worker/ScalaJSWorker.scala | 4 ++-- scalajslib/test/src/mill/scalajslib/WasmTests.scala | 4 ++-- .../mill/scalajslib/worker/api/ScalaJSWorkerApi.scala | 2 +- .../src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala | 8 ++++---- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/example/scalalib/web/8-wasm/build.mill b/example/scalalib/web/8-wasm/build.mill index 59702f946bc..e0560a65ac0 100644 --- a/example/scalalib/web/8-wasm/build.mill +++ b/example/scalalib/web/8-wasm/build.mill @@ -12,7 +12,7 @@ object wasm extends ScalaJSModule { override def moduleSplitStyle = ModuleSplitStyle.FewestModules - override def scalaJSEmitWasm = true + override def scalaJSExperimentalUseWebAssembly = true } // This build defines a single `ScalaJSModule` that uses the `WASM` backend of the scala JS linker. diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index 766a5d54e51..016d1b7737e 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -141,7 +141,7 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => outputPatterns = scalaJSOutputPatterns(), minify = scalaJSMinify(), importMap = scalaJSImportMap(), - emitWasm = scalaJSEmitWasm() + experimentalUseWebAssembly = scalaJSExperimentalUseWebAssembly() ) } @@ -193,7 +193,7 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => outputPatterns: OutputPatterns, minify: Boolean, importMap: Seq[ESModuleImportMapping], - emitWasm: Boolean + experimentalUseWebAssembly: Boolean )(implicit ctx: mill.api.Ctx): Result[Report] = { val outputPath = ctx.dest @@ -215,7 +215,7 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => outputPatterns = outputPatterns, minify = minify, importMap = importMap, - emitWasm + experimentalUseWebAssembly = experimentalUseWebAssembly ) } @@ -297,7 +297,7 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => def scalaJSSourceMap: T[Boolean] = Task { true } /** Whether to emit WASM. As of Nov 2024 scala JS wasm support is experimental */ - def scalaJSEmitWasm: T[Boolean] = Task { false } + def scalaJSExperimentalUseWebAssembly: T[Boolean] = Task { false } /** Name patterns for output. */ def scalaJSOutputPatterns: T[OutputPatterns] = Task { OutputPatterns.Defaults } @@ -377,7 +377,7 @@ trait TestScalaJSModule extends ScalaJSModule with TestModule { outputPatterns = scalaJSOutputPatterns(), minify = scalaJSMinify(), importMap = scalaJSImportMap(), - emitWasm = scalaJSEmitWasm() + experimentalUseWebAssembly = scalaJSExperimentalUseWebAssembly() ) } diff --git a/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala b/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala index 437ca0a6132..3ce55097cc0 100644 --- a/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala +++ b/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala @@ -170,7 +170,7 @@ private[scalajslib] class ScalaJSWorker extends AutoCloseable { outputPatterns: api.OutputPatterns, minify: Boolean, importMap: Seq[api.ESModuleImportMapping], - emitWasm: Boolean + experimentalUseWebAssembly: Boolean )(implicit ctx: Ctx.Home): Result[api.Report] = { bridge(toolsClasspath).link( runClasspath = runClasspath.iterator.map(_.path.toNIO).toSeq, @@ -187,7 +187,7 @@ private[scalajslib] class ScalaJSWorker extends AutoCloseable { outputPatterns = toWorkerApi(outputPatterns), minify = minify, importMap = importMap.map(toWorkerApi), - emitWasm = emitWasm + experimentalUseWebAssembly = experimentalUseWebAssembly ) match { case Right(report) => Result.Success(fromWorkerApi(report)) case Left(message) => Result.Failure(message) diff --git a/scalajslib/test/src/mill/scalajslib/WasmTests.scala b/scalajslib/test/src/mill/scalajslib/WasmTests.scala index effe7553a59..a43f372be9b 100644 --- a/scalajslib/test/src/mill/scalajslib/WasmTests.scala +++ b/scalajslib/test/src/mill/scalajslib/WasmTests.scala @@ -20,7 +20,7 @@ object WasmTests extends TestSuite { override def moduleSplitStyle = ModuleSplitStyle.FewestModules - override def scalaJSEmitWasm: T[Boolean] = true + override def scalaJSExperimentalUseWebAssembly: T[Boolean] = true override lazy val millDiscover = { import mill.main.TokenReaders.given @@ -35,7 +35,7 @@ object WasmTests extends TestSuite { override def moduleKind = ModuleKind.ESModule override def moduleSplitStyle = ModuleSplitStyle.FewestModules - override def scalaJSEmitWasm: T[Boolean] = true + override def scalaJSExperimentalUseWebAssembly: T[Boolean] = true override lazy val millDiscover = { import mill.main.TokenReaders.given diff --git a/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala b/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala index d4a60ae91ce..d9a7601c035 100644 --- a/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala +++ b/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala @@ -19,7 +19,7 @@ private[scalajslib] trait ScalaJSWorkerApi { outputPatterns: OutputPatterns, minify: Boolean, importMap: Seq[ESModuleImportMapping], - emitWasm: Boolean + experimentalUseWebAssembly: Boolean ): Either[String, Report] def run(config: JsEnvConfig, report: Report): Unit diff --git a/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala b/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala index d7bf687edc5..f1022fae005 100644 --- a/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala +++ b/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala @@ -38,7 +38,7 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { outputPatterns: OutputPatterns, minify: Boolean, dest: File, - emitWasm: Boolean + experimentalUseWebAssembly: Boolean ) private def minorIsGreaterThanOrEqual(number: Int) = ScalaJSVersions.current match { case s"1.$n.$_" if n.toIntOption.exists(_ < number) => false @@ -155,7 +155,7 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { else withOutputPatterns val withWasm = - (minorIsGreaterThanOrEqual(17), input.emitWasm) match { + (minorIsGreaterThanOrEqual(17), input.experimentalUseWebAssembly) match { case (_, false) => withMinify case (true, true) => withMinify.withExperimentalUseWebAssembly(true) case (false, true) => @@ -190,7 +190,7 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { outputPatterns: OutputPatterns, minify: Boolean, importMap: Seq[ESModuleImportMapping], - emitWasm: Boolean + experimentalUseWebAssembly: Boolean ): Either[String, Report] = { // On Scala.js 1.2- we want to use the legacy mode either way since // the new mode is not supported and in tests we always use legacy = false @@ -206,7 +206,7 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { outputPatterns = outputPatterns, minify = minify, dest = dest, - emitWasm = emitWasm + experimentalUseWebAssembly = experimentalUseWebAssembly )) val irContainersAndPathsFuture = PathIRContainer.fromClasspath(runClasspath) val testInitializer = From 8943f1452633259bb51cb97bb4ccb61fd8275c6c Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 12:56:33 +0100 Subject: [PATCH 08/13] tighten docs --- example/scalalib/web/8-wasm/build.mill | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/example/scalalib/web/8-wasm/build.mill b/example/scalalib/web/8-wasm/build.mill index e0560a65ac0..01205c7bf19 100644 --- a/example/scalalib/web/8-wasm/build.mill +++ b/example/scalalib/web/8-wasm/build.mill @@ -23,20 +23,14 @@ object wasm extends ScalaJSModule { /** Usage -> mill show wasm.fastLinkJS -[1/1] show +> ./mill show wasm.fastLinkJS # mac/linux { - ... - "dest": "... out/wasm/fastLinkJS.dest" +... +..."jsFileName": "main.js", + "dest": ".../out/wasm/fastLinkJS.dest" } -> ls out/wasm/fastLinkJS.dest -__loader.js main.js main.wasm main.wasm.map - -> node out/foo/fullLinkJS.dest/main.js -Debugger listening on ws://127.0.0.1:57753/d17db228-5159-4e60-be1f-4cc47a396ddf -For help, see: https://nodejs.org/en/docs/inspector -Debugger attached. +> node --experimental-wasm-exnref out/foo/fullLinkJS.dest/main.js # mac/linux hello wasm! */ From 14e0ebb7caa232dfa9a9439bd04df2b09236cd5d Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 14:10:18 +0100 Subject: [PATCH 09/13] . --- example/scalalib/web/8-wasm/build.mill | 2 +- example/scalalib/web/8-wasm/wasm/src/hello.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/scalalib/web/8-wasm/build.mill b/example/scalalib/web/8-wasm/build.mill index 01205c7bf19..0c1f4ad47cb 100644 --- a/example/scalalib/web/8-wasm/build.mill +++ b/example/scalalib/web/8-wasm/build.mill @@ -4,7 +4,7 @@ import mill.scalajslib.api._ object wasm extends ScalaJSModule { - override def scalaVersion = "3.3.4" + override def scalaVersion = "2.13.14" override def scalaJSVersion = "1.17.0" diff --git a/example/scalalib/web/8-wasm/wasm/src/hello.scala b/example/scalalib/web/8-wasm/wasm/src/hello.scala index d8cbbc60ce5..18b869667f7 100644 --- a/example/scalalib/web/8-wasm/wasm/src/hello.scala +++ b/example/scalalib/web/8-wasm/wasm/src/hello.scala @@ -1,6 +1,6 @@ -package hi +package wasm -object Foo { +object wasm { def main(args: Array[String]): Unit = { println("hello wasm!") } From 5afe8d5e8ed02bee3c67ddc8ff55fd0e60f98ec2 Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 14:38:02 +0100 Subject: [PATCH 10/13] *sigh --- example/scalalib/web/8-wasm/build.mill | 1 + scalajslib/src/mill/scalajslib/ScalaJSModule.scala | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/example/scalalib/web/8-wasm/build.mill b/example/scalalib/web/8-wasm/build.mill index 0c1f4ad47cb..722f9f2be69 100644 --- a/example/scalalib/web/8-wasm/build.mill +++ b/example/scalalib/web/8-wasm/build.mill @@ -27,6 +27,7 @@ object wasm extends ScalaJSModule { { ... ..."jsFileName": "main.js", +... "dest": ".../out/wasm/fastLinkJS.dest" } diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index 016d1b7737e..0c4f1ffba32 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -296,7 +296,18 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => /** Whether to emit a source map. */ def scalaJSSourceMap: T[Boolean] = Task { true } - /** Whether to emit WASM. As of Nov 2024 scala JS wasm support is experimental */ + /** Specifies whether to use the experimental WebAssembly backend.. Requires scalaJS > 1.17.0 + * When using this setting, the following properties must also hold: + * + * - `moduleKind = ModuleKind.ESModule` + * - `moduleSplitStyle = ModuleSplitStyle.FewestModules` + * + * @note + * Currently, the WebAssembly backend silently ignores `@JSExport` and + * `@JSExportAll` annotations. This behavior may change in the future, + * either by making them warnings or errors, or by adding support for them. + * All other language features are supported. + */ def scalaJSExperimentalUseWebAssembly: T[Boolean] = Task { false } /** Name patterns for output. */ From 9803345b86510f9459410a398056252b7d085a79 Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 15:00:11 +0100 Subject: [PATCH 11/13] urgh --- example/scalalib/web/8-wasm/build.mill | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/scalalib/web/8-wasm/build.mill b/example/scalalib/web/8-wasm/build.mill index 722f9f2be69..101779c581e 100644 --- a/example/scalalib/web/8-wasm/build.mill +++ b/example/scalalib/web/8-wasm/build.mill @@ -31,7 +31,7 @@ object wasm extends ScalaJSModule { "dest": ".../out/wasm/fastLinkJS.dest" } -> node --experimental-wasm-exnref out/foo/fullLinkJS.dest/main.js # mac/linux +> node --experimental-wasm-exnref out/wasm/fullLinkJS.dest/main.js # mac/linux hello wasm! */ From 2281c1daa1c37443b30d21025fd92c56c7fb11aa Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 15:19:50 +0100 Subject: [PATCH 12/13] Bah, format --- scalajslib/src/mill/scalajslib/ScalaJSModule.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index 0c4f1ffba32..db3248000a9 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -296,7 +296,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => /** Whether to emit a source map. */ def scalaJSSourceMap: T[Boolean] = Task { true } - /** Specifies whether to use the experimental WebAssembly backend.. Requires scalaJS > 1.17.0 + /** + * Specifies whether to use the experimental WebAssembly backend.. Requires scalaJS > 1.17.0 * When using this setting, the following properties must also hold: * * - `moduleKind = ModuleKind.ESModule` From 5829f92e589a6901d55564f890303eedaf474e9d Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Sun, 3 Nov 2024 15:20:43 +0100 Subject: [PATCH 13/13] . --- example/scalalib/web/8-wasm/build.mill | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/scalalib/web/8-wasm/build.mill b/example/scalalib/web/8-wasm/build.mill index 101779c581e..1eaa52edfa8 100644 --- a/example/scalalib/web/8-wasm/build.mill +++ b/example/scalalib/web/8-wasm/build.mill @@ -31,7 +31,7 @@ object wasm extends ScalaJSModule { "dest": ".../out/wasm/fastLinkJS.dest" } -> node --experimental-wasm-exnref out/wasm/fullLinkJS.dest/main.js # mac/linux +> node --experimental-wasm-exnref out/wasm/fastLinkJS.dest/main.js # mac/linux hello wasm! */