Pārlūkot izejas kodu

Updated duktape to 2.01 and made sure that it was configured for debugging. Also updated the debugger node proxy to the latest.

Shaddock Heath 8 gadi atpakaļ
vecāks
revīzija
e91f61f637

+ 101 - 0
Script/DuktapeDebugProxy/Makefile

@@ -0,0 +1,101 @@
+NODE:=$(shell { command -v nodejs || command -v node; } 2>/dev/null)
+DUKLUV:=$(shell command -v dukluv 2>/dev/null)
+
+# Try to get a useful default --source-dirs which works both in the Duktape
+# repo and in the distributable.  We don't want to add '..' because it would
+# scan a lot of undesired files in the Duktape repo (e.g. test262 testcases).
+ifeq ($(wildcard ../tests/ecmascript/*.js),)
+SOURCEDIRS:=../
+else
+SOURCEDIRS:=../tests/ecmascript
+endif
+
+.PHONY: all
+all: run
+
+.PHONY: run
+run: node_modules static/socket.io-1.2.0.js static/jquery-1.11.1.min.js static/reset.css static/jquery-ui.min.js static/jquery-ui.min.css static/images
+	"$(NODE)" duk_debug.js --source-dirs=$(SOURCEDIRS)
+
+rundebug: node_modules static/socket.io-1.2.0.js static/jquery-1.11.1.min.js static/reset.css static/jquery-ui.min.js static/jquery-ui.min.css static/images
+	"$(NODE)" duk_debug.js --source-dirs=$(SOURCEDIRS) --verbose --log-messages /tmp/dukdebug-messages --dump-debug-pretty /tmp/dukdebug-pretty
+
+.PHONY: runproxynodejs
+runproxynodejs: node_modules static/socket.io-1.2.0.js static/jquery-1.11.1.min.js static/reset.css static/jquery-ui.min.js static/jquery-ui.min.css static/images
+	@echo "Running Node.js based debug proxy"
+	"$(NODE)" duk_debug.js --json-proxy
+
+.PHONY: runproxydukluv
+runproxydukluv: duk_debug_meta.json
+	@echo "Running Dukluv based debug proxy (you may need to edit DUKLUV in the Makefile)"
+	"$(DUKLUV)" duk_debug_proxy.js --log-level 2 --metadata duk_debug_meta.json --readable-numbers
+
+.PHONY: runproxy
+runproxy: runproxydukluv
+
+.PHONY: clean
+clean:
+	@rm -f static/socket.io-1.2.0.js
+	@rm -f static/jquery-1.11.1.min.js
+	@rm -f static/jquery.syntaxhighlighter.min.js
+	@rm -f static/jquery.snippet.min.js
+	@rm -f static/jquery.snippet.min.css
+	@rm -f static/prefixfree.min.js
+	@rm -f static/reset.css
+	@rm -f static/jquery-ui.min.js
+	@rm -f static/jquery-ui.min.css
+	@rm -rf static/images
+	@rm -f jquery-ui-1.11.2.zip
+	@rm -rf jquery-ui-1.11.2
+	@rm -rf node_modules
+	@rm -f duk_debug_meta.json
+
+node_modules:
+	npm install
+
+duk_debug_meta.json:
+	python ../tools/merge_debug_meta.py --output $@ \
+		--class-names duk_classnames.yaml \
+		--opcodes duk_opcodes.yaml \
+		--debug-commands duk_debugcommands.yaml \
+		--debug-errors duk_debugerrors.yaml
+
+static/socket.io-1.2.0.js:
+	wget -O $@ http://cdn.socket.io/socket.io-1.2.0.js
+
+static/jquery-1.11.1.min.js:
+	wget -O $@ http://code.jquery.com/jquery-1.11.1.min.js
+
+# http://balupton.github.io/jquery-syntaxhighlighter/demo/
+static/jquery.syntaxhighlighter.min.js:
+	wget -O $@ http://balupton.github.com/jquery-syntaxhighlighter/scripts/jquery.syntaxhighlighter.min.js
+
+# http://steamdev.com/snippet/
+static/jquery.snippet.min.js:
+	wget -O $@ http://steamdev.com/snippet/js/jquery.snippet.min.js
+static/jquery.snippet.min.css:
+	wget -O $@ http://steamdev.com/snippet/css/jquery.snippet.min.css
+
+# http://prismjs.com/
+# http://prismjs.com/plugins/line-highlight/
+#
+# XXX: prism download manually?
+
+# https://raw.github.com/LeaVerou/prefixfree/gh-pages/prefixfree.min.js
+static/prefixfree.min.js:
+	wget -O $@ https://raw.github.com/LeaVerou/prefixfree/gh-pages/prefixfree.min.js
+
+# http://meyerweb.com/eric/tools/css/reset/
+static/reset.css:
+	wget -O $@ http://meyerweb.com/eric/tools/css/reset/reset.css
+
+jquery-ui-1.11.2.zip:
+	wget -O $@ http://jqueryui.com/resources/download/jquery-ui-1.11.2.zip
+jquery-ui-1.11.2: jquery-ui-1.11.2.zip
+	unzip $<
+static/jquery-ui.min.js: jquery-ui-1.11.2
+	cp jquery-ui-1.11.2/jquery-ui.min.js $@
+static/jquery-ui.min.css: jquery-ui-1.11.2
+	cp jquery-ui-1.11.2/jquery-ui.min.css $@
+static/images: jquery-ui-1.11.2
+	cp -r jquery-ui-1.11.2/images static/

+ 5 - 6
Script/DuktapeDebugProxy/README.rst

@@ -24,14 +24,13 @@ 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):
+Compile Duktape command line tool with debugger support:
 
-* ``DUK_OPT_DEBUGGER_SUPPORT``
+* Enable ``DUK_USE_DEBUGGER_SUPPORT`` and ``DUK_USE_INTERRUPT_COUNTER`` for
+  ``tools/configure.py``.
 
-* ``DUK_OPT_INTERRUPT_COUNTER``
-
-* ``DUK_CMDLINE_DEBUGGER_SUPPORT``
+* Enable ``DUK_CMDLINE_DEBUGGER_SUPPORT`` on compiler command line for Duktape
+  command line utility.
 
 The source distributable contains a Makefile to build a "duk" command with
 debugger support::

+ 5 - 5
Script/DuktapeDebugProxy/duk_classnames.yaml

@@ -1,22 +1,22 @@
 # Must match C header.
 class_names:
-  - unused
-  - Arguments
+  - none
+  - Object
   - Array
+  - Function
+  - Arguments
   - Boolean
   - Date
   - Error
-  - Function
   - JSON
   - Math
   - Number
-  - Object
   - RegExp
   - String
   - global
+  - Symbol
   - ObjEnv
   - DecEnv
-  - Buffer
   - Pointer
   - Thread
   - ArrayBuffer

+ 58 - 54
Script/DuktapeDebugProxy/duk_debug.js

@@ -27,8 +27,8 @@ var util = require('util');
 var readline = require('readline');
 var sprintf = require('sprintf').sprintf;
 var utf8 = require('utf8');
-var wrench = require('wrench');  // https://github.com/ryanmcgrath/wrench-js
 var yaml = require('yamljs');
+var recursiveReadSync = require('recursive-readdir-sync');
 
 // Command line options (defaults here, overwritten if necessary)
 var optTargetHost = '127.0.0.1';
@@ -47,12 +47,13 @@ var UI_MESSAGE_CLIPLEN = 128;
 var LOCALS_CLIPLEN = 64;
 var EVAL_CLIPLEN = 4096;
 var GETVAR_CLIPLEN = 4096;
+var SUPPORTED_DEBUG_PROTOCOL_VERSION = 2;
 
 // Commands initiated by Duktape
 var CMD_STATUS = 0x01;
-var CMD_PRINT = 0x02;
-var CMD_ALERT = 0x03;
-var CMD_LOG = 0x04;
+var CMD_UNUSED_2 = 0x02;  // Duktape 1.x: print notify
+var CMD_UNUSED_3 = 0x03;  // Duktape 1.x: alert notify
+var CMD_UNUSED_4 = 0x04;  // Duktape 1.x: log notify
 var CMD_THROW = 0x05;
 var CMD_DETACHING = 0x06;
 
@@ -106,9 +107,9 @@ debugCommandNames.forEach(function (k, i) {
 });
 
 // Duktape heaphdr type constants, must match C headers
-var DUK_HTYPE_STRING = 1;
-var DUK_HTYPE_OBJECT = 2;
-var DUK_HTYPE_BUFFER = 3;
+var DUK_HTYPE_STRING = 0;
+var DUK_HTYPE_OBJECT = 1;
+var DUK_HTYPE_BUFFER = 2;
 
 // Duktape internal class numbers, must match C headers
 var dukClassNameMeta = yaml.load('duk_classnames.yaml');
@@ -116,12 +117,9 @@ var dukClassNames = dukClassNameMeta.class_names;
 
 // Bytecode opcode/extraop metadata
 var dukOpcodes = yaml.load('duk_opcodes.yaml');
-if (dukOpcodes.opcodes.length != 64) {
+if (dukOpcodes.opcodes.length != 256) {
     throw new Error('opcode metadata length incorrect');
 }
-if (dukOpcodes.extra.length != 256) {
-    throw new Error('extraop metadata length incorrect');
-}
 
 /*
  *  Miscellaneous helpers
@@ -445,7 +443,7 @@ SourceFileManager.prototype.scan = function () {
     this.directories.forEach(function (dir) {
         console.log('Scanning source files: ' + dir);
         try {
-            wrench.readdirSyncRecursive(dir).forEach(function (fn) {
+            recursiveReadSync(dir).forEach(function (fn) {
                 var absFn = path.normalize(path.join(dir, fn));   // './foo/bar.js' -> 'foo/bar.js'
                 var ent;
 
@@ -1066,44 +1064,49 @@ Debugger.prototype.decodeBytecodeFromBuffer = function (buf, consts, funcs) {
             ins = buf.readInt32BE(i) >>> 0;
         }
 
-        op = dukOpcodes.opcodes[ins & 0x3f];
-        if (op.extra) {
-            op = dukOpcodes.extra[(ins >> 6) & 0xff];
-        }
+        op = dukOpcodes.opcodes[ins & 0xff];
 
         args = [];
         comments = [];
         if (op.args) {
             for (j = 0, m = op.args.length; j < m; j++) {
+                var A = (ins >>> 8) & 0xff;
+                var B = (ins >>> 16) & 0xff;
+                var C = (ins >>> 24) & 0xff;
+                var BC = (ins >>> 16) & 0xffff;
+                var ABC = (ins >>> 8) & 0xffffff;
+                var Bconst = op & 0x01;
+                var Cconst = op & 0x02;
+
                 switch (op.args[j]) {
-                case 'A_R':   args.push('r' + ((ins >>> 6) & 0xff)); break;
-                case 'A_RI':  args.push('r' + ((ins >>> 6) & 0xff) + '(indirect)'); break;
-                case 'A_C':   args.push('c' + ((ins >>> 6) & 0xff)); break;
-                case 'A_H':   args.push('0x' + ((ins >>> 6) & 0xff).toString(16)); break;
-                case 'A_I':   args.push(((ins >>> 6) & 0xff).toString(10)); break;
-                case 'A_B':   args.push(((ins >>> 6) & 0xff) ? 'true' : 'false'); break;
-                case 'B_RC':  args.push((ins & (1 << 22) ? 'c' : 'r') + ((ins >>> 14) & 0x0ff)); break;
-                case 'B_R':   args.push('r' + ((ins >>> 14) & 0x1ff)); break;
-                case 'B_RI':  args.push('r' + ((ins >>> 14) & 0x1ff) + '(indirect)'); break;
-                case 'B_C':   args.push('c' + ((ins >>> 14) & 0x1ff)); break;
-                case 'B_H':   args.push('0x' + ((ins >>> 14) & 0x1ff).toString(16)); break;
-                case 'B_I':   args.push(((ins >>> 14) & 0x1ff).toString(10)); break;
-                case 'C_RC':  args.push((ins & (1 << 31) ? 'c' : 'r') + ((ins >>> 23) & 0x0ff)); break;
-                case 'C_R':   args.push('r' + ((ins >>> 23) & 0x1ff)); break;
-                case 'C_RI':  args.push('r' + ((ins >>> 23) & 0x1ff) + '(indirect)'); break;
-                case 'C_C':   args.push('c' + ((ins >>> 23) & 0x1ff)); break;
-                case 'C_H':   args.push('0x' + ((ins >>> 23) & 0x1ff).toString(16)); break;
-                case 'C_I':   args.push(((ins >>> 23) & 0x1ff).toString(10)); break;
-                case 'BC_R':  args.push('r' + ((ins >>> 14) & 0x3ffff)); break;
-                case 'BC_C':  args.push('c' + ((ins >>> 14) & 0x3ffff)); break;
-                case 'BC_H':  args.push('0x' + ((ins >>> 14) & 0x3ffff).toString(16)); break;
-                case 'BC_I':  args.push(((ins >>> 14) & 0x3ffff).toString(10)); break;
-                case 'ABC_H': args.push(((ins >>> 6) & 0x03ffffff).toString(16)); break;
-                case 'ABC_I': args.push(((ins >>> 6) & 0x03ffffff).toString(10)); break;
-                case 'BC_LDINT': args.push(((ins >>> 14) & 0x3ffff) - (1 << 17)); break;
-                case 'BC_LDINTX': args.push(((ins >>> 14) & 0x3ffff) - 0); break;  // no bias in LDINTX
+                case 'A_R':   args.push('r' + A); break;
+                case 'A_RI':  args.push('r' + A + '(indirect)'); break;
+                case 'A_C':   args.push('c' + A); break;
+                case 'A_H':   args.push('0x' + A.toString(16)); break;
+                case 'A_I':   args.push(A.toString(10)); break;
+                case 'A_B':   args.push(A ? 'true' : 'false'); break;
+                case 'B_RC':  args.push((Bconst ? 'c' : 'r') + B); break;
+                case 'B_R':   args.push('r' + B); break;
+                case 'B_RI':  args.push('r' + B + '(indirect)'); break;
+                case 'B_C':   args.push('c' + B); break;
+                case 'B_H':   args.push('0x' + B.toString(16)); break;
+                case 'B_I':   args.push(B.toString(10)); break;
+                case 'C_RC':  args.push((Cconst ? 'c' : 'r') + C); break;
+                case 'C_R':   args.push('r' + C); break;
+                case 'C_RI':  args.push('r' + C + '(indirect)'); break;
+                case 'C_C':   args.push('c' + C); break;
+                case 'C_H':   args.push('0x' + C.toString(16)); break;
+                case 'C_I':   args.push(C.toString(10)); break;
+                case 'BC_R':  args.push('r' + BC); break;
+                case 'BC_C':  args.push('c' + BC); break;
+                case 'BC_H':  args.push('0x' + BC.toString(16)); break;
+                case 'BC_I':  args.push(BC.toString(10)); break;
+                case 'ABC_H': args.push(ABC.toString(16)); break;
+                case 'ABC_I': args.push(ABC.toString(10)); break;
+                case 'BC_LDINT': args.push(BC - (1 << 15)); break;
+                case 'BC_LDINTX': args.push(BC - 0); break;  // no bias in LDINTX
                 case 'ABC_JUMP': {
-                    var pc_add = ((ins >>> 6) & 0x03ffffff) - (1 << 25) + 1;  // pc is preincremented before adding
+                    var pc_add = ABC - (1 << 23) + 1;  // pc is preincremented before adding
                     var pc_dst = pc + pc_add;
                     args.push(pc_dst + ' (' + (pc_add >= 0 ? '+' : '') + pc_add + ')');
                     break;
@@ -1214,14 +1217,14 @@ Debugger.prototype.sendBasicInfoRequest = function () {
 
 Debugger.prototype.sendGetVarRequest = function (varname, level) {
     var _this = this;
-    return this.sendRequest([ DVAL_REQ, CMD_GETVAR, varname, (typeof level === 'number' ? level : -1), DVAL_EOM ]).then(function (msg) {
+    return this.sendRequest([ DVAL_REQ, CMD_GETVAR, (typeof level === 'number' ? level : -1), varname, DVAL_EOM ]).then(function (msg) {
         return { found: msg[1] === 1, value: msg[2] };
     });
 };
 
 Debugger.prototype.sendPutVarRequest = function (varname, varvalue, level) {
     var _this = this;
-    return this.sendRequest([ DVAL_REQ, CMD_PUTVAR, varname, varvalue, (typeof level === 'number' ? level : -1), DVAL_EOM ]);
+    return this.sendRequest([ DVAL_REQ, CMD_PUTVAR, (typeof level === 'number' ? level : -1), varname, varvalue, DVAL_EOM ]);
 };
 
 Debugger.prototype.sendInvalidCommandTestRequest = function () {
@@ -1318,7 +1321,13 @@ Debugger.prototype.sendResumeRequest = function () {
 
 Debugger.prototype.sendEvalRequest = function (evalInput, level) {
     var _this = this;
-    return this.sendRequest([ DVAL_REQ, CMD_EVAL, evalInput, (typeof level === 'number' ? level : -1), DVAL_EOM ]).then(function (msg) {
+    // Use explicit level if given.  If no level is given, use null if the call
+    // stack is empty, -1 otherwise.  This works well when we're paused and the
+    // callstack information is not liable to change before we do an Eval.
+    if (typeof level !== 'number') {
+        level = this.callstack && this.callstack.length > 0 ? -1 : null;
+    }
+    return this.sendRequest([ DVAL_REQ, CMD_EVAL, level, evalInput, DVAL_EOM ]).then(function (msg) {
         return { error: msg[1] === 1 /*error*/, value: msg[2] };
     });
 };
