com-lihaoyi/mill

ScalaJs tests fail with `ECONNREFUSED` after 0.10.10 update

carlosedp opened this issue · 7 comments

After updating mill to 0.10.10 (I was using 0.10.9 before and it worked fine), I started to get ECONNREFUSED for the ScalaJS tests in my project: carlosedp/riscvassembler#13

❯ ./mill riscvassembler.scalajs\[3.2.0,1.11.0\].test
[27/104] de.tobiasroeser.mill.vcs.version.VcsVersion.vcsState
[63/104] riscvassembler.scalajs[3.2.0,1.11.0].compile
[info] compiling 5 Scala sources to /Users/cdepaula/repos/riscvassembler/out/riscvassembler/scalajs/3.2.0/1.11.0/compile.dest/classes ...
[info] done compiling
[92/104] riscvassembler.scalajs[3.2.0,1.11.0].test.compile
[info] compiling 4 Scala sources to /Users/cdepaula/repos/riscvassembler/out/riscvassembler/scalajs/3.2.0/1.11.0/test/compile.dest/classes ...
[info] done compiling
[104/104] riscvassembler.scalajs[3.2.0,1.11.0].test.test
Starting process: node
Scala.js Com failed: Error: connect ECONNREFUSED ::1:58183
1 targets failed
riscvassembler.scalajs[3.2.0,1.11.0].test.test org.scalajs.testing.common.RPCCore$ClosedException: org.scalajs.testing.adapter.JSEnvRPC$RunTerminatedException
org.scalajs.testing.adapter.JSEnvRPC$RunTerminatedException
org.scalajs.jsenv.ExternalJSRun$NonZeroExitException: exited with code 255

My lib is built for Scala JVM, ScalaJS and ScalaNative. The error doesn't happen using 0.10.9 (for any platform) or with 0.10.10 for JVM / Native.

Also the error happens on all Scala/ScalaJS version combinations. It appears to be in the connection to Nodejs.

Bumping mill to 0.10.11 gives me this error:

[108/108] riscvassembler.scalajs[3.2.1,1.12.0].test.test
1 targets failed
riscvassembler.scalajs[3.2.1,1.12.0].test.test org.scalajs.jsenv.UnsupportedInputException: Unsupported input: List(CommonJSModule(/Users/cdepaula/repos/riscvassembler/out/riscvassembler/scalajs/3.2.1/1.12.0/test/fastLinkJSTest.dest/main.js))
    org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv.$anonfun$validateInput$1(JSDOMNodeJSEnv.scala:59)
    scala.collection.immutable.List.map(List.scala:246)
    scala.collection.immutable.List.map(List.scala:79)
    org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv.validateInput(JSDOMNodeJSEnv.scala:54)
    org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv.startWithCom(JSDOMNodeJSEnv.scala:47)
    org.scalajs.testing.adapter.JSEnvRPC.<init>(JSEnvRPC.scala:46)
    org.scalajs.testing.adapter.TestAdapter.startManagedRunner(TestAdapter.scala:128)
    org.scalajs.testing.adapter.TestAdapter.$anonfun$getRunnerForThread$1(TestAdapter.scala:120)
    scala.collection.concurrent.TrieMap.getOrElseUpdate(TrieMap.scala:962)
    org.scalajs.testing.adapter.TestAdapter.getRunnerForThread(TestAdapter.scala:120)
    org.scalajs.testing.adapter.TestAdapter.loadFrameworks(TestAdapter.scala:56)
    mill.scalajslib.worker.ScalaJSWorkerImpl.getFramework(ScalaJSWorkerImpl.scala:273)
    mill.scalajslib.worker.ScalaJSWorker.getFramework(ScalaJSWorker.scala:178)
    mill.scalajslib.TestScalaJSModule.$anonfun$testTask$1(ScalaJSModule.scala:346)
    mill.define.Task$TraverseCtx.evaluate(Task.scala:380)

