Changes between Version 7 and Version 8 of JavascriptDebuggingServer


Ignore:
Timestamp:
Jan 17, 2016, 1:53:10 AM (8 years ago)
Author:
leper
Comment:

The JSDebugger was removed in r17655.

Legend:

Unmodified
Added
Removed
Modified
  • JavascriptDebuggingServer

    v7 v8  
    1 [[TOC]]
    2 
    3 = [[span(style=color: red, The JS debugger is temporarily disabled during the SpiderMonkey upgrade (check tickets #2348 and #2973 for details) )]] =
    4 
    5 == Introduction ==
    6 
    7 This page contains technical documentation of the Pyrogenesis script debugger.
    8 If you are only interested in using the debugger rather than changing it, please refer to [wiki:JavascriptDebugging Javascript debugging]
    9 
    10 == Technical background ==
    11 The DebuggingServer component makes debugging commands like (ToggleBreakpoint, Step, Continue etc...) available using a Mongoose webserver.
    12 The format used for return values is JSON, which should be easy to parse from a web-GUI.
    13  
    14 The Debugger uses the JSDBGAPI provided by Spidermonkey 1.8.5. Newer versions of Spidermonkey provide a simplified new API (along with memory leak fixes, performance improvements and more), but unfortunately Mozilla isn't interested in doing the work and publishing a independent build from Firefox at the moment.
    15 We had a [http://irclogs.wildfiregames.com/2013-01-02-QuakeNet-%230ad-dev.log discussion about that on IRC].
    16 We're thinking about upgrading Spidermonkey nevertheless, but that could be a bigger task.
    17 
    18 The JSDBGAPI isn't thread-safe and also our current implementation of ScriptInterfaces (which are basically abstractions of Spidermonkey) isn't thread-safe either.
    19 As a general rule, all Javascript objects are tied to one ScriptInterface which represents one Javascript runtime and one Javascript context and can only be used in one thread (although multiple ScriptInterface can be used in one thread). We do use multiple threads, but they don't share ScriptInterfaces.
    20 One major difficulty about implementing a debugger is not to violate these constraints.
    21 
    22 The idea is that there's one CThreadDebugger class which is responsible for tracking hooks, callbacks, breakpoints and general state information for each of those ScriptInterfaces. The class CDebuggingServer manages multiple ScriptInterfaces (which are potentially multiple threads) using multiple objects of CThreadDebugger.
    23 It passes commands from the Mongoose webserver (triggered by the user) to the CThreadDebugger objects and retrieves state information from these objects and returns it to the user as JSON. The DebuggingServer makes sure not to access any Spidermonkey functions or Javascript objects directly (because they belong to the ScriptInterface's thread).
    24 The DebuggingServer itself should also be thread-safe to accept multiple request asynchronously.
    25 
    26 
    27 == Available commands ==
    28 This section lists all currently implemented commands and gives some examples of data they return.
    29 
    30 === Setting: Simultaneously breaking threads ===
    31 This setting specifies the behaviour when a breakpoint is hit.
    32 If enabled, all other threads executing Javascript code will halt too as soon as possible and their status (ThreadInBreak) will change to true.
    33 Keep in mind that other ScriptInterfaces being executed in the same thread will not halt because their code will only be reached when you continue the execution in the current ScriptInterface. Another limitation is that threads can only be halted by this debugger when they execute Javascript code!
    34 You can set breakpoints with your favourite c++ debugger at the right places if you need seamless debugging between c++ and Javascript.
    35 
    36 ==== Get ====
    37 {{{
    38 http://127.0.0.1:9000/GetSettingSimultaneousThreadBreak
    39 }}}
    40 
    41 Returns:
    42 {{{
    43 #!js
    44 { "Enabled" : true }
    45 }}}
    46 
    47 ==== Set ====
    48 
    49 {{{
    50 http://127.0.0.1:9000/SetSettingSimultaneousThreadBreak?Enabled=false
    51 }}}
    52 Arguments:
    53  * '''Enabled''': If the setting should be enabled (true or false).
    54 
    55 Returns:
    56 Nothing
    57 
    58 === Setting: Breaking on exception ===
    59 This setting specifies if debugger will stop script execution if any exception is thrown by JS code. Even if you disable it, the debugger will still trigger breakpoints for exceptions with the message "Breakpoint".
    60 
    61 ==== Get ====
    62 {{{
    63 http://127.0.0.1:9000/GetSettingBreakOnException
    64 }}}
    65 
    66 Returns:
    67 {{{
    68 #!js
    69 { "Enabled" : true }
    70 }}}
    71 
    72 ==== Set ====
    73 
    74 {{{
    75 http://127.0.0.1:9000/SetSettingBreakOnException?Enabled=false
    76 }}}
    77 Arguments:
    78  * '''Enabled''': If the setting should be enabled (true or false).
    79 
    80 Returns:
    81 Nothing
    82 
    83 
    84 === Toggling (setting/removing) breakpoints: ===
    85 {{{
    86 http://127.0.0.1:9000/ToggleBreakpoint?filename=gui/gamesetup/gamesetup.js&line=1502
    87 }}}
    88 Returns:
    89 Nothing
    90 
    91 === Get the status of all threads ===
    92 {{{
    93 http://127.0.0.1:9000/GetThreadDebuggerStatus
    94 }}}
    95 
    96 Returns:
    97 {{{
    98 #!js
    99 [ { "ThreadDebuggerID" : 1,"ScriptInterfaceName" : "GUI","ThreadInBreak" : true,"BreakFileName" : "gui/gamesetup/gamesetup.js","BreakLine" : 1502 } ]
    100 }}}
    101 Note:
    102 BreakFileName and BreakLine should be considered "undefined" if ThreadInBreak is false!
    103 
    104 === Continue ===
    105 Continue the execution until the next breakpoint is hit.
    106 {{{
    107 http://127.0.0.1:9000/Continue?threadDebuggerID=1
    108 }}}
    109 Arguments:
    110  * '''threadDebuggerID''': The ThreadDebuggerID of the thread that should be continued. You can get this ID by calling GetThreadDebuggerStatus. If you pass 0, all threads will be continued.
    111 
    112 Returns:
    113 Nothing
    114 
    115 Note: The command has no effect if the thread is not stopped.
    116 
    117 === Break ===
    118 Break the execution of all threads as soon as possible.
    119 {{{
    120 http://127.0.0.1:9000/Break
    121 }}}
    122 Arguments:
    123 None
    124 
    125 Returns:
    126 Nothing
    127 
    128 === Step ===
    129 Steps to the next line of code and will step over functions that are called on the current line.
    130 {{{
    131 http://127.0.0.1:9000/Step?threadDebuggerID=1
    132 }}}
    133 Arguments:
    134  * '''threadDebuggerID''': The ThreadDebuggerID of the thread that should be stepped. You can get this ID by calling GetThreadDebuggerStatus.
    135 
    136 Returns:
    137 Nothing
    138 
    139 === Step into ===
    140 Steps into function calls on the current line of code or steps to the next line if there aren't any function calls.
    141 {{{
    142 http://127.0.0.1:9000/StepInto?threadDebuggerID=1
    143 }}}
    144 Arguments:
    145  * '''threadDebuggerID''': The ThreadDebuggerID of the thread that should be stepped. You can get this ID by calling GetThreadDebuggerStatus.
    146 
    147 Returns:
    148 Nothing
    149 
    150 === Step out ===
    151 Steps out of the current function and stops the execution in the parent function.
    152 {{{
    153 http://127.0.0.1:9000/StepOut?threadDebuggerID=1
    154 }}}
    155 Arguments:
    156  * '''threadDebuggerID''': The ThreadDebuggerID of the thread that should be stepped. You can get this ID by calling GetThreadDebuggerStatus.
    157 
    158 Returns:
    159 Nothing
    160 
    161 
    162 
    163 === Getting Callstacks ===
    164 Returns the callstacks of all threads that are in break mode.
    165 {{{
    166 http://127.0.0.1:9000/GetAllCallstacks
    167 }}}
    168 Returns:
    169 {{{
    170 #!js
    171 { "CallStacks" : [{"ThreadDebuggerID" : 1, "CallStack" : ["keywordTestOR","annonymous","testFilter","initMapNameList","selectMapType","__eventhandler31 (selectionchange)","initMain","onTick","__eventhandler28 (tick)"]}] }
    172 }}}
    173 keywordTestOR is the innermost function which got called by an annonymous function, which got called by "testFilter" etc...
    174 You also get the ThreadDebuggerID to know which thread is meant.
    175 
    176 === Getting a stack frame's local values ===
    177 Returns all local variables and their content of the specified thread and nesting level.
    178 {{{
    179 http://127.0.0.1:9000/GetStackFrame?nestingLevel=0&threadDebuggerID=1
    180 }}}
    181 Returns:
    182 {{{
    183 ... a JSON object
    184 }}}
    185 Arguments:
    186  * '''nestingLevel''' If you look at the function above (GetCallstack), nestingLevel=0 would point to the innermost stackframe (keywordTestOR). Native functions as "__eventhandler31" don't return any data.
    187  * '''threadDebuggerID''' The thread you want to get the local variables frame from.
    188 
    189 
    190 === Getting a stack frame's "this" object ===
    191 Returns the "this" object of the specified thread and nesting level as JSON.
    192 {{{
    193 http://127.0.0.1:9000/GetStackFrameThis?nestingLevel=0&threadDebuggerID=1
    194 }}}
    195 Returns:
    196 {{{
    197 ... a JSON object
    198 }}}
    199 Arguments:
    200  * '''nestingLevel''' If you look at the function above (GetCallstack), nestingLevel=0 would point to the innermost stackframe (keywordTestOR). Native functions as "__eventhandler31" don't return any data.
    201  * '''threadDebuggerID''' The thread you want to get the a stack frame from.
    202 
    203 
    204 === Getting the current global object ===
    205 Returns the current global object of the specified thread.
    206 {{{
    207 http://127.0.0.1:9000/GetCurrentGlobalObject?threadDebuggerID=1
    208 }}}
    209 Returns:
    210 {{{
    211 ... a JSON object
    212 }}}
    213 Arguments:
    214  * '''threadDebuggerID''' The thread you want to get the global object from.
    215 
    216 
    217 === Getting a list of .js files ===
    218 Returns all full Vfs paths ending with *.js loaded into the Vfs.
    219 {{{
    220 http://127.0.0.1:9000/EnumVfsJSFiles
    221 }}}
    222 Returns (shortened)
    223 {{{
    224 #!js
    225 ["globalscripts/Math.js","globalscripts/Technologies.js","hwdetect/hwdetect.js","hwdetect/test.js","gui/aiconfig/aiconfig.js","gui/civinfo/civinfo.js"]
    226 }}}
    227 
    228 === Getting a file ===
    229 Returns a whole file without any formatting (no JSON).
    230 {{{
    231 http://127.0.0.1:9000/GetFile?filename=globalscripts/Math.js
    232 }}}
    233 Returns:
    234 A file as plaintext.
    235 
    236 Arguments:
    237  * '''filename''' A full Vfs path to a file
    238 
    239 
    240 
    241 == Known issues ==
    242  * Circular references are not displayed circularly. Instead, it replaces the value with this text: "Debugger: object removed from output because of cyclic reference.".
    243  * It would probably be better to stringify and transfer the global object incrementally (after expanding sub-objects) instead of doing it all at once.
    244  * Apparently GetStackFrameThis, GetStackFrame and GetCurrentGlobalObject don't return non-enumerable properties. I think it's because JS_Stringify is used for converting the objects to JSON. This and the two preceding issues are all reasons for writing an own JSON parser or passing another custom format to the web GUI.
    245  * Quite a lot of little things that aren't perfect but should be acceptable for the first version.
     1= [[span(The JS debugger was removed since the used API was removed in SpiderMonkey (check tickets #2348, #2973, #3708 for details) )]] =