@@ -1398,7 +1407,7 @@ Debugger.prototype.sendDumpHeapRequest = function () {
 Debugger.prototype.sendGetBytecodeRequest = function () {
     var _this = this;
 
-    return this.sendRequest([ DVAL_REQ, CMD_GETBYTECODE, DVAL_EOM ]).then(function (msg) {
+    return this.sendRequest([ DVAL_REQ, CMD_GETBYTECODE, -1 /* level; could be other than -1 too */, DVAL_EOM ]).then(function (msg) {
         var idx = 1;
         var nconst;
         var nfunc;
@@ -1591,7 +1600,8 @@ Debugger.prototype.connectDebugger = function () {
         console.log('Debug version identification:', msg.versionIdentification);
         _this.protocolVersion = ver;
         _this.uiMessage('debugger-info', 'Debug version identification: ' + msg.versionIdentification);
-        if (ver !== 1) {
+        if (ver !== SUPPORTED_DEBUG_PROTOCOL_VERSION) {
+            console.log('Unsupported debug protocol version (got ' + ver + ', support ' + SUPPORTED_DEBUG_PROTOCOL_VERSION + ')');
             _this.uiMessage('debugger-info', 'Protocol version ' + ver + ' unsupported, dropping connection');
             _this.targetStream.destroy();
         } else {
@@ -1701,12 +1711,6 @@ Debugger.prototype.processDebugMessage = function (msg) {
             }
 
             this.emit('exec-status-update');
-        } else if (msg[1] === CMD_PRINT) {
-            this.uiMessage('print', prettyUiStringUnquoted(msg[2], UI_MESSAGE_CLIPLEN));
-        } else if (msg[1] === CMD_ALERT) {
-            this.uiMessage('alert', prettyUiStringUnquoted(msg[2], UI_MESSAGE_CLIPLEN));
-        } else if (msg[1] === CMD_LOG) {
-            this.uiMessage({ type: 'log', level: msg[2], message: prettyUiStringUnquoted(msg[3], UI_MESSAGE_CLIPLEN) });
         } else if (msg[1] === CMD_THROW) {
             this.uiMessage({ type: 'throw', fatal: msg[2], message: (msg[2] ? 'UNCAUGHT: ' : 'THROW: ') + prettyUiStringUnquoted(msg[3], UI_MESSAGE_CLIPLEN), fileName: msg[4], lineNumber: msg[5] });
         } else if (msg[1] === CMD_DETACHING) {

+ 1838 - 0
Script/DuktapeDebugProxy/duk_debug_meta.json

@@ -0,0 +1,1838 @@
+{
+    "error_codes": [
+        "Unknown", 
+        "UnsupportedCommand", 
+        "TooMany", 
+        "NotFound", 
+        "ApplicationError"
+    ], 
+    "opcodes": [
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "LDREG"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "STREG"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "LDCONST"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_LDINT"
+            ], 
+            "name": "LDINT"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_LDINTX"
+            ], 
+            "name": "LDINTX"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDTHIS"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDUNDEF"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDNULL"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDTRUE"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDFALSE"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "BNOT"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "LNOT"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "UNM"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "UNP"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "TYPEOF"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "TYPEOFID"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "EQ_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "EQ_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "EQ_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "EQ_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "NEQ_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "NEQ_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "NEQ_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "NEQ_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "SEQ_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "SEQ_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "SEQ_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "SEQ_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "SNEQ_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "SNEQ_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "SNEQ_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "SNEQ_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "GT_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "GT_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "GT_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "GT_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "GE_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "GE_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "GE_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "GE_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "LT_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "LT_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "LT_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "LT_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "LE_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "LE_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "LE_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "LE_CC"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "IFTRUE_R"
+        }, 
+        {
+            "args": [
+                "BC_C"
+            ], 
+            "name": "IFTRUE_C"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "IFFALSE_R"
+        }, 
+        {
+            "args": [
+                "BC_C"
+            ], 
+            "name": "IFFALSE_C"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "ADD_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "ADD_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "ADD_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "ADD_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "SUB_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "SUB_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "SUB_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "SUB_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "MUL_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "MUL_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "MUL_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "MUL_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "DIV_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "DIV_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "DIV_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "DIV_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "MOD_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "MOD_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "MOD_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "MOD_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "EXP_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "EXP_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "EXP_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "EXP_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "BAND_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "BAND_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "BAND_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "BAND_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "BOR_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "BOR_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "BOR_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "BOR_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "BXOR_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "BXOR_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "BXOR_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "BXOR_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "BASL_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "BASL_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "BASL_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "BASL_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "BLSR_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "BLSR_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "BLSR_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "BLSR_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "BASR_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "BASR_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "BASR_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "BASR_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "INSTOF_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "INSTOF_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "INSTOF_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "INSTOF_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "IN_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "IN_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "IN_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "IN_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "GETPROP_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "GETPROP_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "GETPROP_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "GETPROP_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "PUTPROP_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "PUTPROP_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "PUTPROP_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "PUTPROP_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "DELPROP_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "DELPROP_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "DELPROP_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "DELPROP_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "PREINCR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "PREDECR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "POSTINCR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "POSTDECR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "PREINCV"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "PREDECV"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "POSTINCV"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "POSTDECV"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "PREINCP_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "PREINCP_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "PREINCP_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "PREINCP_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "PREDECP_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "PREDECP_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "PREDECP_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "PREDECP_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "POSTINCP_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "POSTINCP_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "POSTINCP_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "POSTINCP_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "POSTDECP_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "POSTDECP_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "POSTDECP_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "POSTDECP_CC"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "B_R", 
+                "C_R"
+            ], 
+            "flags": [
+                {
+                    "mask": 256, 
+                    "name": "writable"
+                }, 
+                {
+                    "mask": 512, 
+                    "name": "enumerable"
+                }, 
+                {
+                    "mask": 1024, 
+                    "name": "configurable"
+                }, 
+                {
+                    "mask": 2048, 
+                    "name": "accessor"
+                }, 
+                {
+                    "mask": 4096, 
+                    "name": "undef_value"
+                }, 
+                {
+                    "mask": 8192, 
+                    "name": "func_decl"
+                }
+            ], 
+            "name": "DECLVAR_RR"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "B_C", 
+                "C_R"
+            ], 
+            "flags": [
+                {
+                    "mask": 256, 
+                    "name": "writable"
+                }, 
+                {
+                    "mask": 512, 
+                    "name": "enumerable"
+                }, 
+                {
+                    "mask": 1024, 
+                    "name": "configurable"
+                }, 
+                {
+                    "mask": 2048, 
+                    "name": "accessor"
+                }, 
+                {
+                    "mask": 4096, 
+                    "name": "undef_value"
+                }, 
+                {
+                    "mask": 8192, 
+                    "name": "func_decl"
+                }
+            ], 
+            "name": "DECLVAR_CR"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "B_R", 
+                "C_C"
+            ], 
+            "flags": [
+                {
+                    "mask": 256, 
+                    "name": "writable"
+                }, 
+                {
+                    "mask": 512, 
+                    "name": "enumerable"
+                }, 
+                {
+                    "mask": 1024, 
+                    "name": "configurable"
+                }, 
+                {
+                    "mask": 2048, 
+                    "name": "accessor"
+                }, 
+                {
+                    "mask": 4096, 
+                    "name": "undef_value"
+                }, 
+                {
+                    "mask": 8192, 
+                    "name": "func_decl"
+                }
+            ], 
+            "name": "DECLVAR_RC"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "B_C", 
+                "C_C"
+            ], 
+            "flags": [
+                {
+                    "mask": 256, 
+                    "name": "writable"
+                }, 
+                {
+                    "mask": 512, 
+                    "name": "enumerable"
+                }, 
+                {
+                    "mask": 1024, 
+                    "name": "configurable"
+                }, 
+                {
+                    "mask": 2048, 
+                    "name": "accessor"
+                }, 
+                {
+                    "mask": 4096, 
+                    "name": "undef_value"
+                }, 
+                {
+                    "mask": 8192, 
+                    "name": "func_decl"
+                }
+            ], 
+            "name": "DECLVAR_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "REGEXP_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_R"
+            ], 
+            "name": "REGEXP_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_C"
+            ], 
+            "name": "REGEXP_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C", 
+                "C_C"
+            ], 
+            "name": "REGEXP_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R"
+            ], 
+            "name": "CSVAR_RR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C"
+            ], 
+            "name": "CSVAR_CR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R"
+            ], 
+            "name": "CSVAR_RC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_C"
+            ], 
+            "name": "CSVAR_CC"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_I"
+            ], 
+            "name": "CLOSURE"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "GETVAR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "PUTVAR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "DELVAR"
+        }, 
+        {
+            "args": [
+                "ABC_JUMP"
+            ], 
+            "name": "JUMP"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "RETREG"
+        }, 
+        {
+            "name": "RETUNDEF"
+        }, 
+        {
+            "args": [
+                "BC_C"
+            ], 
+            "name": "RETCONST"
+        }, 
+        {
+            "args": [
+                "BC_C"
+            ], 
+            "name": "RETCONSTN"
+        }, 
+        {
+            "args": [
+                "BC_I"
+            ], 
+            "name": "LABEL"
+        }, 
+        {
+            "args": [
+                "BC_I"
+            ], 
+            "name": "ENDLABEL"
+        }, 
+        {
+            "args": [
+                "BC_I"
+            ], 
+            "name": "BREAK"
+        }, 
+        {
+            "args": [
+                "BC_I"
+            ], 
+            "name": "CONTINUE"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "BC_R"
+            ], 
+            "flags": [
+                {
+                    "mask": 64, 
+                    "name": "have_catch"
+                }, 
+                {
+                    "mask": 128, 
+                    "name": "have_finally"
+                }, 
+                {
+                    "mask": 256, 
+                    "name": "catch_binding"
+                }, 
+                {
+                    "mask": 512, 
+                    "name": "with_binding"
+                }
+            ], 
+            "name": "TRYCATCH"
+        }, 
+        {
+            "name": "ENDTRY"
+        }, 
+        {
+            "name": "ENDCATCH"
+        }, 
+        {
+            "name": "ENDFIN"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "THROW"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "CSREG"
+        }, 
+        {
+            "args": [
+                "A_I", 
+                "BC_R"
+            ], 
+            "name": "EVALCALL"
+        }, 
+        {
+            "args": [
+                "A_I", 
+                "BC_R"
+            ], 
+            "name": "CALL"
+        }, 
+        {
+            "args": [
+                "A_I", 
+                "BC_R"
+            ], 
+            "name": "TAILCALL"
+        }, 
+        {
+            "args": [
+                "A_I", 
+                "BC_R"
+            ], 
+            "name": "NEW"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "NEWOBJ"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "NEWARR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_I"
+            ], 
+            "name": "MPUTOBJ"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RI", 
+                "C_I"
+            ], 
+            "name": "MPUTOBJI"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "INITSET"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "INITGET"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_I"
+            ], 
+            "name": "MPUTARR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RI", 
+                "C_I"
+            ], 
+            "name": "MPUTARRI"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "SETALEN"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "INITENUM"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "NEXTENUM"
+        }, 
+        {
+            "name": "INVLHS"
+        }, 
+        {
+            "name": "DEBUGGER"
+        }, 
+        {
+            "name": "NOP"
+        }, 
+        {
+            "args": [
+                "ABC_I"
+            ], 
+            "name": "INVALID"
+        }, 
+        {
+            "name": "UNUSED194"
+        }, 
+        {
+            "name": "UNUSED195"
+        }, 
+        {
+            "name": "UNUSED196"
+        }, 
+        {
+            "name": "UNUSED197"
+        }, 
+        {
+            "name": "UNUSED198"
+        }, 
+        {
+            "name": "UNUSED199"
+        }, 
+        {
+            "name": "UNUSED200"
+        }, 
+        {
+            "name": "UNUSED201"
+        }, 
+        {
+            "name": "UNUSED202"
+        }, 
+        {
+            "name": "UNUSED203"
+        }, 
+        {
+            "name": "UNUSED204"
+        }, 
+        {
+            "name": "UNUSED205"
+        }, 
+        {
+            "name": "UNUSED206"
+        }, 
+        {
+            "name": "UNUSED207"
+        }, 
+        {
+            "name": "UNUSED208"
+        }, 
+        {
+            "name": "UNUSED209"
+        }, 
+        {
+            "name": "UNUSED210"
+        }, 
+        {
+            "name": "UNUSED211"
+        }, 
+        {
+            "name": "UNUSED212"
+        }, 
+        {
+            "name": "UNUSED213"
+        }, 
+        {
+            "name": "UNUSED214"
+        }, 
+        {
+            "name": "UNUSED215"
+        }, 
+        {
+            "name": "UNUSED216"
+        }, 
+        {
+            "name": "UNUSED217"
+        }, 
+        {
+            "name": "UNUSED218"
+        }, 
+        {
+            "name": "UNUSED219"
+        }, 
+        {
+            "name": "UNUSED220"
+        }, 
+        {
+            "name": "UNUSED221"
+        }, 
+        {
+            "name": "UNUSED222"
+        }, 
+        {
+            "name": "UNUSED223"
+        }, 
+        {
+            "name": "UNUSED224"
+        }, 
+        {
+            "name": "UNUSED225"
+        }, 
+        {
+            "name": "UNUSED226"
+        }, 
+        {
+            "name": "UNUSED227"
+        }, 
+        {
+            "name": "UNUSED228"
+        }, 
+        {
+            "name": "UNUSED229"
+        }, 
+        {
+            "name": "UNUSED230"
+        }, 
+        {
+            "name": "UNUSED231"
+        }, 
+        {
+            "name": "UNUSED232"
+        }, 
+        {
+            "name": "UNUSED233"
+        }, 
+        {
+            "name": "UNUSED234"
+        }, 
+        {
+            "name": "UNUSED235"
+        }, 
+        {
+            "name": "UNUSED236"
+        }, 
+        {
+            "name": "UNUSED237"
+        }, 
+        {
+            "name": "UNUSED238"
+        }, 
+        {
+            "name": "UNUSED239"
+        }, 
+        {
+            "name": "UNUSED240"
+        }, 
+        {
+            "name": "UNUSED241"
+        }, 
+        {
+            "name": "UNUSED242"
+        }, 
+        {
+            "name": "UNUSED243"
+        }, 
+        {
+            "name": "UNUSED244"
+        }, 
+        {
+            "name": "UNUSED245"
+        }, 
+        {
+            "name": "UNUSED246"
+        }, 
+        {
+            "name": "UNUSED247"
+        }, 
+        {
+            "name": "UNUSED248"
+        }, 
+        {
+            "name": "UNUSED249"
+        }, 
+        {
+            "name": "UNUSED250"
+        }, 
+        {
+            "name": "UNUSED251"
+        }, 
+        {
+            "name": "UNUSED252"
+        }, 
+        {
+            "name": "UNUSED253"
+        }, 
+        {
+            "name": "UNUSED254"
+        }, 
+        {
+            "name": "UNUSED255"
+        }
+    ], 
+    "client_commands": [
+        "Reserved_0", 
+        "Status", 
+        "Reserved_2", 
+        "Reserved_3", 
+        "Reserved_4", 
+        "Throw", 
+        "Detaching", 
+        "AppNotify"
+    ], 
+    "class_names": [
+        "none", 
+        "Object", 
+        "Array", 
+        "Function", 
+        "Arguments", 
+        "Boolean", 
+        "Date", 
+        "Error", 
+        "JSON", 
+        "Math", 
+        "Number", 
+        "RegExp", 
+        "String", 
+        "global", 
+        "Symbol", 
+        "ObjEnv", 
+        "DecEnv", 
+        "Pointer", 
+        "Thread", 
+        "ArrayBuffer", 
+        "DataView", 
+        "Int8Array", 
+        "Uint8Array", 
+        "Uint8ClampedArray", 
+        "Int16Array", 
+        "Uint16Array", 
+        "Int32Array", 
+        "Uint32Array", 
+        "Float32Array", 
+        "Float64Array"
+    ], 
+    "target_commands": [
+        "Reserved_0", 
+        "Reserved_1", 
+        "Reserved_2", 
+        "Reserved_3", 
+        "Reserved_4", 
+        "Reserved_5", 
+        "Reserved_6", 
+        "Reserved_7", 
+        "Reserved_8", 
+        "Reserved_9", 
+        "Reserved_10", 
+        "Reserved_11", 
+        "Reserved_12", 
+        "Reserved_13", 
+        "Reserved_14", 
+        "Reserved_15", 
+        "BasicInfo", 
+        "TriggerStatus", 
+        "Pause", 
+        "Resume", 
+        "StepInto", 
+        "StepOver", 
+        "StepOut", 
+        "ListBreak", 
+        "AddBreak", 
+        "DelBreak", 
+        "GetVar", 
+        "PutVar", 
+        "GetCallStack", 
+        "GetLocals", 
+        "Eval", 
+        "Detach", 
+        "DumpHeap", 
+        "GetBytecode", 
+        "AppRequest", 
+        "GetHeapObjInfo", 
+        "GetObjPropDesc", 
+        "GetObjPropDescRange"
+    ]
+}