My scalajs object in build.sc is like:

  object scalajs extends Cross[RiscvAssemblerScalajsModule](scalaJsVersions: _*)
  class RiscvAssemblerScalajsModule(val crossScalaVersion: String, crossScalaJsVersion: String)
    extends RiscvAssemblerLib
    with RiscvAssemblerPublish
    with ScalaJSModule {
    def millSourcePath = super.millSourcePath / os.up / os.up
    def scalaJSVersion = crossScalaJsVersion
    def ivyDeps        = Agg(ivy"org.scala-js::scalajs-dom::${versions.scalajsdom}")

    def scalaJSUseMainModuleInitializer = true
    def moduleKind                      = T(ModuleKind.CommonJSModule)
    object test extends Tests with RiscvAssemblerTest {
      // def moduleKind =
      def jsEnvConfig = T(JsEnvConfig.JsDom())
    }
  }
}

Complete build is at: https://github.com/carlosedp/riscvassembler/blob/ce78bd05e582a9c4542c2a874328b93e8dea93b0/build.sc#L70

If I comment the def moduleKind or override it to def moduleKind = T(ModuleKind.NoModule) in the test object, it gives me the previous ECONNREFUSED error on connecting to nodejs.

lefou commented

@lolgab Do you have some thought about this?

lefou commented

I think your latest comment is another issue, as I can't see any ECONNREFUSED in the output. Also, you show it works with 0.10.10, but your initial issue claims, 0.10.10 does no longer work.

Opened #2300 to address the previously error reported here by mistake.

Using the second suggestion from @lolgab from #2300 worked (setting def jsEnvConfig = T(JsEnvConfig.ExoegoJsDomNodeJs() in the project):

  object scalajs extends Cross[RiscvAssemblerScalajsModule](scalaJsVersions: _*)
  class RiscvAssemblerScalajsModule(val crossScalaVersion: String, crossScalaJsVersion: String)
    extends RiscvAssemblerLib
    with RiscvAssemblerPublish
    with ScalaJSModule {
    def millSourcePath = super.millSourcePath / os.up / os.up
    def scalaJSVersion = crossScalaJsVersion
    def ivyDeps        = Agg(ivy"org.scala-js::scalajs-dom::${versions.scalajsdom}")

    def scalaJSUseMainModuleInitializer = true
    def moduleKind                      = T(ModuleKind.CommonJSModule)
    def jsEnvConfig                     = T(JsEnvConfig.ExoegoJsDomNodeJs())
    object test extends Tests with RiscvAssemblerTest {}

Weird that this apparently returned (I'm on mill 0.10.11).

I had to add to build.sc JsEnvConfig.JsDom args as listed in scala-js/scala-js-js-envs#12:

object frontend extends ScalaJSModule with Common {
  def scalaVersion   = versions.scala3
  def scalaJSVersion = versions.scalajs
  def ivyDeps = super.ivyDeps() ++ Agg(
    ivy"org.scala-js::scalajs-dom::${versions.scalajsdom}",
    ivy"com.softwaremill.sttp.client3::core::${versions.sttp}",
  )
  def scalaJSUseMainModuleInitializer = true
  def moduleKind                      = T(ModuleKind.ESModule)
  def jsEnvConfig                     = T(JsEnvConfig.JsDom(args = List("--dns-result-order=ipv4first")))
  def moduleSplitStyle                = ModuleSplitStyle.SmallModulesFor(List("com.carlosedp.zioscalajs.frontend"))

  // These two tasks are used by Vite to get update path
  def fastLinkOut() = T.command(println(fastLinkJS().dest.path))
  def fullLinkOut() = T.command(println(fullLinkJS().dest.path))

  object test extends Tests with Common with TestModule.ScalaTest {
    // Test dependencies
    def ivyDeps = Agg(
      ivy"org.scalatest::scalatest::${versions.scalatest}",
    )
    def moduleKind       = T(ModuleKind.NoModule)
    def moduleSplitStyle = T(ModuleSplitStyle.FewestModules)
  }
}

Without the args, the build fails as seen in https://github.com/carlosedp/zio-scalajs-stack/actions/runs/4583364445/jobs/8094164811.

After adding it, build passes: https://github.com/carlosedp/zio-scalajs-stack/actions/runs/4583401680/jobs/8094220895

From my latest tests, bumping to Nodejs 20 fixed this.
Closing for now.