How To Debug js code in the board?

Posted on
of 2
/ 2
  • My question is:
    may I debug js code in the board? such as C language, step/step into/...

  • are asking a lot...

    That's why I often develop on the PC with a clear separation of concerns and emulating the hardware elements... for applications with UI or MI - user and machine interface - I encapsulate the UI and MI and apply the MVP - Model View Presenter - pattern.

    I was working on some monitor / testing approach using the aspect oriented programming, but the resources are just a bit tight.

    For lower level, Espruino has a trace that allows capturing of what's going on in the interpreter. But I'm not aware of an interactive debugger... (the ugly, dedicated 'console.log' is the candidate... and if the communication is to slow, some stuff has to go pushed into an array which later on dumped...

    Since the console accessible while running connected to the IDE, you can setup some interrupt/interval driven loggings to the console - either included in the code or entered in the console.

    The above option is used in the IDE testing - more a monitorig - function as available (in BETA) in the IDE. See settings - TESTING. It has really nice functions to get started with monitoring what's going on in the code.

  • I'm afraid there's no interactive debugger. You have to debug with print statements, by executing functions one by one, and by looking at the values of variables.

    It's something that I'd like to add at some point in the future - I have an idea of how it can be done without too much trouble - but it's not there now.

  • OK, I understand.
    Thank you.

  • @Gordon
    i am looking for this feature also,
    it's useful for coding, hope to see it in the near future :)

  • Thanks - yes, it's just a matter of finding time for it :)

  • It got me thinking. Maybe a way to do this is to have a 'bullet point' in the IDE inject something at the end of that line. When the parser reaches that thing f.ex new Breakpoint() then timers stop and execution if in control of the serial port. Then the IDE could query values basically just have the Espruino evaluate as per usual through the serial, so if I want to know the value of x then I hover mouse over x and the Espruino evaluates x and returns the result over serial and the IDE could then use that as a popover info box close to the cursor.

    Just had to get it out of my head, probably entirely wrong way to go about this.

  • Actually I hadn't considered that, but it's a really interesting idea. I was planning on adding checks at various points in the parser, but if I were to put something in the lexer I'd only have to put it once. In fact if it were to trap with a character that wasn't allowed in the input (like /xFF) it wouldn't actually slow down execution at all.

    I'm thinking something like node's implementation where Espruino entered a debug> console mode with a few basic commands available. They do breaks very explicitly by having the user write debugger.

    ... problem is, if I do add debugging then the next step to have a nice graphical debugger in the Web IDE (eg, the ability to hover over variables as @alexanderbrevig suggested), and that's something I don't see myself having time for.

  • As soon as you have to touch the code (manually), it's getting messy. I understand that it is a challenge, because between source code and uploaded code there is no simple mapping - for various reasons.

    One major uniqueness of Espruino's is the fact that it runs on the source code. Taking advantage of that should make it possible to have some kind of a source map. Since this is major work, a slightly different approach could be taken: holding on in the IDE of the uploaded / runtime code. It would at least cover the non-dynamic stuff. It means, it does not cover the dynamically loaded modules loaded from board/runtime accessible SD cards at run time. IDE and interpreter can then exchange information / markers... yes it slows down the interpreter, but it could be built to the point that it is to the order of established break points. Since there is something like a PC - program counter - that 'runs' over the code, it shoud be possible that at statement begin the interpreter could check against a list of break points and stop there.

    If the uploaded code('s reperesentation) is still 'too far away' from the code as it is stored by Espruino on uploade, not the uploaded code is held on, but the code as it is on Espruino is down loaded into kind of a debugger and used for debugging.

    This are just all ideas.

    Since we are in an object-oriented AND very dynanic world, I'm thinking about aspect oriented programming using (debug) annotations. The (debug) annotations are considered on code upload when upload for debug is enabled. Same thing - option - for module building (and may holding on to 'for debug built/minified' modules. May be this looks like node's approach.

    For now I'm thinking more of having some simplifying support for unit and regression testing of modules on Espruino and building my application as composition of modules - of the rack modules and custom modules. It's not perfect and looks like 'heavy' in process, and it also does not help to figure out some very strange, unexpected, temporary behavior. Having a solid unit/regression testing though in place reduces the potential of such behaviors immensly. Doing TD / XP development is for me the approach. Any other approach interferes with the code at runtime.

  • Yes, I'm hoping that you won't really have to change code manually at all. But for now the idea is:

    • Run code normally
    • Ctrl-C breaks out of the currently running code, into the debug> prompt. Ctrl-C again would exit that and properly break out of the running code.
    • From there you use next/n, step/s, continue/c to go through your code, and print/p to evaluate an expression. So like text-mode GDB or node's debugger.

    If you wanted to add a breakpoint, you'd add a debugger keyword in the IDE - however there's nothing to say the IDE couldn't do that automatically at some later stage. It could of course also have buttons for next/step/etc which mapped to sending the relevant commands over serial - I'm hoping someone else would do that bit ;)

  • Sounds like - actually IS - a very good plan.

    The way I understand is that the IDE transmitts something on that Ctrl-c to Espruino. Instead of making only a Ctrl-c, could it be a button in the IDE? ...and Ctr-c - or later on - any other configurable thing would/could be a short cut? Ctrl-c may have some consequences depending in which environment one is and on what the current focus is.

    For now, I would not even have a separate prompt: just the console, because from there a lot is already accessible:

    • get and set the value of variables
    • invoke functions
    • ...and do other 'harm' ;-)

    Btw, I was thinking that this entering into debug mode should also be something based on a pin changing state (triggered by a pressing a connected button). Actually very simple: it is already there: a setWatch(function(){ debugger },...); in the code does the job and has all the freedom of configurability - even to the point where a applicaiton oriented event can trigger the debugger... - I love Espruino...

    Regarding the keyword statment debugger; - it is not shimmable or polyfillable. What about something E.bug();. I was also considering !; 'not' statment... but I have no clue about the ramifications and other potential conflicts arising from that. This are just some ideas.

  • Well, Ctrl-C already breaks out of execution so seems like a good starting point. At the moment ctrl-c will only break out of something if it's busy for 1/4 sec after you press ctrl-c, so you'll only get into it if the code has basically hung.

    To be honest, if you want to talk to Espruino via the Web IDE it's got to send a control character via the terminal anyway - for the moment it might as well be ctrl-c :)

  • I see, you mean sending a Ctrl-c to Espruino board... I was more talking about Ctrl-c in the the IDE. Since the console can be a simple serial tty terminal - VT-100 / LA-36 (just threw out my 'collection' of 'physical' ones last fall) - Ctrl-c is for sure the thing to go with.

  • Ok, I've just come up with a branch for the debugger.

    There should be builds with it in here

    To use it, try uploading:

    function hang_me() {
      while (true) {
    function bob() {
    • Then type bob() on the left. It'll hang because of the while(true).
    • Press Ctrl-C - it'll show where you are in the code, with debug> prompt
    • Then you can type in commands to do stuff

      while (true) {
      In debug mode: Expected a simple ID, type 'help' for more info.
      help / h           - this information
      quit / q / Ctrl-C  - Quit debug mode, break execution
      continue / c       - Continue execution
      next / n           - execute to next line
      step / s           - execute to next line, or step into function call
      print ... / p ...  - evaluate and print the next argument
      Execution Interrupted
      at line 2 col 14
      while (true) {
      in function "hang_me" called from line 3 col 11
      in function "bob" called from line 1 col 5

    So overall, I think it's actually pretty useful as-is?

  • That helps already a lot...

    1. Nice stack trace (on quit).

    2. Is quit / q / Ctlr-c in debug> like 'kill process'? - I would not allow Ctrl-c in debug> mode. Wold als not call it Exectuion interrupted... it is actually cancelled/killed/aborted.

    3. next / n - Line or statement: would prefer statement rather than line (is the usual 'over', is it?)

    4. Is p expression in debug> mode the same as expresson in normal console/non debug mode?

  • Other options:

    1. What a bout a non-quitting command to get the stack trace as well?

    2. What about return / r to go to the end of a function just before the 'jumping back' with (anonymous) return value already calculated and in special 'register' and 'queryable'?

    3. What about having the context (this) set in special 'register' and queryable? Helpful in anonymous worlds... scope / context may anway be a challenge, I guess... or not?

  • Just updated with this build.

    Is quit / q / Ctlr-c in debug> like 'kill process'?

    Yes. The idea is that the Web IDE will be able to get out of debug mode automatically with repeated Ctrl-C. You don't want to get into trouble if you click 'upload' while debugging.

    would prefer statement rather than line

    This is just what node.js did. It's probably not too painful to change it.

    Is p expression in debug> mode the same as expresson in normal console/non debug mode?

    Basically - you just have to prefix it with p. It's like GDB (ish).

    What a bout a non-quitting command to get the stack trace as well?

    Not possible right now :(

    What about return / r to go to the end of a function

    In GDB that's called finish. I added it in the last update.

    What about having the context (this) set in special 'register' and queryable?

    You can do p this, but it won't show the top of the scope. In GDB that's info locals, so adding an 'info' command might be cool. To be honest querying the whole scope chain would be good.

  • Ok, newest version is here.

    It's got info locals (i l) and info scopelist (i s) now - which give you more info about local variables.

    You'll also find some documentation here. Feel free to issue some a pull request if you think it could be updated somehow.

  • Thanks it will help

  • Just merged this into master. Latest build here - it's looking really good now.

  • Just tried "Latest build here",

    • got a selectbox (first time, I saw this box)
    • selected 1.3/1.4
    • reset the board
    • started flashing
    • after some seconds got "Can't find STM32 Bootloader"

    Checked flashing with a V1.80 and that runs fine.
    Tried with your link again and got an error.
    Do I have the wrong board for this build (it's from 1st kickstarter) ?

  • The selectbox was because you hadn't connected to the board first, so it couldn't check. Did you actually go to the link above and select the right binary?

    The fact it can't find the bootloader sounds like you didn't reset it into bootloader mode? (with the blue LED)

    I just tried here with an old board and it works fine for me.

  • Connected to the board first.
    Used the link and select binary 1_3
    Reset into bootloader (blue led blinking)
    Didn't work

    After restart of computer, now it works. Looks like a windows/chrome problem.

  • First test, based on above example works fine.
    Second test based on "some documentation here" also works.
    Tested single stepping works fine inside function.
    Calling foo(a,b) is treated as one step, is there a way to step into functions ?
    What is difference between i l and i s ?

    It's a big step forward, I love it and will do some more testing tomorrow.

  • I'm blown away @Gordon. Really good job!
    Just perfect :)

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

How To Debug js code in the board?

Posted by Avatar for LifangXia @LifangXia