+ 1044 - 0
Script/DuktapeDebugProxy/duk_debug_proxy.js

@@ -0,0 +1,1044 @@
+/*
+ *  JSON debug proxy written in DukLuv
+ *
+ *  This single file JSON debug proxy implementation is an alternative to the
+ *  Node.js-based proxy in duk_debug.js.  DukLuv is a much smaller dependency
+ *  than Node.js so embedding DukLuv in a debug client is easier.
+ */
+
+'use strict';
+
+// XXX: Code assumes uv.write() will write fully.  This is not necessarily
+// true; should add support for partial writes (or at least failing when
+// a partial write occurs).
+
+var log = new Duktape.Logger('Proxy');  // default logger
+//log.l = 0;  // enable debug and trace logging
+
+/*
+ *  Config
+ */
+
+var serverHost = '0.0.0.0';
+var serverPort = 9093;
+var targetHost = '127.0.0.1';
+var targetPort = 9091;
+var singleConnection = false;
+var readableNumberValue = false;
+var lenientJsonParse = false;
+var jxParse = false;
+var metadataFile = null;
+var metadata = {};
+var TORTURE = false;  // for manual testing of binary/json parsing robustness
+
+/*
+ *  Duktape 1.x and 2.x buffer harmonization
+ */
+
+var allocPlain = (typeof Uint8Array.allocPlain === 'function' ?
+                  Uint8Array.allocPlain : Duktape.Buffer);
+var plainOf = (typeof Uint8Array.plainOf === 'function' ?
+               Uint8Array.plainOf : Duktape.Buffer);
+var bufferToString = (typeof String.fromBuffer === 'function' ?
+                      String.fromBuffer : String);
+
+/*
+ *  Detect missing 'var' declarations
+ */
+
+// Prevent new bindings on global object.  This detects missing 'var'
+// declarations, e.g. "x = 123;" in a function without declaring it.
+var global = new Function('return this;')();
+log.debug('Preventing extensions on global object');
+log.debug('Global is extensible:', Object.isExtensible(global));
+Object.preventExtensions(global);
+log.debug('Global is extensible:', Object.isExtensible(global));
+
+/*
+ *  Misc helpers
+ */
+
+function jxEncode(v) {
+    return Duktape.enc('jx', v);
+}
+
+function plainBufferCopy(typedarray) {
+    // This is still pretty awkward in Duktape 1.4.x.
+    // Argument may be a "slice" and we want a copy of the slice
+    // (not the full underlying buffer).
+
+    var u8 = new Uint8Array(typedarray.length);
+    u8.set(typedarray);  // make a copy, ensuring there's no slice offset
+    return plainOf(u8);  // get underlying plain buffer
+}
+
+function isObject(x) {
+    // Note that typeof null === 'object'.
+    return (typeof x === 'object' && x !== null);
+}
+
+function readFully(filename, cb) {
+    uv.fs_open(metadataFile, 'r', 0, function (handle, err) {
+        var fileOff = 0;
+        var data = new Uint8Array(256);
+        var dataOff = 0;
+
+        if (err) {
+            return cb(null, err);
+        }
+        function readCb(buf, err) {
+            var res;
+            var newData;
+
+            log.debug('Read callback:', buf.length, err);
+            if (err) {
+                uv.fs_close(handle);
+                return cb(null, err);
+            }
+            if (buf.length == 0) {
+                uv.fs_close(handle);
+                res = new Uint8Array(dataOff);
+                res.set(data.subarray(0, dataOff));
+                res = plainOf(res);  // plain buffer
+                log.debug('Read', res.length, 'bytes from', filename);
+                return cb(res, null);
+            }
+            while (data.length - dataOff < buf.length) {
+                log.debug('Resize file read buffer:', data.length, '->', data.length * 2);
+                newData = new Uint8Array(data.length * 2);
+                newData.set(data);
+                data = newData;
+            }
+            data.set(new Uint8Array(buf), dataOff);
+            dataOff += buf.length;
+            fileOff += buf.length;
+            uv.fs_read(handle, 4096, fileOff, readCb);
+        }
+        uv.fs_read(handle, 4096, fileOff, readCb);
+    });
+}
+
+/*
+ *  JSON proxy server
+ *
+ *  Accepts an incoming JSON proxy client and connects to a debug target,
+ *  tying the two connections together.  Supports both a single connection
+ *  and a persistent mode.
+ */
+
+function JsonProxyServer(host, port) {
+    this.name = 'JsonProxyServer';
+    this.handle = uv.new_tcp();
+    uv.tcp_bind(this.handle, host, port);
+    uv.listen(this.handle, 128, this.onConnection.bind(this));
+}
+
+JsonProxyServer.prototype.onConnection = function onConnection(err) {
+    if (err) {
+        log.error('JSON proxy onConnection error:', err);
+        return;
+    }
+    log.info('JSON proxy client connected');  // XXX: it'd be nice to log remote peer host:port
+
+    var jsonSock = new JsonConnHandler(this);
+    var targSock = new TargetConnHandler(this);
+    jsonSock.targetHandler = targSock;
+    targSock.jsonHandler = jsonSock;
+    uv.accept(this.handle, jsonSock.handle);
+
+    log.info('Connecting to debug target at', targetHost + ':' + targetPort);
+    jsonSock.writeJson({ notify: '_TargetConnecting', args: [ targetHost, targetPort ] });
+    uv.tcp_connect(targSock.handle, targetHost, targetPort, targSock.onConnect.bind(targSock));
+
+    if (singleConnection) {
+        log.info('Single connection mode, stop listening for more connections');
+        uv.shutdown(this.handle);
+        uv.read_stop(this.handle);  // unnecessary but just in case
+        uv.close(this.handle);
+        this.handle = null;
+    }
+};
+
+JsonProxyServer.prototype.onProxyClientDisconnected = function onProxyClientDisconnected() {
+    // When this is invoked the proxy connection and the target connection
+    // have both been closed.
+    if (singleConnection) {
+        log.info('Proxy connection finished (single connection mode: we should be exiting now)');
+    } else {
+        log.info('Proxy connection finished (persistent mode: wait for more connections)');
+    }
+};
+
+/*
+ *  JSON connection handler
+ */
+
+function JsonConnHandler(server) {
+    var i, n;
+
+    this.name = 'JsonConnHandler';
+    this.server = server;
+    this.handle = uv.new_tcp();
+    this.incoming = new Uint8Array(4096);
+    this.incomingOffset = 0;
+    this.targetHandler = null;
+
+    this.commandNumberLookup = {};
+    if (metadata && metadata.target_commands) {
+        for (i = 0, n = metadata.target_commands.length; i < n; i++) {
+            this.commandNumberLookup[metadata.target_commands[i]] = i;
+        }
+    }
+}
+
+JsonConnHandler.prototype.finish = function finish(msg) {
+    var args;
+
+    if (!this.handle) {
+        log.info('JsonConnHandler already disconnected, ignore finish()');
+        return;
+    }
+    log.info('JsonConnHandler finished:', msg);
+    try {
+        args = msg ? [ msg ] : void 0;
+        this.writeJson({ notify: '_Disconnecting', args: args });
+    } catch (e) {
+        log.info('Failed to write _Disconnecting notify, ignoring:', e);
+    }
+    uv.shutdown(this.handle);
+    uv.read_stop(this.handle);
+    uv.close(this.handle);
+    this.handle = null;
+
+    this.targetHandler.finish(msg);  // disconnect target too (if not already disconnected)
+
+    this.server.onProxyClientDisconnected();
+};
+
+JsonConnHandler.prototype.onRead = function onRead(err, data) {
+    var newIncoming;
+    var msg;
+    var errmsg;
+    var tmpBuf;
+
+    log.trace('Received data from JSON socket, err:', err, 'data length:', data ? data.length : 'null');
+
+    if (err) {
+        errmsg = 'Error reading data from JSON debug client: ' + err;
+        this.finish(errmsg);
+        return;
+    }
+    if (data) {
+        // Feed the data one byte at a time when torture testing.
+        if (TORTURE && data.length > 1) {
+            for (var i = 0; i < data.length; i++) {
+                tmpBuf = allocPlain(1);
+                tmpBuf[0] = data[i];
+                this.onRead(null, tmpBuf);
+            }
+            return;
+        }
+
+        // Receive data into 'incoming', resizing as necessary.
+        while (data.length > this.incoming.length - this.incomingOffset) {
+            newIncoming = new Uint8Array(this.incoming.length * 1.3 + 16);
+            newIncoming.set(this.incoming);
+            this.incoming = newIncoming;
+            log.debug('Resize incoming JSON buffer to ' + this.incoming.length);
+        }
+        this.incoming.set(new Uint8Array(data), this.incomingOffset);
+        this.incomingOffset += data.length;
+
+        // Trial parse JSON message(s).
+        while (true) {
+            msg = this.trialParseJsonMessage();
+            if (!msg) {
+                break;
+            }
+            try {
+                this.dispatchJsonMessage(msg);
+            } catch (e) {
+                errmsg = 'JSON message dispatch failed: ' + e;
+                this.writeJson({ notify: '_Error', args: [ errmsg ] });
+                if (lenientJsonParse) {
+                    log.warn('JSON message dispatch failed (lenient mode, ignoring):', e);
+                } else {
+                    log.warn('JSON message dispatch failed (dropping connection):', e);
+                    this.finish(errmsg);
+                }
+            }
+        }
+    } else {
+        this.finish('JSON proxy client disconnected');
+    }
+};
+
+JsonConnHandler.prototype.writeJson = function writeJson(msg) {
+    log.info('PROXY --> CLIENT:', JSON.stringify(msg));
+    if (this.handle) {
+        uv.write(this.handle, JSON.stringify(msg) + '\n');
+    }
+};
+
+JsonConnHandler.prototype.handleDebugMessage = function handleDebugMessage(dvalues) {
+    var msg = {};
+    var idx = 0;
+    var cmd;
+
+    if (dvalues.length <= 0) {
+        throw new Error('invalid dvalues list: length <= 0');
+    }
+    var x = dvalues[idx++];
+    if (!isObject(x)) {
+        throw new Error('invalid initial dvalue: ' + Duktape.enc('jx', dvalues));
+    }
+    if (x.type === 'req') {
+        cmd = dvalues[idx++];
+        if (typeof cmd !== 'number') {
+            throw new Error('invalid command: ' + Duktape.enc('jx', cmd));
+        }
+        msg.request = this.determineCommandName(cmd) || true;
+        msg.command = cmd;
+    } else if (x.type === 'rep') {
+        msg.reply = true;
+    } else if (x.type === 'err') {
+        msg.error = true;
+    } else if (x.type === 'nfy') {
+        cmd = dvalues[idx++];
+        if (typeof cmd !== 'number') {
+            throw new Error('invalid command: ' + Duktape.enc('jx', cmd));
+        }
+        msg.notify = this.determineCommandName(cmd) || true;
+        msg.command = cmd;
+    } else {
+        throw new Error('invalid initial dvalue: ' + Duktape.enc('jx', dvalues));
+    }
+
+    for (; idx < dvalues.length - 1; idx++) {
+        if (!msg.args) {
+            msg.args = [];
+        }
+        msg.args.push(dvalues[idx]);
+    }
+
+    if (!isObject(dvalues[idx]) || dvalues[idx].type !== 'eom') {
+        throw new Error('invalid final dvalue: ' + Duktape.enc('jx', dvalues));
+    }
+
+    this.writeJson(msg);
+};
+
+JsonConnHandler.prototype.determineCommandName = function determineCommandName(cmd) {
+    if (!(metadata && metadata.client_commands)) {
+        return;
+    }
+    return metadata.client_commands[cmd];
+};
+
+JsonConnHandler.prototype.trialParseJsonMessage = function trialParseJsonMessage() {
+    var buf = this.incoming;
+    var avail = this.incomingOffset;
+    var i;
+    var msg, str, errmsg;
+
+    for (i = 0; i < avail; i++) {
+        if (buf[i] == 0x0a) {
+            str = bufferToString(plainBufferCopy(buf.subarray(0, i)));
+            try {
+                if (jxParse) {
+                    msg = Duktape.dec('jx', str);
+                } else {
+                    msg = JSON.parse(str);
+                }
+            } catch (e) {
+                // In lenient mode if JSON parse fails just send back an _Error
+                // and ignore the line (useful for initial development).
+                //
+                // In non-lenient mode drop the connection here; if the failed line
+                // was a request the client is expecting a reply/error message back
+                // (otherwise it may go out of sync) but we can't send a synthetic
+                // one (as we can't parse the request).
+                errmsg = 'JSON parse failed for: ' + jxEncode(str) + ': ' + e;
+                this.writeJson({ notify: '_Error', args: [ errmsg ] });
+                if (lenientJsonParse) {
+                    log.warn('JSON parse failed (lenient mode, ignoring):', e);
+                } else {
+                    log.warn('JSON parse failed (dropping connection):', e);
+                    this.finish(errmsg);
+                }
+            }
+
+            this.incoming.set(this.incoming.subarray(i + 1));
+            this.incomingOffset -= i + 1;
+            return msg;
+        }
+    }
+};
+
+JsonConnHandler.prototype.dispatchJsonMessage = function dispatchJsonMessage(msg) {
+    var cmd;
+    var dvalues = [];
+    var i, n;
+
+    log.info('PROXY <-- CLIENT:', JSON.stringify(msg));
+
+    // Parse message type, determine initial marker for binary message.
+    if (msg.request) {
+        cmd = this.determineCommandNumber(msg.request, msg.command);
+        dvalues.push(new Uint8Array([ 0x01 ]));
+        dvalues.push(this.encodeJsonDvalue(cmd));
+    } else if (msg.reply) {
+        dvalues.push(new Uint8Array([ 0x02 ]));
+    } else if (msg.notify) {
+        cmd = this.determineCommandNumber(msg.notify, msg.command);
+        dvalues.push(new Uint8Array([ 0x04 ]));
+        dvalues.push(this.encodeJsonDvalue(cmd));
+    } else if (msg.error) {
+        dvalues.push(new Uint8Array([ 0x03 ]));
+    } else {
+        throw new Error('invalid input JSON message: ' + jxEncode(msg));
+    }
+
+    // Encode arguments into dvalues.
+    for (i = 0, n = (msg.args ? msg.args.length : 0); i < n; i++) {
+        dvalues.push(this.encodeJsonDvalue(msg.args[i]));
+    }
+
+    // Add an EOM, and write out the dvalues to the debug target.
+    dvalues.push(new Uint8Array([ 0x00 ]));
+    for (i = 0, n = dvalues.length; i < n; i++) {
+        this.targetHandler.writeBinary(dvalues[i]);
+    }
+};
+
+JsonConnHandler.prototype.determineCommandNumber = function determineCommandNumber(name, val) {
+    var res;
+
+    if (typeof name === 'string') {
+        res = this.commandNumberLookup[name];
+        if (!res) {
+            log.info('Unknown command name: ' + name + ', command number: ' + val);
+        }
+    } else if (typeof name === 'number') {
+        res = name;
+    } else if (name !== true) {
+        throw new Error('invalid command name (must be string, number, or "true"): ' + name);
+    }
+    if (typeof res === 'undefined' && typeof val === 'undefined') {
+        throw new Error('cannot determine command number from name: ' + name);
+    }
+    if (typeof val !== 'number' && typeof val !== 'undefined') {
+        throw new Error('invalid command number: ' + val);
+    }
+    res = res || val;
+    return res;
+};
+
+JsonConnHandler.prototype.writeDebugStringToBuffer = function writeDebugStringToBuffer(v, buf, off) {
+    var i, n;
+
+    for (i = 0, n = v.length; i < n; i++) {
+        buf[off + i] = v.charCodeAt(i) & 0xff;  // truncate higher bits
+    }
+};
+
+JsonConnHandler.prototype.encodeJsonDvalue = function encodeJsonDvalue(v) {
+    var buf, dec, len, dv;
+
+    if (isObject(v)) {
+        if (v.type === 'eom') {
+            return new Uint8Array([ 0x00 ]);
+        } else if (v.type === 'req') {
+            return new Uint8Array([ 0x01 ]);
+        } else if (v.type === 'rep') {
+            return new Uint8Array([ 0x02 ]);
+        } else if (v.type === 'err') {
+            return new Uint8Array([ 0x03 ]);
+        } else if (v.type === 'nfy') {
+            return new Uint8Array([ 0x04 ]);
+        } else if (v.type === 'unused') {
+            return new Uint8Array([ 0x15 ]);
+        } else if (v.type === 'undefined') {
+            return new Uint8Array([ 0x16 ]);
+        } else if (v.type === 'number') {
+            dec = Duktape.dec('hex', v.data);
+            len = dec.length;
+            if (len !== 8) {
+                throw new TypeError('value cannot be converted to dvalue: ' + jxEncode(v));
+            }
+            buf = new Uint8Array(1 + len);
+            buf[0] = 0x1a;
+            buf.set(new Uint8Array(dec), 1);
+            return buf;
+        } else if (v.type === 'buffer') {
+            dec = Duktape.dec('hex', v.data);
+            len = dec.length;
+            if (len <= 0xffff) {
+                buf = new Uint8Array(3 + len);
+                buf[0] = 0x14;
+                buf[1] = (len >> 8) & 0xff;
+                buf[2] = (len >> 0) & 0xff;
+                buf.set(new Uint8Arrau(dec), 3);
+                return buf;
+            } else {
+                buf = new Uint8Array(5 + len);
+                buf[0] = 0x13;
+                buf[1] = (len >> 24) & 0xff;
+                buf[2] = (len >> 16) & 0xff;
+                buf[3] = (len >> 8) & 0xff;
+                buf[4] = (len >> 0) & 0xff;
+                buf.set(new Uint8Array(dec), 5);
+                return buf;
+            }
+        } else if (v.type === 'object') {
+            dec = Duktape.dec('hex', v.pointer);
+            len = dec.length;
+            buf = new Uint8Array(3 + len);
+            buf[0] = 0x1b;
+            buf[1] = v.class;
+            buf[2] = len;
+            buf.set(new Uint8Array(dec), 3);
+            return buf;
+        } else if (v.type === 'pointer') {
+            dec = Duktape.dec('hex', v.pointer);
+            len = dec.length;
+            buf = new Uint8Array(2 + len);
+            buf[0] = 0x1c;
+            buf[1] = len;
+            buf.set(new Uint8Array(dec), 2);
+            return buf;
+        } else if (v.type === 'lightfunc') {
+            dec = Duktape.dec('hex', v.pointer);
+            len = dec.length;
+            buf = new Uint8Array(4 + len);
+            buf[0] = 0x1d;
+            buf[1] = (v.flags >> 8) & 0xff;
+            buf[2] = v.flags & 0xff;
+            buf[3] = len;
+            buf.set(new Uint8Array(dec), 4);
+            return buf;
+        } else if (v.type === 'heapptr') {
+            dec = Duktape.dec('hex', v.pointer);
+            len = dec.length;
+            buf = new Uint8Array(2 + len);
+            buf[0] = 0x1e;
+            buf[1] = len;
+            buf.set(new Uint8Array(dec), 2);
+            return buf;
+        }
+    } else if (v === null) {
+        return new Uint8Array([ 0x17 ]);
+    } else if (typeof v === 'boolean') {
+        return new Uint8Array([ v ? 0x18 : 0x19 ]);
+    } else if (typeof v === 'number') {
+        if (Math.floor(v) === v &&     /* whole */
+            (v !== 0 || 1 / v > 0) &&  /* not negative zero */
+            v >= -0x80000000 && v <= 0x7fffffff) {
+            // Represented signed 32-bit integers as plain integers.
+            // Debugger code expects this for all fields that are not
+            // duk_tval representations (e.g. command numbers and such).
+            if (v >= 0x00 && v <= 0x3f) {
+                return new Uint8Array([ 0x80 + v ]);
+            } else if (v >= 0x0000 && v <= 0x3fff) {
+                return new Uint8Array([ 0xc0 + (v >> 8), v & 0xff ]);
+            } else if (v >= -0x80000000 && v <= 0x7fffffff) {
+                return new Uint8Array([ 0x10,
+                                    (v >> 24) & 0xff,
+                                    (v >> 16) & 0xff,
+                                    (v >> 8) & 0xff,
+                                    (v >> 0) & 0xff ]);
+            } else {
+                throw new Error('internal error when encoding integer to dvalue: ' + v);
+            }
+        } else {
+            // Represent non-integers as IEEE double dvalues.
+            buf = new Uint8Array(1 + 8);
+            buf[0] = 0x1a;
+            new DataView(buf).setFloat64(1, v, false);
+            return buf;
+        }
+    } else if (typeof v === 'string') {
+        if (v.length < 0 || v.length > 0xffffffff) {
+            // Not possible in practice.
+            throw new TypeError('cannot convert to dvalue, invalid string length: ' + v.length);
+        }
+        if (v.length <= 0x1f) {
+            buf = new Uint8Array(1 + v.length);
+            buf[0] = 0x60 + v.length;
+            this.writeDebugStringToBuffer(v, buf, 1);
+            return buf;
+        } else if (v.length <= 0xffff) {
+            buf = new Uint8Array(3 + v.length);
+            buf[0] = 0x12;
+            buf[1] = (v.length >> 8) & 0xff;
+            buf[2] = (v.length >> 0) & 0xff;
+            this.writeDebugStringToBuffer(v, buf, 3);
+            return buf;
+        } else {
+            buf = new Uint8Array(5 + v.length);
+            buf[0] = 0x11;
+            buf[1] = (v.length >> 24) & 0xff;
+            buf[2] = (v.length >> 16) & 0xff;
+            buf[3] = (v.length >> 8) & 0xff;
+            buf[4] = (v.length >> 0) & 0xff;
+            this.writeDebugStringToBuffer(v, buf, 5);
+            return buf;
+        }
+    }
+
+    throw new TypeError('value cannot be converted to dvalue: ' + jxEncode(v));
+};
+
+/*
+ *  Target binary connection handler
+ */
+
+function TargetConnHandler(server) {
+    this.name = 'TargetConnHandler';
+    this.server = server;
+    this.handle = uv.new_tcp();
+    this.jsonHandler = null;
+    this.incoming = new Uint8Array(4096);
+    this.incomingOffset = 0;
+    this.dvalues = [];
+}
+
+TargetConnHandler.prototype.finish = function finish(msg) {
+    if (!this.handle) {
+        log.info('TargetConnHandler already disconnected, ignore finish()');
+        return;
+    }
+    log.info('TargetConnHandler finished:', msg);
+
+    this.jsonHandler.writeJson({ notify: '_TargetDisconnected' });
+
+    // XXX: write a notify to target?
+
+    uv.shutdown(this.handle);
+    uv.read_stop(this.handle);
+    uv.close(this.handle);
+    this.handle = null;
+
+    this.jsonHandler.finish(msg);  // disconnect JSON client too (if not already disconnected)
+};
+
+TargetConnHandler.prototype.onConnect = function onConnect(err) {
+    var errmsg;
+
+    if (err) {
+        errmsg = 'Failed to connect to target: ' + err;
+        log.warn(errmsg);
+        this.jsonHandler.writeJson({ notify: '_Error', args: [ String(err) ] });
+        this.finish(errmsg);
+        return;
+    }
+
+    // Once we're connected to the target, start read both binary and JSON
+    // input.  We don't want to read JSON input before this so that we can
+    // always translate incoming messages to dvalues and write them out
+    // without queueing.  Any pending JSON messages will be queued by the
+    // OS instead.
+
+    log.info('Connected to debug target at', targetHost + ':' + targetPort);
+    uv.read_start(this.jsonHandler.handle, this.jsonHandler.onRead.bind(this.jsonHandler));
+    uv.read_start(this.handle, this.onRead.bind(this));
+};
+
+TargetConnHandler.prototype.writeBinary = function writeBinary(buf) {
+    var plain = plainBufferCopy(buf);
+    log.info('PROXY --> TARGET:', Duktape.enc('jx', plain));
+    if (this.handle) {
+        uv.write(this.handle, plain);
+    }
+};
+
+TargetConnHandler.prototype.onRead = function onRead(err, data) {
+    var res;
+    var errmsg;
+    var tmpBuf;
+    var newIncoming;
+
+    log.trace('Received data from target socket, err:', err, 'data length:', data ? data.length : 'null');
+
+    if (err) {
+        errmsg = 'Error reading data from debug target: ' + err;
+        this.finish(errmsg);
+        return;
+    }
+
+    if (data) {
+        // Feed the data one byte at a time when torture testing.
+        if (TORTURE && data.length > 1) {
+            for (var i = 0; i < data.length; i++) {
+                tmpBuf = allocPlain(1);
+                tmpBuf[0] = data[i];
+                this.onRead(null, tmpBuf);
+            }
+            return;
+        }
+
+        // Receive data into 'incoming', resizing as necessary.
+        while (data.length > this.incoming.length - this.incomingOffset) {
+            newIncoming = new Uint8Array(this.incoming.length * 1.3 + 16);
+            newIncoming.set(this.incoming);
+            this.incoming = newIncoming;
+            log.debug('Resize incoming binary buffer to ' + this.incoming.length);
+        }
+        this.incoming.set(new Uint8Array(data), this.incomingOffset);
+        this.incomingOffset += data.length;
+
+        // Trial parse handshake unless done.
+        if (!this.handshake) {
+            this.trialParseHandshake();
+        }
+
+        // Trial parse dvalue(s) and debug messages.
+        if (this.handshake) {
+            for (;;) {
+                res = this.trialParseDvalue();
+                if (!res) {
+                    break;
+                }
+                log.trace('Got dvalue:', Duktape.enc('jx', res.dvalue));
+                this.dvalues.push(res.dvalue);
+                if (isObject(res.dvalue) && res.dvalue.type === 'eom') {
+                    try {
+                        this.jsonHandler.handleDebugMessage(this.dvalues);
+                        this.dvalues = [];
+                    } catch (e) {
+                        errmsg = 'JSON message handling failed: ' + e;
+                        this.jsonHandler.writeJson({ notify: '_Error', args: [ errmsg ] });
+                        if (lenientJsonParse) {
+                            log.warn('JSON message handling failed (lenient mode, ignoring):', e);
+                        } else {
+                            log.warn('JSON message handling failed (dropping connection):', e);
+                            this.finish(errmsg);
+                        }
+                    }
+                }
+            }
+        }
+    } else {
+        log.info('Target disconnected');
+        this.finish('Target disconnected');
+    }
+};
+
+TargetConnHandler.prototype.trialParseHandshake = function trialParseHandshake() {
+    var buf = this.incoming;
+    var avail = this.incomingOffset;
+    var i;
+    var msg;
+    var m;
+    var protocolVersion;
+
+    for (i = 0; i < avail; i++) {
+        if (buf[i] == 0x0a) {
+            msg = bufferToString(plainBufferCopy(buf.subarray(0, i)));
+            this.incoming.set(this.incoming.subarray(i + 1));
+            this.incomingOffset -= i + 1;
+
+            // Generic handshake format: only relies on initial version field.
+            m = /^(\d+) (.*)$/.exec(msg) || {};
+            protocolVersion = +m[1];
+            this.handshake = {
+                line: msg,
+                protocolVersion: protocolVersion,
+                text: m[2]
+            };
+
+            // More detailed v1 handshake line.
+            if (protocolVersion === 1) {
+                m = /^(\d+) (\d+) (.*?) (.*?) (.*)$/.exec(msg) || {};
+                this.handshake.dukVersion = m[1];
+                this.handshake.dukGitDescribe = m[2];
+                this.handshake.targetString = m[3];
+            }
+
+            this.jsonHandler.writeJson({ notify: '_TargetConnected', args: [ msg ] });
+
+            log.info('Target handshake: ' + JSON.stringify(this.handshake));
+            return;
+        }
+    }
+};
+
+TargetConnHandler.prototype.bufferToDebugString = function bufferToDebugString(buf) {
+    return String.fromCharCode.apply(null, buf);
+};
+
+TargetConnHandler.prototype.trialParseDvalue = function trialParseDvalue() {
+    var _this = this;
+    var buf = this.incoming;
+    var avail = this.incomingOffset;
+    var v;
+    var gotValue = false;  // explicit flag for e.g. v === undefined
+    var dv = new DataView(buf);
+    var tmp;
+    var x;
+    var len;
+
+    function consume(n) {
+        log.info('PROXY <-- TARGET:', Duktape.enc('jx', _this.incoming.subarray(0, n)));
+        _this.incoming.set(_this.incoming.subarray(n));
+        _this.incomingOffset -= n;
+    }
+
+    x = buf[0];
+    if (avail <= 0) {
+        ;
+    } else if (x >= 0xc0) {
+        // 0xc0...0xff: integers 0-16383
+        if (avail >= 2) {
+            v = ((x - 0xc0) << 8) + buf[1];
+            consume(2);
+        }
+    } else if (x >= 0x80) {
+        // 0x80...0xbf: integers 0-63
+        v = x - 0x80;
+        consume(1);
+    } else if (x >= 0x60) {
+        // 0x60...0x7f: strings with length 0-31
+        len = x - 0x60;
+        if (avail >= 1 + len) {
+            v = new Uint8Array(len);
+            v.set(buf.subarray(1, 1 + len));
+            v = this.bufferToDebugString(v);
+            consume(1 + len);
+        }
+    } else {
+        switch (x) {
+        case 0x00: consume(1); v = { type: 'eom' }; break;
+        case 0x01: consume(1); v = { type: 'req' }; break;
+        case 0x02: consume(1); v = { type: 'rep' }; break;
+        case 0x03: consume(1); v = { type: 'err' }; break;
+        case 0x04: consume(1); v = { type: 'nfy' }; break;
+        case 0x10:  // 4-byte signed integer
+            if (avail >= 5) {
+                v = dv.getInt32(1, false);
+                consume(5);
+            }
+            break;
+        case 0x11:  // 4-byte string
+            if (avail >= 5) {
+                len = dv.getUint32(1, false);
+                if (avail >= 5 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(5, 5 + len));
+                    v = this.bufferToDebugString(v);
+                    consume(5 + len);
+                }
+            }
+            break;
+        case 0x12:  // 2-byte string
+            if (avail >= 3) {
+                len = dv.getUint16(1, false);
+                if (avail >= 3 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(3, 3 + len));
+                    v = this.bufferToDebugString(v);
+                    consume(3 + len);
+                }
+            }
+            break;
+        case 0x13:  // 4-byte buffer
+            if (avail >= 5) {
+                len = dv.getUint32(1, false);
+                if (avail >= 5 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(5, 5 + len));
+                    v = { type: 'buffer', data: Duktape.enc('hex', plainOf(v)) };
+                    consume(5 + len);
+                }
+            }
+            break;
+        case 0x14:  // 2-byte buffer
+            if (avail >= 3) {
+                len = dv.getUint16(1, false);
+                if (avail >= 3 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(3, 3 + len));
+                    v = { type: 'buffer', data: Duktape.enc('hex', plainOf(v)) };
+                    consume(3 + len);
+                }
+            }
+            break;
+        case 0x15:  // unused/none
+            v = { type: 'unused' };
+            consume(1);
+            break;
+        case 0x16:  // undefined
+            v = { type: 'undefined' };
+            gotValue = true;  // indicate 'v' is actually set
+            consume(1);
+            break;
+        case 0x17:  // null
+            v = null;
+            gotValue = true;  // indicate 'v' is actually set
+            consume(1);
+            break;
+        case 0x18:  // true
+            v = true;
+            consume(1);
+            break;
+        case 0x19:  // false
+            v = false;
+            consume(1);
+            break;
+        case 0x1a:  // number (IEEE double), big endian
+            if (avail >= 9) {
+                tmp = new Uint8Array(8);
+                tmp.set(buf.subarray(1, 9));
+                v = { type: 'number', data: Duktape.enc('hex', plainOf(tmp)) };
+                if (readableNumberValue) {
+                    // The value key should not be used programmatically,
+                    // it is just there to make the dumps more readable.
+                    v.value = new DataView(tmp.buffer).getFloat64(0, false);
+                }
+                consume(9);
+            }
+            break;
+        case 0x1b:  // object
+            if (avail >= 3) {
+                len = buf[2];
+                if (avail >= 3 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(3, 3 + len));
+                    v = { type: 'object', 'class': buf[1], pointer: Duktape.enc('hex', plainOf(v)) };
+                    consume(3 + len);
+                }
+            }
+            break;
+        case 0x1c:  // pointer
+            if (avail >= 2) {
+                len = buf[1];
+                if (avail >= 2 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(2, 2 + len));
+                    v = { type: 'pointer', pointer: Duktape.enc('hex', plainOf(v)) };
+                    consume(2 + len);
+                }
+            }
+            break;
+        case 0x1d:  // lightfunc
+            if (avail >= 4) {
+                len = buf[3];
+                if (avail >= 4 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(4, 4 + len));
+                    v = { type: 'lightfunc', flags: dv.getUint16(1, false), pointer: Duktape.enc('hex', plainOf(v)) };
+                    consume(4 + len);
+                }
+            }
+            break;
+        case 0x1e:  // heapptr
+            if (avail >= 2) {
+                len = buf[1];
+                if (avail >= 2 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(2, 2 + len));
+                    v = { type: 'heapptr', pointer: Duktape.enc('hex', plainOf(v)) };
+                    consume(2 + len);
+                }
+            }
+            break;
+        default:
+            throw new Error('failed parse initial byte: ' + buf[0]);
+        }
+    }
+
+    if (typeof v !== 'undefined' || gotValue) {
+        return { dvalue: v };
+    }
+};
+
+/*
+ *  Main
+ */
+
+function main() {
+    var argv = typeof uv.argv === 'function' ? uv.argv() : [];
+    var i;
+    for (i = 2; i < argv.length; i++) {  // skip dukluv and script name
+        if (argv[i] == '--help') {
+            print('Usage: dukluv ' + argv[1] + ' [option]+');
+            print('');
+            print('    --server-host HOST    JSON proxy server listen address');
+            print('    --server-port PORT    JSON proxy server listen port');
+            print('    --target-host HOST    Debug target address');
+            print('    --target-port PORT    Debug target port');
+            print('    --metadata FILE       Proxy metadata file (usually named duk_debug_meta.json)');
+            print('    --log-level LEVEL     Set log level, default is 2; 0=trace, 1=debug, 2=info, 3=warn, etc');
+            print('    --single              Run a single proxy connection and exit (default: persist for multiple connections)');
+            print('    --readable-numbers    Add a non-programmatic "value" key for IEEE doubles help readability');
+            print('    --lenient             Ignore (with warning) invalid JSON without dropping connection');
+            print('    --jx-parse            Parse JSON proxy input with JX, useful when testing manually');
+            print('');
+            return;  // don't register any sockets/timers etc to exit
+        } else if (argv[i] == '--single') {
+            singleConnection = true;
+            continue;
+        } else if (argv[i] == '--readable-numbers') {
+            readableNumberValue = true;
+            continue;
+        } else if (argv[i] == '--lenient') {
+            lenientJsonParse = true;
+            continue;
+        } else if (argv[i] == '--jx-parse') {
+            jxParse = true;
+            continue;
+        }
+        if (i >= argv.length - 1) {
+            throw new Error('missing option value for ' + argv[i]);
+        }
+        if (argv[i] == '--server-host') {
+            serverHost = argv[i + 1];
+            i++;
+        } else if (argv[i] == '--server-port') {
+            serverPort = Math.floor(+argv[i + 1]);
+            i++;
+        } else if (argv[i] == '--target-host') {
+            targetHost = argv[i + 1];
+            i++;
+        } else if (argv[i] == '--target-port') {
+            targetPort = Math.floor(+argv[i + 1]);
+            i++;
+        } else if (argv[i] == '--metadata') {
+            metadataFile = argv[i + 1];
+            i++;
+        } else if (argv[i] == '--log-level') {
+            log.l = Math.floor(+argv[i + 1]);
+            i++;
+        } else {
+            throw new Error('invalid option ' + argv[i]);
+        }
+    }
+
+    function runServer() {
+        var serverSocket = new JsonProxyServer(serverHost, serverPort);
+        var connMode = singleConnection ? 'single connection mode' : 'persistent connection mode';
+        log.info('Listening for incoming JSON debug connection on ' + serverHost + ':' + serverPort +
+                 ', target is ' + targetHost + ':' + targetPort + ', ' + connMode);
+    }
+
+    if (metadataFile) {
+        log.info('Read proxy metadata from', metadataFile);
+        readFully(metadataFile, function (data, err) {
+            if (err) {
+                log.error('Failed to load metadata:', err);
+                throw err;
+            }
+            try {
+                metadata = JSON.parse(bufferToString(data));
+            } catch (e) {
+                log.error('Failed to parse JSON metadata from ' + metadataFile + ': ' + e);
+                throw e;
+            }
+            runServer();
+        });
+    } else {
+        runServer();
+    }
+}
+
+main();

