Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack trace filenames are different when running from SBT #20

Open
armanbilge opened this issue Nov 24, 2021 · 14 comments
Open

Stack trace filenames are different when running from SBT #20

armanbilge opened this issue Nov 24, 2021 · 14 comments

Comments

@armanbilge
Copy link
Member

Cats Effect isn't strictly necessary for a minimization, but here it helps demonstrate how this issue affects published source maps.

// build.sbt
scalaVersion := "2.13.7"
scalaJSUseMainModuleInitializer := true
libraryDependencies += "org.typelevel" %%% "cats-effect" % "3.2.9"
enablePlugins(ScalaJSPlugin)

// project/plugins.sbt
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.1")

// src/main/scala/Example.scala
import cats.effect.{IO, IOApp}

object Example extends IOApp.Simple {
  override def run: IO[Unit] = IO.raiseError(new Throwable("Boom!"))
}

Running within sbt I get:

java.lang.Throwable: Boom!
    at $c_LExample$.run__Lcats_effect_IO (/workspace/example/target/scala-2.13/example-fastopt/file:/workspace/example/src/main/scala/Example.scala:4:46)
    at $f_Lcats_effect_IOApp__main__AT__V (/workspace/example/target/scala-2.13/example-fastopt/https:/raw.githubusercontent.com/typelevel/cats-effect/v3.2.9/core/js/src/main/scala/cats/effect/IOApp.scala:267:55)
    at $s_LExample__main__AT__V (/workspace/example/target/scala-2.13/example-fastopt/file:/workspace/example/src/main/scala/Example.scala:3:8)
    at /workspace/example/target/scala-2.13/example-fastopt/main.js:43393:1
    at /workspace/example/target/scala-2.13/example-fastopt/main.js:43394:4
    at Script.runInThisContext (node:vm:129:12)
    at Object.runInThisContext (node:vm:305:38)
    at [stdin]:8:25
    at Script.runInThisContext (node:vm:129:12)
    at Object.runInThisContext (node:vm:305:38)

Notice how the filenames are prepended with my workspace and also the URL has lost a slash. If I run directly with node --enable-source-maps I get:

<ref *1> /workspace/example/src/main/scala/Example.scala:4
  override def run: IO[Unit] = IO.raiseError(new Throwable("Boom!"))
                                             ^

java.lang.Throwable: Boom!
    at $c_LExample$.run__Lcats_effect_IO (/workspace/example/src/main/scala/Example.scala:4:46)
    at null.$f_Lcats_effect_IOApp__main__AT__V (https://raw.githubusercontent.com/typelevel/cats-effect/v3.2.9/core/js/src/main/scala/cats/effect/IOApp.scala:267:55)
    at null.$s_LExample__main__AT__V (/workspace/example/src/main/scala/Example.scala:3:8)
    at Object.<anonymous> (/workspace/example/target/scala-2.13/example-fastopt/main.js:43393:1)
    at Object.<anonymous> (/workspace/example/target/scala-2.13/example-fastopt/main.js:43394:4)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) {
  jl_Throwable__f_s: 'Boom!',
  jl_Throwable__f_e: null,
  jl_Throwable__f_enableSuppression: true,
  jl_Throwable__f_writableStackTrace: true,
  jl_Throwable__f_stackTraceStateInternal: [Circular *1],
  jl_Throwable__f_stackTrace: null,
  jl_Throwable__f_suppressed: null
}
@sjrd
Copy link
Member

sjrd commented Nov 24, 2021

I did not know that Node.js had introduced their own --enable-source-maps. It might be useful to investigate if we can use it instead of source-map-support.

You can do so today even from sbt with

jsEnv := new org.scalajs.jsenv.nodejs.NodeJSEnv(
  org.scalajs.jsenv.nodejs.NodeJSEnv.Config()
    .withSourceMap(false).withArgs(List("--enable-source-maps")))

@armanbilge
Copy link
Member Author

Oh, I didn't realize you were using something else? AFAIK --enable-source-maps still requires source-map-support to be installed.

Edit: scratch that, I've just been confused by these two different source maps features :)

@armanbilge
Copy link
Member Author

Hmm, I tried your suggestion of .withSourceMap(false).withArgs(List("--enable-source-maps")) in typelevel/cats-effect#2582 but it doesn't seem to work.

@gzm0
Copy link
Contributor

gzm0 commented Dec 4, 2021

Note that inside NodeJSEnv we execute scripts using the vm module. So that might make the result different.

@armanbilge
Copy link
Member Author

Thanks. Not sure if the native sourcemaps work with the vm module:

They recommend using the V8 stack trace API to customize it, which I assume is what you might already be doing in NodeJSEnv?

@gzm0
Copy link
Contributor

gzm0 commented Dec 4, 2021

Nope :)

require('vm').runInThisContext(
require('fs').readFileSync($pathJS, { encoding: "utf-8" }),
{ filename: $pathJS, displayErrors: true }
)

@armanbilge
Copy link
Member Author

Hmm. Maybe require('source-map-support').install() is doing something magical 😆

@gzm0
Copy link
Contributor

gzm0 commented Dec 4, 2021

It more feels like the path mangling / unmangling is broken. Maybe it assumes that we give it a relative path in fileName and then just concatenates things... 🤷

@armanbilge
Copy link
Member Author

Oh, for sure. I was disappointed that this workaround didn't work:

jsEnv := new org.scalajs.jsenv.nodejs.NodeJSEnv(
  org.scalajs.jsenv.nodejs.NodeJSEnv.Config()
    .withSourceMap(false).withArgs(List("--enable-source-maps")))

It might have to do with the VM thing.

@gzm0
Copy link
Contributor

gzm0 commented Jan 22, 2022

I'm having a more detailed look at this. For starters, I'm going to transfer this to https://github.com/scala-js/scala-js-js-envs, because the issue is almost certainly there. Also, we need to test things there anyways :)

@gzm0 gzm0 transferred this issue from scala-js/scala-js Jan 22, 2022
@gzm0
Copy link
Contributor

gzm0 commented Jan 30, 2022

Well... So it seems this is a known issue (since 2015):

evanw/node-source-map-support#84

Now, the question is why it works in the case you pass a single file.

@armanbilge
Copy link
Member Author

Thanks for looking into this!

The case where it works, it's not using the source-map-support package. It's using Node.js builtin source map implementation. It would be amazing if you could switch the env to use that instead, so we don't have to install the npm package everywhere :)

@gzm0
Copy link
Contributor

gzm0 commented Jan 30, 2022

OK, I can reproduce this on node 14 onward (node 12 seems to have the same issue with the --enable-source-map flag).

@gzm0
Copy link
Contributor

gzm0 commented Jan 30, 2022

What I have found out so far:

  • We could probably replace our entire source map machinery with simply a flag (if we require node >= 12.12.0 which is acceptable IMO).
  • However, it will not work on Script inputs due to VM: Add source mapping support nodejs/node#8042 (with the current implementation). tl;dr: vm.runInThisContext does not support source maps.
  • ATM I do not understand JS contexts sufficiently well to know what our alternatives are (if any).

@sjrd, any thoughts you have would be appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants