diff options
Diffstat (limited to '')
-rw-r--r-- | src/civetweb/src/third_party/duktape-1.5.2/debugger/README.rst | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/src/civetweb/src/third_party/duktape-1.5.2/debugger/README.rst b/src/civetweb/src/third_party/duktape-1.5.2/debugger/README.rst new file mode 100644 index 000000000..f60b3506a --- /dev/null +++ b/src/civetweb/src/third_party/duktape-1.5.2/debugger/README.rst @@ -0,0 +1,384 @@ +========================================= +Duktape debug client and JSON debug proxy +========================================= + +Overview +======== + +Debugger web UI which connects to the Duktape command line tool or any other +target supporting the example TCP transport (``examples/debug-trans-socket``) +on Unix and Windows. + +Also provides a JSON debug proxy with a JSON mapping for the Duktape debug +protocol. + +For detailed documentation of the debugger internals, see `debugger.rst`__. + +__ https://github.com/svaarala/duktape/blob/master/doc/debugger.rst + +Using the debugger web UI +========================= + +Some prerequisites: + +* You'll need Node.js v0.10.x or newer. Older Node.js versions don't support + the required packages. + +Compile Duktape command line tool with debugger support (for further options +see http://wiki.duktape.org/FeatureOptions.html): + +* ``DUK_OPT_DEBUGGER_SUPPORT`` + +* ``DUK_OPT_INTERRUPT_COUNTER`` + +* ``DUK_CMDLINE_DEBUGGER_SUPPORT`` + +The source distributable contains a Makefile to build a "duk" command with +debugger support:: + + $ cd <duktape dist directory> + $ make -f Makefile.dukdebug + +The Duktape Git repo "duk" target has debugger support enabled by default:: + + $ make clean duk + +Start Duktape command line tool so that it waits for a debugger connection:: + + # For now we need to be in the directory containing the source files + # executed so that the 'fileName' properties of functions will match + # that on the debug client. + + # Using source distributable + $ cd <duktape dist directory> + $ ./duk --debugger mandel.js + + # Using Duktape Git repo + $ cd <duktape checkout>/tests/ecmascript/ + $ ../../duk --debugger test-dev-mandel2-func.js + +Start the web UI:: + + # Must be in 'debugger' directory. + + $ cd debugger/ + $ make # runs 'node duk_debug.js' + +Once the required packages are installed, the NodeJS debug client will be +up and running. Open the following in your browser and start debugging: + +* http://localhost:9092/ + +The debug client automatically attaches to the debug target on startup. +If you start the debug target later, you'll need to click "Attach" in the +web UI. + +Using the JSON debug proxy +========================== + +There are two JSON debug proxy implementations: one implemented in DukLuv +and another in Node.js. + +DukLuv JSON proxy +----------------- + +DukLuv (https://github.com/creationix/dukluv) is a small and portable event +loop based on LibUV and Duktape with MIT license (like Duktape). As such it's +easy to embed in a custom debug client: you just include the DukLuv executable +and the JSON proxy source file in your debug client. + +Install DukLuv: + +* Ensure ``cmake`` is installed + +* ``git clone https://github.com/creationix/dukluv.git`` + +* ``git submodule init; git submodule update`` + +* ``make`` + +* Binary should appear in: + + - ``./build/dukluv`` on Linux + + - ``.\build\Debug\dukluv.exe`` on Windows + +Run the proxy:: + + # Using Makefile; autogenerates duk_debug_meta.json + # (You may need to edit DUKLUV in Makefile to point to your DukLuv) + $ make runproxydukluv + + # Manually: see "dukluv duk_debug_proxy.js --help" for help + $ .../path/to/dukluv duk_debug_proxy.js + +Start Duktape command line (or whatever your target is):: + + $ cd <duktape checkout>/tests/ecmascript/ + $ ../../duk --debugger test-dev-mandel2-func.js + +Now connect to the proxy using e.g. telnet:: + + $ telnet localhost 9093 + +The proxy will then connect to the target and you can start issuing commands:: + + $ telnet localhost 9093 + Trying 127.0.0.1... + Connected to localhost. + Escape character is '^]'. + {"notify":"_TargetConnecting","args":["127.0.0.1",9091]} + {"notify":"_TargetConnected","args":["1 10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo"]} + {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]} + {"request":"BasicInfo"} + {"reply":true,"args":[10499,"v1.4.0-140-gc9a6c7c","duk command built from Duktape repo",1]} + {"request":"Eval","args":["print('Hello world!'); 123;"]} + {"notify":"Print","command":2,"args":["Hello world!\n"]} + {"reply":true,"args":[0,{"type":"number","data":"405ec00000000000"}]} + [...] + +The proxy log provides dumps both JSON and dvalue binary traffic which is +quite useful in development:: + + $ make runproxydukluv + Running Dukluv based debug proxy + "dukluv" duk_debug_proxy.js --log-level 2 --metadata duk_debug_meta.json + 2016-02-17T13:59:42.308Z INF Proxy: Read proxy metadata from duk_debug_meta.json + 2016-02-17T13:59:42.325Z INF Proxy: Listening for incoming JSON debug connection on 0.0.0.0:9093, target is 127.0.0.1:9091 + 2016-02-17T13:59:47.994Z INF Proxy: JSON proxy client connected + 2016-02-17T13:59:47.994Z INF Proxy: Connecting to debug target at 127.0.0.1:9091 + 2016-02-17T13:59:47.994Z INF Proxy: PROXY --> CLIENT: {"notify":"_TargetConnecting","args":["127.0.0.1",9091]} + 2016-02-17T13:59:47.994Z INF Proxy: Connected to debug target at 127.0.0.1:9091 + 2016-02-17T13:59:48.003Z INF Proxy: PROXY --> CLIENT: {"notify":"_TargetConnected","args":["1 10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo"]} + 2016-02-17T13:59:48.003Z INF Proxy: Target handshake: {"line":"1 10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo","protocolVersion":1,"text":"10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo","dukVersion":"1","dukGitDescribe":"10499","targetString":"v1.4.0-140-gc9a6c7c"} + 2016-02-17T13:59:48.151Z INF Proxy: PROXY <-- TARGET: |04| + 2016-02-17T13:59:48.152Z INF Proxy: PROXY <-- TARGET: |81| + 2016-02-17T13:59:48.152Z INF Proxy: PROXY <-- TARGET: |81| + 2016-02-17T13:59:48.160Z INF Proxy: PROXY <-- TARGET: |78746573742d6465762d6d616e64656c322d66756e632e6a73| + 2016-02-17T13:59:48.161Z INF Proxy: PROXY <-- TARGET: |66676c6f62616c| + 2016-02-17T13:59:48.165Z INF Proxy: PROXY <-- TARGET: |ba| + 2016-02-17T13:59:48.165Z INF Proxy: PROXY <-- TARGET: |80| + 2016-02-17T13:59:48.165Z INF Proxy: PROXY <-- TARGET: |00| + 2016-02-17T13:59:48.165Z INF Proxy: PROXY --> CLIENT: {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]} + 2016-02-17T13:59:51.289Z INF Proxy: PROXY <-- CLIENT: {"request":"BasicInfo"} + 2016-02-17T13:59:51.289Z INF Proxy: PROXY --> TARGET: |01| + 2016-02-17T13:59:51.289Z INF Proxy: PROXY --> TARGET: |90| + 2016-02-17T13:59:51.289Z INF Proxy: PROXY --> TARGET: |00| + 2016-02-17T13:59:51.291Z INF Proxy: PROXY <-- TARGET: |02| + 2016-02-17T13:59:51.291Z INF Proxy: PROXY <-- TARGET: |e903| + 2016-02-17T13:59:51.292Z INF Proxy: PROXY <-- TARGET: |7376312e342e302d3134302d6763396136633763| + 2016-02-17T13:59:51.293Z INF Proxy: PROXY <-- TARGET: |12002364756b20636f6d6d616e64206275696c742066726f6d2044756b74617065207265706f| + 2016-02-17T13:59:51.293Z INF Proxy: PROXY <-- TARGET: |81| + 2016-02-17T13:59:51.293Z INF Proxy: PROXY <-- TARGET: |00| + 2016-02-17T13:59:51.293Z INF Proxy: PROXY --> CLIENT: {"reply":true,"args":[10499,"v1.4.0-140-gc9a6c7c","duk command built from Duktape repo",1]} + 2016-02-17T14:00:06.105Z INF Proxy: PROXY <-- CLIENT: {"request":"Eval","args":["print('Hello world!'); 123;"]} + 2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |01| + 2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |9e| + 2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |7b7072696e74282748656c6c6f20776f726c642127293b203132333b| + 2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |00| + 2016-02-17T14:00:06.167Z INF Proxy: PROXY <-- TARGET: |04| + 2016-02-17T14:00:06.167Z INF Proxy: PROXY <-- TARGET: |82| + 2016-02-17T14:00:06.167Z INF Proxy: PROXY <-- TARGET: |6d48656c6c6f20776f726c64210a| + 2016-02-17T14:00:06.168Z INF Proxy: PROXY <-- TARGET: |00| + 2016-02-17T14:00:06.168Z INF Proxy: PROXY --> CLIENT: {"notify":"Print","command":2,"args":["Hello world!\n"]} + 2016-02-17T14:00:06.171Z INF Proxy: PROXY <-- TARGET: |02| + 2016-02-17T14:00:06.171Z INF Proxy: PROXY <-- TARGET: |80| + 2016-02-17T14:00:06.173Z INF Proxy: PROXY <-- TARGET: |1a405ec00000000000| + 2016-02-17T14:00:06.173Z INF Proxy: PROXY <-- TARGET: |00| + 2016-02-17T14:00:06.174Z INF Proxy: PROXY --> CLIENT: {"reply":true,"args":[0,{"type":"number","data":"405ec00000000000"}]} + [...] + +Node.js JSON proxy +------------------ + +A Node.js-based JSON debug proxy is also provided by ``duk_debug.js``:: + + # Same prerequisites as for running the debug client + $ make runproxynodejs + +Start Duktape command line (or whatever your target is):: + + $ cd <duktape checkout>/tests/ecmascript/ + $ ../../duk --debugger test-dev-mandel2-func.js + +You can then connect to localhost:9093 and interact with the proxy. +Here's an example session using telnet and manually typed in commands +The ``-->`` (send) and ``<--`` (receiver) markers have been added for +readability and are not part of the stream:: + + $ telnet localhost 9093 + Trying 127.0.0.1... + Connected to localhost. + Escape character is '^]'. + <-- {"notify":"_TargetConnected","args":["1 10199 v1.1.0-275-gbd4d610-dirty duk command built from Duktape repo"]} + <-- {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]} + --> {"request":"BasicInfo"} + <-- {"reply":true,"args":[10199,"v1.1.0-275-gbd4d610-dirty","duk command built from Duktape repo",1]} + --> {"request":"Eval", "args":[ "print(Math.PI)" ]} + <-- {"notify":"Print","command":2,"args":["3.141592653589793\n"]} + <-- {"reply":true,"args":[0,{"type":"undefined"}]} + --> {"request":"Resume"} + <-- {"reply":true,"args":[]} + <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]} + <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]} + <-- {"notify":"Print","command":2,"args":["................................................................................\n"]} + <-- {"notify":"Print","command":2,"args":["................................................................................\n"]} + <-- {"notify":"Print","command":2,"args":["................................................................................\n"]} + [...] + <-- {"notify":"_Disconnecting"} + +A telnet connection allows you to experiment with debug commands by simply +copy-pasting debug commands to the telnet session. This is useful even if +you decide to implement the binary protocol directly. + +The debug target used by the proxy can be configured with ``duk_debug.js`` +command line options. + +Source search path +================== + +The NodeJS debug client needs to be able to find source code files matching +code running on the target ("duk" command line). **The filenames used on the +target and on the debug client must match exactly**, because e.g. breakpoints +are targeted based on the 'fileName' property of Function objects. + +The search path can be set using the ``--source-dirs`` option given to +``duk_debug.js``, with the default search paths including only +``../tests/ecmascript/``. + +The default search path means that if a function on the target has fileName +``foo/bar.js`` it would be loaded from (relative to the duk_debug.js working +directory, ``debugger/``):: + + ../tests/ecmascript/foo/bar.js + +Similarly, if the filesystem contained:: + + ../tests/ecmascript/baz/quux.js + +the web UI dropdown would show ``baz/quux.js``. If you selected that file +and added a breakpoint, the breakpoint fileName sent to the debug target +would be ``baz/quux.js``. + +.. note:: There's much to improve in the search path. For instance, it'd + be nice to add a certain path to search but exclude files based + on paths and patterns, etc. + +Architecture +============ + +:: + + +-------------------+ + | Web browser | [debug UI] + +-------------------+ + | + | http (port 9092) + | socket.io + v + +-------------------+ + | duk_debug.js | [debug client] + +-------------------+ + | /\ + | || + +----------||---- [example tcp transport] (port 9091) + | || (application provides concrete transport) + | || + | ||---- [debug protocol stream] + | || (between debug client and Duktape) + | || + + - - | - - - - -|| - - + + : v || : + : +-------------||-+ : [target] + : | application || | : + : +-------------||-+ : + : ^ || : + : | || : [debug API] + : +----------||-------- debug transport callbacks + : | || : (read, write, peek, read/write flush) + : | || : implemented by application + : | \/ : + : +----------------+ : + : | Duktape | : + : +----------------+ : + + - - - - - - - - - - - + + +The debug transport is application specific: + +* Duktape command line ("duk") and this debug client use an **example** TCP + transport as a concrete example. + +* It is entirely up to the application to come up with the most suitable + transport for its environment. Different mechanisms will be needed for + Wi-Fi, serial, etc. + +The debug protocol running inside the transport is transport independent: + +* The debug protocol is documented in ``doc/debugger.rst``. + +* This debug client provides further concrete examples and clarifications + on how the protocol can be used. + +Using a custom transport +======================== + +Quite possibly your target device cannot use the example TCP transport and +you need to implement your own transport. You'll need to implement your +custom transport both for the target device and for the debug client. + +Target device +------------- + +Implement the debug transport callbacks needed by ``duk_debugger_attach()``. + +See ``doc/debugger.rst`` for details and ``examples/debug-trans-socket`` +for example running code for a TCP transport. + +Debug client alternative 1: duk_debug.js + custom TCP proxy +----------------------------------------------------------- + +If you don't want to change ``duk_debug.js`` you can implement a TCP proxy +which accepts a TCP connection from ``duk_debug.js`` and then uses your +custom transport to talk to the target:: + + +--------------+ TCP +-------+ custom +--------+ + | duk_debug.js | ------> | proxy | ---------> | target | + +--------------+ +-------+ +--------+ + +This is a straightforward option and a proxy can be used with other debug +clients too (perhaps custom scripts talking to the target etc). + +You could also use netcat and implement your proxy so that it talks to +``duk_debug.js`` using stdin/stdout. + +Debug client alternative 2: duk_debug.js + custom NodeJS stream +--------------------------------------------------------------- + +To make ``duk_debug.js`` use a custom transport you need to: + +* Implement your own transport as NodeJS stream. You can add it directly to + ``duk_debug.js`` but it's probably easiest to use a separate module so that + the diff to ``duk_debug.js`` stays minimal. + +* Change ``duk_debug.js`` to use the custom transport instead of a TCP + stream. Search for "CUSTOMTRANSPORT" in ``duk_debug.js``. + +See: + +* http://nodejs.org/api/stream.html + +* https://github.com/substack/stream-handbook + +Debug client alternative 3: custom debug client +----------------------------------------------- + +You can also implement your own debug client and debug UI with support for +your custom transport. + +You'll also need to implement the client part of the Duktape debugger +protocol. See ``doc/debugger.rst`` for the specification and ``duk_debug.js`` +for example running code which should illustrate the protocol in more detail. + +The JSON debug proxy allows you to implement a debug client without needing +to implement the Duktape binary debug protocol. The JSON protocol provides +a roughly 1:1 mapping to the binary protocol but with an easier syntax. |