+ 3 - 3
Script/DuktapeDebugProxy/duk_debugcommands.yaml

@@ -3,9 +3,9 @@
 client_commands:
   - Reserved_0
   - Status
-  - Print
-  - Alert
-  - Log
+  - Reserved_2  # Duktape 1.x: print notify
+  - Reserved_3  # Duktape 1.x: alert notify
+  - Reserved_4  # Duktape 1.x: log notify
   - Throw
   - Detaching
   - AppNotify

+ 822 - 483
Script/DuktapeDebugProxy/duk_opcodes.yaml

@@ -27,632 +27,971 @@ opcodes:
     args:
       - A_R
       - BC_LDINTX
-  - name: MPUTOBJ
+  - name: LDTHIS
     args:
-      - A_R
-      - B_R
-      - C_I
-  - name: MPUTOBJI
+      - BC_R
+  - name: LDUNDEF
     args:
-      - A_R
-      - B_RI
-      - C_I
-  - name: MPUTARR
+      - BC_R
+  - name: LDNULL
     args:
-      - A_R
-      - B_R
-      - C_I
-  - name: MPUTARRI
+      - BC_R
+  - name: LDTRUE
     args:
-      - A_R
-      - B_RI
-      - C_I
-  - name: NEW
+      - BC_R
+  - name: LDFALSE
     args:
