How do I debug for node, as I'm not using an IDE

Hi, I posted this in the github Exercism support group, and got a suggestion that since that was transitioning here, I should repost here. So:

I’ve just started JavaScript after ‘finishing’ the Ruby Track. I successfully finished 3 of the 4 parts of a learning exercise test suite, but when I added the 4th it spewed multi pages of stuff at me, much more than my screen would hold, and refused to run even the successful parts. From what I could easily see, is wasn’t even clear whether it was complaining about my code or the tests themselves. Finally, using node itself for just the last test, I was able to see that I had used a Ruby-like if statement that JavaScript didn’t like. There has got to be a better debugging method than this–so, how does one debug in this environment? (My son is mentoring me, but having told me his feelings about node, I’ve decided I’d better bring the question here)

mea culpa, my son tells me that it’s npm he objects to, not node. I am a thorough newbie here, sorry.

@thelmalu Welcome! Someone with more JS knowledge than me will need to answer your question, but it might help them to know in advance what editor are you using (for example VSCode). I know you said you’re not using an IDE, but it’s quite possible that the editor will have some way of debugging still.

I’d also be interested to know how you found Ruby to be different - what would you have done in this situation in Ruby that you can’t in JavaScript, or is it simply that you never had such verbose error messages in Ruby?

Finally, you might like to post the code that spewed out all the pages of stuff, so that JS people can help understand exactly what you were seeing (even though I understand you’ve solved that specific problem :slightly_smiling_face: )

My editor is Emacs: I know that that’s almost a world in itself, but I use it on the level of a notepad type editor. I do have colors on that flag various things, and it does show me how bracket-like things begin and end, but that’s about it for me.

Ruby allows an x if y statement that I probably wouldn’t even have expected to exist in JavaScript had I thought about it at all. I just did that automatically and apparently it doesn’t exist.

The error dump came via npm, not node: I’ll post it if anyone’s really interested, but I only know how to do that by capturing it into a script and then cleaning out all the unreadable junk that that generates

Thank you for looking at this.
Exercism continues to astound me with the quality of help given in such tension free ways to people who want to learn for career development, and even to people like me, long retired and unable to pay attention to TV and movies


That’s lovely to hear - thanks for saying it!

Based on “The error dump came via npm, not node”, it’ll probably help someone understand the problem more and help unstick you. It might be some setup issue that’s causing that, or an npm flag you can set to be less verbose etc.

You probably don’t need to worry too much about cleaning it up. If you wrap it inside 3 backticks inside a details block (See the cog and “Hide Details” in this editor) then we can decipher it without it overwhelming the whole thread! :slight_smile:

From what you’ve said I am going to assume the code looks something like this:

