[
  {
    "path": ".gitignore",
    "content": "js/\ncompile\nlibmozglue.dylib\nlibmozjs-52.dylib\n.idea/\n\n/vendor/\ncomposer.lock\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"irelance/jsc-decompile-mozjs-34\",\n    \"license\": \"proprietary\",\n    \"type\": \"project\",\n    \"authors\": [\n        {\n            \"name\": \"irelance\",\n            \"email\": \"heirelance@163.com\"\n        }\n    ],\n    \"autoload\": {\n        \"psr-4\": {\n            \"Irelance\\\\Mozjs34\\\\\": \"src\"\n        }\n    },\n    \"require\": {\n        \"php\": \">=7.0.0\"\n    }\n}\n"
  },
  {
    "path": "readme.md",
    "content": "# 1.Summary\n\nThis project is a javascript bytecode decoder for mozilla spider-monkey version 34.\n\nThis version may decompile jsc file compile by cocos-2dx.\n\nIt would not work for different version of Mozilla spider-monkey (without shell of course), for its opcode defined different for each version.\n\nMaybe no longer update, but still a good example to understand how javascript virtual machine work (though different engine has different implement).\n\nIs this project can just decompile \"34\" version only and why?\n\nWell, the truth is may decompile near 34 version before bytecode file structure change.\n\nJs engine may change the file struct for support new language feather, performance optimization, code refactoring, ...\n\nBut think of most change is just to add ```section```(concept come of executable binary file) and add ```operation``` instead of change struct.\n\nSo this project just try to decompile without check magic code. At least, scan.php will work at most time.\n\n# 2.Usage\n\n## 2.1.Install PHP and Composer\n\nIf you are familiar with php, you can skip this part.\n\ninstall php7.0 (still work in php7.4)\n```\n# ubuntu\n$ sudo apt install php7.0\n\n# mac\n$ brew install php7.0\n\n# windows\n# just google an binary one\n```\ninstall composer\n>see https://getcomposer.org/download/\n\ninstall this project\n```\n$ cd path/to/project\n# no dependences, just auto generate the autoload\n$ composer install\n```\n\n## 2.2.decompile *.jsc file\n\n```\n$ cd /path/to/this/project\n$ php run.php /path/to/your.jsc > /path/to/decompile.txt\n#if this didn't work, you can also try below command to get the bitcode\n$ php scan.php /path/to/your.jsc > /path/to/scan.txt\n```\n\n## 2.3. print more info with scan.php\n\nJust remove the slashes in scan.php\n\n# 3. How to guess the bytecode version\n\n| magic code  |  version  |\n|    ---      |    ---    |\n| 2C C0 73 B9 |     33    |\n| 28 C0 73 B9 |     34    |\n| 25 C0 73 B9 |     35    |\n| 04 C0 73 B9 |     36    |\n| FC BF 73 B9 |     37    |\n| F4 BF 73 B9 |     38    |\n| D1 BF 73 B9 |     39    |\n| C3 BF 73 B9 |     40    |\n| B7 BF 73 B9 |     41    |\n| B3 BF 73 B9 |     42    |\n| AB BF 73 B9 |     43    |\n| A0 BF 73 B9 |     44    |\n| 95 BF 73 B9 |     45    |\n| 88 BF 73 B9 |     46    |\n| 81 BF 73 B9 |     47    |\n\nYes, change happens >= 48.\nbytecodeVer(int) change to buildId(string).\nAnd buildId is very like an useragent of browser.\n\n# 4.Besides\n\nThis project is not complete yet.\n\n- A Fatal Bug was found when decompile with a deep context\n\nDecompile result is not a runable file.\nSome local variables are auto generate, for the compiler discards local variables.\n\n"
  },
  {
    "path": "run.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/1\n * Time: 上午10:47\n */\ninclude 'vendor/autoload.php';\n\n\n$decompile = new Irelance\\Mozjs34\\Decompile($argv[1]);\n$decompile->run();\n//$decompile->runResult();\n$contexts = $decompile->getContexts();\nforeach ($contexts as $index => $context) {\n    //if ($index==0) {\n        echo '==================================' . $index . '==================================S', CLIENT_EOL;\n        /* @var \\Irelance\\Mozjs34\\Context $context */\n        $context->printProperties([\n            //'Summaries',\n            //'Atoms',\n            //'Operations',\n            'Argv',\n            'Content',\n            //'Nodes',\n            //'Consts',\n            //'Objects',\n            //'Regexps',\n            //'TryNote',\n            //'ScopeNote',\n        ]);\n        echo '==========================================================================E', CLIENT_EOL;\n    //}\n}\n"
  },
  {
    "path": "scan.php",
    "content": "<?php\r\n/**\r\n * Created by PhpStorm.\r\n * User: irelance\r\n * Date: 2018/10/10\r\n * Time: 17:51\r\n */\r\n\r\ninclude 'vendor/autoload.php';\r\n\r\n\r\n$decompile = new Irelance\\Mozjs34\\Decompile($argv[1]);\r\n$decompile->run();\r\n//$decompile->runResult();\r\n$contexts = $decompile->getContexts();\r\nforeach ($contexts as $index => $context) {\r\n    //if ($index==0) {\r\n    echo '==================================' . $index . '==================================S', CLIENT_EOL;\r\n    /* @var \\Irelance\\Mozjs34\\Context $context */\r\n    $context->printProperties([\r\n        //'Summaries',\r\n        'Atoms',\r\n        'Operations',\r\n        'Argv',\r\n        //'Content',\r\n        'Nodes',\r\n        'Consts',\r\n        //'Objects',\r\n        'Regexps',\r\n        //'TryNote',\r\n        //'ScopeNote',\r\n    ]);\r\n    echo '==========================================================================E', CLIENT_EOL;\r\n    //}\r\n}"
  },
  {
    "path": "src/Constant.php",
    "content": "<?php\n\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/9/30\n * Time: 上午10:05\n */\nnamespace Irelance\\Mozjs34;\nif (php_sapi_name() == 'cli') {\n    define('CLIENT_EOL', PHP_EOL);\n} else {\n    define('CLIENT_EOL', \"<br>\");\n}\n\ndefine('JSID_TYPE_STRING', 0x0);\ndefine('JSID_TYPE_INT', 0x1);\ndefine('JSID_TYPE_VOID', 0x2);\ndefine('JSID_TYPE_SYMBOL', 0x4);\ndefine('JSID_TYPE_MASK', 0x7);\n\ndefine(\"js_undefined_str\", \"undefined\");\ndefine(\"js_typeof_str\", \"typeof\");\ndefine(\"js_void_str\", \"void\");\ndefine(\"js_null_str\", \"null\");\ndefine(\"js_false_str\", \"false\");\ndefine(\"js_true_str\", \"true\");\ndefine(\"js_throw_str\", \"throw\");\ndefine(\"js_in_str\", \"in\");\ndefine(\"js_instanceof_str\", \"instanceof\");\ndefine(\"js_this_str\", \"this\");\ndefine(\"js_new_str\", \"new\");\n\nclass Constant\n{\n    const _ConstTag = [\n        'SCRIPT_INT',\n        'SCRIPT_DOUBLE',\n        'SCRIPT_ATOM',\n        'SCRIPT_TRUE',\n        'SCRIPT_FALSE',\n        'SCRIPT_NULL',\n        'SCRIPT_OBJECT',\n        'SCRIPT_VOID',\n        'SCRIPT_HOLE',\n    ];\n\n    const _Class = [\n        'CK_BlockObject',\n        'CK_WithObject',\n        'CK_JSFunction',\n        'CK_JSObject'\n    ];\n\n    const _ScriptBits = [\n        'NoScriptRval',\n        'SavedCallerFun',\n        'Strict',\n        'ContainsDynamicNameAccess',\n        'FunHasExtensibleScope',\n        'FunNeedsDeclEnvObject',\n        'FunHasAnyAliasedFormal',\n        'ArgumentsHasVarBinding',\n        'NeedsArgsObj',\n        'IsGeneratorExp',\n        'IsLegacyGenerator',\n        'IsStarGenerator',\n        'OwnSource',\n        'ExplicitUseStrict',\n        'SelfHosted',\n        'IsCompileAndGo',\n        'HasSingleton',\n        'TreatAsRunOnce',\n        'HasLazyScript'\n    ];\n\n    const _FirstWordFlag = [\n        'HasAtom' => 0x1,\n        'IsStarGenerator' => 0x2,\n        'IsLazy' => 0x4,\n        'HasSingletonType' => 0x8\n    ];\n\n    const _Opcode = [\n        0 => ['op' => 'JSOP_NOP', 'val' => 0, 'name' => \"nop\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        1 => ['op' => 'JSOP_UNDEFINED', 'val' => 1, 'name' => js_undefined_str, 'image' => \"\", 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        2 => ['op' => 'JSOP_UNUSED2', 'val' => 2, 'name' => \"unused2\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 0, 'format' => ['JOF_BYTE']],\n        3 => ['op' => 'JSOP_ENTERWITH', 'val' => 3, 'name' => \"enterwith\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 0, 'format' => ['JOF_OBJECT']],\n        4 => ['op' => 'JSOP_LEAVEWITH', 'val' => 4, 'name' => \"leavewith\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        5 => ['op' => 'JSOP_RETURN', 'val' => 5, 'name' => \"return\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 0, 'format' => ['JOF_BYTE']],\n        6 => ['op' => 'JSOP_GOTO', 'val' => 6, 'name' => \"goto\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 0, 'format' => ['JOF_JUMP']],\n        7 => ['op' => 'JSOP_IFEQ', 'val' => 7, 'name' => \"ifeq\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 0, 'format' => ['JOF_JUMP', 'JOF_DETECTING']],\n        8 => ['op' => 'JSOP_IFNE', 'val' => 8, 'name' => \"ifne\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 0, 'format' => ['JOF_JUMP']],\n        9 => ['op' => 'JSOP_ARGUMENTS', 'val' => 9, 'name' => \"arguments\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        10 => ['op' => 'JSOP_SWAP', 'val' => 10, 'name' => \"swap\", 'image' => NULL, 'len' => 1, 'use' => 2, 'def' => 2, 'format' => ['JOF_BYTE']],\n        11 => ['op' => 'JSOP_POPN', 'val' => 11, 'name' => \"popn\", 'image' => NULL, 'len' => 3, 'use' => -1, 'def' => 0, 'format' => ['JOF_UINT16']],\n        12 => ['op' => 'JSOP_DUP', 'val' => 12, 'name' => \"dup\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 2, 'format' => ['JOF_BYTE']],\n        13 => ['op' => 'JSOP_DUP2', 'val' => 13, 'name' => \"dup2\", 'image' => NULL, 'len' => 1, 'use' => 2, 'def' => 4, 'format' => ['JOF_BYTE']],\n        14 => ['op' => 'JSOP_SETCONST', 'val' => 14, 'name' => \"setconst\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_SET']],\n        15 => ['op' => 'JSOP_BITOR', 'val' => 15, 'name' => \"bitor\", 'image' => \"|\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        16 => ['op' => 'JSOP_BITXOR', 'val' => 16, 'name' => \"bitxor\", 'image' => \"^\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        17 => ['op' => 'JSOP_BITAND', 'val' => 17, 'name' => \"bitand\", 'image' => \"&\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        18 => ['op' => 'JSOP_EQ', 'val' => 18, 'name' => \"eq\", 'image' => \"==\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH', 'JOF_DETECTING']],\n        19 => ['op' => 'JSOP_NE', 'val' => 19, 'name' => \"ne\", 'image' => \"!=\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH', 'JOF_DETECTING']],\n        20 => ['op' => 'JSOP_LT', 'val' => 20, 'name' => \"lt\", 'image' => \"<\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        21 => ['op' => 'JSOP_LE', 'val' => 21, 'name' => \"le\", 'image' => \"<=\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        22 => ['op' => 'JSOP_GT', 'val' => 22, 'name' => \"gt\", 'image' => \">\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        23 => ['op' => 'JSOP_GE', 'val' => 23, 'name' => \"ge\", 'image' => \">=\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        24 => ['op' => 'JSOP_LSH', 'val' => 24, 'name' => \"lsh\", 'image' => \"<<\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        25 => ['op' => 'JSOP_RSH', 'val' => 25, 'name' => \"rsh\", 'image' => \">>\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        26 => ['op' => 'JSOP_URSH', 'val' => 26, 'name' => \"ursh\", 'image' => \">>>\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        27 => ['op' => 'JSOP_ADD', 'val' => 27, 'name' => \"add\", 'image' => \"+\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        28 => ['op' => 'JSOP_SUB', 'val' => 28, 'name' => \"sub\", 'image' => \"-\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        29 => ['op' => 'JSOP_MUL', 'val' => 29, 'name' => \"mul\", 'image' => \"*\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        30 => ['op' => 'JSOP_DIV', 'val' => 30, 'name' => \"div\", 'image' => \"/\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        31 => ['op' => 'JSOP_MOD', 'val' => 31, 'name' => \"mod\", 'image' => \"%\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        32 => ['op' => 'JSOP_NOT', 'val' => 32, 'name' => \"not\", 'image' => \"!\", 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ARITH', 'JOF_DETECTING']],\n        33 => ['op' => 'JSOP_BITNOT', 'val' => 33, 'name' => \"bitnot\", 'image' => \"~\", 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ARITH']],\n        34 => ['op' => 'JSOP_NEG', 'val' => 34, 'name' => \"neg\", 'image' => \"- \", 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ARITH']],\n        35 => ['op' => 'JSOP_POS', 'val' => 35, 'name' => \"pos\", 'image' => \"+ \", 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ARITH']],\n        36 => ['op' => 'JSOP_DELNAME', 'val' => 36, 'name' => \"delname\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME']],\n        37 => ['op' => 'JSOP_DELPROP', 'val' => 37, 'name' => \"delprop\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_PROP']],\n        38 => ['op' => 'JSOP_DELELEM', 'val' => 38, 'name' => \"delelem\", 'image' => NULL, 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ELEM']],\n        39 => ['op' => 'JSOP_TYPEOF', 'val' => 39, 'name' => js_typeof_str, 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_DETECTING']],\n        40 => ['op' => 'JSOP_VOID', 'val' => 40, 'name' => js_void_str, 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE']],\n        41 => ['op' => 'JSOP_SPREADCALL', 'val' => 41, 'name' => \"spreadcall\", 'image' => NULL, 'len' => 1, 'use' => 3, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_INVOKE', 'JOF_TYPESET']],\n        42 => ['op' => 'JSOP_SPREADNEW', 'val' => 42, 'name' => \"spreadnew\", 'image' => NULL, 'len' => 1, 'use' => 3, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_INVOKE', 'JOF_TYPESET']],\n        43 => ['op' => 'JSOP_SPREADEVAL', 'val' => 43, 'name' => \"spreadeval\", 'image' => NULL, 'len' => 1, 'use' => 3, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_INVOKE', 'JOF_TYPESET']],\n        44 => ['op' => 'JSOP_DUPAT', 'val' => 44, 'name' => \"dupat\", 'image' => NULL, 'len' => 4, 'use' => 0, 'def' => 1, 'format' => ['JOF_UINT24']],\n        45 => ['op' => 'JSOP_UNUSED45', 'val' => 45, 'name' => \"unused45\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        46 => ['op' => 'JSOP_UNUSED46', 'val' => 46, 'name' => \"unused46\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        47 => ['op' => 'JSOP_UNUSED47', 'val' => 47, 'name' => \"unused47\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        48 => ['op' => 'JSOP_UNUSED48', 'val' => 48, 'name' => \"unused48\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        49 => ['op' => 'JSOP_UNUSED49', 'val' => 49, 'name' => \"unused49\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        50 => ['op' => 'JSOP_UNUSED50', 'val' => 50, 'name' => \"unused50\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        51 => ['op' => 'JSOP_UNUSED51', 'val' => 51, 'name' => \"unused51\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        52 => ['op' => 'JSOP_UNUSED52', 'val' => 52, 'name' => \"unused52\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        53 => ['op' => 'JSOP_GETPROP', 'val' => 53, 'name' => \"getprop\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_PROP', 'JOF_TYPESET', 'JOF_TMPSLOT3']],\n        54 => ['op' => 'JSOP_SETPROP', 'val' => 54, 'name' => \"setprop\", 'image' => NULL, 'len' => 5, 'use' => 2, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_PROP', 'JOF_SET', 'JOF_DETECTING']],\n        55 => ['op' => 'JSOP_GETELEM', 'val' => 55, 'name' => \"getelem\", 'image' => NULL, 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ELEM', 'JOF_TYPESET', 'JOF_LEFTASSOC']],\n        56 => ['op' => 'JSOP_SETELEM', 'val' => 56, 'name' => \"setelem\", 'image' => NULL, 'len' => 1, 'use' => 3, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ELEM', 'JOF_SET', 'JOF_DETECTING']],\n        57 => ['op' => 'JSOP_UNUSED57', 'val' => 57, 'name' => \"unused57\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        58 => ['op' => 'JSOP_CALL', 'val' => 58, 'name' => \"call\", 'image' => NULL, 'len' => 3, 'use' => -1, 'def' => 1, 'format' => ['JOF_UINT16', 'JOF_INVOKE', 'JOF_TYPESET']],\n        59 => ['op' => 'JSOP_NAME', 'val' => 59, 'name' => \"name\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_TYPESET']],\n        60 => ['op' => 'JSOP_DOUBLE', 'val' => 60, 'name' => \"double\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_DOUBLE']],\n        61 => ['op' => 'JSOP_STRING', 'val' => 61, 'name' => \"string\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_ATOM']],\n        62 => ['op' => 'JSOP_ZERO', 'val' => 62, 'name' => \"zero\", 'image' => \"0\", 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        63 => ['op' => 'JSOP_ONE', 'val' => 63, 'name' => \"one\", 'image' => \"1\", 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        64 => ['op' => 'JSOP_NULL', 'val' => 64, 'name' => js_null_str, 'image' => js_null_str, 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        65 => ['op' => 'JSOP_THIS', 'val' => 65, 'name' => js_this_str, 'image' => js_this_str, 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        66 => ['op' => 'JSOP_FALSE', 'val' => 66, 'name' => js_false_str, 'image' => js_false_str, 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        67 => ['op' => 'JSOP_TRUE', 'val' => 67, 'name' => js_true_str, 'image' => js_true_str, 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        68 => ['op' => 'JSOP_OR', 'val' => 68, 'name' => \"or\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_JUMP', 'JOF_DETECTING', 'JOF_LEFTASSOC']],\n        69 => ['op' => 'JSOP_AND', 'val' => 69, 'name' => \"and\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_JUMP', 'JOF_DETECTING', 'JOF_LEFTASSOC']],\n        70 => ['op' => 'JSOP_TABLESWITCH', 'val' => 70, 'name' => \"tableswitch\", 'image' => NULL, 'len' => -1, 'use' => 1, 'def' => 0, 'format' => ['JOF_TABLESWITCH', 'JOF_DETECTING']],\n        71 => ['op' => 'JSOP_RUNONCE', 'val' => 71, 'name' => \"runonce\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        72 => ['op' => 'JSOP_STRICTEQ', 'val' => 72, 'name' => \"stricteq\", 'image' => \"===\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_DETECTING', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        73 => ['op' => 'JSOP_STRICTNE', 'val' => 73, 'name' => \"strictne\", 'image' => \"!==\", 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_DETECTING', 'JOF_LEFTASSOC', 'JOF_ARITH']],\n        74 => ['op' => 'JSOP_SETCALL', 'val' => 74, 'name' => \"setcall\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        75 => ['op' => 'JSOP_ITER', 'val' => 75, 'name' => \"iter\", 'image' => NULL, 'len' => 2, 'use' => 1, 'def' => 1, 'format' => ['JOF_UINT8']],\n        76 => ['op' => 'JSOP_MOREITER', 'val' => 76, 'name' => \"moreiter\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 2, 'format' => ['JOF_BYTE']],\n        77 => ['op' => 'JSOP_ITERNEXT', 'val' => 77, 'name' => \"iternext\", 'image' => \"<next>\", 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        78 => ['op' => 'JSOP_ENDITER', 'val' => 78, 'name' => \"enditer\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 0, 'format' => ['JOF_BYTE']],\n        79 => ['op' => 'JSOP_FUNAPPLY', 'val' => 79, 'name' => \"funapply\", 'image' => NULL, 'len' => 3, 'use' => -1, 'def' => 1, 'format' => ['JOF_UINT16', 'JOF_INVOKE', 'JOF_TYPESET']],\n        80 => ['op' => 'JSOP_OBJECT', 'val' => 80, 'name' => \"object\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_OBJECT']],\n        81 => ['op' => 'JSOP_POP', 'val' => 81, 'name' => \"pop\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 0, 'format' => ['JOF_BYTE']],\n        82 => ['op' => 'JSOP_NEW', 'val' => 82, 'name' => js_new_str, 'image' => NULL, 'len' => 3, 'use' => -1, 'def' => 1, 'format' => ['JOF_UINT16', 'JOF_INVOKE', 'JOF_TYPESET']],\n        83 => ['op' => 'JSOP_UNUSED83', 'val' => 83, 'name' => \"unused83\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        84 => ['op' => 'JSOP_GETARG', 'val' => 84, 'name' => \"getarg\", 'image' => NULL, 'len' => 3, 'use' => 0, 'def' => 1, 'format' => ['JOF_QARG', 'JOF_NAME']],\n        85 => ['op' => 'JSOP_SETARG', 'val' => 85, 'name' => \"setarg\", 'image' => NULL, 'len' => 3, 'use' => 1, 'def' => 1, 'format' => ['JOF_QARG', 'JOF_NAME', 'JOF_SET']],\n        86 => ['op' => 'JSOP_GETLOCAL', 'val' => 86, 'name' => \"getlocal\", 'image' => NULL, 'len' => 4, 'use' => 0, 'def' => 1, 'format' => ['JOF_LOCAL', 'JOF_NAME']],\n        87 => ['op' => 'JSOP_SETLOCAL', 'val' => 87, 'name' => \"setlocal\", 'image' => NULL, 'len' => 4, 'use' => 1, 'def' => 1, 'format' => ['JOF_LOCAL', 'JOF_NAME', 'JOF_SET', 'JOF_DETECTING']],\n        88 => ['op' => 'JSOP_UINT16', 'val' => 88, 'name' => \"uint16\", 'image' => NULL, 'len' => 3, 'use' => 0, 'def' => 1, 'format' => ['JOF_UINT16']],\n        89 => ['op' => 'JSOP_NEWINIT', 'val' => 89, 'name' => \"newinit\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_UINT8']],\n        90 => ['op' => 'JSOP_NEWARRAY', 'val' => 90, 'name' => \"newarray\", 'image' => NULL, 'len' => 4, 'use' => 0, 'def' => 1, 'format' => ['JOF_UINT24']],\n        91 => ['op' => 'JSOP_NEWOBJECT', 'val' => 91, 'name' => \"newobject\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_OBJECT']],\n        92 => ['op' => 'JSOP_ENDINIT', 'val' => 92, 'name' => \"endinit\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        93 => ['op' => 'JSOP_INITPROP', 'val' => 93, 'name' => \"initprop\", 'image' => NULL, 'len' => 5, 'use' => 2, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_PROP', 'JOF_SET', 'JOF_DETECTING']],\n        94 => ['op' => 'JSOP_INITELEM', 'val' => 94, 'name' => \"initelem\", 'image' => NULL, 'len' => 1, 'use' => 3, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ELEM', 'JOF_SET', 'JOF_DETECTING']],\n        95 => ['op' => 'JSOP_INITELEM_INC', 'val' => 95, 'name' => \"initelem_inc\", 'image' => NULL, 'len' => 1, 'use' => 3, 'def' => 2, 'format' => ['JOF_BYTE', 'JOF_ELEM', 'JOF_SET']],\n        96 => ['op' => 'JSOP_INITELEM_ARRAY', 'val' => 96, 'name' => \"initelem_array\", 'image' => NULL, 'len' => 4, 'use' => 2, 'def' => 1, 'format' => ['JOF_UINT24', 'JOF_ELEM', 'JOF_SET', 'JOF_DETECTING']],\n        97 => ['op' => 'JSOP_INITPROP_GETTER', 'val' => 97, 'name' => \"initprop_getter\", 'image' => NULL, 'len' => 5, 'use' => 2, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_PROP', 'JOF_SET', 'JOF_DETECTING']],\n        98 => ['op' => 'JSOP_INITPROP_SETTER', 'val' => 98, 'name' => \"initprop_setter\", 'image' => NULL, 'len' => 5, 'use' => 2, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_PROP', 'JOF_SET', 'JOF_DETECTING']],\n        99 => ['op' => 'JSOP_INITELEM_GETTER', 'val' => 99, 'name' => \"initelem_getter\", 'image' => NULL, 'len' => 1, 'use' => 3, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ELEM', 'JOF_SET', 'JOF_DETECTING']],\n        100 => ['op' => 'JSOP_INITELEM_SETTER', 'val' => 100, 'name' => \"initelem_setter\", 'image' => NULL, 'len' => 1, 'use' => 3, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ELEM', 'JOF_SET', 'JOF_DETECTING']],\n        101 => ['op' => 'JSOP_CALLSITEOBJ', 'val' => 101, 'name' => \"callsiteobj\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_OBJECT']],\n        102 => ['op' => 'JSOP_NEWARRAY_COPYONWRITE', 'val' => 102, 'name' => \"newarray_copyonwrite\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_OBJECT']],\n        103 => ['op' => 'JSOP_UNUSED103', 'val' => 103, 'name' => \"unused103\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        104 => ['op' => 'JSOP_UNUSED104', 'val' => 104, 'name' => \"unused104\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        105 => ['op' => 'JSOP_UNUSED105', 'val' => 105, 'name' => \"unused105\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        106 => ['op' => 'JSOP_LABEL', 'val' => 106, 'name' => \"label\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 0, 'format' => ['JOF_JUMP']],\n        107 => ['op' => 'JSOP_UNUSED107', 'val' => 107, 'name' => \"unused107\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        108 => ['op' => 'JSOP_FUNCALL', 'val' => 108, 'name' => \"funcall\", 'image' => NULL, 'len' => 3, 'use' => -1, 'def' => 1, 'format' => ['JOF_UINT16', 'JOF_INVOKE', 'JOF_TYPESET']],\n        109 => ['op' => 'JSOP_LOOPHEAD', 'val' => 109, 'name' => \"loophead\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        110 => ['op' => 'JSOP_BINDNAME', 'val' => 110, 'name' => \"bindname\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_SET']],\n        111 => ['op' => 'JSOP_SETNAME', 'val' => 111, 'name' => \"setname\", 'image' => NULL, 'len' => 5, 'use' => 2, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_SET', 'JOF_DETECTING']],\n        112 => ['op' => 'JSOP_THROW', 'val' => 112, 'name' => js_throw_str, 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 0, 'format' => ['JOF_BYTE']],\n        113 => ['op' => 'JSOP_IN', 'val' => 113, 'name' => js_in_str, 'image' => js_in_str, 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC']],\n        114 => ['op' => 'JSOP_INSTANCEOF', 'val' => 114, 'name' => js_instanceof_str, 'image' => js_instanceof_str, 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_LEFTASSOC', 'JOF_TMPSLOT']],\n        115 => ['op' => 'JSOP_DEBUGGER', 'val' => 115, 'name' => \"debugger\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        116 => ['op' => 'JSOP_GOSUB', 'val' => 116, 'name' => \"gosub\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 0, 'format' => ['JOF_JUMP']],\n        117 => ['op' => 'JSOP_RETSUB', 'val' => 117, 'name' => \"retsub\", 'image' => NULL, 'len' => 1, 'use' => 2, 'def' => 0, 'format' => ['JOF_BYTE']],\n        118 => ['op' => 'JSOP_EXCEPTION', 'val' => 118, 'name' => \"exception\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        119 => ['op' => 'JSOP_LINENO', 'val' => 119, 'name' => \"lineno\", 'image' => NULL, 'len' => 3, 'use' => 0, 'def' => 0, 'format' => ['JOF_UINT16']],\n        120 => ['op' => 'JSOP_CONDSWITCH', 'val' => 120, 'name' => \"condswitch\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        121 => ['op' => 'JSOP_CASE', 'val' => 121, 'name' => \"case\", 'image' => NULL, 'len' => 5, 'use' => 2, 'def' => 1, 'format' => ['JOF_JUMP']],\n        122 => ['op' => 'JSOP_DEFAULT', 'val' => 122, 'name' => \"default\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 0, 'format' => ['JOF_JUMP']],\n        123 => ['op' => 'JSOP_EVAL', 'val' => 123, 'name' => \"eval\", 'image' => NULL, 'len' => 3, 'use' => -1, 'def' => 1, 'format' => ['JOF_UINT16', 'JOF_INVOKE', 'JOF_TYPESET']],\n        124 => ['op' => 'JSOP_UNUSED124', 'val' => 124, 'name' => \"unused124\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        125 => ['op' => 'JSOP_UNUSED125', 'val' => 125, 'name' => \"unused125\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        126 => ['op' => 'JSOP_UNUSED126', 'val' => 126, 'name' => \"unused126\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        127 => ['op' => 'JSOP_DEFFUN', 'val' => 127, 'name' => \"deffun\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 0, 'format' => ['JOF_OBJECT']],\n        128 => ['op' => 'JSOP_DEFCONST', 'val' => 128, 'name' => \"defconst\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 0, 'format' => ['JOF_ATOM']],\n        129 => ['op' => 'JSOP_DEFVAR', 'val' => 129, 'name' => \"defvar\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 0, 'format' => ['JOF_ATOM']],\n        130 => ['op' => 'JSOP_LAMBDA', 'val' => 130, 'name' => \"lambda\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_OBJECT']],\n        131 => ['op' => 'JSOP_LAMBDA_ARROW', 'val' => 131, 'name' => \"lambda_arrow\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_OBJECT']],\n        132 => ['op' => 'JSOP_CALLEE', 'val' => 132, 'name' => \"callee\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        133 => ['op' => 'JSOP_PICK', 'val' => 133, 'name' => \"pick\", 'image' => NULL, 'len' => 2, 'use' => 0, 'def' => 0, 'format' => ['JOF_UINT8', 'JOF_TMPSLOT2']],\n        134 => ['op' => 'JSOP_TRY', 'val' => 134, 'name' => \"try\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        135 => ['op' => 'JSOP_FINALLY', 'val' => 135, 'name' => \"finally\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 2, 'format' => ['JOF_BYTE']],\n        136 => ['op' => 'JSOP_GETALIASEDVAR', 'val' => 136, 'name' => \"getaliasedvar\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_SCOPECOORD', 'JOF_NAME', 'JOF_TYPESET']],\n        137 => ['op' => 'JSOP_SETALIASEDVAR', 'val' => 137, 'name' => \"setaliasedvar\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_SCOPECOORD', 'JOF_NAME', 'JOF_SET', 'JOF_DETECTING']],\n        138 => ['op' => 'JSOP_UNUSED138', 'val' => 138, 'name' => \"unused138\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        139 => ['op' => 'JSOP_UNUSED139', 'val' => 139, 'name' => \"unused139\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        140 => ['op' => 'JSOP_UNUSED140', 'val' => 140, 'name' => \"unused140\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        141 => ['op' => 'JSOP_UNUSED141', 'val' => 141, 'name' => \"unused141\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        142 => ['op' => 'JSOP_UNUSED142', 'val' => 142, 'name' => \"unused142\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        143 => ['op' => 'JSOP_GETINTRINSIC', 'val' => 143, 'name' => \"getintrinsic\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_TYPESET']],\n        144 => ['op' => 'JSOP_SETINTRINSIC', 'val' => 144, 'name' => \"setintrinsic\", 'image' => NULL, 'len' => 5, 'use' => 2, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_SET', 'JOF_DETECTING']],\n        145 => ['op' => 'JSOP_BINDINTRINSIC', 'val' => 145, 'name' => \"bindintrinsic\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_SET']],\n        146 => ['op' => 'JSOP_UNUSED146', 'val' => 146, 'name' => \"unused146\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        147 => ['op' => 'JSOP_UNUSED147', 'val' => 147, 'name' => \"unused147\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        148 => ['op' => 'JSOP_UNUSED148', 'val' => 148, 'name' => \"unused148\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        149 => ['op' => 'JSOP_BACKPATCH', 'val' => 149, 'name' => \"backpatch\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 0, 'format' => ['JOF_JUMP']],\n        150 => ['op' => 'JSOP_UNUSED150', 'val' => 150, 'name' => \"unused150\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        151 => ['op' => 'JSOP_THROWING', 'val' => 151, 'name' => \"throwing\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 0, 'format' => ['JOF_BYTE']],\n        152 => ['op' => 'JSOP_SETRVAL', 'val' => 152, 'name' => \"setrval\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 0, 'format' => ['JOF_BYTE']],\n        153 => ['op' => 'JSOP_RETRVAL', 'val' => 153, 'name' => \"retrval\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        154 => ['op' => 'JSOP_GETGNAME', 'val' => 154, 'name' => \"getgname\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_TYPESET', 'JOF_GNAME']],\n        155 => ['op' => 'JSOP_SETGNAME', 'val' => 155, 'name' => \"setgname\", 'image' => NULL, 'len' => 5, 'use' => 2, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_SET', 'JOF_DETECTING', 'JOF_GNAME']],\n        156 => ['op' => 'JSOP_UNUSED156', 'val' => 156, 'name' => \"unused156\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        157 => ['op' => 'JSOP_UNUSED157', 'val' => 157, 'name' => \"unused157\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        158 => ['op' => 'JSOP_UNUSED158', 'val' => 158, 'name' => \"unused158\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        159 => ['op' => 'JSOP_UNUSED159', 'val' => 159, 'name' => \"unused159\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        160 => ['op' => 'JSOP_REGEXP', 'val' => 160, 'name' => \"regexp\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_REGEXP']],\n        161 => ['op' => 'JSOP_UNUSED161', 'val' => 161, 'name' => \"unused161\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        162 => ['op' => 'JSOP_UNUSED162', 'val' => 162, 'name' => \"unused162\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        163 => ['op' => 'JSOP_UNUSED163', 'val' => 163, 'name' => \"unused163\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        164 => ['op' => 'JSOP_UNUSED164', 'val' => 164, 'name' => \"unused164\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        165 => ['op' => 'JSOP_UNUSED165', 'val' => 165, 'name' => \"unused165\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        166 => ['op' => 'JSOP_UNUSED166', 'val' => 166, 'name' => \"unused166\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        167 => ['op' => 'JSOP_UNUSED167', 'val' => 167, 'name' => \"unused167\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        168 => ['op' => 'JSOP_UNUSED168', 'val' => 168, 'name' => \"unused168\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        169 => ['op' => 'JSOP_UNUSED169', 'val' => 169, 'name' => \"unused169\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        170 => ['op' => 'JSOP_UNUSED170', 'val' => 170, 'name' => \"unused170\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        171 => ['op' => 'JSOP_UNUSED171', 'val' => 171, 'name' => \"unused171\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        172 => ['op' => 'JSOP_UNUSED172', 'val' => 172, 'name' => \"unused172\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        173 => ['op' => 'JSOP_UNUSED173', 'val' => 173, 'name' => \"unused173\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        174 => ['op' => 'JSOP_UNUSED174', 'val' => 174, 'name' => \"unused174\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        175 => ['op' => 'JSOP_UNUSED175', 'val' => 175, 'name' => \"unused175\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        176 => ['op' => 'JSOP_UNUSED176', 'val' => 176, 'name' => \"unused176\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        177 => ['op' => 'JSOP_UNUSED177', 'val' => 177, 'name' => \"unused177\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        178 => ['op' => 'JSOP_UNUSED178', 'val' => 178, 'name' => \"unused178\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        179 => ['op' => 'JSOP_UNUSED179', 'val' => 179, 'name' => \"unused179\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        180 => ['op' => 'JSOP_UNUSED180', 'val' => 180, 'name' => \"unused180\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        181 => ['op' => 'JSOP_UNUSED181', 'val' => 181, 'name' => \"unused181\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        182 => ['op' => 'JSOP_UNUSED182', 'val' => 182, 'name' => \"unused182\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        183 => ['op' => 'JSOP_UNUSED183', 'val' => 183, 'name' => \"unused183\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        184 => ['op' => 'JSOP_CALLPROP', 'val' => 184, 'name' => \"callprop\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_PROP', 'JOF_TYPESET', 'JOF_TMPSLOT3']],\n        185 => ['op' => 'JSOP_UNUSED185', 'val' => 185, 'name' => \"unused185\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        186 => ['op' => 'JSOP_UNUSED186', 'val' => 186, 'name' => \"unused186\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        187 => ['op' => 'JSOP_UNUSED187', 'val' => 187, 'name' => \"unused187\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        188 => ['op' => 'JSOP_UINT24', 'val' => 188, 'name' => \"uint24\", 'image' => NULL, 'len' => 4, 'use' => 0, 'def' => 1, 'format' => ['JOF_UINT24']],\n        189 => ['op' => 'JSOP_UNUSED189', 'val' => 189, 'name' => \"unused189\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        190 => ['op' => 'JSOP_UNUSED190', 'val' => 190, 'name' => \"unused190\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        191 => ['op' => 'JSOP_UNUSED191', 'val' => 191, 'name' => \"unused191\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        192 => ['op' => 'JSOP_UNUSED192', 'val' => 192, 'name' => \"unused192\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        193 => ['op' => 'JSOP_CALLELEM', 'val' => 193, 'name' => \"callelem\", 'image' => NULL, 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_ELEM', 'JOF_TYPESET', 'JOF_LEFTASSOC']],\n        194 => ['op' => 'JSOP_MUTATEPROTO', 'val' => 194, 'name' => \"mutateproto\", 'image' => NULL, 'len' => 1, 'use' => 2, 'def' => 1, 'format' => ['JOF_BYTE']],\n        195 => ['op' => 'JSOP_GETXPROP', 'val' => 195, 'name' => \"getxprop\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_PROP', 'JOF_TYPESET']],\n        196 => ['op' => 'JSOP_UNUSED196', 'val' => 196, 'name' => \"unused196\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        197 => ['op' => 'JSOP_TYPEOFEXPR', 'val' => 197, 'name' => \"typeofexpr\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_DETECTING']],\n        198 => ['op' => 'JSOP_PUSHBLOCKSCOPE', 'val' => 198, 'name' => \"pushblockscope\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 0, 'format' => ['JOF_OBJECT']],\n        199 => ['op' => 'JSOP_POPBLOCKSCOPE', 'val' => 199, 'name' => \"popblockscope\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        200 => ['op' => 'JSOP_DEBUGLEAVEBLOCK', 'val' => 200, 'name' => \"debugleaveblock\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        201 => ['op' => 'JSOP_UNUSED201', 'val' => 201, 'name' => \"unused201\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        202 => ['op' => 'JSOP_GENERATOR', 'val' => 202, 'name' => \"generator\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        203 => ['op' => 'JSOP_YIELD', 'val' => 203, 'name' => \"yield\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE']],\n        204 => ['op' => 'JSOP_ARRAYPUSH', 'val' => 204, 'name' => \"arraypush\", 'image' => NULL, 'len' => 1, 'use' => 2, 'def' => 0, 'format' => ['JOF_BYTE']],\n        205 => ['op' => 'JSOP_UNUSED205', 'val' => 205, 'name' => \"unused205\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        206 => ['op' => 'JSOP_UNUSED206', 'val' => 206, 'name' => \"unused206\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        207 => ['op' => 'JSOP_UNUSED207', 'val' => 207, 'name' => \"unused207\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        208 => ['op' => 'JSOP_UNUSED208', 'val' => 208, 'name' => \"unused208\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        209 => ['op' => 'JSOP_UNUSED209', 'val' => 209, 'name' => \"unused209\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        210 => ['op' => 'JSOP_UNUSED210', 'val' => 210, 'name' => \"unused210\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        211 => ['op' => 'JSOP_UNUSED211', 'val' => 211, 'name' => \"unused211\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        212 => ['op' => 'JSOP_UNUSED212', 'val' => 212, 'name' => \"unused212\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        213 => ['op' => 'JSOP_UNUSED213', 'val' => 213, 'name' => \"unused213\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        214 => ['op' => 'JSOP_BINDGNAME', 'val' => 214, 'name' => \"bindgname\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_NAME', 'JOF_SET', 'JOF_GNAME']],\n        215 => ['op' => 'JSOP_INT8', 'val' => 215, 'name' => \"int8\", 'image' => NULL, 'len' => 2, 'use' => 0, 'def' => 1, 'format' => ['JOF_INT8']],\n        216 => ['op' => 'JSOP_INT32', 'val' => 216, 'name' => \"int32\", 'image' => NULL, 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_INT32']],\n        217 => ['op' => 'JSOP_LENGTH', 'val' => 217, 'name' => \"length\", 'image' => NULL, 'len' => 5, 'use' => 1, 'def' => 1, 'format' => ['JOF_ATOM', 'JOF_PROP', 'JOF_TYPESET', 'JOF_TMPSLOT3']],\n        218 => ['op' => 'JSOP_HOLE', 'val' => 218, 'name' => \"hole\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE']],\n        219 => ['op' => 'JSOP_UNUSED219', 'val' => 219, 'name' => \"unused219\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        220 => ['op' => 'JSOP_UNUSED220', 'val' => 220, 'name' => \"unused220\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        221 => ['op' => 'JSOP_UNUSED221', 'val' => 221, 'name' => \"unused221\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        222 => ['op' => 'JSOP_UNUSED222', 'val' => 222, 'name' => \"unused222\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        223 => ['op' => 'JSOP_UNUSED223', 'val' => 223, 'name' => \"unused223\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 0, 'format' => ['JOF_BYTE']],\n        224 => ['op' => 'JSOP_REST', 'val' => 224, 'name' => \"rest\", 'image' => NULL, 'len' => 1, 'use' => 0, 'def' => 1, 'format' => ['JOF_BYTE', 'JOF_TYPESET']],\n        225 => ['op' => 'JSOP_TOID', 'val' => 225, 'name' => \"toid\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE']],\n        226 => ['op' => 'JSOP_IMPLICITTHIS', 'val' => 226, 'name' => \"implicitthis\", 'image' => \"\", 'len' => 5, 'use' => 0, 'def' => 1, 'format' => ['JOF_ATOM']],\n        227 => ['op' => 'JSOP_LOOPENTRY', 'val' => 227, 'name' => \"loopentry\", 'image' => NULL, 'len' => 2, 'use' => 0, 'def' => 0, 'format' => ['JOF_UINT8']],\n        228 => ['op' => 'JSOP_TOSTRING', 'val' => 228, 'name' => \"tostring\", 'image' => NULL, 'len' => 1, 'use' => 1, 'def' => 1, 'format' => ['JOF_BYTE']],\n    ];\n}\n"
  },
  {
    "path": "src/Context.php",
    "content": "<?php\n\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/1\n * Time: 下午3:25\n */\nnamespace Irelance\\Mozjs34;\n\nuse Irelance\\Mozjs34\\Helper\\Operation;\nuse Irelance\\Mozjs34\\Helper\\Reveal;\nuse Irelance\\Mozjs34\\Helper\\Stack;\n\nclass Context\n{\n    use Reveal;\n    use Operation;\n\n    public $index = null;\n    public $decompile = null;\n    protected $isDebug = false;\n\n    protected $content = '';\n    protected $stack = [];\n\n    protected $argvs = [];\n    protected $summaries = [];\n    protected $operations = [];\n    protected $nodes = [];\n    protected $atoms = [];\n    protected $consts = [];\n    protected $objects = [];\n    protected $regexps = [];\n    protected $tryNotes = [];\n    protected $scopeNotes = [];\n    protected $hasLazyScript;\n\n    public function addArgv($value)\n    {\n        $this->argvs[] = $value;\n    }\n\n    public function addSummary($key, $value)\n    {\n        if (isset($this->summaries[$key])) {\n            return false;\n        }\n        $this->summaries[$key] = $value;\n        return true;\n    }\n\n    public function addOperation($parserIndex, array $operation)\n    {\n        $this->operations[$parserIndex] = $operation;\n    }\n\n    public function addNode($node)\n    {\n        $this->nodes[] = $node;\n    }\n\n    public function addAtom($atom)\n    {\n        $this->atoms[] = $atom;\n    }\n\n    public function addConst($const)\n    {\n        $this->consts[] = $const;\n    }\n\n    public function addObject($classKind, array $extra)\n    {\n        $this->objects[] = array_merge($extra, ['classKind' => $classKind]);\n    }\n\n    public function addRegexp($source, $flagsword)\n    {\n        $this->regexps[] = [\n            'source' => $source,\n            'flagsword' => $flagsword,\n        ];\n    }\n\n    public function addTryNote($kind, $stackDepth, $start, $length)\n    {\n        $this->tryNotes[] = ['kind' => $kind, 'stackDepth' => $stackDepth, 'start' => $start, 'length' => $length];\n    }\n\n    public function addScopeNote($index, $start, $length, $parent)\n    {\n        $this->scopeNotes[$index] = ['parent' => $parent, 'start' => $start, 'length' => $length];\n    }\n\n    public function addHasLazyScript($packedFields)\n    {\n        $this->hasLazyScript = $packedFields;\n    }\n\n    public function getSummary($key)\n    {\n        return $this->summaries[$key];\n    }\n\n    /**\n     * @param $stack Stack|array\n     */\n    public function pushStack($stack)\n    {\n        if (is_array($stack)) {\n            $stack = new Stack($stack);\n        }\n        array_push($this->stack, $stack);\n    }\n\n    /**\n     * @return Stack\n     */\n    public function popStack()\n    {\n        return array_pop($this->stack);\n    }\n\n    protected $storageScript = [];\n\n    public function writeScript($parserIndex, $string, $offset = 0)\n    {\n        $this->storageScript[$parserIndex * 2 + $offset] = ['value' => $string];\n    }\n\n    public function appendScript($parserIndex, $string, $offset = 0)\n    {\n        if (!isset($this->storageScript[$parserIndex * 2 + $offset])) {\n            $this->writeScript($parserIndex, $string, $offset);\n            return;\n        }\n        $this->storageScript[$parserIndex * 2 + $offset]['value'] .= $string;\n    }\n\n    public function getScript($parserIndex, $offset = 0)\n    {\n        if (!isset($this->storageScript[$parserIndex * 2 + $offset])) {\n            return ['value' => ''];\n        }\n        return $this->storageScript[$parserIndex * 2 + $offset];\n    }\n\n    public function dropScript($parserIndex, $offset = 0)\n    {\n        if (isset($this->storageScript[$parserIndex * 2 + $offset])) {\n            unset($this->storageScript[$parserIndex * 2 + $offset]);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Decompile.php",
    "content": "<?php\n\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/9/20\n * Time: 上午8:04\n *\n * js/src/jsscript.h\n * js/src/vm/Xdr.h\n */\n\nnamespace Irelance\\Mozjs34;\n\nuse Irelance\\Mozjs34\\Helper\\Stack;\n\nclass Decompile\n{\n    use Xdr\\Common;\n    use Xdr\\Script;\n    use Xdr\\Atom;\n    use Xdr\\ObjectXdr;\n    use Xdr\\Scope;\n    use Xdr\\Operation;\n\n    public $isDebug = false;\n    private $fp;\n    protected $parseIndex = 0;\n\n    protected $buildId = '';\n    protected $contexts = [];\n\n    public $bytecodes = [];\n    public $bytecodeLength = 0;\n\n    public function __construct($filename)\n    {\n        $this->fp = fopen($filename, 'rb');\n        $this->init();\n    }\n\n    public function __destruct()\n    {\n        fclose($this->fp);\n    }\n\n    public function init()\n    {\n        $i = 0;\n        while (!feof($this->fp)) {\n            $c = fgetc($this->fp);\n            $this->bytecodes[$i] = ord($c);\n            $i++;\n        }\n        $this->bytecodeLength = count($this->bytecodes);\n    }\n\n    protected function parserVersion()\n    {\n        $this->parseIndex = 0;\n        $bytecodeVer = $this->todec();\n        return $bytecodeVer;\n    }\n\n    public function run()\n    {\n        $this->parserVersion();\n        $this->XDRScript();\n    }\n\n    public function runResult()\n    {\n        echo '----------------ByteCode---------------', CLIENT_EOL;\n        echo 'file size :', $this->bytecodeLength, CLIENT_EOL;\n        echo 'parse size :', 1 + $this->parseIndex, CLIENT_EOL;\n        echo '---------------------------------------', CLIENT_EOL;\n    }\n\n    public function getContexts()\n    {\n        return $this->contexts;\n    }\n\n    protected $localVariable = [];\n\n    public function setLocalVariable($index, $value)\n    {\n        $this->localVariable[$index] = $value;\n    }\n\n    public function getLocalVariable($index)\n    {\n        if (!isset($this->localVariable[$index])) {\n            return new Stack(['parserIndex' => 0, 'type' => 'undefined', 'value' => 'undefined']);\n        }\n        return $this->localVariable[$index];\n    }\n\n    protected $aliasedVariable = [];\n\n    public function setAliasedVariable($hops, $slot, $value)\n    {\n        if (!isset($this->aliasedVariable[$hops])) {\n            $this->aliasedVariable[$hops] = [];\n        }\n        $this->aliasedVariable[$hops][$slot] = $value;\n    }\n\n    public function getAliasedVariable($hops, $slot)\n    {\n        if (!isset($this->aliasedVariable[$hops][$slot])) {\n            return new Stack(['parserIndex' => 0, 'type' => 'undefined', 'value' => 'undefined']);\n        }\n        return $this->aliasedVariable[$hops][$slot];\n    }\n\n    protected $globalVariable = [];\n\n    public function setGlobalVariable($key, $value)\n    {\n        $this->globalVariable[$key] = $value;\n    }\n\n    public function getGlobalVariable($key)\n    {\n        if (!isset($this->localVariable[$key])) {\n            return new Stack(['parserIndex' => 0, 'type' => 'undefined', 'name' => $key, 'value' => $key]);\n        }\n        return $this->globalVariable[$key];\n    }\n}\n"
  },
  {
    "path": "src/Helper/Operation.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/11\n * Time: 上午11:06\n */\n\nnamespace Irelance\\Mozjs34\\Helper;\n\n\nuse Irelance\\Mozjs34\\Constant;\n\n/**\n * @method Stack popStack()\n */\ntrait Operation\n{\n    protected $logicStacks = [];\n\n    protected function gotoNextOperation($nextOperation)\n    {\n        while (isset($nextOperation['params']['offset'])) {\n            $goto = $nextOperation['parserIndex'] + $nextOperation['params']['offset'];\n            if (!isset($this->operations[$goto])) {\n                return false;\n            }\n            $nextOperation = $this->operations[$goto];\n        }\n        return $nextOperation;\n    }\n\n    public function getNextOperation($operation)\n    {\n        $nextIndex = $operation['parserIndex'] + $operation['length'];\n        if (!isset($this->operations[$nextIndex])) {\n            return false;\n        }\n        return $this->operations[$nextIndex];\n    }\n\n    public function revealOperations($start, $end, $conditons = [], $isCover = true)\n    {\n        $operationKeys = array_keys($this->operations);\n        $operationKeysFlip = array_flip($operationKeys);\n        $start = $operationKeysFlip[$start];\n        $end = $operationKeysFlip[$end];\n        for ($i = $start; $i < $end; $i++) {\n            $operation = $this->operations[$operationKeys[$i]];\n            if (!$operation['isCover']) {\n                if ($this->isDebug) {\n                    echo '[', $operationKeys[$i], ']', $operation['name'], json_encode($operation['params']), ' pop: ', $operation['pop'], ' push: ', $operation['push'], ' byte: ', $operation['length'], CLIENT_EOL;\n                }\n                $this->revealOperation($operation, $conditons);\n                $this->operations[$operationKeys[$i]]['isCover'] = $isCover;\n            }\n        }\n    }\n\n    protected function hasOperation($start, $end, $name)\n    {\n        $operationKeys = array_keys($this->operations);\n        $operationKeysFlip = array_flip($operationKeys);\n        $start = $operationKeysFlip[$start];\n        $end = $operationKeysFlip[$end];\n        for ($i = $start + 1; $i < $end; $i++) {\n            $operation = $this->operations[$operationKeys[$i]];\n            if ($operation['name'] == $name) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    protected function findFirstOperation($name, $start = null, $end = null)\n    {\n        if (is_string($name)) {\n            $name = [$name];\n        }\n        $operationKeys = array_keys($this->operations);\n        $operationKeysFlip = array_flip($operationKeys);\n        $start = is_null($start) ? 0 : $operationKeysFlip[$start];\n        $end = is_null($end) ? count($operationKeys) : $operationKeysFlip[$end];\n        for ($i = $start; $i < $end; $i++) {\n            $operation = $this->operations[$operationKeys[$i]];\n            if (in_array($operation['name'], $name)) {\n                return $operation;\n            }\n        }\n        return false;\n    }\n\n    public function revealOperation($operation, $conditons = [])\n    {\n        switch ($operation['name']) {\n            case 'JSOP_RETRVAL':\n            case 'JSOP_ENDINIT':\n            case 'JSOP_NOP':\n                break;\n            case 'JSOP_RETURN':\n                $value = $this->getLogicValue($operation, $this->popStack());\n                $this->writeScript($operation['parserIndex'], 'return ' . $value . ';');\n                break;\n            //change stack\n            case 'JSOP_POP':\n            case 'JSOP_SETRVAL':\n                $rVal = $this->popStack();\n                if ($rVal && $script = $rVal->getScript()) {\n                    $this->writeScript($operation['parserIndex'], $script . ';');\n                }\n                break;\n            case 'JSOP_POPN':\n                $n = $operation['params']['n'];\n                for ($i = 0; $i < $n; $i++) {\n                    $this->popStack();\n                }\n                break;\n            case 'JSOP_DUP':\n                $val = $this->popStack();\n                $this->pushStack($val);\n                $this->pushStack($val);\n                break;\n            case 'JSOP_DUP2':\n                $val1 = $this->popStack();\n                $val2 = $this->popStack();\n                $this->pushStack($val2);\n                $this->pushStack($val1);\n                $this->pushStack($val2);\n                $this->pushStack($val1);\n                break;\n            case 'JSOP_DUPAT':\n                $number = $operation['params']['n'];\n                $temp = [];\n                for ($i = 0; $i < $number; $i++) {\n                    $temp[$i] = $this->popStack();\n                }\n                for ($i = $number - 1; $i >= 0; $i--) {\n                    $this->pushStack($temp[$i]);\n                }\n                $this->pushStack($temp[$number - 1]);\n                break;\n            case 'JSOP_PICK':\n                $number = $operation['params']['n'];\n                $temp = [];\n                for ($i = 0; $i < $number; $i++) {\n                    $temp[$i] = $this->popStack();\n                }\n                $nTh = $this->popStack();\n                for ($i = $number - 1; $i >= 0; $i--) {\n                    $this->pushStack($temp[$i]);\n                }\n                $this->pushStack($nTh);\n                break;\n            case 'JSOP_SWAP':// v1, v2 => v2, v1\n                $val1 = $this->popStack();\n                $val2 = $this->popStack();\n                $this->pushStack($val1);\n                $this->pushStack($val2);\n                break;\n            //control goto\n            case 'JSOP_GOTO':\n                if (!empty($conditons)) {\n                    if (isset($conditons['type']) && $conditons['type'] == 'switch') {\n                        $gotoIndex = $operation['parserIndex'] + $operation['params']['offset'];\n                        if ($gotoIndex >= $conditons['defaultIndex']) {\n                            $this->writeScript($operation['parserIndex'], 'break;');\n                            $this->writeScript($gotoIndex, '}', +1);\n                            return;\n                        }\n                    }\n                }\n                $this->_getBranchContinue($operation) || $this->_getBranchBreak($operation);\n                break;\n            //control branch\n            case 'JSOP_IFEQ':\n                $value = $this->getLogicValue($operation, $this->popStack());\n                //storage stack for k=x?a:b\n                $stackCopy = serialize($this->stack);\n                $this->appendScript($operation['parserIndex'], 'if(' . $value . '){');\n                if ($operation['params']['offset'] > 0) {\n                    $elseStart = $this->gotoNextOperation($operation);\n                    $this->revealOperations($operation['parserIndex'] + $operation['length'], $elseStart['parserIndex']);\n                    $gotoOperation = $this->_getBranchGoto($operation);\n                    while ($this->_getBranchContinue($gotoOperation) || $this->_getBranchBreak($gotoOperation)) {\n                        $gotoOperation = $this->findFirstOperation('JSOP_GOTO', $gotoOperation['parserIndex'] + $gotoOperation['length']);\n                        if (!$gotoOperation) {\n                            break;\n                        }\n                    }\n                    $hasNextOperation = false;\n                    $nextOperationIndex = false;\n                    if ($gotoOperation) {\n                        $hasNextOperation = $gotoOperation['name'];\n                        $nextOperationIndex = $gotoOperation['parserIndex'];\n                        if ($elseIfOperation = $this->findFirstOperation(\n                            'JSOP_IFEQ',\n                            $gotoOperation['parserIndex'],\n                            $gotoOperation['parserIndex'] + $gotoOperation['params']['offset']\n                        )\n                        ) {\n                            $hasNextOperation = $elseIfOperation['name'];\n                            $nextOperationIndex = $elseIfOperation['parserIndex'];\n                        }\n                    }\n                    switch ($hasNextOperation) {\n                        case 'JSOP_IFEQ':\n                            $this->writeScript($nextOperationIndex, '} else ');\n                            break;\n                        case 'JSOP_GOTO':\n                            $this->writeScript($nextOperationIndex, '} else {');\n                        default:\n                            $this->appendScript($operation['parserIndex'] + $operation['params']['offset'], '}', +1);\n                            break;\n                    }\n                    $oldCount = count(unserialize($stackCopy));\n                    $newCount = count($this->stack);\n                    if ($oldCount != $newCount) {\n                        if (($newCount - $oldCount) != 1) {\n                            exit(\"[error] JSOP_IFEQ Unknown Type\");\n                        }\n                        $this->dropScript($nextOperationIndex);\n                        $this->dropScript($operation['parserIndex']);\n                        $this->dropScript($operation['parserIndex'] + $operation['params']['offset'], +1);\n                        if (!$gotoOperation) {\n                            exit(\"[error] JSOP_IFEQ No Goto \");\n                        }\n                        $setIndex = $gotoOperation['parserIndex'] + $gotoOperation['params']['offset'];\n                        $setOperation = $this->operations[$setIndex];\n                        switch ($setOperation['name']) {\n                            case 'JSOP_SETELEM':\n                            case 'JSOP_SETNAME':\n                            case 'JSOP_SETCONST':\n                            case 'JSOP_SETPROP':\n                            case 'JSOP_INITPROP':\n                                $endOperation = $this->getNextOperation($setOperation);\n                                break;\n                            default://todo find all ending operation\n                                $endOperation = $this->findFirstOperation(\n                                    ['JSOP_SETRVAL', 'JSOP_GOTO', 'JSOP_POP', 'JSOP_RETURN', 'JSOP_IFEQ', 'JSOP_IFNE',\n                                    ],\n                                    $setIndex\n                                );\n                                break;\n                        }\n                        if (!$endOperation) {\n                            exit(\"[error] JSOP_IFEQ Unknown endOperation \" . $operation['parserIndex']);\n                        }\n                        $this->revealOperations($setIndex, $endOperation['parserIndex'], [], false);\n                        $left = $this->popStack();\n                        $this->stack = unserialize($stackCopy);\n                        $this->revealOperations($gotoOperation['parserIndex'] + 5, $endOperation['parserIndex']);\n                        $right = $this->popStack();\n                        $this->pushStack(['type' => 'script', 'script' => $value . '?' . $left->getScript() . ':' . $right->getScript()]);\n                        return;\n                    }\n                }\n                break;\n            case 'JSOP_TABLESWITCH':\n                //case type is int\n                $val = $this->popStack();\n                $this->writeScript($operation['parserIndex'], 'switch(' . $val->getValue() . '){');\n                $caseCurrent = $operation['params']['low'];\n                $contents = [];\n                foreach ($operation['params']['offset'] as $offset) {\n                    if ($offset) {\n                        $contentIndex = $operation['parserIndex'] + $offset;\n                        if (!isset($contents[$contentIndex])) {\n                            $contents[$contentIndex] = [];\n                        }\n                        $contents[$contentIndex][] = ['value' => 'case ' . $caseCurrent . ':'];\n                    }\n                    $caseCurrent++;\n                }\n                $defaultIndex = $operation['parserIndex'] + $operation['params']['len'];\n                $this->_renderSwitch($contents, $defaultIndex);\n                break;\n            //control branch switch case type is mix\n            case 'JSOP_CONDSWITCH':\n                $name = $this->popStack();\n                $this->writeScript($operation['parserIndex'], 'switch(' . $name->getValue() . '){');\n                $this->pushStack(['type' => 'switch', 'value' => []]);\n                break;\n            case 'JSOP_CASE':\n                $val = $this->popStack();\n                $switch = $this->popStack();\n                $contentIndex = $operation['parserIndex'] + $operation['params']['offset'];\n                if (!isset($switch->value[$contentIndex])) {\n                    $switch->value[$contentIndex] = [];\n                }\n                $switch->value[$contentIndex][] = ['value' => 'case ' . $val->getValue() . ':'];\n                $this->pushStack($switch);\n                break;\n            case 'JSOP_DEFAULT':\n                $switch = $this->popStack();\n                $this->_renderSwitch($switch->value, $operation['parserIndex'] + $operation['params']['offset']);\n                break;\n            //control loop\n            case 'JSOP_IFNE':\n                $value = $this->getLogicValue($operation, $this->popStack());\n                $this->writeScript($operation['parserIndex'], 'if(' . $value . ')');\n                break;\n            case 'JSOP_LOOPHEAD':\n                $gotoOperation = $this->_getLoopGoto($operation);\n                $isDo = !$gotoOperation;\n                if ($isDo) {\n                    $this->writeScript($operation['parserIndex'], 'do{', -1);\n                    $entryOperation = $this->operations[$operation['parserIndex'] + $operation['length']];\n                    $ifOperation = $entryOperation;\n                    do {\n                        $ifOperation = $this->_getLoopLogic($ifOperation);\n                    } while ($this->operations[$ifOperation['parserIndex'] + $ifOperation['params']['offset']]['parserIndex'] != $operation['parserIndex']);\n                } else {\n                    $entryOperation = $this->operations[$gotoOperation['parserIndex'] + $gotoOperation['params']['offset']];\n                    $ifOperation = $this->_getLoopLogic($entryOperation);\n                }\n                $this->revealOperations($entryOperation['parserIndex'], $ifOperation['parserIndex'] + $ifOperation['length']);\n                $this->revealOperations($operation['parserIndex'] + $operation['length'], $entryOperation['parserIndex']);\n                if ($isDo) {\n                    $this->writeScript(\n                        $ifOperation['parserIndex'],\n                        str_replace('if(', '} while(', $this->getScript($ifOperation['parserIndex'])['value'])\n                    );\n                } else {\n                    $this->writeScript(\n                        $operation['parserIndex'],\n                        str_replace('if(', 'while(', $this->getScript($ifOperation['parserIndex'])['value']) . '{',\n                        -1\n                    );\n                    $this->writeScript($ifOperation['parserIndex'], '}');\n                }\n                break;\n            case 'JSOP_LOOPENTRY':\n                break;\n            //For-In Statement\n            case 'JSOP_ITER':\n                $val = $this->popStack();\n                $this->pushStack($val);\n                break;\n            case 'JSOP_ITERNEXT':\n                $this->pushStack(['type' => 'script', 'name' => '_iternext']);\n                break;\n            case 'JSOP_MOREITER':\n                $val = $this->popStack();\n                $this->pushStack([]);\n                $this->pushStack(['type' => 'script', 'script' => $val->getValue() . ' has _iternext']);\n                break;\n            case 'JSOP_ENDITER':\n                $val = $this->popStack();\n                break;\n            //math\n            case 'JSOP_BITNOT':\n            case 'JSOP_NEG':\n                $value = $this->getLogicValue($operation, $this->popStack());\n                $this->pushStack(['script' => '(' . $operation['image'] . $value . ')', 'type' => 'script']);\n                break;\n            case 'JSOP_POS':\n                break;\n            //math\n            case 'JSOP_ADD':\n            case 'JSOP_SUB':\n            case 'JSOP_MUL':\n            case 'JSOP_DIV':\n            case 'JSOP_MOD':\n            case 'JSOP_BITOR':\n            case 'JSOP_BITXOR':\n            case 'JSOP_BITAND':\n            case 'JSOP_RSH':\n            case 'JSOP_LSH':\n            case 'JSOP_URSH':\n                //logic\n            case 'JSOP_EQ':\n            case 'JSOP_NE':\n            case 'JSOP_LT':\n            case 'JSOP_LE':\n            case 'JSOP_GT':\n            case 'JSOP_GE':\n            case 'JSOP_STRICTEQ':\n            case 'JSOP_STRICTNE':\n            case 'JSOP_IN':\n                $right = $this->popStack();\n                $rVal = $right->getValue();\n                $left = $this->popStack();\n                $lVal = $left->getValue();\n                if ($left->type == 'logic') {\n                    $lVal = $this->_combineLogicByParserIndex($left->operation['parserIndex']);\n                }\n                if ($right->type == 'logic') {\n                    $rVal = $this->_combineLogicByParserIndex($right->operation['parserIndex']);\n                }\n                $this->pushStack(['script' => '(' . $lVal . ' ' . $operation['image'] . ' ' . $rVal . ')', 'type' => 'script']);\n                break;\n            case 'JSOP_OR':\n                $script = $this->popStack();\n                $gotoIndex = $operation['parserIndex'] + $operation['params']['offset'];\n                $this->logicStacks[$operation['parserIndex']] = ['type' => 'or', 'goto' => $gotoIndex, 'value' => $script->getValue()];\n                $this->pushStack(['type' => 'logic', 'operation' => $operation]);\n                break;\n            case 'JSOP_AND':\n                $script = $this->popStack();\n                $gotoIndex = $operation['parserIndex'] + $operation['params']['offset'];\n                $this->logicStacks[$operation['parserIndex']] = ['type' => 'and', 'goto' => $gotoIndex, 'value' => $script->getValue()];\n                $this->pushStack(['type' => 'logic', 'operation' => $operation]);\n                break;\n            case 'JSOP_NOT':\n                $script = $this->popStack();\n                $this->logicStacks[$operation['parserIndex']] = ['type' => 'not', 'value' => $script->getValue()];\n                $this->pushStack(['type' => 'logic', 'operation' => $operation]);\n                break;\n            //typeof\n            case 'JSOP_TYPEOF':\n            case 'JSOP_TYPEOFEXPR':\n                $name = $this->popStack();\n                $this->pushStack(['script' => 'typeof ' . $name->getValue(), 'type' => 'script']);\n                break;\n            //instanceof\n            case 'JSOP_INSTANCEOF':\n                $rVal = $this->popStack();\n                $lVal = $this->popStack();\n                $this->pushStack(['script' => $lVal->getValue() . ' instanceof ' . $rVal->getValue(), 'type' => 'script']);\n                break;\n            //Function\n            case 'JSOP_NEW':\n            case 'JSOP_FUNAPPLY'://apply\n            case 'JSOP_FUNCALL'://call\n            case 'JSOP_EVAL'://eval\n            case 'JSOP_CALL':\n                $_argc = $operation['params']['argc'];\n                $_argv = [];\n                for ($i = 0; $i < $_argc; $i++) {\n                    $_argv[] = $this->popStack();\n                }\n                $_this = $this->popStack();\n                $_callee = $this->popStack();\n                $write = '';\n                if (!empty($this->logicStacks)) {\n                    $write .= $this->_combineLogicByGotoIndex($operation['parserIndex'] + $operation['length']);\n                }\n                if ($operation['name'] == 'JSOP_NEW') {\n                    $write = 'new ';\n                }\n                $write .= $_callee->name ? $_callee->name : ('(' . $_callee->getScript() . ')');\n                $write .= '(';\n                if ($_argc) {\n                    for ($i = $_argc - 1; $i >= 0; $i--) {\n                        //$argv = $_argv[$i]->getScript() ? $_argv[$i]->getScript() : $_argv[$i]->name;//todo\n                        $argv = $_argv[$i]->getValue();\n                        $write .= $argv . ',';\n                    }\n                    $write = substr($write, 0, strlen($write) - 1);\n                }\n                $write .= ')';\n                $this->pushStack(['type' => 'script', 'script' => $write]);\n                break;\n            //Object\n            case 'JSOP_NEWINIT':\n                $this->pushStack(['value' => [], 'type' => 'object']);\n                break;\n            case 'JSOP_INITPROP':\n                $name = $this->atoms[$operation['params']['nameIndex']];\n                $val = $this->popStack();\n                $array = $this->popStack();\n                $array->value[$name] = $val;\n                $this->pushStack($array);\n                break;\n            case 'JSOP_DELPROP':\n                $obj = $this->popStack();\n                $this->pushStack(['type' => 'script', 'script' => 'delete ' . $obj->getValue() . '.' . $this->atoms[$operation['params']['nameIndex']]]);\n                break;\n            case 'JSOP_SETPROP':\n                $value = $this->getLogicValue($operation, $this->popStack());\n                $name = $this->popStack();\n                $this->pushStack(['type' => 'script', 'script' => $name->getValue() . '.' . $this->atoms[$operation['params']['nameIndex']] . '=' . $value]);\n                break;\n            case 'JSOP_GETPROP':\n            case 'JSOP_CALLPROP':\n                $obj = $this->popStack();\n                $this->pushStack(['name' => $obj->getValue() . '.' . $this->atoms[$operation['params']['nameIndex']]]);\n                break;\n            case 'JSOP_INITELEM':\n            case 'JSOP_INITELEM_INC':\n                $val = $this->popStack();\n                $name = $this->popStack();\n                $array = $this->popStack();\n                $array->value[$name->getValue()] = $val;\n                $this->pushStack($array);\n                break;\n            case 'JSOP_DELELEM':\n                $propval = $this->popStack();\n                $obj = $this->popStack();\n                $this->pushStack(['type' => 'script', 'script' => 'delete ' . $obj->getValue() . '[' . $propval->getValue() . ']']);\n                break;\n            case 'JSOP_SETELEM':\n                $value = $this->getLogicValue($operation, $this->popStack());\n                $propval = $this->popStack();\n                $obj = $this->popStack();\n                $this->pushStack(['type' => 'script', 'script' => $obj->getValue() . '[' . $propval->getValue() . ']=' . $value]);\n                break;\n            case 'JSOP_GETELEM':\n            case 'JSOP_CALLELEM':\n                $propval = $this->popStack();\n                $obj = $this->popStack();\n                $this->pushStack(['name' => $obj->getValue() . '[' . $propval->getValue() . ']']);\n                break;\n            //Array\n            case 'JSOP_NEWARRAY':\n                $this->pushStack(['value' => [], 'type' => 'array']);\n                break;\n            case 'JSOP_INITELEM_ARRAY':\n                $val = $this->popStack();\n                $array = $this->popStack();\n                $array->value[] = $val;\n                $this->pushStack($array);\n                break;\n            case 'JSOP_LENGTH':\n                $name = $this->popStack();\n                $this->pushStack(['type' => 'script', 'script' => $name->getValue() . '.length']);\n                break;\n            //压入变量\n            case 'JSOP_NAME':\n            case 'JSOP_BINDNAME':\n            case 'JSOP_IMPLICITTHIS':\n                $this->pushStack(['name' => $this->atoms[$operation['params']['nameIndex']]]);\n                break;\n            //定义变量\n            case 'JSOP_DEFVAR':\n                $this->writeScript($operation['parserIndex'], 'var ' . $this->atoms[$operation['params']['nameIndex']] . ';');\n                break;\n            case 'JSOP_DEFCONST':\n                $this->writeScript($operation['parserIndex'], 'const ' . $this->atoms[$operation['params']['nameIndex']] . ';');\n                break;\n            case 'JSOP_DEFFUN':\n                $object = $this->objects[$operation['params']['funcIndex']];\n                $this->writeScript($operation['parserIndex'], 'function ' . $object['name'] . '( __ARGV_' . $object['contextIndex'] . '__ ){ __FUNC_' . $object['contextIndex'] . '__ }');\n                break;\n            //定义常量 ['isJson'=>false,'value'=>'xxxx']\n            case 'JSOP_TRUE':\n                $this->pushStack(['value' => 'true', 'type' => 'boolean']);\n                break;\n            case 'JSOP_FALSE':\n                $this->pushStack(['value' => 'false', 'type' => 'boolean']);\n                break;\n            case 'JSOP_NULL':\n                $this->pushStack(['value' => 'null', 'type' => 'null']);\n                break;\n            case 'JSOP_VOID':\n                $val = $this->popStack();\n            case 'JSOP_UNDEFINED':\n                $this->pushStack(['value' => 'undefined', 'type' => 'undefined']);\n                break;\n            case 'JSOP_ZERO':\n                $this->pushStack(['value' => 0, 'type' => 'number']);\n                break;\n            case 'JSOP_ONE':\n                $this->pushStack(['value' => 1, 'type' => 'number']);\n                break;\n            case 'JSOP_INT8':\n            case 'JSOP_UINT16':\n            case 'JSOP_UINT24':\n            case 'JSOP_INT32':\n                $this->pushStack(['value' => $operation['params']['val'], 'type' => 'number']);\n                break;\n            case 'JSOP_DOUBLE':\n                $this->pushStack(['value' => $this->consts[$operation['params']['constIndex']]['value'], 'type' => 'number']);\n                break;\n            case 'JSOP_STRING':\n                $this->pushStack(['value' => $this->atoms[$operation['params']['atomIndex']], 'type' => 'string']);\n                break;\n            case 'JSOP_REGEXP':\n                $this->pushStack(['value' => '/' . $this->regexps[$operation['params']['regexpIndex']]['source'] . '/', 'type' => 'regexp']);\n                break;\n            case 'JSOP_OBJECT'://todo\n                $object = $this->objects[$operation['params']['objectIndex']];\n                $value = [];\n                foreach ($object['initialized'] as $k => $v) {\n                    $type = 'undefined';\n                    switch ($v['type']) {\n                        case 'SCRIPT_INT':\n                        case 'SCRIPT_DOUBLE':\n                            $type = 'number';\n                            break;\n                        case 'SCRIPT_ATOM':\n                            $type = 'string';\n                            break;\n                        case 'SCRIPT_TRUE':\n                        case 'SCRIPT_FALSE':\n                            $type = 'boolean';\n                            break;\n                        case 'SCRIPT_NULL':\n                            $type = 'null';\n                            break;\n                        case 'SCRIPT_OBJECT'://todo maybe function\n                            $type = 'object';\n                            break;\n                        //case 'SCRIPT_VOID':\n                        //case 'SCRIPT_HOLE':\n                    }\n                    $value[$k] = new Stack(['value' => $v['value'], 'type' => $type]);\n                }\n                $this->pushStack(['value' => $value, 'type' => 1 == $object['isArray'] ? 'array' : 'object']);\n                break;\n            case 'JSOP_LAMBDA_ARROW':\n                $_this = $this->popStack();\n                $object = $this->objects[$operation['params']['funcIndex']];\n                $this->pushStack(['value' => $object['contextIndex'], 'type' => 'function']);\n                break;\n            case 'JSOP_LAMBDA':\n                $object = $this->objects[$operation['params']['funcIndex']];\n                $this->pushStack(['value' => $object['contextIndex'], 'type' => 'function']);\n                break;\n            //赋值\n            case 'JSOP_SETNAME':\n                $value = $this->getLogicValue($operation, $this->popStack());\n                $name = $this->popStack();\n                $name->value = $value;\n                $name->script = $name->getValue() . ' = ' . $value;\n                $name->type = 'script';\n                $this->pushStack($name);\n                break;\n            case 'JSOP_SETCONST':\n                $value = $this->getLogicValue($operation, $this->popStack());\n                $name = $this->atoms[$operation['params']['nameIndex']];\n                $this->pushStack([\n                    'type' => 'script',\n                    'name' => $name->value,\n                    'value' => $value,\n                    'script' => $name->value . ' = ' . $value,\n                ]);\n                break;\n            //delete\n            case 'JSOP_DELNAME':\n                $this->pushStack(['type' => 'script', 'script' => 'delete ' . $this->atoms[$operation['params']['nameIndex']]]);\n                break;\n            //todo list\n            //Other\n            case 'JSOP_TOSTRING':\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_LINENO':\n                break;\n            //With Statement\n            case 'JSOP_ENTERWITH':\n                $val = $this->popStack();\n                break;\n            case 'JSOP_LEAVEWITH':\n                break;\n            //Arguments\n            case 'JSOP_CALLEE':\n                $this->pushStack([]);\n                break;\n            case 'JSOP_ARGUMENTS':\n                $this->pushStack(['name' => 'arguments']);\n                break;\n            case 'JSOP_REST':\n                $this->pushStack(['name' => 'rest']);\n                break;\n            case 'JSOP_SETARG':\n                $val = $this->popStack();\n                $this->pushStack([\n                    'type' => 'script',\n                    'name' => $this->argvs[$operation['params']['argno']],\n                    'script' => $this->argvs[$operation['params']['argno']] . ' = ' . $val->getValue(),\n                ]);\n                break;\n            case 'JSOP_GETARG':\n                $this->pushStack(['name' => $this->argvs[$operation['params']['argno']]]);\n                break;\n            //Array\n            case 'JSOP_NEWARRAY_COPYONWRITE':\n                $this->pushStack([]);\n                break;\n            case 'JSOP_HOLE':\n                $this->pushStack([]);\n                break;\n            case 'JSOP_ARRAYPUSH':\n                $val = $this->popStack();\n                $array = $this->popStack();\n                break;\n            //Object\n            case 'JSOP_TOID':\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_MUTATEPROTO':\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_GETXPROP':\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_CALLSITEOBJ':\n                $this->pushStack([]);\n                break;\n            case 'JSOP_INITPROP_GETTER':\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_INITPROP_SETTER':\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_INITELEM_GETTER':\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_INITELEM_SETTER':\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_NEWOBJECT':\n                $this->pushStack(['value' => [], 'type' => 'object']);\n                break;\n            //This\n            case 'JSOP_THIS':\n                $this->pushStack(['name' => 'this']);\n                break;\n            //Function\n            case 'JSOP_SETCALL':\n                break;\n            case 'JSOP_RUNONCE':\n                break;\n            case 'JSOP_SPREADCALL':\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_SPREADNEW':\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            case 'JSOP_SPREADEVAL':\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n            //Free Variables\n            case 'JSOP_BINDGNAME':\n            case 'JSOP_GETGNAME'://todo check if this different from local, for just access variable name\n                $key = $this->atoms[$operation['params']['nameIndex']];\n                $this->pushStack($this->decompile->getGlobalVariable($key));\n                break;\n            case 'JSOP_SETGNAME':\n                $value = $this->popStack();\n                $bind = $this->popStack();\n                $key = $this->atoms[$operation['params']['nameIndex']];\n                $globalVar = [\n                    'type' => 'script',\n                    'name' => $key,\n                    'value' => $value,\n                    'script' => $key . '=' . $value->getValue(),\n                ];\n                $this->decompile->setLocalVariable($key, $globalVar);\n                $this->pushStack($globalVar);\n                break;\n            //Local Variables\n            case 'JSOP_GETLOCAL'://todo\n                $localno = $operation['params']['localno'];\n                $this->pushStack($this->decompile->getLocalVariable($localno));\n                break;\n            case 'JSOP_SETLOCAL'://todo\n                $raw = $this->popStack();\n                $value = $raw->name ?: $this->getLogicValue($operation, $raw);\n                $localno = $operation['params']['localno'];\n                $name = '_local' . $localno;\n                $localVar = [\n                    'type' => 'script',\n                    'name' => $name,\n                    'value' => $value,\n                    'script' => $name . '=' . $value,\n                ];\n                $this->decompile->setLocalVariable($localno, $localVar);\n                $this->pushStack($localVar);\n                break;\n            //Generator\n            case 'JSOP_GENERATOR':\n                break;\n            case 'JSOP_YIELD':\n                $val = $this->popStack();\n                $this->pushStack(['type' => 'script', 'value' => 'yield ' . $val->getValue()]);\n                break;\n            //Aliased Variables\n            case 'JSOP_GETALIASEDVAR'://todo\n                $aliasedVar = $this->decompile->getAliasedVariable($operation['params']['hops'], $operation['params']['slot']);\n                $this->pushStack($aliasedVar);\n                break;\n            case 'JSOP_SETALIASEDVAR'://todo\n                $value = $this->getLogicValue($operation, $this->popStack());\n                $aliasedVar = ['type' => 'aliasedVar', 'name' => '_aliased' . rand(1000, 9999)];\n                $this->decompile->setAliasedVariable($operation['params']['hops'], $operation['params']['slot'], $aliasedVar);\n                $this->pushStack(['type' => 'script', 'name' => $aliasedVar['name'], 'script' => $aliasedVar['name'] . '=' . $value]);\n                break;\n            //Exception Handling\n            case 'JSOP_TRY':\n                $this->writeScript($operation['parserIndex'], 'try{');\n                break;\n            case 'JSOP_THROW':\n                $val = $this->popStack();\n                $this->writeScript($operation['parserIndex'], 'throw ' . $val->getValue());\n                break;\n            case 'JSOP_GOSUB':\n                break;\n            case 'JSOP_EXCEPTION':\n                $exception = ['type' => 'exception', 'value' => '@error'];\n                $this->writeScript($operation['parserIndex'], '}catch(' . $exception['value'] . '){');\n                $this->pushStack($exception);\n                break;\n            case 'JSOP_DEBUGLEAVEBLOCK':\n                $this->writeScript($operation['parserIndex'], '}\n        ');\n                break;\n            case 'JSOP_FINALLY':\n                $this->writeScript($operation['parserIndex'], 'finally{\n        ');\n                $this->pushStack([]);\n                $this->pushStack([]);\n                break;\n            case 'JSOP_RETSUB':\n                $this->writeScript($operation['parserIndex'], '}');\n                $val = $this->popStack();\n                $val = $this->popStack();\n                break;\n            //todo\n            case 'JSOP_DEBUGGER':\n                break;\n            case 'JSOP_THROWING':\n                $val = $this->popStack();\n                break;\n            //Block-local Scope\n            case 'JSOP_POPBLOCKSCOPE':\n                break;\n            case 'JSOP_PUSHBLOCKSCOPE':\n                break;\n            //Jumps\n            case 'JSOP_BACKPATCH':\n                break;\n            case 'JSOP_LABEL':\n                break;\n            //Intrinsics\n            case 'JSOP_BINDINTRINSIC':\n                $this->pushStack([]);\n                break;\n            case 'JSOP_GETINTRINSIC':\n                $this->pushStack([]);\n                break;\n            case 'JSOP_SETINTRINSIC':\n                $val = $this->popStack();\n                $val = $this->popStack();\n                $this->pushStack([]);\n                break;\n\n        }\n    }\n\n    protected function _renderSwitch($contents, $defaultIndex)\n    {\n        $contentEndings = array_keys($contents);\n        $contentEndings[] = $defaultIndex;\n        $i = 1;\n        foreach ($contents as $start => $content) {\n            $caseWrite = '';\n            foreach ($content as $case) {\n                $caseWrite .= $case['value'];\n            }\n            $this->writeScript($start, $caseWrite, -1);\n            $this->revealOperations($start, $contentEndings[$i], ['type' => 'switch', 'defaultIndex' => $defaultIndex,]);\n            $i++;\n        }\n        $this->writeScript($defaultIndex, 'default:');\n    }\n\n    protected function getLogicValue($operation, Stack $val)\n    {\n        $value = $val->getValue();\n        if (!empty($this->logicStacks)) {\n            $value = $this->_combineLogicByGotoIndex($operation['parserIndex'] + $operation['length']) . $value;\n        }\n        return $value;\n    }\n\n    protected function _getLoopGoto($operation)\n    {\n        $gotoIndex = $operation['parserIndex'] - 5;\n        if (!isset($this->operations[$gotoIndex])) {\n            return false;\n        }\n        $gotoOperation = $this->operations[$gotoIndex];\n        if ($gotoOperation['name'] !== 'JSOP_GOTO') {\n            return false;\n        }\n        return $gotoOperation;\n    }\n\n    protected function _getLoopLogic($entry)\n    {\n        $if = $entry;\n        do {\n            $if = $this->findFirstOperation(\n                ['JSOP_IFNE', 'JSOP_IFEQ'],\n                $if['parserIndex'] + $if['length']\n            );\n            if (!$if) {\n                return false;\n            }\n        } while ($if['params']['offset'] > 0);\n        return $if;\n    }\n\n    protected function _getBranchGoto($operation)\n    {\n        $gotoIndex = $operation['parserIndex'] + $operation['params']['offset'] - 5;\n        if (!isset($this->operations[$gotoIndex])) {\n            return false;\n        }\n        $gotoOperation = $this->operations[$gotoIndex];\n        if ($gotoOperation['name'] !== 'JSOP_GOTO') {\n            return false;\n        }\n        return $gotoOperation;\n    }\n\n    protected function _getBranchBreak($goto)\n    {\n        if ($goto['params']['offset'] > 0) {\n            if ($this->hasOperation($goto['parserIndex'], $goto['parserIndex'] + $goto['params']['offset'], 'JSOP_LOOPENTRY')) {\n                $this->writeScript($goto['parserIndex'], 'break;');\n                return true;\n            }\n        }\n        return false;\n    }\n\n    protected function _getBranchContinue($goto)\n    {\n        if ($goto['params']['offset'] < 0) {\n            $nextOperation = $this->gotoNextOperation($goto);\n            if ($nextOperation['name'] == 'JSOP_LOOPENTRY') {\n                $this->writeScript($goto['parserIndex'], 'continue;');\n                return true;\n            }\n        }\n        return false;\n    }\n\n    protected function _combineLogic()\n    {\n        ksort($this->logicStacks);\n        while (count($this->logicStacks) > 1) {\n            $this->_combineLogicUnit();\n        }\n        $result = array_pop($this->logicStacks);\n        switch ($result['type']) {\n            case 'not':\n                $result['value'] = '!(' . $result['value'] . ')';\n                break;\n            case 'and':\n                $result['value'] = $result['value'] . '&&';\n                break;\n            case 'or':\n                $result['value'] = $result['value'] . '||';\n                break;\n        }\n        return $result['value'];\n    }\n\n    protected function _getLogicScript($stack)\n    {\n        $value = '';\n        $isNot = $stack['type'] == 'not';\n        if ($isNot) {\n            $value .= '!(';\n        }\n        $value .= $stack['value'];\n        if ($isNot) {\n            $value .= ')';\n        }\n        switch ($stack['type']) {\n            case 'and':\n                $value .= ' && ';\n                break;\n            case 'or':\n                $value .= ' || ';\n                break;\n        }\n        return $value;\n    }\n\n    protected function _combineLogicUnit()\n    {\n        $logicStackKeys = array_keys($this->logicStacks);\n        $logicStackKeysCount = count($logicStackKeys);\n        $tree = ['type' => 'script'];\n        for ($i = 0; $i < $logicStackKeysCount; $i++) {\n            $logicStack = $this->logicStacks[$logicStackKeys[$i]];\n            if (is_null($logicStack['value'])) {\n                $preStack = $this->logicStacks[$logicStackKeys[$i - 1]];\n                $this->logicStacks[$logicStackKeys[$i]]['value'] = $preStack['type'] == 'not' ? ('!(' . $preStack['value'] . ')') : $preStack['value'];\n                unset($this->logicStacks[$logicStackKeys[$i - 1]]);\n            } elseif (!isset($logicStackKeys[$i + 1])) {//if last one\n                $preStack = $this->logicStacks[$logicStackKeys[$i - 1]];\n                $value = $this->_getLogicScript($preStack) . $this->_getLogicScript($logicStack);\n                $this->logicStacks[$logicStackKeys[$i - 1]] = ['value' => $value, 'type' => 'script'];\n                unset($this->logicStacks[$logicStackKeys[$i]]);\n            } elseif (!isset($logicStack['goto'])) {\n                continue;\n            } elseif ($logicStackKeys[$i + 1] == $logicStack['goto']) {\n                $nextLogicStack = $this->logicStacks[$logicStackKeys[$i + 1]];\n                $isNot = $nextLogicStack['type'] == 'not' ? '!' : '';\n                switch ($logicStack['type']) {\n                    case 'and':\n                        $tree['value'] = $isNot . '(' . $logicStack['value'] . ' && ' . $nextLogicStack['value'] . ')';\n                        break;\n                    case 'or':\n                        $tree['value'] = $isNot . '(' . $logicStack['value'] . ' || ' . $nextLogicStack['value'] . ')';\n                        break;\n                    case 'script':\n                        $tree['value'] = $logicStack['value'] . $nextLogicStack['value'];\n                        break;\n                }\n                if (isset($nextLogicStack['goto'])) {\n                    $tree['goto'] = $nextLogicStack['goto'];\n                    $tree['type'] = $nextLogicStack['type'];\n                }\n                unset($this->logicStacks[$logicStackKeys[$i]]);\n                $this->logicStacks[$logicStackKeys[$i + 1]] = $tree;\n                break;\n            }\n        }\n    }\n\n    protected function _combineLogicByGotoIndex($index)\n    {\n        krsort($this->logicStacks);\n        $executeFlag = true;\n        $execute = [];\n        $storage = [];\n        foreach ($this->logicStacks as $key => $value) {\n            if (isset($value['goto']) && $value['goto'] > $index) {\n                $executeFlag = false;\n            }\n            if ($executeFlag) {\n                $execute[$key] = $value;\n            } else {\n                $storage[$key] = $value;\n            }\n        }\n        $result = '';\n        if (!empty($execute)) {\n            $this->logicStacks = $execute;\n            $result = $this->_combineLogic();\n        }\n        $this->logicStacks = $storage;\n        return $result;\n    }\n\n    protected function _combineLogicByParserIndex($index)\n    {\n        ksort($this->logicStacks);\n        $executeFlag = true;\n        $execute = [];\n        $storage = [];\n        foreach ($this->logicStacks as $key => $value) {\n            if ($key > $index) {\n                $executeFlag = false;\n            }\n            if ($executeFlag) {\n                $execute[$key] = $value;\n            } else {\n                $storage[$key] = $value;\n            }\n        }\n        $result = '';\n        if (!empty($execute)) {\n            $this->logicStacks = $execute;\n            $result = $this->_combineLogic();\n        }\n        $this->logicStacks = $storage;\n        return $result;\n    }\n}\n"
  },
  {
    "path": "src/Helper/Reveal.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/11\n * Time: 上午10:13\n */\n\nnamespace Irelance\\Mozjs34\\Helper;\n\n\nuse Irelance\\Mozjs34\\Constant;\n\ntrait Reveal\n{\n    public function printSummaries()\n    {\n        if (count($this->summaries)) {\n            echo '---------------Summaries---------------', CLIENT_EOL;\n            foreach ($this->summaries as $key => $value) {\n                echo $key, ' : ', $value, CLIENT_EOL;\n            }\n            echo '---------------------------------------', CLIENT_EOL;\n        }\n    }\n\n    public function printOperations()\n    {\n        echo '---------------Operations--------------', CLIENT_EOL;\n        foreach ($this->operations as $key => $operation) {\n            $op = Constant::_Opcode[$operation['id']];\n            echo '[', $key, ']', $op['op'], json_encode($operation['params']), ' pop: ', $operation['pop'], ' push: ', $operation['push'], ' byte: ', $operation['length'], CLIENT_EOL;\n        }\n        echo '---------------------------------------', CLIENT_EOL;\n    }\n\n    public function printNodes()\n    {\n        echo '-----------------Nodes-----------------', CLIENT_EOL;\n        echo implode(', ', $this->nodes), CLIENT_EOL;\n        echo '---------------------------------------', CLIENT_EOL;\n    }\n\n    public function printAtoms()\n    {\n        if (count($this->atoms)) {\n            echo '-----------------Atoms-----------------', CLIENT_EOL;\n            foreach ($this->atoms as $key => $value) {\n                echo $key, ' : ', $value, CLIENT_EOL;\n            }\n            echo '---------------------------------------', CLIENT_EOL;\n        }\n    }\n\n    public function printConsts()\n    {\n        if (count($this->consts)) {\n            echo '-----------------Consts----------------', CLIENT_EOL;\n            foreach ($this->consts as $key => $const) {\n                echo $key, ' : [', $const['type'], ']', $const['value'], CLIENT_EOL;\n            }\n            echo '---------------------------------------', CLIENT_EOL;\n        }\n    }\n\n    public function printObjects()\n    {\n        if (count($this->objects)) {\n            echo '-----------------Objects---------------', CLIENT_EOL;\n            foreach ($this->objects as $object) {\n                echo json_encode($object), CLIENT_EOL;\n            }\n            echo '---------------------------------------', CLIENT_EOL;\n        }\n    }\n\n    public function printRegexps()\n    {\n        if (count($this->regexps)) {\n            echo '-----------------Regexps---------------', CLIENT_EOL;\n            foreach ($this->regexps as $regexp) {\n                echo $regexp['source'], CLIENT_EOL;\n            }\n            echo '---------------------------------------', CLIENT_EOL;\n        }\n    }\n\n    public function printTryNote()\n    {\n        if (count($this->tryNotes)) {\n            echo '-----------------Objects---------------', CLIENT_EOL;\n            foreach ($this->tryNotes as $tryNote) {\n                echo json_encode($tryNote), CLIENT_EOL;\n            }\n            echo '---------------------------------------', CLIENT_EOL;\n        }\n    }\n\n    public function printScopeNote()\n    {\n        if (count($this->scopeNotes)) {\n            echo '---------------ScopeNotes---------------', CLIENT_EOL;\n            foreach ($this->scopeNotes as $id => $scopeNote) {\n                echo $id, ' : ', json_encode($scopeNote), CLIENT_EOL;\n            }\n            echo '---------------------------------------', CLIENT_EOL;\n        }\n    }\n\n    public function printProperties(array $types)\n    {\n        foreach ($types as $type) {\n            $call = 'print' . $type;\n            if (method_exists($this, $call)) {\n                $this->$call();\n            }\n        }\n    }\n\n    public function printContent()\n    {\n        foreach ($this->operations as $key => $operation) {\n            if (!$this->operations[$key]['isCover']) {\n                if ($this->isDebug) {\n                    echo $key, CLIENT_EOL;\n                }\n                $this->revealOperation($operation);\n                $this->operations[$key]['isCover'] = true;\n            }\n        }\n\n        ksort($this->storageScript);\n        $scriptKeys = array_keys($this->storageScript);\n        $scriptKeysCount = count($scriptKeys);\n        echo '----------------Content----------------', CLIENT_EOL;\n        for ($i = 0; $i < $scriptKeysCount; $i++) {\n            $script = $this->storageScript[$scriptKeys[$i]];\n            if ($this->isDebug) {\n                echo '[', $scriptKeys[$i] / 2, ']', $script['value'], CLIENT_EOL;\n            } else {\n                echo $script['value'], CLIENT_EOL;\n            }\n        }\n        echo '---------------------------------------', CLIENT_EOL;\n    }\n\n    public function printArgv()\n    {\n        echo '------------------Argv------------------', CLIENT_EOL;\n        echo implode(',', $this->argvs), CLIENT_EOL;\n        echo '---------------------------------------', CLIENT_EOL;\n    }\n}\n"
  },
  {
    "path": "src/Helper/Stack.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/12\n * Time: 下午1:43\n */\n\nnamespace Irelance\\Mozjs34\\Helper;\n\n\nclass Stack\n{\n    public $type;\n    public $name;\n    public $value;//raw input value\n    public $script;//raw input script\n\n    public function __construct(array $props)\n    {\n        foreach ($props as $prop => $value) {\n            $this->$prop = $value;\n        }\n    }\n\n    public function getValue()\n    {\n        if ($this->name) {\n            return $this->name;\n        }\n        return $this->getScript();\n    }\n\n    public function getScript()\n    {\n        if ($this->script) {\n            return $this->script;\n        }\n        $this->script = self::renderBase($this);\n        return $this->script;\n    }\n\n    public static function renderBase(self $input)\n    {\n        switch ($input->type) {\n            case 'script':\n                return $input->script;\n            case 'function':\n                return 'function () { __FUNC_' . $input->value . '__ }';\n            case 'string':\n                return '\"' . $input->value . '\"';\n            case 'object':\n                return self::renderObject($input->value);\n            case 'array':\n                return self::renderArray($input->value);\n            case 'number':\n            case 'boolean':\n            case 'null':\n            case 'undefined':\n            case 'regexp':\n        }\n        return $input->value;\n    }\n\n    public static function renderArray($array)\n    {\n        $result = '[';\n        foreach ($array as $item) {\n            $result .= $item->getValue() . ',';\n        }\n        $resultLen = strlen($result);\n        if ($resultLen>1) {\n            $result = substr($result, 0, $resultLen - 1);\n        }\n        $result .= ']';\n        return $result;\n    }\n\n    public static function renderObject($object)\n    {\n        $result = '{';\n        foreach ($object as $key => $value) {\n            $result .= $key . ':';\n            $result .= $value->getValue() . ',';\n        }\n        $resultLen = strlen($result);\n        if ($resultLen>1) {\n            $result = substr($result, 0, $resultLen - 1);\n        }\n        $result .= '}';\n        return $result;\n    }\n}\n"
  },
  {
    "path": "src/Xdr/Atom.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/10\n * Time: 上午11:30\n */\n\nnamespace Irelance\\Mozjs34\\Xdr;\n\ntrait Atom\n{\n    protected function getLatin1Chars($length)\n    {\n        $end = $this->parseIndex + $length;\n        $atom = '';\n        for (; $this->parseIndex < $end; $this->parseIndex++) {\n            $atom .= chr($this->bytecodes[$this->parseIndex]);\n        }\n        return $atom;\n    }\n\n    protected function getTwoByteChar()\n    {\n        $char = '\\u' . dechex($this->bytecodes[$this->parseIndex + 1]) . dechex($this->bytecodes[$this->parseIndex]);\n        $this->parseIndex += 2;\n        return $char;\n    }\n\n    protected function getTwoByteChars($length)\n    {\n        $atom = '';\n        for ($i = 0; $i < $length; $i++) {\n            $atom .= $this->getTwoByteChar();\n        }\n        return json_decode('\"' . $atom . '\"');\n    }\n\n    public function XDRAtom()\n    {\n        $lengthAndEncoding = $this->todec();\n        $hasLatin1Chars = $lengthAndEncoding & 1;\n        $length = $lengthAndEncoding >> 1;\n        if ($hasLatin1Chars) {\n            $atom = $this->getLatin1Chars($length);\n        } else {\n            $atom = $this->getTwoByteChars($length);\n        }\n        return $atom;\n    }\n}\n"
  },
  {
    "path": "src/Xdr/Common.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/10\n * Time: 上午11:30\n */\n\nnamespace Irelance\\Mozjs34\\Xdr;\n\nuse Irelance\\Mozjs34\\Constant;\n\n\ntrait Common\n{\n    protected function getRawHex($length)\n    {\n        $end = $this->parseIndex + $length;\n        $result = '';\n        for (; $this->parseIndex < $end; $this->parseIndex++) {\n            $result .= sprintf('%02s', dechex($this->bytecodes[$this->parseIndex]));\n        }\n        return $result;\n    }\n\n    protected function getCString()\n    {\n        $result = '';\n        while ($this->bytecodes[$this->parseIndex]) {\n            $result .= chr($this->bytecodes[$this->parseIndex]);\n            $this->parseIndex++;\n        }\n        $this->parseIndex++;\n        return $result;\n    }\n\n    protected function todec($length = 4)//length include start\n    {\n        return $this->littleEndian2Dec($length);\n    }\n\n    protected function littleEndian2Dec($length)\n    {\n        $result = '';\n        for ($i = $this->parseIndex + $length - 1; $i >= $this->parseIndex; $i--) {\n            $result .= sprintf('%02s', dechex($this->bytecodes[$i]));\n        }\n        $this->parseIndex += $length;\n        return hexdec($result);\n    }\n\n    protected function bigEndian2Dec($length)\n    {\n        $end = $this->parseIndex + $length;\n        $result = '';\n        for (; $this->parseIndex < $end; $this->parseIndex++) {\n            $result .= sprintf('%02s', dechex($this->bytecodes[$this->parseIndex]));\n        }\n        return hexdec($result);\n    }\n\n    protected function uInt32ToInt32($num)\n    {\n        return unpack('l', pack('L', $num))[1];\n    }\n\n    protected function uIntToInt($num, $bit)\n    {\n        $half = 1 << ($bit - 1);\n        if ($num <= $half) {\n            return $num;\n        }\n        $max = (1 << $bit) - 1;\n        return -(($num - 1) ^ $max);\n    }\n\n    public function xdrConst()\n    {\n        $type = $this->todec();\n        $const = [\n            'type' => Constant::_ConstTag[$type],\n        ];\n        switch ($type) {\n            case 0:\n                $const['value'] = $this->todec();\n                break;\n            case 1:\n                $value = unpack('d', pack('H*', $this->getRawHex(8)));\n                $const['value'] = $value[1];\n                break;\n            case 2:\n                $const['value'] = $this->XDRAtom();\n                break;\n            case 3:\n                $const['value'] = true;\n                break;\n            case 4:\n                $const['value'] = false;\n                break;\n            case 5:\n                $const['value'] = null;\n                break;\n            case 6:\n                $object = $this->xdrCK_JSObject();\n                $const['value'] = \"__OBJECT__\";\n                $const['extra'] = $object;\n                break;\n            case 7:\n                $const['value'] = \"__VOID__\";\n                break;\n            case 8:\n                $const['value'] = \"__HOLE__\";\n                break;\n            default:\n                $const['value'] = \"__ERROR__\";\n                break;\n        }\n        return $const;\n    }\n\n    public function XDRInterpretedFunction()\n    {\n        $result = ['name' => ''];\n        $firstword = $this->todec();\n        if ($firstword & Constant::_FirstWordFlag['HasAtom']) {\n            $result['name'] = $this->XDRAtom();\n        }\n        $flagsword = $this->todec();\n        if ($firstword & Constant::_FirstWordFlag['IsLazy']) {\n            $this->XDRLazyScript();\n            $result['type'] = 'lazy';\n        } else {\n            $result['type'] = 'block';\n            $result['contextIndex'] = $this->XDRScript()->index;\n        }\n        return $result;\n    }\n\n    public function XDRLazyFreeVariables()\n    {\n        //for 0 -> numFreeVariables\n        //$atom=$this->XDRAtom();\n    }\n\n    public function XDRLazyScript()\n    {\n        //XDRLazyScript\n        $begin = $this->todec();\n        $end = $this->todec();\n        $lineno = $this->todec();\n        $column = $this->todec();\n        $packedFields = $this->todec(8);\n        $this->XDRLazyFreeVariables();\n    }\n}\n"
  },
  {
    "path": "src/Xdr/ObjectXdr.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/10\n * Time: 上午11:49\n */\n\nnamespace Irelance\\Mozjs34\\Xdr;\n\n\ntrait ObjectXdr\n{\n    public function xdrObjectExtra($objectType)\n    {\n        $result = 'xdr';\n        switch ($objectType) {\n            case 'CK_BlockObject':\n            case 'CK_WithObject':\n            case 'CK_JSFunction':\n            case 'CK_JSObject':\n                $result .= $objectType;\n                break;\n            default:\n                $result .= 'CK_Not';\n                break;\n        }\n        return $this->$result();\n    }\n\n    protected function xdrCK_Not()\n    {\n        return [];\n    }\n\n    protected function xdrCK_BlockObject()\n    {\n        $result = [\n            'enclosingStaticScopeIndex' => $this->todec(),\n            'count' => $this->todec(),\n            'offset' => $this->todec(),\n            'atoms' => [],\n        ];\n        for ($i = 0; $i < $result['count']; $i++) {\n            $result['atoms'][] = [\n                'atom' => $this->XDRAtom(),\n                'aliased' => $this->todec(),\n            ];\n        }\n\n        return $result;\n    }\n\n    protected function xdrCK_WithObject()\n    {\n        return [\n            'enclosingStaticScopeIndex' => $this->todec(),\n        ];\n    }\n\n    protected function xdrCK_JSFunction()\n    {\n        return array_merge([\n            'funEnclosingScopeIndex' => $funEnclosingScopeIndex = $this->todec(),\n        ],$this->XDRInterpretedFunction());\n    }\n\n    public function xdrCK_JSObject()\n    {\n        $result = [];\n        $result['isArray'] = $isArray = $this->todec();\n        $this->todec();//isArray ? length : kind\n        $result['capacity'] = $capacity = $this->todec();\n        $initialized = $this->todec();\n        $result['initialized'] = [];\n        for ($i = 0; $i < $initialized; $i++) {\n            $result['initialized'][] = $tmpValue = $this->xdrConst();\n        }\n        $nslot = $this->todec();\n        $result['nslot'] = [];\n        for ($i = 0; $i < $nslot; $i++) {\n            $idType = $this->todec();\n            if ($idType == JSID_TYPE_STRING) {\n                $key = $this->XDRAtom();\n            } else {\n                $key = $this->todec();\n            }\n            $val = $this->xdrConst();\n            $result['nslot'][$key] = $val;\n        }\n        $isSingletonTyped = $this->todec();\n        $frozen = $this->todec();\n        if ($isArray) {\n            $copyOnWrite = $this->todec();\n        }\n        return $result;\n    }\n\n}\n"
  },
  {
    "path": "src/Xdr/Operation.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/11\n * Time: 上午11:21\n */\n\nnamespace Irelance\\Mozjs34\\Xdr;\n\nuse Irelance\\Mozjs34\\Constant;\n\ntrait Operation\n{\n    public function parserOperation()\n    {\n        $op = Constant::_Opcode[$this->bytecodes[$this->parseIndex]];\n        $result = [\n            'id' => $op['val'],\n            'name' => $op['op'],\n            'parserIndex' => $this->parseIndex,\n            'params' => [],\n            'length' => $op['len'],\n            'image' => $op['image'],\n            'push' => $op['def'],\n            'pop' => $op['use'],\n            'isCover' => false,\n        ];\n        $this->parseIndex++;\n        switch ($op['op']) {\n            case 'JSOP_ENTERWITH':\n                $result['params']['staticWithIndex'] = $this->bigEndian2Dec(4);\n                break;\n            case 'JSOP_GOTO':\n            case 'JSOP_IFEQ':\n            case 'JSOP_IFNE':\n            case 'JSOP_OR':\n            case 'JSOP_AND':\n            case 'JSOP_LABEL':\n            case 'JSOP_GOSUB':\n            case 'JSOP_CASE':\n            case 'JSOP_DEFAULT':\n            case 'JSOP_BACKPATCH':\n                $result['params']['offset'] = $this->uInt32ToInt32($this->bigEndian2Dec(4));\n                break;\n            case 'JSOP_CALL':\n            case 'JSOP_FUNAPPLY':\n            case 'JSOP_NEW':\n            case 'JSOP_FUNCALL':\n            case 'JSOP_EVAL':\n                $result['params']['argc'] = $this->bigEndian2Dec(2);\n                break;\n            case 'JSOP_GETARG':\n            case 'JSOP_SETARG':\n                $result['params']['argno'] = $this->bigEndian2Dec(2);\n                break;\n            case 'JSOP_PICK':\n                $result['params']['n'] = $this->bigEndian2Dec(1);\n                break;\n            case 'JSOP_POPN':\n                $result['params']['n'] = $this->bigEndian2Dec(2);\n                break;\n            case 'JSOP_DUPAT':\n                $result['params']['n'] = $this->bigEndian2Dec(3);\n                break;\n            case 'JSOP_SETCONST':\n            case 'JSOP_DELNAME':\n            case 'JSOP_DELPROP':\n            case 'JSOP_GETPROP':\n            case 'JSOP_SETPROP':\n            case 'JSOP_INITPROP':\n            case 'JSOP_NAME':\n            case 'JSOP_INITPROP_GETTER':\n            case 'JSOP_INITPROP_SETTER':\n            case 'JSOP_BINDNAME':\n            case 'JSOP_SETNAME':\n            case 'JSOP_DEFCONST':\n            case 'JSOP_DEFVAR':\n            case 'JSOP_GETINTRINSIC':\n            case 'JSOP_SETINTRINSIC':\n            case 'JSOP_BINDINTRINSIC':\n            case 'JSOP_GETGNAME':\n            case 'JSOP_SETGNAME':\n            case 'JSOP_CALLPROP':\n            case 'JSOP_GETXPROP':\n            case 'JSOP_BINDGNAME':\n            case 'JSOP_LENGTH':\n            case 'JSOP_IMPLICITTHIS':\n                $result['params']['nameIndex'] = $this->bigEndian2Dec(4);\n                break;\n            case 'JSOP_DOUBLE':\n                $result['params']['constIndex'] = $this->bigEndian2Dec(4);\n                break;\n            case 'JSOP_STRING':\n                $result['params']['atomIndex'] = $this->bigEndian2Dec(4);\n                break;\n            case 'JSOP_OBJECT':\n            case 'JSOP_CALLSITEOBJ':\n            case 'JSOP_NEWARRAY_COPYONWRITE':\n                $result['params']['objectIndex'] = $this->bigEndian2Dec(4);\n                break;\n            case 'JSOP_DEFFUN':\n            case 'JSOP_LAMBDA':\n            case 'JSOP_LAMBDA_ARROW':\n                $result['params']['funcIndex'] = $this->bigEndian2Dec(4);\n                break;\n            case 'JSOP_REGEXP':\n                $result['params']['regexpIndex'] = $this->bigEndian2Dec(4);\n                break;\n            case 'JSOP_PUSHBLOCKSCOPE':\n                $result['params']['staticBlockObjectIndex'] = $this->bigEndian2Dec(4);\n                break;\n            case 'JSOP_TABLESWITCH':\n                $result['params']['len'] = $this->uInt32ToInt32($this->bigEndian2Dec(4));\n                $result['params']['low'] = $this->uInt32ToInt32($this->bigEndian2Dec(4));\n                $result['params']['high'] = $this->uInt32ToInt32($this->bigEndian2Dec(4));\n                $result['params']['offset'] = [];\n                $end = $result['params']['high'] - $result['params']['low'];\n                for ($i = 0; $i <= $end; $i++) {\n                    $result['params']['offset'][$i] = $this->uInt32ToInt32($this->bigEndian2Dec(4));\n                }\n                break;\n            case 'JSOP_ITER':\n                $result['params']['flags'] = $this->bigEndian2Dec(1);\n                break;\n            case 'JSOP_GETLOCAL'://todo uint32_t localno but op len is 4\n            case 'JSOP_SETLOCAL'://todo uint32_t localno but op len is 4\n                $result['params']['localno'] = $this->bigEndian2Dec(3);\n                break;\n            case 'JSOP_INT8':\n                $result['params']['val'] = $this->uIntToInt($this->bigEndian2Dec(1), 8);\n                break;\n            case 'JSOP_UINT16':\n                $result['params']['val'] = $this->bigEndian2Dec(2);\n                break;\n            case 'JSOP_UINT24':\n                $result['params']['val'] = $this->bigEndian2Dec(3);\n                break;\n            case 'JSOP_INT32':\n                $result['params']['val'] = $this->uInt32ToInt32($this->bigEndian2Dec(4));\n                break;\n            case 'JSOP_NEWINIT':\n                $result['params']['kind'] = $this->bigEndian2Dec(1);\n                $result['params']['extra'] = $this->bigEndian2Dec(3);\n                break;\n            case 'JSOP_NEWARRAY':\n                $result['params']['length'] = $this->bigEndian2Dec(3);\n                break;\n            case 'JSOP_NEWOBJECT':\n                $result['params']['baseobjIndex'] = $this->bigEndian2Dec(4);\n                break;\n            case 'JSOP_INITELEM_ARRAY':\n                $result['params']['index'] = $this->bigEndian2Dec(3);\n                break;\n            case 'JSOP_LINENO':\n                $result['params']['lineno'] = $this->bigEndian2Dec(2);\n                break;\n            case 'JSOP_GETALIASEDVAR':\n            case 'JSOP_SETALIASEDVAR':\n                $result['params']['hops'] = $this->bigEndian2Dec(1);\n                $result['params']['slot'] = $this->bigEndian2Dec(3);\n                break;\n            case 'JSOP_LOOPENTRY':\n                $result['params']['BITFIELD'] = $this->bigEndian2Dec(1);\n                $result['params']['depth'] = $result['params']['BITFIELD'] - 128;\n                break;\n        }\n        return $result;\n    }\n}\n"
  },
  {
    "path": "src/Xdr/Scope.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/10\n * Time: 上午11:47\n */\n\nnamespace Irelance\\Mozjs34\\Xdr;\n/**\n * @method \\Irelance\\Mozjs34\\Xdr\\Common todec(int $length = 4)\n *\n * @property integer $parseIndex\n * @property array $bytecodes\n */\ntrait Scope\n{\n    protected function XDRSizedBindingNames()\n    {\n        $length = $this->todec();\n        $result = [];\n        for ($i = 0; $i < $length; $i++) {\n            $u8 = $this->todec(1);\n            $hasAtom = $u8 >> 1;\n            if ($hasAtom) {\n                $result[] = $this->XDRAtom();\n            }\n        }\n        return $result;\n    }\n\n    public function xdrScopeExtra($scopeKind)\n    {\n        $result = 'xdr';\n        switch ($scopeKind) {\n            case 'Function':\n                $result .= 'Function';\n                break;\n            case 'FunctionBodyVar':\n            case 'ParameterExpressionVar':\n                $result .= 'Var';\n                break;\n            case 'Lexical':\n            case 'SimpleCatch':\n            case 'Catch':\n            case 'NamedLambda':\n            case 'StrictNamedLambda':\n                $result .= 'Lexical';\n                break;\n            case 'With':\n                $result .= 'With';\n                break;\n            case 'Eval':\n            case 'StrictEval':\n                $result .= 'Eval';\n                break;\n            case 'Global':\n            case 'NonSyntactic':\n                $result .= 'Global';\n                break;\n            case 'Module':\n            default:\n                $result .= 'Not';\n        }\n        return $this->$result();\n    }\n\n    protected function xdrNot()\n    {\n        return [];\n    }\n\n    protected function xdrWith()\n    {\n        return [];\n    }\n\n    protected function xdrLexical()\n    {\n        return [\n            'bindingNames' => $this->XDRSizedBindingNames(),\n            'constStart' => $this->todec(),\n            'firstFrameSlot' => $this->todec(),\n            'nextFrameSlot' => $this->todec()\n        ];\n    }\n\n    protected function xdrFunction()\n    {\n        return [\n            'bindingNames' => $this->XDRSizedBindingNames(),\n            'needsEnvironment' => $this->todec(1),\n            'hasParameterExprs' => $this->todec(1),\n            'nonPositionalFormalStart' => $this->todec(2),\n            'varStart' => $this->todec(2),\n            'nextFrameSlot' => $this->todec(),\n        ];\n    }\n\n    protected function xdrVar()\n    {\n        return [\n            'bindingNames' => $this->XDRSizedBindingNames(),\n            'needsEnvironment' => $this->todec(1),\n            'firstFrameSlot' => $this->todec(),\n            'nextFrameSlot' => $this->todec()\n        ];\n    }\n\n    protected function xdrGlobal()\n    {\n        return [\n            'bindingNames' => $this->XDRSizedBindingNames(),\n            'letStart' => $this->todec(),\n            'constStart' => $this->todec(),\n        ];\n    }\n\n    protected function xdrEval()\n    {\n        return [\n            'bindingNames' => $this->XDRSizedBindingNames(),\n            'length' => $this->todec(),\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Xdr/Script.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: irelance\n * Date: 2017/10/10\n * Time: 上午11:30\n */\n\nnamespace Irelance\\Mozjs34\\Xdr;\n\nuse Irelance\\Mozjs34\\Context;\nuse Irelance\\Mozjs34\\Constant;\n\n/**\n * @method \\Irelance\\Mozjs34\\Xdr\\Common todec(int $length = 4)\n *\n * @property integer $parseIndex\n * @property array $bytecodes\n */\ntrait Script\n{\n\n    protected function parserHeader(Context $context)\n    {\n        $nargs = $this->todec(2);\n        $context->addSummary('nargs', $nargs);\n        $context->addSummary('nblocklocals', $this->todec(2));\n        $nvars = $this->todec();\n        $context->addSummary('nvars', $nvars);\n        $context->addSummary('length', $this->todec());\n        $context->addSummary('prologLength', $this->todec());\n        $context->addSummary('version', $this->todec());\n        $context->addSummary('natoms', $this->todec());\n        $context->addSummary('nsrcnotes', $this->todec());\n        $context->addSummary('nconsts', $this->todec());\n        $context->addSummary('nobjects', $this->todec());\n        $context->addSummary('nregexps', $this->todec());\n        $context->addSummary('ntrynotes', $this->todec());\n        $context->addSummary('nblockscopes', $this->todec());\n        $context->addSummary('nTypeSets', $this->todec());\n        $context->addSummary('funLength', $this->todec());\n        $scriptBit = $this->todec();\n        $context->addSummary('scriptBits', $scriptBit);\n        $scriptBits = array_flip(Constant::_ScriptBits);\n        if ($scriptBit & (1 << $scriptBits['OwnSource'])) {\n            $context->addSummary('hasSource', $this->todec(1));\n            $context->addSummary('retrievable', $this->todec(1));\n            if($context->getSummary('hasSource') && !$context->getSummary('retirevable')) {\n                $context->addSummary('sourceLength', $this->todec());\n                $context->addSummary('sourcecompressedLength', $this->todec());\n                $context->addSummary('argumentsNotIncluded', $this->todec(1));\n                $context->addSummary(\n                    'sourceBytes',\n                    $this->getRawHex(\n                        $context->getSummary('sourcecompressedLength') ?\n                            $context->getSummary('sourcecompressedLength') :\n                            $context->getSummary('sourceLength') * 2\n                    )\n                    );\n            }\n\n            $context->addSummary('hasSourceMap', $this->todec(1));\n            if($context->getSummary('hasSourceMap')) {\n                $context->addSummary('sourceMapURLLen', $this->todec());\n                $context->addSummary('sourceMapURL', $this->getRawHex($context->getSummary('sourceMapURLLen') * 2));\n            }\n\n            $context->addSummary('haveDisplayURL', $this->todec(1));\n            if($context->getSummary('haveDisplayURL')) {\n                $context->addSummary('displayURLLen', $this->todec());\n                $context->addSummary('displayURL', $this->getRawHex($context->getSummary('displayURLLen')));\n            }\n\n            $context->addSummary('haveFilename', $this->todec(1));\n            if($context->getSummary('haveFilename')) {\n                $context->addSummary('buildPath', $this->getCString());\n            }\n            \n        }\n        $nameCount = $nargs + $nvars;\n        for ($i = 0; $i < $nameCount; $i++) {\n            $atom = $this->XDRAtom();\n            $context->addArgv($atom);\n        }\n        for ($i = 0; $i < $nameCount; $i++) {\n            $u8 = $this->todec(1);\n        }\n        $context->addSummary('sourceStart_', $this->todec());\n        $context->addSummary('sourceEnd_', $this->todec());\n        $context->addSummary('lineno', $this->todec());\n        $context->addSummary('column', $this->todec());\n        $context->addSummary('nslots', $this->todec());\n        $context->addSummary('staticLevel', $this->todec());\n    }\n\n    protected function parserScript(Context $context)\n    {\n        $end = $this->parseIndex + $context->getSummary('length');\n        for (; $this->parseIndex < $end;) {\n            $context->addOperation($this->parseIndex, $this->parserOperation());\n        }\n        $this->parseIndex = $end;\n    }\n\n    protected function parserSrcNodes(Context $context)\n    {\n        $end = $this->parseIndex + $context->getSummary('nsrcnotes');\n        for (; $this->parseIndex < $end; $this->parseIndex++) {\n            $context->addNode($this->bytecodes[$this->parseIndex]);\n        }\n    }\n\n    protected function parserAtoms(Context $context)\n    {\n        if ($natoms = $context->getSummary('natoms')) {\n            for ($i = 0; $i < $natoms; $i++) {\n                $context->addAtom($this->XDRAtom());\n            }\n        }\n    }\n\n    protected function parseConsts(Context $context)\n    {\n        if ($nconsts = $context->getSummary('nconsts')) {\n            for ($i = 0; $i < $nconsts; $i++) {\n                $context->addConst($this->xdrConst());\n            }\n        }\n    }\n\n    protected function parserObject(Context $context)\n    {\n        $context->addObject(\n            $classKind = Constant::_Class[$this->todec()],\n            $extra = $this->xdrObjectExtra($classKind)\n        );\n    }\n\n    protected function parserObjects(Context $context)\n    {\n        if ($nobjects = $context->getSummary('nobjects')) {\n            for ($i = 0; $i < $nobjects; $i++) {\n                $this->parserObject($context);\n            }\n        }\n    }\n\n    protected function parserRegexps(Context $context)\n    {\n        if ($nregexps = $context->getSummary('nregexps')) {\n            for ($i = 0; $i < $nregexps; $i++) {\n                $context->addRegexp(\n                    $source = $this->XDRAtom(),\n                    $flagsword = $this->todec()\n                );\n            }\n        }\n    }\n\n    protected function parserTryNotes(Context $context)\n    {\n        if ($ntrynotes = $context->getSummary('ntrynotes')) {\n            for ($i = 0; $i < $ntrynotes; $i++) {\n                $context->addTryNote(\n                    $kind = $this->todec(1),\n                    $stackDepth = $this->todec(),\n                    $start = $this->todec(),\n                    $length = $this->todec()\n                );\n            }\n        }\n    }\n\n    protected function parserScopeNotes(Context $context)\n    {\n        if ($nscopeNotes = $context->getSummary('nblockscopes')) {\n            for ($i = 0; $i < $nscopeNotes; $i++) {\n                $context->addScopeNote(\n                    $index = $this->todec(),\n                    $start = $this->todec(),\n                    $length = $this->todec(),\n                    $parent = $this->todec()\n                );\n            }\n        }\n    }\n\n    protected function parserHasLazyScript(Context $context)\n    {\n        $scriptBits = array_flip(Constant::_ScriptBits);\n        $HasLazyScript = $scriptBits['HasLazyScript'];\n        if ($context->getSummary('scriptBits') & (1 << $HasLazyScript)) {\n            $packedFields = $this->todec(8);\n            $context->addHasLazyScript($packedFields);\n            $this->XDRLazyFreeVariables();\n        }\n    }\n\n    public function XDRScript()\n    {\n        $context = new Context();\n        $index = count($this->contexts);\n        $this->contexts[] = $context;\n        $context->index = $index;\n        $this->parseScriptIndex = $index;\n        $context->decompile = $this;\n        $this->parserHeader($context);//header storage the base info of a context, if jsc compile with no setSourceIsLazy(true), raw source save here\n        $this->parserScript($context);//get the operations and parse to script (maybe not good enough to parse here)\n        $this->parserSrcNodes($context);\n        $this->parserAtoms($context);//this section save strings\n        $this->parseConsts($context);\n        $this->parserObjects($context);//this section save local simple objects\n        $this->parserRegexps($context);\n        $this->parserTryNotes($context);\n        $this->parserScopeNotes($context);//this section save block scope info\n        $this->parserHasLazyScript($context);\n        return $context;\n    }\n}\n"
  }
]