-      - B_R
-      - C_I
-  - name: NEWI
+      - BC_R
+  - name: BNOT
     args:
-      - B_RI
-      - C_I
-  - name: REGEXP
+      - A_R
+      - BC_R
+  - name: LNOT
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: CSREG
+      - BC_R
+  - name: UNM
     args:
       - A_R
-      - B_R
-  - name: CSREGI
+      - BC_R
+  - name: UNP
     args:
-      - A_RI
-      - B_R
-  - name: GETVAR
+      - A_R
+      - BC_R
+  - name: TYPEOF
     args:
       - A_R
-      - BC_C
-  - name: PUTVAR
+      - BC_R
+  - name: TYPEOFID
     args:
       - A_R
       - BC_C
-  - name: DECLVAR
-    args:
-      - A_H
-      - B_RC
-      - C_RC
-    flags:
-      - mask: 0x40
-        name: writable
-      - mask: 0x80
-        name: enumerable
-      - mask: 0x100
-        name: configurable
-      - mask: 0x200
-        name: accessor
-      - mask: 0x400
-        name: undef_value
-      - mask: 0x800
-        name: func_decl
-  - name: DELVAR
+  - name: EQ_RR
     args:
       - A_R
-      - B_RC
-  - name: CSVAR
+      - B_R
+      - C_R
+  - name: EQ_CR
     args:
       - A_R