export function hello() {
  return 'Hello, World!' if false

And running npm test then “generates a lot of errorring”

$ npm test

> test
> jest --no-cache ./*

 FAIL  ./hello-world.spec.js
  ● Test suite failed to run
    SyntaxError: C:\Users\Derk-Jan\Exercism\javascript\hello-world\hello-world.js: Missing semicolon. (2:24)

      1 | export function hello() {
    > 2 |   return 'Hello, World!' if false;
        |                         ^
      3 | }
      4 |

      at instantiate (node_modules/@babel/parser/src/parse-error/credentials.ts:62:21)
      at toParseError (node_modules/@babel/parser/src/parse-error.ts:60:12)
      at Parser.raise (node_modules/@babel/parser/src/tokenizer/index.ts:1474:19)
      at Parser.semicolon (node_modules/@babel/parser/src/parser/util.ts:142:10)
      at Parser.parseReturnStatement (node_modules/@babel/parser/src/parser/statement.ts:921:12)
      at Parser.parseStatementContent (node_modules/@babel/parser/src/parser/statement.ts:414:21)
      at Parser.parseStatement (node_modules/@babel/parser/src/parser/statement.ts:359:17)
      at Parser.parseBlockOrModuleBlockBody (node_modules/@babel/parser/src/parser/statement.ts:1241:25)
      at Parser.parseBlockBody (node_modules/@babel/parser/src/parser/statement.ts:1216:10)
      at Parser.parseBlock (node_modules/@babel/parser/src/parser/statement.ts:1184:10)
      at Parser.parseFunctionBody (node_modules/@babel/parser/src/parser/expression.ts:2564:24)
      at Parser.parseFunctionBodyAndFinish (node_modules/@babel/parser/src/parser/expression.ts:2533:10)
      at callback (node_modules/@babel/parser/src/parser/statement.ts:1472:12)
      at Parser.withSmartMixTopicForbiddingContext (node_modules/@babel/parser/src/parser/expression.ts:3063:14)
      at Parser.parseFunction (node_modules/@babel/parser/src/parser/statement.ts:1470:10)
      at Parser.parseFunctionStatement (node_modules/@babel/parser/src/parser/statement.ts:891:17)
      at Parser.parseStatementContent (node_modules/@babel/parser/src/parser/statement.ts:395:21)
      at Parser.parseStatement (node_modules/@babel/parser/src/parser/statement.ts:359:17)
      at Parser.parseExportDeclaration (node_modules/@babel/parser/src/parser/statement.ts:2402:17)
      at Parser.maybeParseExportDeclaration (node_modules/@babel/parser/src/parser/statement.ts:2324:31)
      at Parser.parseExport (node_modules/@babel/parser/src/parser/statement.ts:2227:29)
      at Parser.parseStatementContent (node_modules/@babel/parser/src/parser/statement.ts:492:25)
      at Parser.parseStatement (node_modules/@babel/parser/src/parser/statement.ts:359:17)
      at Parser.parseBlockOrModuleBlockBody (node_modules/@babel/parser/src/parser/statement.ts:1241:25)
      at Parser.parseBlockBody (node_modules/@babel/parser/src/parser/statement.ts:1216:10)
          at (<anonymous>)
      at normalizeFile (node_modules/@babel/core/src/transformation/normalize-file.ts:43:18)
          at (<anonymous>)
      at run (node_modules/@babel/core/src/transformation/index.ts:38:23)
          at (<anonymous>)
      at transform (node_modules/@babel/core/src/transform.ts:29:17)
          at (<anonymous>)
      at evaluateSync (node_modules/gensync/index.js:251:28)
      at fn (node_modules/gensync/index.js:89:14)
      at stopHiding - secret - don't use this - v1 (node_modules/@babel/core/src/errors/rewrite-stack-trace.ts:97:14)        
      at transformSync (node_modules/@babel/core/src/transform.ts:66:10)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        1.559 s
Ran all test suites matching /.\\*/i.

What you see above is the error message (a syntax error) followed by a stack trace. The syntax x if y doesn’t exist in JavaScript (it does not support modifiers) – as you’ve figured out. The test suite (based on jest) will give the full stack trace because it’s an unhandled error.

There is no way to run the test suite without any stack trace in this case, unfortunately.

As for your son’s aversion for npm, let him know that yarn and pnpm also work for every exercise in the track :slight_smile:

Does the error you encounter look anything like the message above? If not, it would be helpful if you could capture (copy and paste) or redirect (npm test > file.txt 2>&1, then open file.text) the error message and post it here.

1 Like

Yes, you have it right down to the ‘missing semicolon’ syntax error.
However, mine was preceded by this:

Jest encountered an unexpected token

Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

All scrolled by so quickly that I failed to see what had happened, and my clumsy attempt to scroll back to the beginning didn’t catch those either. The ‘unexpected token’ comment meant nothing to me. I might have eventually understood the ‘missing semicolon’ syntax error.

So, is there a straightforward way for me to debug without going to an IDE? I’m doing this for (high quality) amusement and I don’t want to make it into real work.

I will pass your ‘slight smile’ and its comment on to my son.

Thank you very much for pinning it, and for paying attention.

1 Like

Yes. Jest isn’t very fun when it comes to “helpful error messages”.

So, is there a straightforward way for me to debug without going to an IDE? I’m doing this for (high quality) amusement and I don’t want to make it into real work.

There are “debuggers” that can run on JavaScript code, but I don’t think that’s what you’re asking for, because a debugger (to step through the code and inspect variables) is not going to run when there is a syntax error. The by far easiest way would be to to run the tests and see if Jest complains about syntax.

Online alternative

Without installing an IDE, you can also use a tool such as this JavaScript validator which will add squiggly red lines underneath parts it doesn’t understand. Once you get the hang of it, you’ll need this less and less. DO NOTE that this validator doesn’t understand export and import .

Thank you.
I’ve actually gotten through a few of the learning exercises now and I’m beginning to feel a bit less intimidated – even by the massive dumps generated by a simple error.



npm and jest and all seem like a fairly complex harness; isn’t there a way for her to just run something like node my-main.js and get the error messages straight from node?

[ I object to all of npm and the rest of those mentioned. They’re fine in themselves. I object to the insane ‘ecosystem’ which downloads a thousand files into each exercise’s separate subdirectory, just to be able to run jest or whatever. Not specifically in the context of exercism. I object to the entire node / npm package dependency nightmare. ]

I hadn’t yet become familiar with node; I can readily use it for what I was looking for--I just hadn’t found that out yet.

I feel you, but right now it is what it is.

If it helps, while working on the Javascript track I did bash scripts to run npm install in one go in all exercises or the ones provided as arguments, but also to remove the node_modules in all of them or in a subset. Also to run the tests in all exercises and unskip all the tests. You can see these scripts in andrerfcsantos Github: exercism/javascript. The files in that folder are the scripts, ignore all the subfolder exercises. It’s still not great you have to run scripts, but in my case made things slightly more manageable.

It really isn’t about the klunkiness of using it in exercism. It’s the overall dependency nightmare. I like JS as a language – I am disheartened by the tangled mess that comes with it.

The short answer is: no.

The long answer is:

no, because we chose to use jest. You’ll need to have jest installed locally (and all of its dependencies). We could bundle it in the exercise but that will increase the repository size by waaay too much. The reason we chose to do it like this is because, if you’re learning JavaScript, you’ll likely need to know how to use these tools down the line, anyway.

The only way around it would be to switch to Node.js test runner which is currently experimental. We would be able to do that once it becomes stable. At that moment, rewriting the test-runner and all these tests would be a decent way to start running on node-only. It will come with a lot of caveats, because we would not be able to run something like babel to transpile code for older node versions.

Deno offers https:// urls for packages, but this doesn’t solve the issue: packages still need to be fetched.

Thank you.
In the intervening time I have made my peace with both node and test suite error dumps. I now manage to find what’s gone wrong easily enough.
…This evening I submitted a very simple learning exercise and found that – except for variable names – I had done it exactly as you did, which made me feel ridiculously good. . .Although extremely simple, there were many possible solutions, and I had chosen the same one as the person whose solutions I look at first. Thanks for everything.