The MWScript Debugger

MoneyWorks 9.2.1 and later has a debugger for the MWScript scripting language. The debugger can be used to proactively debug scripts by setting breakpoints and stepping through the script line-by-line, or it can be entered if a runtime error occurs, or a long-running operation needs to be interrupted.

Debugging runtime errors

For a regular user who does not have the Scripting privilege, there is not much they can do about errors in the scripts you deploy, other than reporting the bug to you so that you can fix it. For that reason, every script you deploy should have a constant meta declaration with a string containing your contact details. This string will be shown to the user in error alerts.

For someone who does have the Scripting privilege for the document, a runtime error will come with the option of dropping into the debugger, or opening the scripts window at the point of the error.

Edit selects the line in the script editor. Ignore just aborts execution of the current handler call from MoneyWorks without unloading the script (same as Debugger Stop button).

Infinite loops

The MWScript virtual machine does not know that this is an error, so will happily follow your script's instructions to endlessly perform a loop with no possible exit condition, or — even worse — endlessly put up alert boxes. In the first case, after a few seconds, MoneyWorks should show an indeterminate progress window with a message "A script is running....". Since you have the Scripting privilege, this window will have an enabled Stop button. You can use this to immediately drop into the Debugger. Here you can examine the script to see what is happening, and you can use the Debugger's Stop button to abort execution of the current handler and return control from your script to MoneyWorks. Stop does not deactivate the script, so MoneyWorks will continue to call your handlers as appropriate. If it calls your handler again and you're back in the loop, the bigger hammer is the Deactivate button, which will deactivate the script without calling the Unload handler.

In the case of an infinite loop of alert boxes, there will be no delay long enough for an indeterminate progress window, so in this case, hold the Ctrl+Shift keys down when clicking a button in the alert. Prior to v9.2.1 this would offer the opportunity to disable the script. From v9.2.1, it will enter the debugger.

Breakpoints

While developing or testing your script, you can proactively enter the debugger from any point in your script by setting a breakpoint in the Scripts window. Click in the darker grey breakpoint margin next to the line number of the line(s) that you want to stop at. A white blob will be placed, indicating a breakpoint. When your script reaches that line, the debugger will be invoked.

You must leave the script window open while debugging. Breakpoints are discarded if you close the script window or select a different script in the Scripts window.

When you set a breakpoint on a line that does not correspond exactly to a virtual machine instruction, you will find that the debugger window displays the breakpoint on the line that does correspond to a virtual machine instruction.

The Debugger

The Debugger contains 3 panes:

  • The script with the current line of execution indicated by a ▷ in the margin
  • The local variables for the current handler, along with the script's properties. You can double-click array variables to expand, or double-click on strings and tables to show them in a viewer window. The string viewer will show invisible characters such as newlines and tabs and spaces, as well as other ASCII control characters, along with the length in characters and bytes; it will alternatively display a warning if the string is not valid UTF-8 or if it contains a NUL character (these conditions will prevent a string from behaving properly in most situations)
  • The call stack — the sequence of handler calls that led to where you are now. You can click on the other points in the call stack to navigate to that point in the script and show that handler's local variables (it may be a different script if you have scripts calling each other via public handlers)

You can resize the panes by dragging the separators between them.

Single-stepping

If you entered the debugger via a breakpoint or interrupting the script via Stop button etc, you can continue or single-step through the script using the toolbar icons (or pressing the indicated key).

  • Continue (c) will continue execution; if there are no further breakpoints or fatal errors, the debugger will close
  • Step Over (o) will step to the next line/instruction. Step Over will step over a handler call.
  • Step In (i) will step into handler calls. If there is no handler call on the line, it is effectively the same as Step Over.
     
    You cannot step into MoneyWorks intrinsic functions or calls to public handlers in other scripts (to do that, you need to open that script and put a breakpoint in it).
     
    If you are at a line with multiple handler calls in an expression (for example an expression like:
    let a = Foo(5) + Bar(3)), Step In will step into the first one (Foo); to step into Bar you will need to use Step In when exiting Foo
  • Step Out (u) will execute until the current handler returns to its caller
  • Stop will abort the current handler call chain and return control to MoneyWorks without deactivating the script. The script will also be opened in the Script editor at the current line
  • Deactivate will Stop and deactivate the script, so MoneyWorks will not call your handlers until you reactivate the script. If you close the Scripts window with the script deactivated (thus saving the state to the server), the script will also be deactivated for other users when they next log in.

Changing breakpoints

You can set or clear breakpoints from the debugger by clicking in the breakpoint margin. When you Continue or Step Out, a breakpoint in the intervening code will drop you back into the debugger. Breakpoints set in the debugger will persist until you clear them or until the script is unloaded.

Fatal error

If you entered the debugger due to a fatal runtime error in your script, you cannot Continue execution, but you can examine the call stack and variable values to determine the cause of the error before either Stopping or Deactivating the script. Fatal errors include things like passing the wrong number of parameters to an intrinsic function or a NULL or invalid handle to a function. These are conditions that your script should not allow to happen. If a user without the Scripting privilege gets a fatal error, that will Stop the script for them, but they won't be able to fix the error.

Navigating in the script

As with the Script Editor, you can search the script within the debugger using ⌘-F/Ctrl-F. Highlighted matches can be stepped through with the return key (shift-return to step backwards). Press tab to exit the search field. When the script is active use ⌘-G/Ctrl-G to find the next instance of the highlighted text (Find Selected), or Shift-⌘-G to Find Selected Backwards. Since the text is read-only you can also just use g or shift-G.

Posted in Uncategorized | Comments Off on The MWScript Debugger