-      - B_RC
-  - name: CSVARI
+      - B_C
+      - C_R
+  - name: EQ_RC
     args:
-      - A_RI
-      - B_RC
-  - name: CLOSURE
+      - A_R
+      - B_R
+      - C_C
+  - name: EQ_CC
     args:
       - A_R
-      - BC_I
-  - name: GETPROP
+      - B_C
+      - C_C
+  - name: NEQ_RR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: PUTPROP
+      - B_R
+      - C_R
+  - name: NEQ_CR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: DELPROP
+      - B_C
+      - C_R
+  - name: NEQ_RC
     args:
       - A_R
       - B_R
-      - C_RC
-  - name: CSPROP
+      - C_C
+  - name: NEQ_CC
     args:
       - A_R
-      - B_R
-      - C_RC
-  - name: CSPROPI
+      - B_C
+      - C_C
+  - name: SEQ_RR
     args:
-      - A_RI
+      - A_R
       - B_R
-      - C_RC
-  - name: ADD
+      - C_R
+  - name: SEQ_CR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: SUB
+      - B_C
+      - C_R
+  - name: SEQ_RC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: MUL
+      - B_R
+      - C_C
+  - name: SEQ_CC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: DIV
+      - B_C
+      - C_C
+  - name: SNEQ_RR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: MOD
+      - B_R
+      - C_R
+  - name: SNEQ_CR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: BAND
+      - B_C
+      - C_R
+  - name: SNEQ_RC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: BOR
+      - B_R
+      - C_C
+  - name: SNEQ_CC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: BXOR
+      - B_C
+      - C_C
+  - name: GT_RR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: BASL
+      - B_R
+      - C_R
+  - name: GT_CR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: BLSR
+      - B_C
+      - C_R
+  - name: GT_RC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: BASR
+      - B_R
+      - C_C
+  - name: GT_CC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: EQ
+      - B_C
+      - C_C
+  - name: GE_RR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: NEQ
+      - B_R
+      - C_R
+  - name: GE_CR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: SEQ
+      - B_C
+      - C_R
+  - name: GE_RC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: SNEQ
+      - B_R
+      - C_C
+  - name: GE_CC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: GT
+      - B_C
+      - C_C
+  - name: LT_RR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: GE
+      - B_R
+      - C_R
+  - name: LT_CR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: LT
+      - B_C
+      - C_R
+  - name: LT_RC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: LE
+      - B_R
+      - C_C
+  - name: LT_CC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: IF
-    args:
-      - A_B
-      - B_RC
-  - name: JUMP
+      - B_C
+      - C_C
+  - name: LE_RR
     args:
-      - ABC_JUMP
-  - name: RETURN
+      - A_R
+      - B_R
+      - C_R
+  - name: LE_CR
     args:
-      - A_H
-      - B_RC
-    flags:
-      - mask: 0x40
-        name: have_retval
-  - name: CALL
+      - A_R
+      - B_C
+      - C_R
+  - name: LE_RC
     args:
-      - A_H
+      - A_R
       - B_R
-      - C_I
-    flags:
-      - mask: 0x40
-        name: tailcall
-      - mask: 0x80
-        name: evalcall
-  - name: CALLI
+      - C_C
+  - name: LE_CC
     args:
