3

Spago doesn't use source maps to refer to the source code location of an error in the stack trace.

Here is my Main.purs:

f :: Unit -> Unit 
f _ = unsafeCrashWith "error"

main :: Effect Unit 
main = do 
  pure $ f unit

I ran these commands to build and run the program:

spago build --purs-args "-g source maps"
spago run

In the output, I get references to lines in index.js files, e.g.

<my-project>/output/Partial/foreign.js:6
  throw new Error(msg);
  ^

Error: error
    at exports._crashWith (<my-project>/output/Partial/foreign.js:6:9)
    at <my-project>/output/Partial.Unsafe/index.js:8:35
    at exports._unsafePartial (<my-project>/output/Partial.Unsafe/foreign.js:6:10)
    at Object.unsafeCrashWith (<my-project>/output/Partial.Unsafe/index.js:7:12)
    at f (<my-project>/output/Main/index.js:14:27)
    at Object.<anonymous> (<my-project>/output/Main/index.js:16:63)
    at Module._compile (internal/modules/cjs/loader.js:1072:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)
    at Module.load (internal/modules/cjs/loader.js:937:32)
    at Function.Module._load (internal/modules/cjs/loader.js:778:12)

What I want is for this stack trace to use the source maps to refer to the actual purescript source code locations.

1 Answers1

2

Ok, there's quite a lot here. Some are your mistakes, some are undocumented gotchas.

So first of all, if you run purs compile --help, you should see the following section in there:

  -g,--codegen ARG         Specifies comma-separated codegen targets to include.
                           Accepted codegen targets are 'corefn', 'docs', 'js',
                           'sourcemaps'. The default target is 'js', but if this
                           option is used only the targets specified will be
                           used.

This gives us two pieces of information:

  1. It should be sourcemaps (no spaces), not source maps. So your parameter should be --purs-args "-g sourcemaps"
  2. If you only specify sourcemaps, you will get only source maps, no actual JS output. So your parameter should be --purs-args "-g sourcemaps,js"

But besides these two, there is an undocumented gotcha: there should be no space after -g (surprise!)

Well, to be fair, it's not that wild, it's a somewhat accepted pattern. And it goes like this:

  1. For the short version of the parameter, the value should come right after the letter, no space. So --purs-args "-gsourcemaps,js"
  2. For the long version, the value should come after an equals sign. So --purs-args "--codegen=sourcemaps,js"

Ok, so now, if you run spago build --purs-args "-gsourcemaps,js", you should see index.js.map files generated next to the index.js files. So far so good.

But - oh no! When you spago run, you still see JS callstack only. What's going on?

Well, turns out, even though Node does support source maps starting with v12.12, they are disabled by default. You have to enable them explicitly by passing the --enable-source-maps parameter to Node itself. And in order to pass extra parameters to Node, Spago offers the handy -b|--node-args option.

So, putting together all of the above, here's your final solution:

> spago build --purs-args "-gsourcemaps,js"
...

> spago run --node-args "--enable-source-maps"

Error: error
    at exports._crashWith (C:\o\purs-pg\output\Partial\foreign.js:6:9)
    at C:\o\purs-pg\output\Partial.Unsafe\index.js:8:35
        -> C:\o\purs-pg\.spago\partial\v3.0.0\src\Partial\Unsafe.purs:24:23
    at exports._unsafePartial (C:\o\purs-pg\output\Partial.Unsafe\foreign.js:6:10)
    at Object.unsafeCrashWith (C:\o\purs-pg\output\Partial.Unsafe\index.js:7:12)
        -> C:\o\purs-pg\.spago\partial\v3.0.0\src\Partial\Unsafe.purs:24:23
    at f (C:\o\purs-pg\output\Main\index.js:39:27)
        -> C:\o\purs-pg\src\Main.purs:79:1
    at Object.<anonymous> (C:\o\purs-pg\output\Main\index.js:41:63)
        -> C:\o\purs-pg\src\Main.purs:84:10
    at Module._compile (internal/modules/cjs/loader.js:1158:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)
    at Module.load (internal/modules/cjs/loader.js:1002:32)
    at Function.Module._load (internal/modules/cjs/loader.js:895:16)

In conclusion, I'd like to note that Spago itself has a parameter -x|--source-maps, which is for some reason allowed for both run and build commands but in reality doesn't actually apply to them: it only works for bundle-app and bundle-module.

Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172
  • Thank you for your detailed response. I tried rebuilding my example from scratch via ` > spago build --purs-args "-gsourcemaps,js" > spago run --node-args "--enable-source-maps" ` However, this still gave me the stacktrace for the `index.js` files. I eventually got it to work by setting the environment variable first like this: ` export NODE_OPTIONS="--enable-source-maps" ` It seems like node just ignores the flag "--enable-source-maps"??? – Henry Blanchette Apr 14 '22 at 18:34
  • What version of Node do you have installed? – Fyodor Soikin Apr 14 '22 at 19:00
  • I have node v16.8.0 – Henry Blanchette Apr 14 '22 at 19:03
  • Well, [the docs](https://nodejs.org/dist/latest-v16.x/docs/api/cli.html#cli_enable_source_maps) say it should work fine. Could be a bug. Or could be a typo on your part. – Fyodor Soikin Apr 14 '22 at 19:11