HMD Developer Console
From SpinetiX Support Wiki
Contents
Description
The Developer Console (a.k.a. JavaScript debugger) is a component of HMD Professional (version 2.2.3 and above) that enables easy, integrated debugging of any script. With the Developer Console you can:
- Set breakpoints in .svg, .smil and .js source files.
- Automatically break into the debugger when an unhandled exception is thrown.
- Examine the call stack and the variables in all scopes.
- Examine the properties of the program objects, including native objects.
- View snapshots of the SVG tree as it is manipulated by the script.
User manual
Activation of the debugger
The debugger is enabled only when the developer console is visible. To open the developer console, click on "Show developer console" in the "Settings" menu.
Once enabled, there are three ways to enter the debugger:
- When an unhandled exception is thrown a dialog box will pop up asking to either ignore or debug the exception.
- Setting breakpoints in the source code.
- Clicking on the "Break" button in the developer console, which will enter the debugger at the next JavaScript instruction.
Note: the debugger must be enabled before opening the document to be debugged.
Source code windows
To view the source code of a script and set breakpoints, either
- drag and drop a source file from the finder to the developer console, which will create a new tab with the source code view,
- or right click on the file in the finder, and select the "View source" option, which will create a new floating window with the source code view.
It is possible to move a floating source code window to the developer console by right-clicking anywhere on the source window and selecting the "Pin to the console" option. Conversely it is possible to float a source window by selecting the "Float window" option.
Note that source code windows may open automatically when stepping through the code, in which case they will always open first as tabs in the developer console, but can be floated thereafter if needed.
To set a breakpoint, left-click in the gray margin on the left side of the source view (where the line numbers are shown). The breakpoint will be materialized by a red dot. Alternatively a breakpoint may be set by right-clicking anywhere on the line and selecting the "Insert breakpoint" option.
To remove a breakpoint, click again on the breakpoint, or select the "Remove breakpoint" option in the right-click menu.
Stepping through the code
When the breakpoint is reached, the developer console switches automatically to source code window and shows the current line, also known as the "program counter", with a yellow arrow.
It is then possible to step through the code with the step and next buttons:
- Clicking "Next" or hitting F10 will execute code until the program counter moves to the next line in the same script, skipping over any function call, or returns from the current function.
- Clicking "Step Into" or hitting F11 will execute code until the program counter moves to any other line, including inside a function call.
- Clicking "Step Out" or hitting Shift+F11 will execute code until the current script or function returns.
To exit the debugger and let program execution continue until the next breakpoint or exception, click on "Continue" or hit F5.
If the program seems to be running in an infinite loop, it is possible to enter the debugger at once by clicking on "Break". This will break into the debugger on the next JavaScript instruction. If no JavaScript code is executing when "Break" is clicked, the debugger will be entered at the first instruction of any script executed thereafter.
Viewing the call stack
When the program is stopped by the debugger, it is possible to examine the call stack, that is the list of successive function calls that lead from the root script to the function that is currently executing.
In the sample screenshot on the right side, a breakpoint was set at line 7 in the file below, inside the square()
function. We can see that this function was called by distance()
which in turn was called from the main script at line 16.We can also see with which arguments each function was called.
It is possible to double-click on any of the function calls in the call stack view to examine the corresponding stack frame:
- The line of code to which the call will return is shown with a green arrow in the corresponding source code window.
- The local variables view is updated to show the scopes of the calling function.
By default the top stack frame is selected, which is the one which triggered the debugger.
Below is the source code used in this example.
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg xmlns="http://www.w3.org/2000/svg">
3 <script>
4 <![CDATA[
5
6 function square( a ) {
7 return a * a;
8 }
9
10 function distance( x1, y1, x2, y2 ) {
11 var L2 = square( x2-x1 ) + square( y2-y1 );
12 var D = Math.sqrt( L2 );
13 return D;
14 }
15
16 var d = distance( 10, 10, 100, 100 );
17 alert( 'd='+d );
18
19 ]]>
20 </script>
21 </svg>
Examining variables
To see the local variables of a script or function, switch to the "Local variables" view. It contains a list of all variables in the current scope and their current value.
Some variables are objects, which will be indicated by an expander arrow to the left. Clicking on the arrow expands the view to list the properties of the object. For examples, in the screenshot on the right side, the "event" object in the local scope has been expanded to show its properties.
JavaScript supports the concept of "closures", i.e. a function, typically a callback, defined into a parent function and which has access to the local variables of the parent. In this case the variables of the local function, known as the "local scope" are shown in the local variables view and the local variables of the parent, i.e. the "parent scope" can be examined by expanding the "[Outer scope]" line.
There may be any number of levels in the scope chain, which ultimately is terminated by the "global object", i.e. the object which holds the global variables, which in SVG is of class "SVGGlobal".
In the sample code below, a timer is installed which causes an unhandled exception to be thrown after two seconds when it tries to use the undefined variable "z". On the screenshot of the local variables view, we can see that the local scope of the callback contains the "event" parameter, the "this" pointer and the "n" local variable. We can see also that there is a closure in the scope chain, with the local variable ("x", "y" and "timer") of the delayOperation() function in which callback() was defined. Finally we see that the last object in the scope chain is the "SVGGlobal" global scope. <?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
<script>
<![CDATA[
function delayedOperation() {
var timer = createTimer( 2000, 1000 );
var x = 100, y = 200;
timer.addEventListener( "SVGTimer",
function callback( event ) {
var n;
n = Math.sqrt( x + z );
alert( 'n='+n );
},
false
);
timer.start();
}
delayedOperation();
]]>
</script>
</svg>
Examining the SVG tree
The debugger can show the current state of any XML fragment and of the rendering XML tree.
A breakpoint is set inside the textAreaWithBackground()
function, just before it returns (see image 1). This function builds a new XML fragment. When the breakpoint is hit, the local variables tab will show that the variable named "g" is a native object of class SVGElement pointing to a <g> XML element. Double-clicking on the line will open a new tab in the developer console to show the XML fragment containing this node and will highlight the line which corresponds to the clicked XML element.
If we click "Continue", a second breakpoint is hit just after the point where the fragment is inserted into the main rendering tree. A dump of the rendering is always available in the developer console. By switching to this tab, we can see that it now contains the fragment. Note that the xml:id of the element at the root of the XML fragment is used to label the tab in the developer console. For example, "svg" is often used for the rendering tree. If the root element does not have an id, "XML Tree" is used instead.
Below is the source code used in this example.
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720" >
<script>
<![CDATA[
function textAreaWithBackground( text, color, x, y, width, height ) {
var svgNS = "http://www.w3.org/2000/svg";
var g = document.createElementNS( svgNS, "g" );
g.setAttribute( "transform", "translate(" + x + "," + y + ")" );
var rect = document.createElementNS( svgNS, "rect" );
rect.setAttribute( "fill", color );
rect.setAttribute( "stroke", "none" );
rect.setAttribute( "width", width );
rect.setAttribute( "height", height );
g.appendChild( rect );
var textArea = document.createElementNS( svgNS, "textArea" );
textArea.textContent = text;
textArea.setAttribute( "width", width );
textArea.setAttribute( "height", height );
g.appendChild( textArea );
return g;
}
var twb = textAreaWithBackground( "Hello !", "yellow", 320, 180, 640, 360 );
document.getElementById( "content" ).appendChild( twb );
alert( 'OK!' );
]]>
</script>
<g xml:id="content" font-size="48" font-family="Arial" text-align="center" display-align="center" />
</svg>