-      - A_H
-      - B_RI
-      - C_I
-  - name: TRYCATCH
+      - A_R
+      - B_C
+      - C_C
+  - name: IFTRUE_R
     args:
-      - A_H
-      # base register for two consecutive regs (base_reg + 0, base_reg + 1) used for two things:
-      # - input: either 'with' target register or catch varname constant (base_reg + 0), depending on flags
-      # - output: when caught, catch value (base_reg + 0) and type (base_reg + 1)
       - BC_R
-    flags:
-      - mask: 0x40
-        name: have_catch
-      - mask: 0x80
-        name: have_finally
-      - mask: 0x100
-        name: catch_binding
-      - mask: 0x200
-        name: with_binding
-  - name: EXTRA
-    extra: true
-  - name: PREINCR
+  - name: IFTRUE_C
     args:
-      - A_R
-      - BC_R
-  - name: PREDECR
+      - BC_C
+  - name: IFFALSE_R
     args:
-      - A_R
       - BC_R
-  - name: POSTINCR
+  - name: IFFALSE_C
+    args:
+      - BC_C
+  - name: ADD_RR
     args:
       - A_R
-      - BC_R
-  - name: POSTDECR
+      - B_R
+      - C_R
+  - name: ADD_CR
     args:
       - A_R
-      - BC_R
-  - name: PREINCV
+      - B_C
+      - C_R
+  - name: ADD_RC
     args:
       - A_R
-      - BC_C
-  - name: PREDECV
+      - B_R
+      - C_C
+  - name: ADD_CC
     args:
       - A_R
-      - BC_C
-  - name: POSTINCV
+      - B_C
+      - C_C
+  - name: SUB_RR
     args:
       - A_R
-      - BC_C
-  - name: POSTDECV
+      - B_R
+      - C_R
+  - name: SUB_CR
     args:
       - A_R
-      - BC_C
-  - name: PREINCP
+      - B_C
+      - C_R
+  - name: SUB_RC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: PREDECP
+      - B_R
+      - C_C
+  - name: SUB_CC
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: POSTINCP
+      - B_C
+      - C_C
+  - name: MUL_RR
     args:
       - A_R
-      - B_RC
-      - C_RC
-  - name: POSTDECP
+      - B_R
+      - C_R
+  - name: MUL_CR
     args:
       - A_R
-      - B_RC
-      - C_RC
-
-extra:
-  - name: NOP
-  - name: INVALID
+      - B_C
+      - C_R
+  - name: MUL_RC
     args:
-      - BC_I
-  - name: LDTHIS
+      - A_R
+      - B_R
+      - C_C
+  - name: MUL_CC
     args:
-      - BC_R
-  - name: LDUNDEF
+      - A_R
+      - B_C
+      - C_C
+  - name: DIV_RR
     args:
-      - BC_R
-  - name: LDNULL
+      - A_R
+      - B_R
+      - C_R
+  - name: DIV_CR
     args:
-      - BC_R
-  - name: LDTRUE
+      - A_R
+      - B_C
+      - C_R
+  - name: DIV_RC
     args:
-      - BC_R
-  - name: LDFALSE
+      - A_R
+      - B_R
+      - C_C
+  - name: DIV_CC
     args:
-      - BC_R
-  - name: NEWOBJ
+      - A_R
+      - B_C
+      - C_C
+  - name: MOD_RR
     args:
-      # XXX: extend to BC?
+      - A_R
       - B_R
-  - name: NEWARR
+      - C_R
+  - name: MOD_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: MOD_RC
     args:
-      # XXX: extend to BC?
+      - A_R
       - B_R
-  - name: SETALEN
+      - C_C
+  - name: MOD_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: EXP_RR
     args:
+      - A_R
       - B_R
       - C_R
-  - name: TYPEOF
+  - name: EXP_CR
     args:
-      - BC_R
-  - name: TYPEOFID
+      - A_R
+      - B_C
+      - C_R
+  - name: EXP_RC
     args:
+      - A_R
       - B_R
-      # maybe changed to C_C later
-      - C_RC
-  - name: INITENUM
+      - C_C
+  - name: EXP_CC
     args:
-      - B_R
-      - C_R
-  - name: NEXTENUM
+      - A_R
+      - B_C
+      - C_C
+  - name: BAND_RR
     args:
+      - A_R
       - B_R
       - C_R
-  - name: INITSET
+  - name: BAND_CR
     args:
-      - B_R
+      - A_R
+      - B_C
       - C_R
-  - name: INITSETI
+  - name: BAND_RC
     args:
+      - A_R
       - B_R
-      - C_RI
-  - name: INITGET
+      - C_C
+  - name: BAND_CC
     args:
-      - B_R
-      - C_RI
-  - name: INITGETI
+      - A_R
+      - B_C
+      - C_C
+  - name: BOR_RR
     args:
+      - A_R
       - B_R
-      - C_RI
-  - name: ENDTRY
-  - name: ENDCATCH
-  - name: ENDFIN
-  - name: THROW
+      - C_R
+  - name: BOR_CR
     args:
-      - BC_R
-  - name: INVLHS
-  - name: UNM
+      - A_R
+      - B_C
+      - C_R
+  - name: BOR_RC
     args:
-      - BC_R
-  - name: UNP
+      - A_R
+      - B_R
+      - C_C
+  - name: BOR_CC
     args:
-      - BC_R
-  - name: DEBUGGER
-  - name: BREAK
+      - A_R
+      - B_C
+      - C_C
+  - name: BXOR_RR
     args:
-      - BC_I
-  - name: CONTINUE
+      - A_R
+      - B_R
+      - C_R
+  - name: BXOR_CR
     args:
-      - BC_I
-  - name: BNOT
+      - A_R
+      - B_C
+      - C_R
+  - name: BXOR_RC
     args:
-      - BC_R
-  - name: LNOT
+      - A_R
+      - B_R
+      - C_C
+  - name: BXOR_CC
     args:
-      - BC_R
-  - name: INSTOF
+      - A_R
+      - B_C
+      - C_C
+  - name: BASL_RR
     args:
+      - A_R
       - B_R
-      - C_RC
-  - name: IN
+      - C_R
+  - name: BASL_CR
     args:
+      - A_R
+      - B_C
+      - C_R
+  - name: BASL_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: BASL_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: BLSR_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: BLSR_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: BLSR_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: BLSR_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: BASR_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: BASR_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: BASR_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: BASR_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: INSTOF_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: INSTOF_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: INSTOF_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: INSTOF_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: IN_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: IN_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: IN_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: IN_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: GETPROP_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: GETPROP_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: GETPROP_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: GETPROP_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: PUTPROP_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: PUTPROP_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: PUTPROP_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: PUTPROP_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: DELPROP_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: DELPROP_CR   # unused now
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: DELPROP_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: DELPROP_CC   # unused now
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: PREINCR
+    args:
+      - A_R
+      - BC_R
+  - name: PREDECR
+    args:
+      - A_R
+      - BC_R
+  - name: POSTINCR
+    args:
+      - A_R
+      - BC_R
+  - name: POSTDECR
+    args:
+      - A_R
+      - BC_R
+  - name: PREINCV
+    args:
+      - A_R
+      - BC_C
+  - name: PREDECV
+    args:
+      - A_R
+      - BC_C
+  - name: POSTINCV
+    args:
+      - A_R
+      - BC_C
+  - name: POSTDECV
+    args:
+      - A_R
+      - BC_C
+  - name: PREINCP_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: PREINCP_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: PREINCP_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: PREINCP_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: PREDECP_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: PREDECP_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: PREDECP_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: PREDECP_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: POSTINCP_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: POSTINCP_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: POSTINCP_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: POSTINCP_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: POSTDECP_RR
+    args:
+      - A_R
+      - B_R
+      - C_R
+  - name: POSTDECP_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: POSTDECP_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: POSTDECP_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: DECLVAR_RR
+    args:
+      - A_H
+      - B_R
+      - C_R
+    flags:
+      - mask: 0x100
+        name: writable
+      - mask: 0x200
+        name: enumerable
+      - mask: 0x400
+        name: configurable
+      - mask: 0x800
+        name: accessor
+      - mask: 0x1000
+        name: undef_value
+      - mask: 0x2000
+        name: func_decl
+  - name: DECLVAR_CR
+    args:
+      - A_H
+      - B_C
+      - C_R
+    flags:
+      - mask: 0x100
+        name: writable
+      - mask: 0x200
+        name: enumerable
+      - mask: 0x400
+        name: configurable
+      - mask: 0x800
+        name: accessor
+      - mask: 0x1000
+        name: undef_value
+      - mask: 0x2000
+        name: func_decl
+  - name: DECLVAR_RC
+    args:
+      - A_H
+      - B_R
+      - C_C
+    flags:
+      - mask: 0x100
+        name: writable
+      - mask: 0x200
+        name: enumerable
+      - mask: 0x400
+        name: configurable
+      - mask: 0x800
+        name: accessor
+      - mask: 0x1000
+        name: undef_value
+      - mask: 0x2000
+        name: func_decl
+  - name: DECLVAR_CC
+    args:
+      - A_H
+      - B_C
+      - C_C
+    flags:
+      - mask: 0x100
+        name: writable
+      - mask: 0x200
+        name: enumerable
+      - mask: 0x400
+        name: configurable
+      - mask: 0x800
+        name: accessor
+      - mask: 0x1000
+        name: undef_value
+      - mask: 0x2000
+        name: func_decl
+  - name: REGEXP_RR
+    args:
+      - A_R
       - B_R
-      - C_RC
+      - C_R
+  - name: REGEXP_CR
+    args:
+      - A_R
+      - B_C
+      - C_R
+  - name: REGEXP_RC
+    args:
+      - A_R
+      - B_R
+      - C_C
+  - name: REGEXP_CC
+    args:
+      - A_R
+      - B_C
+      - C_C
+  - name: CSVAR_RR
+    args:
+      - A_R
+      - B_R
+  - name: CSVAR_CR
+    args:
+      - A_R
+      - B_C
+  - name: CSVAR_RC
+    args:
+      - A_R
+      - B_R
+  - name: CSVAR_CC
+    args:
+      - A_R
+      - B_C
+  - name: CLOSURE
+    args:
+      - A_R
+      - BC_I
+  - name: GETVAR
+    args:
+      - A_R
+      - BC_C
+  - name: PUTVAR
+    args:
+      - A_R
+      - BC_C
+  - name: DELVAR
+    args:
+      - A_R
+      - BC_C
+  - name: JUMP
+    args:
+      - ABC_JUMP
+  - name: RETREG
+    args:
+      - BC_R
+  - name: RETUNDEF
+  - name: RETCONST
+    args:
+      - BC_C
+  - name: RETCONSTN
+    args:
+      - BC_C
   - name: LABEL
     args:
       - BC_I
   - name: ENDLABEL
     args:
       - BC_I
-  - name: EXTRA34
-  - name: EXTRA35
-  - name: EXTRA36
-  - name: EXTRA37
-  - name: EXTRA38
-  - name: EXTRA39
-  - name: EXTRA40
-  - name: EXTRA41
-  - name: EXTRA42
-  - name: EXTRA43
-  - name: EXTRA44
-  - name: EXTRA45
-  - name: EXTRA46
-  - name: EXTRA47
-  - name: EXTRA48
-  - name: EXTRA49
-  - name: EXTRA50
-  - name: EXTRA51
-  - name: EXTRA52
-  - name: EXTRA53
-  - name: EXTRA54
-  - name: EXTRA55
-  - name: EXTRA56
-  - name: EXTRA57
-  - name: EXTRA58
-  - name: EXTRA59
-  - name: EXTRA60
-  - name: EXTRA61
-  - name: EXTRA62
-  - name: EXTRA63
-  - name: EXTRA64
-  - name: EXTRA65
-  - name: EXTRA66
-  - name: EXTRA67
-  - name: EXTRA68
-  - name: EXTRA69
-  - name: EXTRA70
-  - name: EXTRA71
-  - name: EXTRA72
-  - name: EXTRA73
-  - name: EXTRA74
-  - name: EXTRA75
-  - name: EXTRA76
-  - name: EXTRA77
-  - name: EXTRA78
-  - name: EXTRA79
-  - name: EXTRA80
-  - name: EXTRA81
-  - name: EXTRA82
-  - name: EXTRA83
-  - name: EXTRA84
-  - name: EXTRA85
-  - name: EXTRA86
-  - name: EXTRA87
-  - name: EXTRA88
-  - name: EXTRA89
-  - name: EXTRA90
-  - name: EXTRA91
-  - name: EXTRA92
-  - name: EXTRA93
-  - name: EXTRA94
-  - name: EXTRA95
-  - name: EXTRA96
-  - name: EXTRA97
-  - name: EXTRA98
-  - name: EXTRA99
-  - name: EXTRA100
-  - name: EXTRA101
-  - name: EXTRA102
-  - name: EXTRA103
-  - name: EXTRA104
-  - name: EXTRA105
-  - name: EXTRA106
-  - name: EXTRA107
-  - name: EXTRA108
-  - name: EXTRA109
-  - name: EXTRA110
-  - name: EXTRA111
-  - name: EXTRA112
-  - name: EXTRA113
-  - name: EXTRA114
-  - name: EXTRA115
-  - name: EXTRA116
-  - name: EXTRA117
-  - name: EXTRA118
-  - name: EXTRA119
-  - name: EXTRA120
-  - name: EXTRA121
-  - name: EXTRA122
-  - name: EXTRA123
-  - name: EXTRA124
-  - name: EXTRA125
-  - name: EXTRA126
-  - name: EXTRA127
-  - name: EXTRA128
-  - name: EXTRA129
-  - name: EXTRA130
-  - name: EXTRA131
-  - name: EXTRA132
-  - name: EXTRA133
-  - name: EXTRA134
-  - name: EXTRA135
-  - name: EXTRA136
-  - name: EXTRA137
-  - name: EXTRA138
-  - name: EXTRA139
-  - name: EXTRA140
-  - name: EXTRA141
-  - name: EXTRA142
-  - name: EXTRA143
-  - name: EXTRA144
-  - name: EXTRA145
-  - name: EXTRA146
-  - name: EXTRA147
-  - name: EXTRA148
-  - name: EXTRA149
-  - name: EXTRA150
-  - name: EXTRA151
-  - name: EXTRA152
-  - name: EXTRA153
-  - name: EXTRA154
-  - name: EXTRA155
-  - name: EXTRA156
-  - name: EXTRA157
-  - name: EXTRA158
-  - name: EXTRA159
-  - name: EXTRA160
-  - name: EXTRA161
-  - name: EXTRA162
-  - name: EXTRA163
-  - name: EXTRA164
-  - name: EXTRA165
-  - name: EXTRA166
-  - name: EXTRA167
-  - name: EXTRA168
-  - name: EXTRA169
-  - name: EXTRA170
-  - name: EXTRA171
-  - name: EXTRA172
-  - name: EXTRA173
-  - name: EXTRA174
-  - name: EXTRA175
-  - name: EXTRA176
-  - name: EXTRA177
-  - name: EXTRA178
-  - name: EXTRA179
-  - name: EXTRA180
-  - name: EXTRA181
-  - name: EXTRA182
-  - name: EXTRA183
-  - name: EXTRA184
-  - name: EXTRA185
-  - name: EXTRA186
-  - name: EXTRA187
-  - name: EXTRA188
-  - name: EXTRA189
-  - name: EXTRA190
-  - name: EXTRA191
-  - name: EXTRA192
-  - name: EXTRA193
-  - name: EXTRA194
-  - name: EXTRA195
-  - name: EXTRA196
-  - name: EXTRA197
-  - name: EXTRA198
-  - name: EXTRA199
-  - name: EXTRA200
-  - name: EXTRA201
-  - name: EXTRA202
-  - name: EXTRA203
-  - name: EXTRA204
-  - name: EXTRA205
-  - name: EXTRA206
-  - name: EXTRA207
-  - name: EXTRA208
-  - name: EXTRA209
-  - name: EXTRA210
-  - name: EXTRA211
-  - name: EXTRA212
-  - name: EXTRA213
-  - name: EXTRA214
-  - name: EXTRA215
-  - name: EXTRA216
-  - name: EXTRA217
-  - name: EXTRA218
-  - name: EXTRA219
-  - name: EXTRA220
-  - name: EXTRA221
-  - name: EXTRA222
-  - name: EXTRA223
-  - name: EXTRA224
-  - name: EXTRA225
-  - name: EXTRA226
-  - name: EXTRA227
-  - name: EXTRA228
-  - name: EXTRA229
-  - name: EXTRA230
-  - name: EXTRA231
-  - name: EXTRA232
-  - name: EXTRA233
-  - name: EXTRA234
-  - name: EXTRA235
-  - name: EXTRA236
-  - name: EXTRA237
-  - name: EXTRA238
-  - name: EXTRA239
-  - name: EXTRA240
-  - name: EXTRA241
-  - name: EXTRA242
-  - name: EXTRA243
-  - name: EXTRA244
-  - name: EXTRA245
-  - name: EXTRA246
-  - name: EXTRA247
-  - name: EXTRA248
-  - name: EXTRA249
-  - name: EXTRA250
-  - name: EXTRA251
-  - name: EXTRA252
-  - name: EXTRA253
-  - name: EXTRA254
-  - name: EXTRA255
+  - name: BREAK
+    args:
+      - BC_I
+  - name: CONTINUE
+    args:
+      - BC_I
+  - name: TRYCATCH
+    args:
+      - A_H
+      # base register for two consecutive regs (base_reg + 0, base_reg + 1) used for two things:
+      # - input: either 'with' target register or catch varname constant (base_reg + 0), depending on flags
+      # - output: when caught, catch value (base_reg + 0) and type (base_reg + 1)
+      - BC_R
+    flags:
+      - mask: 0x40
+        name: have_catch
+      - mask: 0x80
+        name: have_finally
+      - mask: 0x100
+        name: catch_binding
+      - mask: 0x200
+        name: with_binding
+  - name: ENDTRY
+  - name: ENDCATCH
+  - name: ENDFIN
+  - name: THROW
+    args:
+      - BC_R
+  - name: CSREG
+    args:
+      - A_R
+      - BC_R
+  - name: EVALCALL
+    args:
+      - A_I
+      - BC_R
+  - name: CALL
+    args:
+      - A_I
+      - BC_R
+  - name: TAILCALL
+    args:
+      - A_I
+      - BC_R
+  - name: NEW
+    args:
+      - A_I
+      - BC_R
+  - name: NEWOBJ
+    args:
+      - BC_R
+  - name: NEWARR
+    args:
+      - BC_R
+  - name: MPUTOBJ
+    args:
+      - A_R
+      - B_R
+      - C_I
+  - name: MPUTOBJI
+    args:
+      - A_R
+      - B_RI
+      - C_I
+  - name: INITSET
+    args:
+      - A_R
+      - BC_R
+  - name: INITGET
+    args:
+      - A_R
+      - BC_R
+  - name: MPUTARR
+    args:
+      - A_R
+      - B_R
+      - C_I
+  - name: MPUTARRI
+    args:
+      - A_R
+      - B_RI
+      - C_I
+  - name: SETALEN
+    args:
+      - B_R
+      - C_R
+  - name: INITENUM
+    args:
+      - B_R
+      - C_R
+  - name: NEXTENUM
+    args:
+      - B_R
+      - C_R
+  - name: INVLHS
+  - name: DEBUGGER
+  - name: NOP
+  - name: INVALID
+    args:
+      - ABC_I
+  - name: UNUSED194
+  - name: UNUSED195
+  - name: UNUSED196
+  - name: UNUSED197
+  - name: UNUSED198
+  - name: UNUSED199
+  - name: UNUSED200
+  - name: UNUSED201
+  - name: UNUSED202
+  - name: UNUSED203
+  - name: UNUSED204
+  - name: UNUSED205
+  - name: UNUSED206
+  - name: UNUSED207
+  - name: UNUSED208
+  - name: UNUSED209
+  - name: UNUSED210
+  - name: UNUSED211
+  - name: UNUSED212
+  - name: UNUSED213
+  - name: UNUSED214
+  - name: UNUSED215
+  - name: UNUSED216
+  - name: UNUSED217
+  - name: UNUSED218
+  - name: UNUSED219
+  - name: UNUSED220
+  - name: UNUSED221
+  - name: UNUSED222
+  - name: UNUSED223
+  - name: UNUSED224
+  - name: UNUSED225
+  - name: UNUSED226
+  - name: UNUSED227
+  - name: UNUSED228
+  - name: UNUSED229
+  - name: UNUSED230
+  - name: UNUSED231
+  - name: UNUSED232
+  - name: UNUSED233
+  - name: UNUSED234
+  - name: UNUSED235
+  - name: UNUSED236
+  - name: UNUSED237
+  - name: UNUSED238
+  - name: UNUSED239
+  - name: UNUSED240
+  - name: UNUSED241
+  - name: UNUSED242
+  - name: UNUSED243
+  - name: UNUSED244
+  - name: UNUSED245
+  - name: UNUSED246
+  - name: UNUSED247
+  - name: UNUSED248
+  - name: UNUSED249
+  - name: UNUSED250
+  - name: UNUSED251
+  - name: UNUSED252
+  - name: UNUSED253
+  - name: UNUSED254
+  - name: UNUSED255

+ 1 - 2
Script/DuktapeDebugProxy/package.json

@@ -14,14 +14,13 @@
     "express": "~4.10.1",
     "http": "0.0.0",
     "minimist": "~1.1.0",
-    "monaco-editor": "^0.8.1",
     "readline": "0.0.5",
+    "recursive-readdir-sync": "^1.0.6",
     "socket.io": "~1.2.1",
     "sprintf": "~0.1.5",
     "stream": "0.0.2",
     "utf8": "~2.0.0",
     "util": "~0.10.3",
-    "wrench": "~1.5.8",
     "yamljs": "~0.2.1"
   },
   "main": "duk_debug.js"

+ 2 - 1
Source/AtomicApp/Player/IPCPlayerApp.cpp

@@ -827,7 +827,7 @@ void duk_trans_socket_write_flush_cb(void *udata) {
     }
 #endif // OSX ad LINUX
 
-    void debugger_detached (void *udata) {
+    void debugger_detached (duk_context* ctx, void *udata) {
 
         fflush(stderr);
 
@@ -1031,6 +1031,7 @@ void duk_trans_socket_write_flush_cb(void *udata) {
             duk_trans_socket_peek_cb,
             duk_trans_socket_read_flush_cb,
             duk_trans_socket_write_flush_cb,
+            NULL, // duk_debug_request_function - no custom application specific request functions
             debugger_detached,
             NULL);
     }

+ 0 - 1
Source/AtomicEditor/Editors/JSResourceEditor.cpp

@@ -160,7 +160,6 @@ void JSResourceEditor::HandleWebMessage(StringHash eventType, VariantMap& eventD
             }
         }
     }
-
     handler->Success();
 }
 

+ 1 - 1
Source/AtomicJS/Javascript/JSPlugin.cpp

@@ -363,7 +363,7 @@ namespace Atomic
         gJSVMExports.duk_log_va = duk_log_va;
         gJSVMExports.duk_push_context_dump = duk_push_context_dump;
         gJSVMExports.duk_debugger_detach = duk_debugger_detach;
-        gJSVMExports.duk_debugger_attach_custom = duk_debugger_attach_custom;
+        gJSVMExports.duk_debugger_attach_custom = duk_debugger_attach;
         gJSVMExports.duk_debugger_cooperate = duk_debugger_cooperate;
 
     }

+ 6 - 5
Source/AtomicJS/Javascript/JSPluginExports.h

@@ -23,6 +23,7 @@
 #pragma once
 
 #include <Duktape/duktape.h>
+#include <Duktape/duk_logging.h>
 
 namespace Atomic
 {
@@ -51,8 +52,8 @@ namespace Atomic
         typedef void(*__duk_get_memory_functions)(duk_context *ctx, duk_memory_functions *out_funcs);
         typedef void(*__duk_gc)(duk_context *ctx, duk_uint_t flags);
 
-        typedef void(*__duk_throw)(duk_context *ctx);
-        typedef void(*__duk_fatal)(duk_context *ctx, duk_errcode_t err_code, const char *err_msg);
+        typedef void(*__duk_throw_raw)(duk_context *ctx);
+        typedef void(*__duk_fatal_raw)(duk_context *ctx, const char *err_msg);
         typedef void(*__duk_error_raw)(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...);
         typedef void(*__duk_error_va_raw)(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap);
 
@@ -261,7 +262,7 @@ namespace Atomic
         typedef duk_int_t(*__duk_pcall_method)(duk_context *ctx, duk_idx_t nargs);
         typedef duk_int_t(*__duk_pcall_prop)(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs);
         typedef void(*__duk_new)(duk_context *ctx, duk_idx_t nargs);
-        typedef duk_int_t(*__duk_safe_call)(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets);
+        typedef duk_int_t(*__duk_safe_call)(duk_context *ctx, duk_safe_call_function func, void* data, duk_idx_t nargs, duk_idx_t nrets);
 
         typedef duk_int_t(*__duk_eval_raw)(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags);
         typedef duk_int_t(*__duk_compile_raw)(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags);
@@ -297,8 +298,8 @@ namespace Atomic
             __duk_get_memory_functions duk_get_memory_functions;
             __duk_gc duk_gc;
 
-            __duk_throw duk_throw;
-            __duk_fatal duk_fatal;
+            __duk_throw_raw duk_throw_raw;
+            __duk_fatal_raw duk_fatal_raw;
             __duk_error_raw duk_error_raw;
             __duk_error_va_raw duk_error_va_raw;
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 183 - 962
Source/ThirdParty/Duktape/duk_config.h


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 368 - 224
Source/ThirdParty/Duktape/duktape.c


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 409 - 340
Source/ThirdParty/Duktape/duktape.h


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels