distil 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +28 -0
- data/VERSION +1 -0
- data/bin/distil +45 -0
- data/distil.gemspec +586 -0
- data/lib/bootstrap-template.js +56 -0
- data/lib/configurable.rb +125 -0
- data/lib/file-set.rb +42 -0
- data/lib/file-types/css-file.rb +75 -0
- data/lib/file-types/html-file.rb +11 -0
- data/lib/file-types/javascript-file.rb +98 -0
- data/lib/file-types/json-file.rb +14 -0
- data/lib/file-types/nib-file.rb +9 -0
- data/lib/jsdoc.conf +18 -0
- data/lib/jsl.conf +121 -0
- data/lib/project.rb +96 -0
- data/lib/source-file.rb +181 -0
- data/lib/target.rb +96 -0
- data/lib/task.rb +239 -0
- data/lib/tasks/copy-task.rb +21 -0
- data/lib/tasks/css-task.rb +18 -0
- data/lib/tasks/javascript-task.rb +125 -0
- data/lib/tasks/multiple-output-task.rb +134 -0
- data/lib/tasks/nib-task.rb +83 -0
- data/lib/tasks/output-task.rb +73 -0
- data/lib/tasks/single-output-task.rb +83 -0
- data/lib/tasks/test-task.rb +280 -0
- data/lib/test/HtmlTestReporter.js +127 -0
- data/lib/test/Test.js +248 -0
- data/lib/test/TestReporter.js +79 -0
- data/lib/test/TestRunner.js +132 -0
- data/lib/test/browser.rb +97 -0
- data/lib/test/scriptwrapper.html +10 -0
- data/lib/test/unittest.html +127 -0
- data/vendor/Makefile +35 -0
- data/vendor/extconf.rb +3 -0
- data/vendor/jsdoc-extras/plugins/distil-plugin.js +142 -0
- data/vendor/jsdoc-extras/plugins/interface-plugin.js +36 -0
- data/vendor/jsdoc-extras/templates/coherent/allclasses.tmpl +17 -0
- data/vendor/jsdoc-extras/templates/coherent/allfiles.tmpl +53 -0
- data/vendor/jsdoc-extras/templates/coherent/class.tmpl +803 -0
- data/vendor/jsdoc-extras/templates/coherent/index.tmpl +37 -0
- data/vendor/jsdoc-extras/templates/coherent/publish.js +242 -0
- data/vendor/jsdoc-extras/templates/coherent/showdown.js +421 -0
- data/vendor/jsdoc-extras/templates/coherent/static/code-footer.html +3 -0
- data/vendor/jsdoc-extras/templates/coherent/static/code-header.html +7 -0
- data/vendor/jsdoc-extras/templates/coherent/static/default.css +297 -0
- data/vendor/jsdoc-extras/templates/coherent/static/header.html +2 -0
- data/vendor/jsdoc-extras/templates/coherent/static/index.html +19 -0
- data/vendor/jsdoc-extras/templates/coherent/symbol.tmpl +35 -0
- data/vendor/jsdoc-toolkit/README.txt +183 -0
- data/vendor/jsdoc-toolkit/app/frame/Chain.js +102 -0
- data/vendor/jsdoc-toolkit/app/frame/Dumper.js +144 -0
- data/vendor/jsdoc-toolkit/app/frame/Hash.js +84 -0
- data/vendor/jsdoc-toolkit/app/frame/Link.js +171 -0
- data/vendor/jsdoc-toolkit/app/frame/Namespace.js +10 -0
- data/vendor/jsdoc-toolkit/app/frame/Opt.js +134 -0
- data/vendor/jsdoc-toolkit/app/frame/Reflection.js +26 -0
- data/vendor/jsdoc-toolkit/app/frame/String.js +93 -0
- data/vendor/jsdoc-toolkit/app/frame/Testrun.js +129 -0
- data/vendor/jsdoc-toolkit/app/frame.js +33 -0
- data/vendor/jsdoc-toolkit/app/handlers/FOODOC.js +26 -0
- data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/DomReader.js +159 -0
- data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLDoc.js +16 -0
- data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLParse.js +292 -0
- data/vendor/jsdoc-toolkit/app/handlers/XMLDOC.js +26 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocComment.js +204 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocTag.js +300 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsDoc.js +126 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsPlate.js +109 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Lang.js +144 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Parser.js +144 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/PluginManager.js +33 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Symbol.js +644 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js +241 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/TextStream.js +41 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Token.js +18 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenReader.js +332 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenStream.js +133 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Util.js +32 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Walker.js +499 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC.js +106 -0
- data/vendor/jsdoc-toolkit/app/main.js +129 -0
- data/vendor/jsdoc-toolkit/app/plugins/commentSrcJson.js +20 -0
- data/vendor/jsdoc-toolkit/app/plugins/frameworkPrototype.js +16 -0
- data/vendor/jsdoc-toolkit/app/plugins/functionCall.js +10 -0
- data/vendor/jsdoc-toolkit/app/plugins/publishSrcHilite.js +54 -0
- data/vendor/jsdoc-toolkit/app/plugins/symbolLink.js +10 -0
- data/vendor/jsdoc-toolkit/app/plugins/tagParamConfig.js +31 -0
- data/vendor/jsdoc-toolkit/app/plugins/tagSynonyms.js +43 -0
- data/vendor/jsdoc-toolkit/app/run.js +348 -0
- data/vendor/jsdoc-toolkit/app/t/TestDoc.js +144 -0
- data/vendor/jsdoc-toolkit/app/t/runner.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/addon.js +24 -0
- data/vendor/jsdoc-toolkit/app/test/anon_inner.js +14 -0
- data/vendor/jsdoc-toolkit/app/test/augments.js +31 -0
- data/vendor/jsdoc-toolkit/app/test/augments2.js +26 -0
- data/vendor/jsdoc-toolkit/app/test/borrows.js +46 -0
- data/vendor/jsdoc-toolkit/app/test/borrows2.js +23 -0
- data/vendor/jsdoc-toolkit/app/test/config.js +22 -0
- data/vendor/jsdoc-toolkit/app/test/constructs.js +18 -0
- data/vendor/jsdoc-toolkit/app/test/encoding.js +10 -0
- data/vendor/jsdoc-toolkit/app/test/encoding_other.js +12 -0
- data/vendor/jsdoc-toolkit/app/test/event.js +54 -0
- data/vendor/jsdoc-toolkit/app/test/exports.js +14 -0
- data/vendor/jsdoc-toolkit/app/test/functions_anon.js +39 -0
- data/vendor/jsdoc-toolkit/app/test/functions_nested.js +33 -0
- data/vendor/jsdoc-toolkit/app/test/global.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/globals.js +25 -0
- data/vendor/jsdoc-toolkit/app/test/ignore.js +10 -0
- data/vendor/jsdoc-toolkit/app/test/inner.js +16 -0
- data/vendor/jsdoc-toolkit/app/test/jsdoc_test.js +477 -0
- data/vendor/jsdoc-toolkit/app/test/lend.js +33 -0
- data/vendor/jsdoc-toolkit/app/test/memberof.js +19 -0
- data/vendor/jsdoc-toolkit/app/test/memberof2.js +38 -0
- data/vendor/jsdoc-toolkit/app/test/memberof3.js +33 -0
- data/vendor/jsdoc-toolkit/app/test/memberof_constructor.js +17 -0
- data/vendor/jsdoc-toolkit/app/test/module.js +17 -0
- data/vendor/jsdoc-toolkit/app/test/name.js +19 -0
- data/vendor/jsdoc-toolkit/app/test/namespace_nested.js +23 -0
- data/vendor/jsdoc-toolkit/app/test/nocode.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/oblit_anon.js +20 -0
- data/vendor/jsdoc-toolkit/app/test/overview.js +20 -0
- data/vendor/jsdoc-toolkit/app/test/param_inline.js +37 -0
- data/vendor/jsdoc-toolkit/app/test/params_optional.js +8 -0
- data/vendor/jsdoc-toolkit/app/test/prototype.js +17 -0
- data/vendor/jsdoc-toolkit/app/test/prototype_nested.js +9 -0
- data/vendor/jsdoc-toolkit/app/test/prototype_oblit.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/prototype_oblit_constructor.js +24 -0
- data/vendor/jsdoc-toolkit/app/test/public.js +10 -0
- data/vendor/jsdoc-toolkit/app/test/scripts/code.js +5 -0
- data/vendor/jsdoc-toolkit/app/test/scripts/notcode.txt +5 -0
- data/vendor/jsdoc-toolkit/app/test/shared.js +42 -0
- data/vendor/jsdoc-toolkit/app/test/shared2.js +2 -0
- data/vendor/jsdoc-toolkit/app/test/shortcuts.js +22 -0
- data/vendor/jsdoc-toolkit/app/test/static_this.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/synonyms.js +31 -0
- data/vendor/jsdoc-toolkit/app/test/tosource.js +23 -0
- data/vendor/jsdoc-toolkit/app/test/variable_redefine.js +14 -0
- data/vendor/jsdoc-toolkit/app/test.js +342 -0
- data/vendor/jsdoc-toolkit/changes.txt +116 -0
- data/vendor/jsdoc-toolkit/conf/sample.conf +31 -0
- data/vendor/jsdoc-toolkit/java/build.xml +36 -0
- data/vendor/jsdoc-toolkit/java/build_1.4.xml +36 -0
- data/vendor/jsdoc-toolkit/java/classes/js.jar +0 -0
- data/vendor/jsdoc-toolkit/java/src/JsDebugRun.java +21 -0
- data/vendor/jsdoc-toolkit/java/src/JsRun.java +21 -0
- data/vendor/jsdoc-toolkit/jsdebug.jar +0 -0
- data/vendor/jsdoc-toolkit/jsrun.jar +0 -0
- data/vendor/jsdoc-toolkit/jsrun.sh +53 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/allclasses.tmpl +17 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/allfiles.tmpl +56 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/class.tmpl +649 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/index.tmpl +39 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/publish.js +201 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-footer.html +3 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-header.html +14 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/default.css +162 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/header.html +2 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/index.html +19 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/symbol.tmpl +35 -0
- data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.cpp +333 -0
- data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.h +86 -0
- data/vendor/jsl-0.3.0/src/Makefile.in +375 -0
- data/vendor/jsl-0.3.0/src/Makefile.ref +372 -0
- data/vendor/jsl-0.3.0/src/README.html +826 -0
- data/vendor/jsl-0.3.0/src/SpiderMonkey.rsp +12 -0
- data/vendor/jsl-0.3.0/src/_jsl_online.php +223 -0
- data/vendor/jsl-0.3.0/src/config/AIX4.1.mk +65 -0
- data/vendor/jsl-0.3.0/src/config/AIX4.2.mk +64 -0
- data/vendor/jsl-0.3.0/src/config/AIX4.3.mk +65 -0
- data/vendor/jsl-0.3.0/src/config/Darwin.mk +81 -0
- data/vendor/jsl-0.3.0/src/config/Darwin1.3.mk +81 -0
- data/vendor/jsl-0.3.0/src/config/Darwin1.4.mk +41 -0
- data/vendor/jsl-0.3.0/src/config/Darwin5.2.mk +81 -0
- data/vendor/jsl-0.3.0/src/config/Darwin5.3.mk +81 -0
- data/vendor/jsl-0.3.0/src/config/HP-UXB.10.10.mk +77 -0
- data/vendor/jsl-0.3.0/src/config/HP-UXB.10.20.mk +77 -0
- data/vendor/jsl-0.3.0/src/config/HP-UXB.11.00.mk +80 -0
- data/vendor/jsl-0.3.0/src/config/IRIX.mk +87 -0
- data/vendor/jsl-0.3.0/src/config/IRIX5.3.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/IRIX6.1.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/IRIX6.2.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/IRIX6.3.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/IRIX6.5.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/Linux_All.mk +103 -0
- data/vendor/jsl-0.3.0/src/config/Mac_OS10.0.mk +82 -0
- data/vendor/jsl-0.3.0/src/config/OSF1V4.0.mk +72 -0
- data/vendor/jsl-0.3.0/src/config/OSF1V5.0.mk +69 -0
- data/vendor/jsl-0.3.0/src/config/SunOS4.1.4.mk +101 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.3.mk +91 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.4.mk +92 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.5.1.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.5.mk +87 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.6.mk +89 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.7.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.8.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.9.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/WINNT4.0.mk +112 -0
- data/vendor/jsl-0.3.0/src/config/WINNT5.0.mk +112 -0
- data/vendor/jsl-0.3.0/src/config/WINNT5.1.mk +112 -0
- data/vendor/jsl-0.3.0/src/config/WINNT5.2.mk +112 -0
- data/vendor/jsl-0.3.0/src/config/dgux.mk +64 -0
- data/vendor/jsl-0.3.0/src/config.mk +166 -0
- data/vendor/jsl-0.3.0/src/editline/Makefile.ref +144 -0
- data/vendor/jsl-0.3.0/src/editline/README +83 -0
- data/vendor/jsl-0.3.0/src/editline/editline.3 +175 -0
- data/vendor/jsl-0.3.0/src/editline/editline.c +1369 -0
- data/vendor/jsl-0.3.0/src/editline/editline.h +135 -0
- data/vendor/jsl-0.3.0/src/editline/sysunix.c +182 -0
- data/vendor/jsl-0.3.0/src/editline/unix.h +82 -0
- data/vendor/jsl-0.3.0/src/fdlibm/Makefile.in +127 -0
- data/vendor/jsl-0.3.0/src/fdlibm/Makefile.ref +192 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_acos.c +147 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_acosh.c +105 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_asin.c +156 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_atan2.c +165 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_atanh.c +110 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_cosh.c +133 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_exp.c +202 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_fmod.c +184 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_gamma.c +71 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_gamma_r.c +70 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_hypot.c +173 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_j0.c +524 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_j1.c +523 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_jn.c +315 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma.c +71 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma_r.c +347 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_log.c +184 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_log10.c +134 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_pow.c +386 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_rem_pio2.c +221 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_remainder.c +120 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_scalb.c +89 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_sinh.c +122 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_sqrt.c +497 -0
- data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.dsp +160 -0
- data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.h +273 -0
- data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mak +1453 -0
- data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mdp +0 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_cos.c +134 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_rem_pio2.c +354 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_sin.c +114 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_standard.c +785 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_tan.c +170 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_asinh.c +101 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_atan.c +175 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_cbrt.c +133 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_ceil.c +120 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_copysign.c +72 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_cos.c +118 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_erf.c +356 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_expm1.c +267 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_fabs.c +70 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_finite.c +71 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_floor.c +121 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_frexp.c +99 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_ilogb.c +85 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_isnan.c +74 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_ldexp.c +66 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_lib_version.c +73 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_log1p.c +211 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_logb.c +79 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_matherr.c +64 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_modf.c +132 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_nextafter.c +124 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_rint.c +131 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_scalbn.c +107 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_signgam.c +40 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_significand.c +68 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_sin.c +118 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_tan.c +112 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_tanh.c +122 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_acos.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_acosh.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_asin.c +80 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_atan2.c +79 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_atanh.c +81 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_cosh.c +77 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_exp.c +88 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_fmod.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_gamma.c +85 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_gamma_r.c +81 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_hypot.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_j0.c +105 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_j1.c +106 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_jn.c +128 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma.c +85 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma_r.c +81 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_log.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_log10.c +81 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_pow.c +99 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_remainder.c +77 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_scalb.c +95 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_sinh.c +77 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_sqrt.c +77 -0
- data/vendor/jsl-0.3.0/src/js.c +2447 -0
- data/vendor/jsl-0.3.0/src/js.dsp +420 -0
- data/vendor/jsl-0.3.0/src/js.mak +4025 -0
- data/vendor/jsl-0.3.0/src/js.mdp +0 -0
- data/vendor/jsl-0.3.0/src/js.msg +291 -0
- data/vendor/jsl-0.3.0/src/js.pkg +2 -0
- data/vendor/jsl-0.3.0/src/js3240.rc +79 -0
- data/vendor/jsl-0.3.0/src/jsOS240.def +654 -0
- data/vendor/jsl-0.3.0/src/jsapi.c +4405 -0
- data/vendor/jsl-0.3.0/src/jsapi.h +1856 -0
- data/vendor/jsl-0.3.0/src/jsarena.c +567 -0
- data/vendor/jsl-0.3.0/src/jsarena.h +302 -0
- data/vendor/jsl-0.3.0/src/jsarray.c +1428 -0
- data/vendor/jsl-0.3.0/src/jsarray.h +77 -0
- data/vendor/jsl-0.3.0/src/jsatom.c +927 -0
- data/vendor/jsl-0.3.0/src/jsatom.h +426 -0
- data/vendor/jsl-0.3.0/src/jsbit.h +113 -0
- data/vendor/jsl-0.3.0/src/jsbool.c +220 -0
- data/vendor/jsl-0.3.0/src/jsbool.h +62 -0
- data/vendor/jsl-0.3.0/src/jsclist.h +139 -0
- data/vendor/jsl-0.3.0/src/jscntxt.c +1036 -0
- data/vendor/jsl-0.3.0/src/jscntxt.h +608 -0
- data/vendor/jsl-0.3.0/src/jscompat.h +57 -0
- data/vendor/jsl-0.3.0/src/jsconfig.h +489 -0
- data/vendor/jsl-0.3.0/src/jsconfig.mk +181 -0
- data/vendor/jsl-0.3.0/src/jscpucfg.c +377 -0
- data/vendor/jsl-0.3.0/src/jscpucfg.h +204 -0
- data/vendor/jsl-0.3.0/src/jsdate.c +2238 -0
- data/vendor/jsl-0.3.0/src/jsdate.h +118 -0
- data/vendor/jsl-0.3.0/src/jsdbgapi.c +1260 -0
- data/vendor/jsl-0.3.0/src/jsdbgapi.h +345 -0
- data/vendor/jsl-0.3.0/src/jsdhash.c +763 -0
- data/vendor/jsl-0.3.0/src/jsdhash.h +579 -0
- data/vendor/jsl-0.3.0/src/jsdtoa.c +3135 -0
- data/vendor/jsl-0.3.0/src/jsdtoa.h +130 -0
- data/vendor/jsl-0.3.0/src/jsemit.c +4851 -0
- data/vendor/jsl-0.3.0/src/jsemit.h +576 -0
- data/vendor/jsl-0.3.0/src/jsexn.c +1084 -0
- data/vendor/jsl-0.3.0/src/jsexn.h +102 -0
- data/vendor/jsl-0.3.0/src/jsfile.c +2610 -0
- data/vendor/jsl-0.3.0/src/jsfile.h +50 -0
- data/vendor/jsl-0.3.0/src/jsfile.msg +89 -0
- data/vendor/jsl-0.3.0/src/jsfun.c +2015 -0
- data/vendor/jsl-0.3.0/src/jsfun.h +158 -0
- data/vendor/jsl-0.3.0/src/jsgc.c +1441 -0
- data/vendor/jsl-0.3.0/src/jsgc.h +230 -0
- data/vendor/jsl-0.3.0/src/jshash.c +471 -0
- data/vendor/jsl-0.3.0/src/jshash.h +152 -0
- data/vendor/jsl-0.3.0/src/jsify.pl +485 -0
- data/vendor/jsl-0.3.0/src/jsinterp.c +4797 -0
- data/vendor/jsl-0.3.0/src/jsinterp.h +302 -0
- data/vendor/jsl-0.3.0/src/jsl-test.js +28 -0
- data/vendor/jsl-0.3.0/src/jsl.c +2371 -0
- data/vendor/jsl-0.3.0/src/jsl.conf +127 -0
- data/vendor/jsl-0.3.0/src/jsl.conf.old +124 -0
- data/vendor/jsl-0.3.0/src/jsl.dsp +242 -0
- data/vendor/jsl-0.3.0/src/jsl.dsw +59 -0
- data/vendor/jsl-0.3.0/src/jslibmath.h +290 -0
- data/vendor/jsl-0.3.0/src/jslock.c +1261 -0
- data/vendor/jsl-0.3.0/src/jslock.h +289 -0
- data/vendor/jsl-0.3.0/src/jslocko.asm +59 -0
- data/vendor/jsl-0.3.0/src/jslog2.c +83 -0
- data/vendor/jsl-0.3.0/src/jslong.c +281 -0
- data/vendor/jsl-0.3.0/src/jslong.h +437 -0
- data/vendor/jsl-0.3.0/src/jsmath.c +477 -0
- data/vendor/jsl-0.3.0/src/jsmath.h +55 -0
- data/vendor/jsl-0.3.0/src/jsnum.c +1148 -0
- data/vendor/jsl-0.3.0/src/jsnum.h +257 -0
- data/vendor/jsl-0.3.0/src/jsobj.c +4066 -0
- data/vendor/jsl-0.3.0/src/jsobj.h +475 -0
- data/vendor/jsl-0.3.0/src/jsopcode.c +2730 -0
- data/vendor/jsl-0.3.0/src/jsopcode.h +275 -0
- data/vendor/jsl-0.3.0/src/jsopcode.tbl +344 -0
- data/vendor/jsl-0.3.0/src/jsosdep.h +127 -0
- data/vendor/jsl-0.3.0/src/jsotypes.h +211 -0
- data/vendor/jsl-0.3.0/src/jsparse.c +4438 -0
- data/vendor/jsl-0.3.0/src/jsparse.h +345 -0
- data/vendor/jsl-0.3.0/src/jsprf.c +1212 -0
- data/vendor/jsl-0.3.0/src/jsprf.h +148 -0
- data/vendor/jsl-0.3.0/src/jsprvtd.h +174 -0
- data/vendor/jsl-0.3.0/src/jspubtd.h +586 -0
- data/vendor/jsl-0.3.0/src/jsregexp.c +3831 -0
- data/vendor/jsl-0.3.0/src/jsregexp.h +180 -0
- data/vendor/jsl-0.3.0/src/jsscan.c +1814 -0
- data/vendor/jsl-0.3.0/src/jsscan.h +267 -0
- data/vendor/jsl-0.3.0/src/jsscope.c +1639 -0
- data/vendor/jsl-0.3.0/src/jsscope.h +389 -0
- data/vendor/jsl-0.3.0/src/jsscript.c +1284 -0
- data/vendor/jsl-0.3.0/src/jsscript.h +179 -0
- data/vendor/jsl-0.3.0/src/jsshell.msg +50 -0
- data/vendor/jsl-0.3.0/src/jsstddef.h +83 -0
- data/vendor/jsl-0.3.0/src/jsstr.c +4502 -0
- data/vendor/jsl-0.3.0/src/jsstr.h +448 -0
- data/vendor/jsl-0.3.0/src/jstypes.h +391 -0
- data/vendor/jsl-0.3.0/src/jsutil.c +157 -0
- data/vendor/jsl-0.3.0/src/jsutil.h +75 -0
- data/vendor/jsl-0.3.0/src/jsxdrapi.c +686 -0
- data/vendor/jsl-0.3.0/src/jsxdrapi.h +193 -0
- data/vendor/jsl-0.3.0/src/liveconnect/LiveConnect.dsp +157 -0
- data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsp +120 -0
- data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsw +44 -0
- data/vendor/jsl-0.3.0/src/liveconnect/Makefile.in +106 -0
- data/vendor/jsl-0.3.0/src/liveconnect/Makefile.ref +169 -0
- data/vendor/jsl-0.3.0/src/liveconnect/README.html +719 -0
- data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSException.h +14 -0
- data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSObject.h +155 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.in +89 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.ref +57 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/Makefile.ref +47 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSException.java +140 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSObject.java +183 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSProxy.java +58 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSRunnable.java +70 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSUtil.java +59 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/Makefile.ref +53 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.1.mk +45 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.2.mk +45 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.3.mk +50 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.10.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.20.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.11.00.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.2.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.3.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.5.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/Linux_All.mk +73 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V4.0.mk +65 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V5.0.mk +62 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.5.1.mk +55 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.6.mk +39 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.7.mk +39 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.8.mk +39 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/WINNT4.0.mk +53 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj.c +884 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj.msg +98 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JSObject.c +1379 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaArray.c +481 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaClass.c +749 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaMember.c +186 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaObject.c +1099 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaPackage.c +548 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_array.c +207 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_class.c +765 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_convert.c +954 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_field.c +421 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.c +504 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.h +161 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_method.c +1823 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_nodl.c +1 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_private.h +689 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_simpleapi.c +219 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_utils.c +513 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsjava.h +313 -0
- data/vendor/jsl-0.3.0/src/liveconnect/liveconnect.pkg +3 -0
- data/vendor/jsl-0.3.0/src/liveconnect/netscape_javascript_JSObject.h +155 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.cpp +785 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.h +197 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.cpp +163 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.h +76 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsILiveconnect.h +195 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsISecureLiveconnect.h +84 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsISecurityContext.h +135 -0
- data/vendor/jsl-0.3.0/src/liveconnect/win32.order +6 -0
- data/vendor/jsl-0.3.0/src/lock_SunOS.s +114 -0
- data/vendor/jsl-0.3.0/src/perfect.js +39 -0
- data/vendor/jsl-0.3.0/src/perlconnect/JS.def +6 -0
- data/vendor/jsl-0.3.0/src/perlconnect/JS.dsp +107 -0
- data/vendor/jsl-0.3.0/src/perlconnect/JS.pm +318 -0
- data/vendor/jsl-0.3.0/src/perlconnect/JS.xs +1050 -0
- data/vendor/jsl-0.3.0/src/perlconnect/Makefile.PL +67 -0
- data/vendor/jsl-0.3.0/src/perlconnect/Makefile.ref +152 -0
- data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsp +103 -0
- data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsw +59 -0
- data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.pm +126 -0
- data/vendor/jsl-0.3.0/src/perlconnect/PerlConnectShell.dsp +89 -0
- data/vendor/jsl-0.3.0/src/perlconnect/README.html +345 -0
- data/vendor/jsl-0.3.0/src/perlconnect/bg.jpg +0 -0
- data/vendor/jsl-0.3.0/src/perlconnect/jsperl.c +1100 -0
- data/vendor/jsl-0.3.0/src/perlconnect/jsperl.h +52 -0
- data/vendor/jsl-0.3.0/src/perlconnect/jsperlbuild.pl +81 -0
- data/vendor/jsl-0.3.0/src/perlconnect/jsperlpvt.h +57 -0
- data/vendor/jsl-0.3.0/src/perlconnect/test.js +73 -0
- data/vendor/jsl-0.3.0/src/perlconnect/test.pl +244 -0
- data/vendor/jsl-0.3.0/src/perlconnect/typemap +121 -0
- data/vendor/jsl-0.3.0/src/plify_jsdhash.sed +31 -0
- data/vendor/jsl-0.3.0/src/prmjtime.c +646 -0
- data/vendor/jsl-0.3.0/src/prmjtime.h +95 -0
- data/vendor/jsl-0.3.0/src/resource.h +15 -0
- data/vendor/jsl-0.3.0/src/rules.mk +193 -0
- data/vendor/jsl-0.3.0/src/win32.order +391 -0
- data/vendor/jsl-0.3.0/tests/conf/always_use_option_explicit.js +4 -0
- data/vendor/jsl-0.3.0/tests/conf/define.js +8 -0
- data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-1.js +7 -0
- data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-2.js +8 -0
- data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-3.js +27 -0
- data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-4.js +4 -0
- data/vendor/jsl-0.3.0/tests/conf/lambda_assign_requires_semicolon.js +24 -0
- data/vendor/jsl-0.3.0/tests/conf/legacy_control_comments.js +8 -0
- data/vendor/jsl-0.3.0/tests/control_comments/control_comments.js +33 -0
- data/vendor/jsl-0.3.0/tests/control_comments/declare.js +26 -0
- data/vendor/jsl-0.3.0/tests/control_comments/import-overflow.js +9 -0
- data/vendor/jsl-0.3.0/tests/control_comments/import.js +5 -0
- data/vendor/jsl-0.3.0/tests/control_comments/import2.js +2 -0
- data/vendor/jsl-0.3.0/tests/control_comments/invalid_fallthru.js +13 -0
- data/vendor/jsl-0.3.0/tests/control_comments/option_explicit-with.js +12 -0
- data/vendor/jsl-0.3.0/tests/control_comments/option_explicit.js +64 -0
- data/vendor/jsl-0.3.0/tests/errors/unterminated_comment.js +8 -0
- data/vendor/jsl-0.3.0/tests/html/script_tag_in_js_literal.html +14 -0
- data/vendor/jsl-0.3.0/tests/run_tests.pl +71 -0
- data/vendor/jsl-0.3.0/tests/warnings/ambiguous_else_stmt.js +21 -0
- data/vendor/jsl-0.3.0/tests/warnings/ambiguous_nested_stmt.js +66 -0
- data/vendor/jsl-0.3.0/tests/warnings/ambiguous_newline.js +261 -0
- data/vendor/jsl-0.3.0/tests/warnings/anon_no_return_value.js +26 -0
- data/vendor/jsl-0.3.0/tests/warnings/assign_to_function_call.js +16 -0
- data/vendor/jsl-0.3.0/tests/warnings/block_without_braces.js +13 -0
- data/vendor/jsl-0.3.0/tests/warnings/comma_separated_stmts.js +17 -0
- data/vendor/jsl-0.3.0/tests/warnings/comparison_type_conv.js +44 -0
- data/vendor/jsl-0.3.0/tests/warnings/default_not_at_end.js +15 -0
- data/vendor/jsl-0.3.0/tests/warnings/dup_option_explicit.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/duplicate_case_in_switch.js +62 -0
- data/vendor/jsl-0.3.0/tests/warnings/duplicate_formal.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/empty_statement.js +29 -0
- data/vendor/jsl-0.3.0/tests/warnings/equal_as_assign.js +7 -0
- data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt-ignore.js +21 -0
- data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt.js +63 -0
- data/vendor/jsl-0.3.0/tests/warnings/jsl_cc_not_understood.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/leading_decimal_point.js +7 -0
- data/vendor/jsl-0.3.0/tests/warnings/legacy_cc_not_understood.js +9 -0
- data/vendor/jsl-0.3.0/tests/warnings/meaningless_block.js +12 -0
- data/vendor/jsl-0.3.0/tests/warnings/misplaced_regex.js +20 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_break.js +87 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_break_for_last_case.js +19 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_default_case.js +51 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_option_explicit.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_semicolon.js +19 -0
- data/vendor/jsl-0.3.0/tests/warnings/multiple_plus_minus.js +10 -0
- data/vendor/jsl-0.3.0/tests/warnings/nested_comment.js +6 -0
- data/vendor/jsl-0.3.0/tests/warnings/no_return_value.js +25 -0
- data/vendor/jsl-0.3.0/tests/warnings/octal_number.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/parseint_missing_radix.js +15 -0
- data/vendor/jsl-0.3.0/tests/warnings/partial_option_explicit.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/redeclared_var.js +10 -0
- data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/bad_backref.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/deprecated_usage.js +11 -0
- data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/invalid_backref.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/trailing_comma.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/trailing_comma_in_array.js +8 -0
- data/vendor/jsl-0.3.0/tests/warnings/trailing_decimal_point.js +7 -0
- data/vendor/jsl-0.3.0/tests/warnings/unreachable_code.js +29 -0
- data/vendor/jsl-0.3.0/tests/warnings/use_of_label.js +19 -0
- data/vendor/jsl-0.3.0/tests/warnings/useless_assign.js +20 -0
- data/vendor/jsl-0.3.0/tests/warnings/useless_comparison.js +55 -0
- data/vendor/jsl-0.3.0/tests/warnings/useless_void.js +6 -0
- data/vendor/jsl-0.3.0/tests/warnings/var_hides_arg.js +4 -0
- data/vendor/jsl-0.3.0/tests/warnings/with_statement.js +7 -0
- data/vendor/yuicompressor-2.4.2.jar +0 -0
- metadata +605 -0
|
@@ -0,0 +1,2730 @@
|
|
|
1
|
+
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
2
|
+
*
|
|
3
|
+
* ***** BEGIN LICENSE BLOCK *****
|
|
4
|
+
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
5
|
+
*
|
|
6
|
+
* The contents of this file are subject to the Mozilla Public License Version
|
|
7
|
+
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
8
|
+
* the License. You may obtain a copy of the License at
|
|
9
|
+
* http://www.mozilla.org/MPL/
|
|
10
|
+
*
|
|
11
|
+
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
12
|
+
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
13
|
+
* for the specific language governing rights and limitations under the
|
|
14
|
+
* License.
|
|
15
|
+
*
|
|
16
|
+
* The Original Code is Mozilla Communicator client code, released
|
|
17
|
+
* March 31, 1998.
|
|
18
|
+
*
|
|
19
|
+
* The Initial Developer of the Original Code is
|
|
20
|
+
* Netscape Communications Corporation.
|
|
21
|
+
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
22
|
+
* the Initial Developer. All Rights Reserved.
|
|
23
|
+
*
|
|
24
|
+
* Contributor(s):
|
|
25
|
+
*
|
|
26
|
+
* Alternatively, the contents of this file may be used under the terms of
|
|
27
|
+
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
28
|
+
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
29
|
+
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
30
|
+
* of those above. If you wish to allow use of your version of this file only
|
|
31
|
+
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
32
|
+
* use your version of this file under the terms of the MPL, indicate your
|
|
33
|
+
* decision by deleting the provisions above and replace them with the notice
|
|
34
|
+
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
35
|
+
* the provisions above, a recipient may use your version of this file under
|
|
36
|
+
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
37
|
+
*
|
|
38
|
+
* ***** END LICENSE BLOCK ***** */
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
* JS bytecode descriptors, disassemblers, and decompilers.
|
|
42
|
+
*/
|
|
43
|
+
#include "jsstddef.h"
|
|
44
|
+
#ifdef HAVE_MEMORY_H
|
|
45
|
+
#include <memory.h>
|
|
46
|
+
#endif
|
|
47
|
+
#include <stdarg.h>
|
|
48
|
+
#include <stdio.h>
|
|
49
|
+
#include <stdlib.h>
|
|
50
|
+
#include <string.h>
|
|
51
|
+
#include "jstypes.h"
|
|
52
|
+
#include "jsarena.h" /* Added by JSIFY */
|
|
53
|
+
#include "jsutil.h" /* Added by JSIFY */
|
|
54
|
+
#include "jsdtoa.h"
|
|
55
|
+
#include "jsprf.h"
|
|
56
|
+
#include "jsapi.h"
|
|
57
|
+
#include "jsarray.h"
|
|
58
|
+
#include "jsatom.h"
|
|
59
|
+
#include "jscntxt.h"
|
|
60
|
+
#include "jsconfig.h"
|
|
61
|
+
#include "jsdbgapi.h"
|
|
62
|
+
#include "jsemit.h"
|
|
63
|
+
#include "jsfun.h"
|
|
64
|
+
#include "jslock.h"
|
|
65
|
+
#include "jsobj.h"
|
|
66
|
+
#include "jsopcode.h"
|
|
67
|
+
#include "jsregexp.h"
|
|
68
|
+
#include "jsscope.h"
|
|
69
|
+
#include "jsscript.h"
|
|
70
|
+
#include "jsstr.h"
|
|
71
|
+
|
|
72
|
+
const char js_const_str[] = "const";
|
|
73
|
+
const char js_var_str[] = "var";
|
|
74
|
+
const char js_function_str[] = "function";
|
|
75
|
+
const char js_in_str[] = "in";
|
|
76
|
+
const char js_instanceof_str[] = "instanceof";
|
|
77
|
+
const char js_new_str[] = "new";
|
|
78
|
+
const char js_delete_str[] = "delete";
|
|
79
|
+
const char js_typeof_str[] = "typeof";
|
|
80
|
+
const char js_void_str[] = "void";
|
|
81
|
+
const char js_null_str[] = "null";
|
|
82
|
+
const char js_this_str[] = "this";
|
|
83
|
+
const char js_false_str[] = "false";
|
|
84
|
+
const char js_true_str[] = "true";
|
|
85
|
+
|
|
86
|
+
const char *js_incop_str[] = {"++", "--"};
|
|
87
|
+
|
|
88
|
+
/* Pollute the namespace locally for MSVC Win16, but not for WatCom. */
|
|
89
|
+
#ifdef __WINDOWS_386__
|
|
90
|
+
#ifdef FAR
|
|
91
|
+
#undef FAR
|
|
92
|
+
#endif
|
|
93
|
+
#else /* !__WINDOWS_386__ */
|
|
94
|
+
#ifndef FAR
|
|
95
|
+
#define FAR
|
|
96
|
+
#endif
|
|
97
|
+
#endif /* !__WINDOWS_386__ */
|
|
98
|
+
|
|
99
|
+
const JSCodeSpec FAR js_CodeSpec[] = {
|
|
100
|
+
#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
|
|
101
|
+
{name,token,length,nuses,ndefs,prec,format},
|
|
102
|
+
#include "jsopcode.tbl"
|
|
103
|
+
#undef OPDEF
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
uintN js_NumCodeSpecs = sizeof (js_CodeSpec) / sizeof js_CodeSpec[0];
|
|
107
|
+
|
|
108
|
+
/************************************************************************/
|
|
109
|
+
|
|
110
|
+
static ptrdiff_t
|
|
111
|
+
GetJumpOffset(jsbytecode *pc, jsbytecode *pc2)
|
|
112
|
+
{
|
|
113
|
+
uint32 type;
|
|
114
|
+
|
|
115
|
+
type = (js_CodeSpec[*pc].format & JOF_TYPEMASK);
|
|
116
|
+
if (JOF_TYPE_IS_EXTENDED_JUMP(type))
|
|
117
|
+
return GET_JUMPX_OFFSET(pc2);
|
|
118
|
+
return GET_JUMP_OFFSET(pc2);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#ifdef DEBUG
|
|
122
|
+
|
|
123
|
+
JS_FRIEND_API(void)
|
|
124
|
+
js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp)
|
|
125
|
+
{
|
|
126
|
+
jsbytecode *pc, *end;
|
|
127
|
+
uintN len;
|
|
128
|
+
|
|
129
|
+
pc = script->code;
|
|
130
|
+
end = pc + script->length;
|
|
131
|
+
while (pc < end) {
|
|
132
|
+
if (pc == script->main)
|
|
133
|
+
fputs("main:\n", fp);
|
|
134
|
+
len = js_Disassemble1(cx, script, pc,
|
|
135
|
+
PTRDIFF(pc, script->code, jsbytecode),
|
|
136
|
+
lines, fp);
|
|
137
|
+
if (!len)
|
|
138
|
+
return;
|
|
139
|
+
pc += len;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
JS_FRIEND_API(uintN)
|
|
144
|
+
js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
|
|
145
|
+
JSBool lines, FILE *fp)
|
|
146
|
+
{
|
|
147
|
+
JSOp op;
|
|
148
|
+
const JSCodeSpec *cs;
|
|
149
|
+
ptrdiff_t len, off, jmplen;
|
|
150
|
+
uint32 type;
|
|
151
|
+
JSAtom *atom;
|
|
152
|
+
JSString *str;
|
|
153
|
+
char *cstr;
|
|
154
|
+
|
|
155
|
+
op = (JSOp)*pc;
|
|
156
|
+
if (op >= JSOP_LIMIT) {
|
|
157
|
+
char numBuf1[12], numBuf2[12];
|
|
158
|
+
JS_snprintf(numBuf1, sizeof numBuf1, "%d", op);
|
|
159
|
+
JS_snprintf(numBuf2, sizeof numBuf2, "%d", JSOP_LIMIT);
|
|
160
|
+
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
161
|
+
JSMSG_BYTECODE_TOO_BIG, numBuf1, numBuf2);
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
cs = &js_CodeSpec[op];
|
|
165
|
+
len = (ptrdiff_t) cs->length;
|
|
166
|
+
fprintf(fp, "%05u:", loc);
|
|
167
|
+
if (lines)
|
|
168
|
+
fprintf(fp, "%4u", JS_PCToLineNumber(cx, script, pc));
|
|
169
|
+
fprintf(fp, " %s", cs->name);
|
|
170
|
+
type = cs->format & JOF_TYPEMASK;
|
|
171
|
+
switch (type) {
|
|
172
|
+
case JOF_BYTE:
|
|
173
|
+
if (op == JSOP_TRAP) {
|
|
174
|
+
op = JS_GetTrapOpcode(cx, script, pc);
|
|
175
|
+
if (op == JSOP_LIMIT)
|
|
176
|
+
return 0;
|
|
177
|
+
len = (ptrdiff_t) js_CodeSpec[op].length;
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
|
|
181
|
+
case JOF_JUMP:
|
|
182
|
+
case JOF_JUMPX:
|
|
183
|
+
off = GetJumpOffset(pc, pc);
|
|
184
|
+
fprintf(fp, " %u (%d)", loc + off, off);
|
|
185
|
+
break;
|
|
186
|
+
|
|
187
|
+
case JOF_CONST:
|
|
188
|
+
atom = GET_ATOM(cx, script, pc);
|
|
189
|
+
str = js_ValueToSource(cx, ATOM_KEY(atom));
|
|
190
|
+
if (!str)
|
|
191
|
+
return 0;
|
|
192
|
+
cstr = js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
|
|
193
|
+
if (!cstr)
|
|
194
|
+
return 0;
|
|
195
|
+
fprintf(fp, " %s", cstr);
|
|
196
|
+
JS_free(cx, cstr);
|
|
197
|
+
break;
|
|
198
|
+
|
|
199
|
+
case JOF_UINT16:
|
|
200
|
+
fprintf(fp, " %u", GET_ARGC(pc));
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
#if JS_HAS_SWITCH_STATEMENT
|
|
204
|
+
case JOF_TABLESWITCH:
|
|
205
|
+
case JOF_TABLESWITCHX:
|
|
206
|
+
{
|
|
207
|
+
jsbytecode *pc2;
|
|
208
|
+
jsint i, low, high;
|
|
209
|
+
|
|
210
|
+
jmplen = (type == JOF_TABLESWITCH) ? JUMP_OFFSET_LEN
|
|
211
|
+
: JUMPX_OFFSET_LEN;
|
|
212
|
+
pc2 = pc;
|
|
213
|
+
off = GetJumpOffset(pc, pc2);
|
|
214
|
+
pc2 += jmplen;
|
|
215
|
+
low = GET_JUMP_OFFSET(pc2);
|
|
216
|
+
pc2 += JUMP_OFFSET_LEN;
|
|
217
|
+
high = GET_JUMP_OFFSET(pc2);
|
|
218
|
+
pc2 += JUMP_OFFSET_LEN;
|
|
219
|
+
fprintf(fp, " defaultOffset %d low %d high %d", off, low, high);
|
|
220
|
+
for (i = low; i <= high; i++) {
|
|
221
|
+
off = GetJumpOffset(pc, pc2);
|
|
222
|
+
fprintf(fp, "\n\t%d: %d", i, off);
|
|
223
|
+
pc2 += jmplen;
|
|
224
|
+
}
|
|
225
|
+
len = 1 + pc2 - pc;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
case JOF_LOOKUPSWITCH:
|
|
230
|
+
case JOF_LOOKUPSWITCHX:
|
|
231
|
+
{
|
|
232
|
+
jsbytecode *pc2;
|
|
233
|
+
jsatomid npairs;
|
|
234
|
+
|
|
235
|
+
jmplen = (type == JOF_LOOKUPSWITCH) ? JUMP_OFFSET_LEN
|
|
236
|
+
: JUMPX_OFFSET_LEN;
|
|
237
|
+
pc2 = pc;
|
|
238
|
+
off = GetJumpOffset(pc, pc2);
|
|
239
|
+
pc2 += jmplen;
|
|
240
|
+
npairs = GET_ATOM_INDEX(pc2);
|
|
241
|
+
pc2 += ATOM_INDEX_LEN;
|
|
242
|
+
fprintf(fp, " offset %d npairs %u", off, (uintN) npairs);
|
|
243
|
+
while (npairs) {
|
|
244
|
+
atom = GET_ATOM(cx, script, pc2);
|
|
245
|
+
pc2 += ATOM_INDEX_LEN;
|
|
246
|
+
off = GetJumpOffset(pc, pc2);
|
|
247
|
+
pc2 += jmplen;
|
|
248
|
+
|
|
249
|
+
str = js_ValueToSource(cx, ATOM_KEY(atom));
|
|
250
|
+
if (!str)
|
|
251
|
+
return 0;
|
|
252
|
+
cstr = js_DeflateString(cx, JSSTRING_CHARS(str),
|
|
253
|
+
JSSTRING_LENGTH(str));
|
|
254
|
+
if (!cstr)
|
|
255
|
+
return 0;
|
|
256
|
+
fprintf(fp, "\n\t%s: %d", cstr, off);
|
|
257
|
+
JS_free(cx, cstr);
|
|
258
|
+
npairs--;
|
|
259
|
+
}
|
|
260
|
+
len = 1 + pc2 - pc;
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
#endif /* JS_HAS_SWITCH_STATEMENT */
|
|
264
|
+
|
|
265
|
+
case JOF_QARG:
|
|
266
|
+
fprintf(fp, " %u", GET_ARGNO(pc));
|
|
267
|
+
break;
|
|
268
|
+
|
|
269
|
+
case JOF_QVAR:
|
|
270
|
+
fprintf(fp, " %u", GET_VARNO(pc));
|
|
271
|
+
break;
|
|
272
|
+
|
|
273
|
+
#if JS_HAS_LEXICAL_CLOSURE
|
|
274
|
+
case JOF_DEFLOCALVAR:
|
|
275
|
+
fprintf(fp, " %u", GET_VARNO(pc));
|
|
276
|
+
pc += VARNO_LEN;
|
|
277
|
+
atom = GET_ATOM(cx, script, pc);
|
|
278
|
+
str = js_ValueToSource(cx, ATOM_KEY(atom));
|
|
279
|
+
if (!str)
|
|
280
|
+
return 0;
|
|
281
|
+
cstr = js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
|
|
282
|
+
if (!cstr)
|
|
283
|
+
return 0;
|
|
284
|
+
fprintf(fp, " %s", cstr);
|
|
285
|
+
JS_free(cx, cstr);
|
|
286
|
+
break;
|
|
287
|
+
#endif
|
|
288
|
+
|
|
289
|
+
default: {
|
|
290
|
+
char numBuf[12];
|
|
291
|
+
JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format);
|
|
292
|
+
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
293
|
+
JSMSG_UNKNOWN_FORMAT, numBuf);
|
|
294
|
+
return 0;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
fputs("\n", fp);
|
|
298
|
+
return len;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
#endif /* DEBUG */
|
|
302
|
+
|
|
303
|
+
/************************************************************************/
|
|
304
|
+
|
|
305
|
+
/*
|
|
306
|
+
* Sprintf, but with unlimited and automatically allocated buffering.
|
|
307
|
+
*/
|
|
308
|
+
typedef struct Sprinter {
|
|
309
|
+
JSContext *context; /* context executing the decompiler */
|
|
310
|
+
JSArenaPool *pool; /* string allocation pool */
|
|
311
|
+
char *base; /* base address of buffer in pool */
|
|
312
|
+
size_t size; /* size of buffer allocated at base */
|
|
313
|
+
ptrdiff_t offset; /* offset of next free char in buffer */
|
|
314
|
+
} Sprinter;
|
|
315
|
+
|
|
316
|
+
#define INIT_SPRINTER(cx, sp, ap, off) \
|
|
317
|
+
((sp)->context = cx, (sp)->pool = ap, (sp)->base = NULL, (sp)->size = 0, \
|
|
318
|
+
(sp)->offset = off)
|
|
319
|
+
|
|
320
|
+
#define OFF2STR(sp,off) ((sp)->base + (off))
|
|
321
|
+
#define STR2OFF(sp,str) ((str) - (sp)->base)
|
|
322
|
+
#define RETRACT(sp,str) ((sp)->offset = STR2OFF(sp, str))
|
|
323
|
+
|
|
324
|
+
static JSBool
|
|
325
|
+
SprintAlloc(Sprinter *sp, size_t nb)
|
|
326
|
+
{
|
|
327
|
+
if (!sp->base) {
|
|
328
|
+
JS_ARENA_ALLOCATE_CAST(sp->base, char *, sp->pool, nb);
|
|
329
|
+
} else {
|
|
330
|
+
JS_ARENA_GROW_CAST(sp->base, char *, sp->pool, sp->size, nb);
|
|
331
|
+
}
|
|
332
|
+
if (!sp->base) {
|
|
333
|
+
JS_ReportOutOfMemory(sp->context);
|
|
334
|
+
return JS_FALSE;
|
|
335
|
+
}
|
|
336
|
+
sp->size += nb;
|
|
337
|
+
return JS_TRUE;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
static ptrdiff_t
|
|
341
|
+
SprintPut(Sprinter *sp, const char *s, size_t len)
|
|
342
|
+
{
|
|
343
|
+
ptrdiff_t nb, offset;
|
|
344
|
+
char *bp;
|
|
345
|
+
|
|
346
|
+
/* Allocate space for s, including the '\0' at the end. */
|
|
347
|
+
nb = (sp->offset + len + 1) - sp->size;
|
|
348
|
+
if (nb > 0 && !SprintAlloc(sp, nb))
|
|
349
|
+
return -1;
|
|
350
|
+
|
|
351
|
+
/* Advance offset and copy s into sp's buffer. */
|
|
352
|
+
offset = sp->offset;
|
|
353
|
+
sp->offset += len;
|
|
354
|
+
bp = sp->base + offset;
|
|
355
|
+
memmove(bp, s, len);
|
|
356
|
+
bp[len] = 0;
|
|
357
|
+
return offset;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
static ptrdiff_t
|
|
361
|
+
Sprint(Sprinter *sp, const char *format, ...)
|
|
362
|
+
{
|
|
363
|
+
va_list ap;
|
|
364
|
+
char *bp;
|
|
365
|
+
ptrdiff_t offset;
|
|
366
|
+
|
|
367
|
+
va_start(ap, format);
|
|
368
|
+
bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
|
|
369
|
+
va_end(ap);
|
|
370
|
+
if (!bp) {
|
|
371
|
+
JS_ReportOutOfMemory(sp->context);
|
|
372
|
+
return -1;
|
|
373
|
+
}
|
|
374
|
+
offset = SprintPut(sp, bp, strlen(bp));
|
|
375
|
+
free(bp);
|
|
376
|
+
return offset;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const jschar js_EscapeMap[] = {
|
|
380
|
+
'\b', 'b',
|
|
381
|
+
'\f', 'f',
|
|
382
|
+
'\n', 'n',
|
|
383
|
+
'\r', 'r',
|
|
384
|
+
'\t', 't',
|
|
385
|
+
'\v', 'v',
|
|
386
|
+
'"', '"',
|
|
387
|
+
'\'', '\'',
|
|
388
|
+
'\\', '\\',
|
|
389
|
+
0
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
static char *
|
|
393
|
+
QuoteString(Sprinter *sp, JSString *str, jschar quote)
|
|
394
|
+
{
|
|
395
|
+
ptrdiff_t off, len, nb;
|
|
396
|
+
const jschar *s, *t, *u, *z;
|
|
397
|
+
char *bp;
|
|
398
|
+
jschar c;
|
|
399
|
+
JSBool ok;
|
|
400
|
+
|
|
401
|
+
/* Sample off first for later return value pointer computation. */
|
|
402
|
+
off = sp->offset;
|
|
403
|
+
if (quote && Sprint(sp, "%c", (char)quote) < 0)
|
|
404
|
+
return NULL;
|
|
405
|
+
|
|
406
|
+
/* Loop control variables: z points at end of string sentinel. */
|
|
407
|
+
s = JSSTRING_CHARS(str);
|
|
408
|
+
z = s + JSSTRING_LENGTH(str);
|
|
409
|
+
for (t = s; t < z; s = ++t) {
|
|
410
|
+
/* Move t forward from s past un-quote-worthy characters. */
|
|
411
|
+
c = *t;
|
|
412
|
+
while (JS_ISPRINT(c) && c != quote && c != '\\' && !(c >> 8)) {
|
|
413
|
+
c = *++t;
|
|
414
|
+
if (t == z)
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
len = PTRDIFF(t, s, jschar);
|
|
418
|
+
|
|
419
|
+
/* Allocate space for s, including the '\0' at the end. */
|
|
420
|
+
nb = (sp->offset + len + 1) - sp->size;
|
|
421
|
+
if (nb > 0 && !SprintAlloc(sp, nb))
|
|
422
|
+
return NULL;
|
|
423
|
+
|
|
424
|
+
/* Advance sp->offset and copy s into sp's buffer. */
|
|
425
|
+
bp = sp->base + sp->offset;
|
|
426
|
+
sp->offset += len;
|
|
427
|
+
while (--len >= 0)
|
|
428
|
+
*bp++ = (char) *s++;
|
|
429
|
+
*bp = '\0';
|
|
430
|
+
|
|
431
|
+
if (t == z)
|
|
432
|
+
break;
|
|
433
|
+
|
|
434
|
+
/* Use js_EscapeMap, \u, or \x only if necessary. */
|
|
435
|
+
if ((u = js_strchr(js_EscapeMap, c)) != NULL)
|
|
436
|
+
ok = Sprint(sp, "\\%c", (char)u[1]) >= 0;
|
|
437
|
+
else
|
|
438
|
+
ok = Sprint(sp, (c >> 8) ? "\\u%04X" : "\\x%02X", c) >= 0;
|
|
439
|
+
if (!ok)
|
|
440
|
+
return NULL;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/* Sprint the closing quote and return the quoted string. */
|
|
444
|
+
if (quote && Sprint(sp, "%c", (char)quote) < 0)
|
|
445
|
+
return NULL;
|
|
446
|
+
return OFF2STR(sp, off);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
JSString *
|
|
450
|
+
js_QuoteString(JSContext *cx, JSString *str, jschar quote)
|
|
451
|
+
{
|
|
452
|
+
void *mark;
|
|
453
|
+
Sprinter sprinter;
|
|
454
|
+
char *bytes;
|
|
455
|
+
JSString *escstr;
|
|
456
|
+
|
|
457
|
+
mark = JS_ARENA_MARK(&cx->tempPool);
|
|
458
|
+
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
|
459
|
+
bytes = QuoteString(&sprinter, str, quote);
|
|
460
|
+
escstr = bytes ? JS_NewStringCopyZ(cx, bytes) : NULL;
|
|
461
|
+
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
|
462
|
+
return escstr;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/************************************************************************/
|
|
466
|
+
|
|
467
|
+
struct JSPrinter {
|
|
468
|
+
Sprinter sprinter; /* base class state */
|
|
469
|
+
JSArenaPool pool; /* string allocation pool */
|
|
470
|
+
uintN indent; /* indentation in spaces */
|
|
471
|
+
JSPackedBool pretty; /* pretty-print: indent, use newlines */
|
|
472
|
+
JSPackedBool grouped; /* in parenthesized expression context */
|
|
473
|
+
JSScript *script; /* script being printed */
|
|
474
|
+
JSScope *scope; /* script function scope */
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
/*
|
|
478
|
+
* Hack another flag, a la JS_DONT_PRETTY_PRINT, into uintN indent parameters
|
|
479
|
+
* to functions such as js_DecompileFunction and js_NewPrinter. This time, as
|
|
480
|
+
* opposed to JS_DONT_PRETTY_PRINT back in the dark ages, we can assume that a
|
|
481
|
+
* uintN is at least 32 bits.
|
|
482
|
+
*/
|
|
483
|
+
#define JS_IN_GROUP_CONTEXT 0x10000
|
|
484
|
+
|
|
485
|
+
JSPrinter *
|
|
486
|
+
js_NewPrinter(JSContext *cx, const char *name, uintN indent, JSBool pretty)
|
|
487
|
+
{
|
|
488
|
+
JSPrinter *jp;
|
|
489
|
+
|
|
490
|
+
jp = (JSPrinter *) JS_malloc(cx, sizeof(JSPrinter));
|
|
491
|
+
if (!jp)
|
|
492
|
+
return NULL;
|
|
493
|
+
INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
|
|
494
|
+
JS_InitArenaPool(&jp->pool, name, 256, 1);
|
|
495
|
+
jp->indent = indent & ~JS_IN_GROUP_CONTEXT;
|
|
496
|
+
jp->pretty = pretty;
|
|
497
|
+
jp->grouped = (indent & JS_IN_GROUP_CONTEXT) != 0;
|
|
498
|
+
jp->script = NULL;
|
|
499
|
+
jp->scope = NULL;
|
|
500
|
+
return jp;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
void
|
|
504
|
+
js_DestroyPrinter(JSPrinter *jp)
|
|
505
|
+
{
|
|
506
|
+
JS_FinishArenaPool(&jp->pool);
|
|
507
|
+
JS_free(jp->sprinter.context, jp);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
JSString *
|
|
511
|
+
js_GetPrinterOutput(JSPrinter *jp)
|
|
512
|
+
{
|
|
513
|
+
JSContext *cx;
|
|
514
|
+
JSString *str;
|
|
515
|
+
|
|
516
|
+
cx = jp->sprinter.context;
|
|
517
|
+
if (!jp->sprinter.base)
|
|
518
|
+
return cx->runtime->emptyString;
|
|
519
|
+
str = JS_NewStringCopyZ(cx, jp->sprinter.base);
|
|
520
|
+
if (!str)
|
|
521
|
+
return NULL;
|
|
522
|
+
JS_FreeArenaPool(&jp->pool);
|
|
523
|
+
INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
|
|
524
|
+
return str;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
int
|
|
528
|
+
js_printf(JSPrinter *jp, const char *format, ...)
|
|
529
|
+
{
|
|
530
|
+
va_list ap;
|
|
531
|
+
char *bp, *fp;
|
|
532
|
+
int cc;
|
|
533
|
+
|
|
534
|
+
if (*format == '\0')
|
|
535
|
+
return 0;
|
|
536
|
+
|
|
537
|
+
va_start(ap, format);
|
|
538
|
+
|
|
539
|
+
/* If pretty-printing, expand magic tab into a run of jp->indent spaces. */
|
|
540
|
+
if (*format == '\t') {
|
|
541
|
+
if (jp->pretty && Sprint(&jp->sprinter, "%*s", jp->indent, "") < 0)
|
|
542
|
+
return -1;
|
|
543
|
+
format++;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/* Suppress newlines (must be once per format, at the end) if not pretty. */
|
|
547
|
+
fp = NULL;
|
|
548
|
+
if (!jp->pretty && format[cc = strlen(format)-1] == '\n') {
|
|
549
|
+
fp = JS_strdup(jp->sprinter.context, format);
|
|
550
|
+
if (!fp)
|
|
551
|
+
return -1;
|
|
552
|
+
fp[cc] = '\0';
|
|
553
|
+
format = fp;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/* Allocate temp space, convert format, and put. */
|
|
557
|
+
bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
|
|
558
|
+
if (fp) {
|
|
559
|
+
JS_free(jp->sprinter.context, fp);
|
|
560
|
+
format = NULL;
|
|
561
|
+
}
|
|
562
|
+
if (!bp) {
|
|
563
|
+
JS_ReportOutOfMemory(jp->sprinter.context);
|
|
564
|
+
return -1;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
cc = strlen(bp);
|
|
568
|
+
if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0)
|
|
569
|
+
cc = -1;
|
|
570
|
+
free(bp);
|
|
571
|
+
|
|
572
|
+
va_end(ap);
|
|
573
|
+
return cc;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
JSBool
|
|
577
|
+
js_puts(JSPrinter *jp, const char *s)
|
|
578
|
+
{
|
|
579
|
+
return SprintPut(&jp->sprinter, s, strlen(s)) >= 0;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/************************************************************************/
|
|
583
|
+
|
|
584
|
+
typedef struct SprintStack {
|
|
585
|
+
Sprinter sprinter; /* sprinter for postfix to infix buffering */
|
|
586
|
+
ptrdiff_t *offsets; /* stack of postfix string offsets */
|
|
587
|
+
jsbytecode *opcodes; /* parallel stack of JS opcodes */
|
|
588
|
+
uintN top; /* top of stack index */
|
|
589
|
+
JSPrinter *printer; /* permanent output goes here */
|
|
590
|
+
} SprintStack;
|
|
591
|
+
|
|
592
|
+
/* Gap between stacked strings to allow for insertion of parens and commas. */
|
|
593
|
+
#define PAREN_SLOP (2 + 1)
|
|
594
|
+
|
|
595
|
+
/*
|
|
596
|
+
* These pseudo-ops help js_DecompileValueGenerator decompile JSOP_SETNAME,
|
|
597
|
+
* JSOP_SETPROP, and JSOP_SETELEM, respectively. See the first assertion in
|
|
598
|
+
* PushOff.
|
|
599
|
+
*/
|
|
600
|
+
#define JSOP_GETPROP2 254
|
|
601
|
+
#define JSOP_GETELEM2 255
|
|
602
|
+
|
|
603
|
+
static JSBool
|
|
604
|
+
PushOff(SprintStack *ss, ptrdiff_t off, JSOp op)
|
|
605
|
+
{
|
|
606
|
+
uintN top;
|
|
607
|
+
|
|
608
|
+
#if JSOP_LIMIT > JSOP_GETPROP2
|
|
609
|
+
#error JSOP_LIMIT must be <= JSOP_GETPROP2
|
|
610
|
+
#endif
|
|
611
|
+
if (!SprintAlloc(&ss->sprinter, PAREN_SLOP))
|
|
612
|
+
return JS_FALSE;
|
|
613
|
+
|
|
614
|
+
/* ss->top points to the next free slot; be paranoid about overflow. */
|
|
615
|
+
top = ss->top;
|
|
616
|
+
JS_ASSERT(top < ss->printer->script->depth);
|
|
617
|
+
if (top >= ss->printer->script->depth) {
|
|
618
|
+
JS_ReportOutOfMemory(ss->sprinter.context);
|
|
619
|
+
return JS_FALSE;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/* The opcodes stack must contain real bytecodes that index js_CodeSpec. */
|
|
623
|
+
ss->offsets[top] = off;
|
|
624
|
+
ss->opcodes[top] = (op == JSOP_GETPROP2) ? JSOP_GETPROP
|
|
625
|
+
: (op == JSOP_GETELEM2) ? JSOP_GETELEM
|
|
626
|
+
: (jsbytecode) op;
|
|
627
|
+
ss->top = ++top;
|
|
628
|
+
ss->sprinter.offset += PAREN_SLOP;
|
|
629
|
+
return JS_TRUE;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
static ptrdiff_t
|
|
633
|
+
PopOff(SprintStack *ss, JSOp op)
|
|
634
|
+
{
|
|
635
|
+
uintN top;
|
|
636
|
+
const JSCodeSpec *cs, *topcs;
|
|
637
|
+
ptrdiff_t off;
|
|
638
|
+
|
|
639
|
+
/* ss->top points to the next free slot; be paranoid about underflow. */
|
|
640
|
+
top = ss->top;
|
|
641
|
+
JS_ASSERT(top != 0);
|
|
642
|
+
if (top == 0)
|
|
643
|
+
return 0;
|
|
644
|
+
|
|
645
|
+
ss->top = --top;
|
|
646
|
+
topcs = &js_CodeSpec[ss->opcodes[top]];
|
|
647
|
+
cs = &js_CodeSpec[op];
|
|
648
|
+
if (topcs->prec != 0 && topcs->prec < cs->prec) {
|
|
649
|
+
ss->offsets[top] -= 2;
|
|
650
|
+
ss->sprinter.offset = ss->offsets[top];
|
|
651
|
+
off = Sprint(&ss->sprinter, "(%s)",
|
|
652
|
+
OFF2STR(&ss->sprinter, ss->sprinter.offset + 2));
|
|
653
|
+
} else {
|
|
654
|
+
off = ss->sprinter.offset = ss->offsets[top];
|
|
655
|
+
}
|
|
656
|
+
return off;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
#if JS_HAS_SWITCH_STATEMENT
|
|
660
|
+
typedef struct TableEntry {
|
|
661
|
+
jsval key;
|
|
662
|
+
ptrdiff_t offset;
|
|
663
|
+
JSAtom *label;
|
|
664
|
+
jsint order; /* source order for stable tableswitch sort */
|
|
665
|
+
} TableEntry;
|
|
666
|
+
|
|
667
|
+
static int
|
|
668
|
+
CompareOffsets(const void *v1, const void *v2, void *arg)
|
|
669
|
+
{
|
|
670
|
+
const TableEntry *te1 = (const TableEntry *) v1,
|
|
671
|
+
*te2 = (const TableEntry *) v2;
|
|
672
|
+
|
|
673
|
+
if (te1->offset == te2->offset)
|
|
674
|
+
return (int) (te1->order - te2->order);
|
|
675
|
+
return (int) (te1->offset - te2->offset);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
static JSBool
|
|
679
|
+
Decompile(SprintStack *ss, jsbytecode *pc, intN nb);
|
|
680
|
+
|
|
681
|
+
static JSBool
|
|
682
|
+
DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
|
|
683
|
+
jsbytecode *pc, ptrdiff_t switchLength,
|
|
684
|
+
ptrdiff_t defaultOffset, JSBool isCondSwitch)
|
|
685
|
+
{
|
|
686
|
+
JSContext *cx;
|
|
687
|
+
JSPrinter *jp;
|
|
688
|
+
char *lval, *rval;
|
|
689
|
+
uintN i;
|
|
690
|
+
ptrdiff_t diff, off, off2, caseExprOff;
|
|
691
|
+
jsval key;
|
|
692
|
+
JSString *str;
|
|
693
|
+
|
|
694
|
+
cx = ss->sprinter.context;
|
|
695
|
+
jp = ss->printer;
|
|
696
|
+
|
|
697
|
+
lval = OFF2STR(&ss->sprinter, PopOff(ss, JSOP_NOP));
|
|
698
|
+
js_printf(jp, "\tswitch (%s) {\n", lval);
|
|
699
|
+
|
|
700
|
+
if (tableLength) {
|
|
701
|
+
diff = table[0].offset - defaultOffset;
|
|
702
|
+
if (diff > 0) {
|
|
703
|
+
jp->indent += 2;
|
|
704
|
+
js_printf(jp, "\tdefault:\n");
|
|
705
|
+
jp->indent += 2;
|
|
706
|
+
if (!Decompile(ss, pc + defaultOffset, diff))
|
|
707
|
+
return JS_FALSE;
|
|
708
|
+
jp->indent -= 4;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
caseExprOff = isCondSwitch
|
|
712
|
+
? (ptrdiff_t) js_CodeSpec[JSOP_CONDSWITCH].length
|
|
713
|
+
: 0;
|
|
714
|
+
|
|
715
|
+
for (i = 0; i < tableLength; i++) {
|
|
716
|
+
off = table[i].offset;
|
|
717
|
+
off2 = (i + 1 < tableLength) ? table[i + 1].offset : switchLength;
|
|
718
|
+
|
|
719
|
+
key = table[i].key;
|
|
720
|
+
if (isCondSwitch) {
|
|
721
|
+
ptrdiff_t nextCaseExprOff;
|
|
722
|
+
|
|
723
|
+
/*
|
|
724
|
+
* key encodes the JSOP_CASE bytecode's offset from switchtop.
|
|
725
|
+
* The next case expression follows immediately, unless we are
|
|
726
|
+
* at the last case.
|
|
727
|
+
*/
|
|
728
|
+
nextCaseExprOff = (ptrdiff_t)JSVAL_TO_INT(key);
|
|
729
|
+
nextCaseExprOff += js_CodeSpec[pc[nextCaseExprOff]].length;
|
|
730
|
+
jp->indent += 2;
|
|
731
|
+
if (!Decompile(ss, pc + caseExprOff,
|
|
732
|
+
nextCaseExprOff - caseExprOff)) {
|
|
733
|
+
return JS_FALSE;
|
|
734
|
+
}
|
|
735
|
+
caseExprOff = nextCaseExprOff;
|
|
736
|
+
} else {
|
|
737
|
+
/*
|
|
738
|
+
* key comes from an atom, not the decompiler, so we need to
|
|
739
|
+
* quote it if it's a string literal. But if table[i].label
|
|
740
|
+
* is non-null, key was constant-propagated and label is the
|
|
741
|
+
* name of the const we should show as the case label. We set
|
|
742
|
+
* key to undefined so this identifier is escaped, if required
|
|
743
|
+
* by non-ASCII characters, but not quoted, by QuoteString.
|
|
744
|
+
*/
|
|
745
|
+
if (table[i].label) {
|
|
746
|
+
str = ATOM_TO_STRING(table[i].label);
|
|
747
|
+
key = JSVAL_VOID;
|
|
748
|
+
} else {
|
|
749
|
+
str = js_ValueToString(cx, key);
|
|
750
|
+
if (!str)
|
|
751
|
+
return JS_FALSE;
|
|
752
|
+
}
|
|
753
|
+
rval = QuoteString(&ss->sprinter, str,
|
|
754
|
+
JSVAL_IS_STRING(key) ? (jschar)'"' : 0);
|
|
755
|
+
if (!rval)
|
|
756
|
+
return JS_FALSE;
|
|
757
|
+
RETRACT(&ss->sprinter, rval);
|
|
758
|
+
jp->indent += 2;
|
|
759
|
+
js_printf(jp, "\tcase %s:\n", rval);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
jp->indent += 2;
|
|
763
|
+
if (off <= defaultOffset && defaultOffset < off2) {
|
|
764
|
+
diff = defaultOffset - off;
|
|
765
|
+
if (diff != 0) {
|
|
766
|
+
if (!Decompile(ss, pc + off, diff))
|
|
767
|
+
return JS_FALSE;
|
|
768
|
+
off = defaultOffset;
|
|
769
|
+
}
|
|
770
|
+
jp->indent -= 2;
|
|
771
|
+
js_printf(jp, "\tdefault:\n");
|
|
772
|
+
jp->indent += 2;
|
|
773
|
+
}
|
|
774
|
+
if (!Decompile(ss, pc + off, off2 - off))
|
|
775
|
+
return JS_FALSE;
|
|
776
|
+
jp->indent -= 4;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
if (defaultOffset == switchLength) {
|
|
781
|
+
jp->indent += 2;
|
|
782
|
+
js_printf(jp, "\tdefault:;\n");
|
|
783
|
+
jp->indent -= 2;
|
|
784
|
+
}
|
|
785
|
+
js_printf(jp, "\t}\n");
|
|
786
|
+
return JS_TRUE;
|
|
787
|
+
}
|
|
788
|
+
#endif
|
|
789
|
+
|
|
790
|
+
static JSAtom *
|
|
791
|
+
GetSlotAtom(JSPrinter *jp, JSPropertyOp getter, uintN slot)
|
|
792
|
+
{
|
|
793
|
+
JSScope *scope;
|
|
794
|
+
JSScopeProperty *sprop;
|
|
795
|
+
JSObject *obj, *proto;
|
|
796
|
+
|
|
797
|
+
scope = jp->scope;
|
|
798
|
+
while (scope) {
|
|
799
|
+
for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
|
|
800
|
+
if (sprop->getter != getter)
|
|
801
|
+
continue;
|
|
802
|
+
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
|
|
803
|
+
JS_ASSERT(!JSVAL_IS_INT(sprop->id));
|
|
804
|
+
if ((uintN) sprop->shortid == slot)
|
|
805
|
+
return (JSAtom *) sprop->id;
|
|
806
|
+
}
|
|
807
|
+
obj = scope->object;
|
|
808
|
+
if (!obj)
|
|
809
|
+
break;
|
|
810
|
+
proto = OBJ_GET_PROTO(jp->sprinter.context, obj);
|
|
811
|
+
if (!proto)
|
|
812
|
+
break;
|
|
813
|
+
scope = OBJ_SCOPE(proto);
|
|
814
|
+
}
|
|
815
|
+
return NULL;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
static const char *
|
|
819
|
+
VarPrefix(jssrcnote *sn)
|
|
820
|
+
{
|
|
821
|
+
const char *kw;
|
|
822
|
+
static char buf[8];
|
|
823
|
+
|
|
824
|
+
kw = NULL;
|
|
825
|
+
if (sn) {
|
|
826
|
+
if (SN_TYPE(sn) == SRC_VAR)
|
|
827
|
+
kw = js_var_str;
|
|
828
|
+
else if (SN_TYPE(sn) == SRC_CONST)
|
|
829
|
+
kw = js_const_str;
|
|
830
|
+
}
|
|
831
|
+
if (!kw)
|
|
832
|
+
return "";
|
|
833
|
+
JS_snprintf(buf, sizeof buf, "%s ", kw);
|
|
834
|
+
return buf;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
static JSBool
|
|
838
|
+
Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|
839
|
+
{
|
|
840
|
+
JSContext *cx;
|
|
841
|
+
JSPrinter *jp, *jp2;
|
|
842
|
+
jsbytecode *endpc, *done, *forelem_tail, *forelem_done;
|
|
843
|
+
ptrdiff_t tail, todo, len, oplen, cond, next;
|
|
844
|
+
JSOp op, lastop, saveop;
|
|
845
|
+
const JSCodeSpec *cs, *topcs;
|
|
846
|
+
jssrcnote *sn, *sn2;
|
|
847
|
+
const char *lval, *rval, *xval, *fmt;
|
|
848
|
+
jsint i, argc;
|
|
849
|
+
char **argv;
|
|
850
|
+
JSAtom *atom;
|
|
851
|
+
JSObject *obj;
|
|
852
|
+
JSFunction *fun;
|
|
853
|
+
JSString *str;
|
|
854
|
+
JSBool ok;
|
|
855
|
+
jsval val;
|
|
856
|
+
static const char catch_cookie[] = "/*CATCH*/";
|
|
857
|
+
static const char with_cookie[] = "/*WITH*/";
|
|
858
|
+
|
|
859
|
+
/*
|
|
860
|
+
* Local macros
|
|
861
|
+
*/
|
|
862
|
+
#define DECOMPILE_CODE(pc,nb) if (!Decompile(ss, pc, nb)) return JS_FALSE
|
|
863
|
+
#define POP_STR() OFF2STR(&ss->sprinter, PopOff(ss, op))
|
|
864
|
+
#define LOCAL_ASSERT(expr) JS_ASSERT(expr); if (!(expr)) return JS_FALSE
|
|
865
|
+
|
|
866
|
+
/*
|
|
867
|
+
* Callers know that ATOM_IS_STRING(atom), and we leave it to the optimizer to
|
|
868
|
+
* common ATOM_TO_STRING(atom) here and near the call sites.
|
|
869
|
+
*/
|
|
870
|
+
#define ATOM_IS_IDENTIFIER(atom) \
|
|
871
|
+
(!ATOM_KEYWORD(atom) && js_IsIdentifier(ATOM_TO_STRING(atom)))
|
|
872
|
+
|
|
873
|
+
/*
|
|
874
|
+
* Get atom from script's atom map, quote/escape its string appropriately into
|
|
875
|
+
* rval, and select fmt from the quoted and unquoted alternatives.
|
|
876
|
+
*/
|
|
877
|
+
#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval) \
|
|
878
|
+
JS_BEGIN_MACRO \
|
|
879
|
+
jschar quote_; \
|
|
880
|
+
atom = GET_ATOM(cx, jp->script, pc); \
|
|
881
|
+
if (!ATOM_IS_IDENTIFIER(atom)) { \
|
|
882
|
+
quote_ = '\''; \
|
|
883
|
+
fmt = qfmt; \
|
|
884
|
+
} else { \
|
|
885
|
+
quote_ = 0; \
|
|
886
|
+
fmt = ufmt; \
|
|
887
|
+
} \
|
|
888
|
+
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), quote_); \
|
|
889
|
+
if (!rval) \
|
|
890
|
+
return JS_FALSE; \
|
|
891
|
+
JS_END_MACRO
|
|
892
|
+
|
|
893
|
+
cx = ss->sprinter.context;
|
|
894
|
+
jp = ss->printer;
|
|
895
|
+
endpc = pc + nb;
|
|
896
|
+
forelem_tail = forelem_done = NULL;
|
|
897
|
+
tail = -1;
|
|
898
|
+
todo = -2; /* NB: different from Sprint() error return. */
|
|
899
|
+
op = JSOP_NOP;
|
|
900
|
+
sn = NULL;
|
|
901
|
+
rval = NULL;
|
|
902
|
+
|
|
903
|
+
while (pc < endpc) {
|
|
904
|
+
lastop = op;
|
|
905
|
+
op = saveop = (JSOp) *pc;
|
|
906
|
+
if (op >= JSOP_LIMIT) {
|
|
907
|
+
switch (op) {
|
|
908
|
+
case JSOP_GETPROP2:
|
|
909
|
+
saveop = JSOP_GETPROP;
|
|
910
|
+
break;
|
|
911
|
+
case JSOP_GETELEM2:
|
|
912
|
+
saveop = JSOP_GETELEM;
|
|
913
|
+
break;
|
|
914
|
+
default:;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
cs = &js_CodeSpec[saveop];
|
|
918
|
+
len = oplen = cs->length;
|
|
919
|
+
|
|
920
|
+
if (cs->token) {
|
|
921
|
+
switch (cs->nuses) {
|
|
922
|
+
case 2:
|
|
923
|
+
rval = POP_STR();
|
|
924
|
+
lval = POP_STR();
|
|
925
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
926
|
+
if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
|
|
927
|
+
/* Print only the right operand of the assignment-op. */
|
|
928
|
+
todo = SprintPut(&ss->sprinter, rval, strlen(rval));
|
|
929
|
+
} else {
|
|
930
|
+
todo = Sprint(&ss->sprinter, "%s %s %s",
|
|
931
|
+
lval, cs->token, rval);
|
|
932
|
+
}
|
|
933
|
+
break;
|
|
934
|
+
|
|
935
|
+
case 1:
|
|
936
|
+
rval = POP_STR();
|
|
937
|
+
todo = Sprint(&ss->sprinter, "%s%s", cs->token, rval);
|
|
938
|
+
break;
|
|
939
|
+
|
|
940
|
+
case 0:
|
|
941
|
+
#if JS_HAS_GETTER_SETTER
|
|
942
|
+
if (op == JSOP_GETTER || op == JSOP_SETTER) {
|
|
943
|
+
todo = -2;
|
|
944
|
+
break;
|
|
945
|
+
}
|
|
946
|
+
#endif
|
|
947
|
+
todo = SprintPut(&ss->sprinter, cs->token, strlen(cs->token));
|
|
948
|
+
break;
|
|
949
|
+
|
|
950
|
+
default:
|
|
951
|
+
todo = -2;
|
|
952
|
+
break;
|
|
953
|
+
}
|
|
954
|
+
} else {
|
|
955
|
+
switch (op) {
|
|
956
|
+
case JSOP_NOP:
|
|
957
|
+
/*
|
|
958
|
+
* Check for a do-while loop, a for-loop with an empty
|
|
959
|
+
* initializer part, a labeled statement, a function
|
|
960
|
+
* definition, or try/finally.
|
|
961
|
+
*/
|
|
962
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
963
|
+
todo = -2;
|
|
964
|
+
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
|
|
965
|
+
#if JS_HAS_DO_WHILE_LOOP
|
|
966
|
+
case SRC_WHILE:
|
|
967
|
+
js_printf(jp, "\tdo {\n");
|
|
968
|
+
jp->indent += 4;
|
|
969
|
+
break;
|
|
970
|
+
#endif /* JS_HAS_DO_WHILE_LOOP */
|
|
971
|
+
|
|
972
|
+
case SRC_FOR:
|
|
973
|
+
rval = "";
|
|
974
|
+
|
|
975
|
+
do_forloop:
|
|
976
|
+
/* Skip the JSOP_NOP or JSOP_POP bytecode. */
|
|
977
|
+
pc++;
|
|
978
|
+
|
|
979
|
+
/* Get the cond, next, and loop-closing tail offsets. */
|
|
980
|
+
cond = js_GetSrcNoteOffset(sn, 0);
|
|
981
|
+
next = js_GetSrcNoteOffset(sn, 1);
|
|
982
|
+
tail = js_GetSrcNoteOffset(sn, 2);
|
|
983
|
+
LOCAL_ASSERT(tail + GetJumpOffset(pc+tail, pc+tail) == 0);
|
|
984
|
+
|
|
985
|
+
/* Print the keyword and the possibly empty init-part. */
|
|
986
|
+
js_printf(jp, "\tfor (%s;", rval);
|
|
987
|
+
|
|
988
|
+
if (pc[cond] == JSOP_IFEQ || pc[cond] == JSOP_IFEQX) {
|
|
989
|
+
/* Decompile the loop condition. */
|
|
990
|
+
DECOMPILE_CODE(pc, cond);
|
|
991
|
+
js_printf(jp, " %s", POP_STR());
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/* Need a semicolon whether or not there was a cond. */
|
|
995
|
+
js_puts(jp, ";");
|
|
996
|
+
|
|
997
|
+
if (pc[next] != JSOP_GOTO && pc[next] != JSOP_GOTOX) {
|
|
998
|
+
/* Decompile the loop updater. */
|
|
999
|
+
DECOMPILE_CODE(pc + next, tail - next - 1);
|
|
1000
|
+
js_printf(jp, " %s", POP_STR());
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/* Do the loop body. */
|
|
1004
|
+
js_printf(jp, ") {\n");
|
|
1005
|
+
jp->indent += 4;
|
|
1006
|
+
oplen = (cond) ? js_CodeSpec[pc[cond]].length : 0;
|
|
1007
|
+
DECOMPILE_CODE(pc + cond + oplen, next - cond - oplen);
|
|
1008
|
+
jp->indent -= 4;
|
|
1009
|
+
js_printf(jp, "\t}\n");
|
|
1010
|
+
|
|
1011
|
+
/* Set len so pc skips over the entire loop. */
|
|
1012
|
+
len = tail + js_CodeSpec[pc[tail]].length;
|
|
1013
|
+
break;
|
|
1014
|
+
|
|
1015
|
+
case SRC_LABEL:
|
|
1016
|
+
atom = js_GetAtom(cx, &jp->script->atomMap,
|
|
1017
|
+
(jsatomid) js_GetSrcNoteOffset(sn, 0));
|
|
1018
|
+
jp->indent -= 4;
|
|
1019
|
+
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1020
|
+
if (!rval)
|
|
1021
|
+
return JS_FALSE;
|
|
1022
|
+
RETRACT(&ss->sprinter, rval);
|
|
1023
|
+
js_printf(jp, "\t%s:\n", rval);
|
|
1024
|
+
jp->indent += 4;
|
|
1025
|
+
break;
|
|
1026
|
+
|
|
1027
|
+
case SRC_LABELBRACE:
|
|
1028
|
+
atom = js_GetAtom(cx, &jp->script->atomMap,
|
|
1029
|
+
(jsatomid) js_GetSrcNoteOffset(sn, 0));
|
|
1030
|
+
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1031
|
+
if (!rval)
|
|
1032
|
+
return JS_FALSE;
|
|
1033
|
+
RETRACT(&ss->sprinter, rval);
|
|
1034
|
+
js_printf(jp, "\t%s: {\n", rval);
|
|
1035
|
+
jp->indent += 4;
|
|
1036
|
+
break;
|
|
1037
|
+
|
|
1038
|
+
case SRC_ENDBRACE:
|
|
1039
|
+
jp->indent -= 4;
|
|
1040
|
+
js_printf(jp, "\t}\n");
|
|
1041
|
+
break;
|
|
1042
|
+
|
|
1043
|
+
case SRC_CATCH:
|
|
1044
|
+
jp->indent -= 4;
|
|
1045
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1046
|
+
pc += oplen;
|
|
1047
|
+
js_printf(jp, "\t} catch (");
|
|
1048
|
+
|
|
1049
|
+
LOCAL_ASSERT(*pc == JSOP_NAME);
|
|
1050
|
+
pc += js_CodeSpec[JSOP_NAME].length;
|
|
1051
|
+
LOCAL_ASSERT(*pc == JSOP_PUSHOBJ);
|
|
1052
|
+
pc += js_CodeSpec[JSOP_PUSHOBJ].length;
|
|
1053
|
+
LOCAL_ASSERT(*pc == JSOP_NEWINIT);
|
|
1054
|
+
pc += js_CodeSpec[JSOP_NEWINIT].length;
|
|
1055
|
+
LOCAL_ASSERT(*pc == JSOP_EXCEPTION);
|
|
1056
|
+
pc += js_CodeSpec[JSOP_EXCEPTION].length;
|
|
1057
|
+
LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
|
|
1058
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1059
|
+
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1060
|
+
if (!rval)
|
|
1061
|
+
return JS_FALSE;
|
|
1062
|
+
RETRACT(&ss->sprinter, rval);
|
|
1063
|
+
js_printf(jp, "%s", rval);
|
|
1064
|
+
pc += js_CodeSpec[JSOP_INITCATCHVAR].length;
|
|
1065
|
+
LOCAL_ASSERT(*pc == JSOP_ENTERWITH);
|
|
1066
|
+
pc += js_CodeSpec[JSOP_ENTERWITH].length;
|
|
1067
|
+
|
|
1068
|
+
len = js_GetSrcNoteOffset(sn, 0);
|
|
1069
|
+
if (len) {
|
|
1070
|
+
js_printf(jp, " if ");
|
|
1071
|
+
DECOMPILE_CODE(pc, len);
|
|
1072
|
+
js_printf(jp, "%s", POP_STR());
|
|
1073
|
+
pc += len;
|
|
1074
|
+
LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
|
|
1075
|
+
pc += js_CodeSpec[*pc].length;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
js_printf(jp, ") {\n");
|
|
1079
|
+
jp->indent += 4;
|
|
1080
|
+
todo = Sprint(&ss->sprinter, catch_cookie);
|
|
1081
|
+
len = 0;
|
|
1082
|
+
break;
|
|
1083
|
+
|
|
1084
|
+
case SRC_FUNCDEF:
|
|
1085
|
+
atom = js_GetAtom(cx, &jp->script->atomMap,
|
|
1086
|
+
(jsatomid) js_GetSrcNoteOffset(sn, 0));
|
|
1087
|
+
JS_ASSERT(ATOM_IS_OBJECT(atom));
|
|
1088
|
+
do_function:
|
|
1089
|
+
obj = ATOM_TO_OBJECT(atom);
|
|
1090
|
+
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
|
1091
|
+
jp2 = js_NewPrinter(cx, JS_GetFunctionName(fun),
|
|
1092
|
+
jp->indent, jp->pretty);
|
|
1093
|
+
if (!jp2)
|
|
1094
|
+
return JS_FALSE;
|
|
1095
|
+
jp2->scope = jp->scope;
|
|
1096
|
+
if (js_DecompileFunction(jp2, fun)) {
|
|
1097
|
+
str = js_GetPrinterOutput(jp2);
|
|
1098
|
+
if (str)
|
|
1099
|
+
js_printf(jp, "%s\n", JS_GetStringBytes(str));
|
|
1100
|
+
}
|
|
1101
|
+
js_DestroyPrinter(jp2);
|
|
1102
|
+
break;
|
|
1103
|
+
|
|
1104
|
+
default:;
|
|
1105
|
+
}
|
|
1106
|
+
case JSOP_RETRVAL:
|
|
1107
|
+
break;
|
|
1108
|
+
|
|
1109
|
+
case JSOP_GROUP:
|
|
1110
|
+
/* Use last real op so PopOff adds parens if needed. */
|
|
1111
|
+
todo = PopOff(ss, lastop);
|
|
1112
|
+
|
|
1113
|
+
/* Now add user-supplied parens only if PopOff did not. */
|
|
1114
|
+
cs = &js_CodeSpec[lastop];
|
|
1115
|
+
topcs = &js_CodeSpec[ss->opcodes[ss->top]];
|
|
1116
|
+
if (topcs->prec >= cs->prec) {
|
|
1117
|
+
todo = Sprint(&ss->sprinter, "(%s)",
|
|
1118
|
+
OFF2STR(&ss->sprinter, todo));
|
|
1119
|
+
}
|
|
1120
|
+
break;
|
|
1121
|
+
|
|
1122
|
+
case JSOP_PUSH:
|
|
1123
|
+
case JSOP_PUSHOBJ:
|
|
1124
|
+
case JSOP_BINDNAME:
|
|
1125
|
+
todo = Sprint(&ss->sprinter, "");
|
|
1126
|
+
break;
|
|
1127
|
+
|
|
1128
|
+
#if JS_HAS_EXCEPTIONS
|
|
1129
|
+
case JSOP_TRY:
|
|
1130
|
+
js_printf(jp, "\ttry {\n");
|
|
1131
|
+
jp->indent += 4;
|
|
1132
|
+
todo = -2;
|
|
1133
|
+
break;
|
|
1134
|
+
|
|
1135
|
+
{
|
|
1136
|
+
static const char finally_cookie[] = "/*FINALLY*/";
|
|
1137
|
+
|
|
1138
|
+
case JSOP_FINALLY:
|
|
1139
|
+
jp->indent -= 4;
|
|
1140
|
+
js_printf(jp, "\t} finally {\n");
|
|
1141
|
+
jp->indent += 4;
|
|
1142
|
+
|
|
1143
|
+
/*
|
|
1144
|
+
* We must push an empty string placeholder for gosub's return
|
|
1145
|
+
* address, popped by JSOP_RETSUB and counted by script->depth
|
|
1146
|
+
* but not by ss->top (see JSOP_SETSP, below).
|
|
1147
|
+
*/
|
|
1148
|
+
todo = Sprint(&ss->sprinter, finally_cookie);
|
|
1149
|
+
break;
|
|
1150
|
+
|
|
1151
|
+
case JSOP_RETSUB:
|
|
1152
|
+
rval = POP_STR();
|
|
1153
|
+
LOCAL_ASSERT(strcmp(rval, finally_cookie) == 0);
|
|
1154
|
+
todo = -2;
|
|
1155
|
+
break;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
case JSOP_SWAP:
|
|
1159
|
+
/*
|
|
1160
|
+
* We don't generate this opcode currently, and previously we
|
|
1161
|
+
* did not need to decompile it. If old, serialized bytecode
|
|
1162
|
+
* uses it still, we should fall through and set todo = -2.
|
|
1163
|
+
*/
|
|
1164
|
+
/* FALL THROUGH */
|
|
1165
|
+
|
|
1166
|
+
case JSOP_GOSUB:
|
|
1167
|
+
case JSOP_GOSUBX:
|
|
1168
|
+
/*
|
|
1169
|
+
* JSOP_GOSUB and GOSUBX have no effect on the decompiler's
|
|
1170
|
+
* string stack because the next op in bytecode order finds
|
|
1171
|
+
* the stack balanced by a JSOP_RETSUB executed elsewhere.
|
|
1172
|
+
*/
|
|
1173
|
+
todo = -2;
|
|
1174
|
+
break;
|
|
1175
|
+
|
|
1176
|
+
case JSOP_SETSP:
|
|
1177
|
+
/*
|
|
1178
|
+
* The compiler models operand stack depth and fixes the stack
|
|
1179
|
+
* pointer on entry to a catch clause based on its depth model.
|
|
1180
|
+
* The decompiler must match the code generator's model, which
|
|
1181
|
+
* is why JSOP_FINALLY pushes a cookie that JSOP_RETSUB pops.
|
|
1182
|
+
*/
|
|
1183
|
+
LOCAL_ASSERT(ss->top >= (uintN) GET_ATOM_INDEX(pc));
|
|
1184
|
+
ss->top = (uintN) GET_ATOM_INDEX(pc);
|
|
1185
|
+
break;
|
|
1186
|
+
|
|
1187
|
+
case JSOP_EXCEPTION:
|
|
1188
|
+
/*
|
|
1189
|
+
* The only other JSOP_EXCEPTION case occurs as part of a code
|
|
1190
|
+
* sequence that follows a SRC_CATCH-annotated JSOP_NOP.
|
|
1191
|
+
*/
|
|
1192
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1193
|
+
LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_HIDDEN);
|
|
1194
|
+
todo = -2;
|
|
1195
|
+
break;
|
|
1196
|
+
#endif /* JS_HAS_EXCEPTIONS */
|
|
1197
|
+
|
|
1198
|
+
case JSOP_POP:
|
|
1199
|
+
case JSOP_POPV:
|
|
1200
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1201
|
+
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
|
|
1202
|
+
case SRC_FOR:
|
|
1203
|
+
rval = POP_STR();
|
|
1204
|
+
todo = -2;
|
|
1205
|
+
goto do_forloop;
|
|
1206
|
+
|
|
1207
|
+
case SRC_PCDELTA:
|
|
1208
|
+
/* Pop and save to avoid blowing stack depth budget. */
|
|
1209
|
+
lval = JS_strdup(cx, POP_STR());
|
|
1210
|
+
if (!lval)
|
|
1211
|
+
return JS_FALSE;
|
|
1212
|
+
|
|
1213
|
+
/*
|
|
1214
|
+
* The offset tells distance to the end of the right-hand
|
|
1215
|
+
* operand of the comma operator.
|
|
1216
|
+
*/
|
|
1217
|
+
done = pc + len;
|
|
1218
|
+
pc += js_GetSrcNoteOffset(sn, 0);
|
|
1219
|
+
len = 0;
|
|
1220
|
+
|
|
1221
|
+
if (!Decompile(ss, done, pc - done)) {
|
|
1222
|
+
JS_free(cx, (char *)lval);
|
|
1223
|
+
return JS_FALSE;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/* Pop Decompile result and print comma expression. */
|
|
1227
|
+
rval = POP_STR();
|
|
1228
|
+
todo = Sprint(&ss->sprinter, "%s, %s", lval, rval);
|
|
1229
|
+
JS_free(cx, (char *)lval);
|
|
1230
|
+
break;
|
|
1231
|
+
|
|
1232
|
+
case SRC_HIDDEN:
|
|
1233
|
+
/* Hide this pop, it's from a goto in a with or for/in. */
|
|
1234
|
+
todo = -2;
|
|
1235
|
+
break;
|
|
1236
|
+
|
|
1237
|
+
default:
|
|
1238
|
+
rval = POP_STR();
|
|
1239
|
+
if (*rval != '\0')
|
|
1240
|
+
js_printf(jp, "\t%s;\n", rval);
|
|
1241
|
+
todo = -2;
|
|
1242
|
+
break;
|
|
1243
|
+
}
|
|
1244
|
+
break;
|
|
1245
|
+
|
|
1246
|
+
case JSOP_POP2:
|
|
1247
|
+
(void) PopOff(ss, op);
|
|
1248
|
+
(void) PopOff(ss, op);
|
|
1249
|
+
todo = -2;
|
|
1250
|
+
break;
|
|
1251
|
+
|
|
1252
|
+
case JSOP_ENTERWITH:
|
|
1253
|
+
JS_ASSERT(!js_GetSrcNote(jp->script, pc));
|
|
1254
|
+
rval = POP_STR();
|
|
1255
|
+
js_printf(jp, "\twith (%s) {\n", rval);
|
|
1256
|
+
jp->indent += 4;
|
|
1257
|
+
todo = Sprint(&ss->sprinter, with_cookie);
|
|
1258
|
+
break;
|
|
1259
|
+
|
|
1260
|
+
case JSOP_LEAVEWITH:
|
|
1261
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1262
|
+
todo = -2;
|
|
1263
|
+
if (sn && SN_TYPE(sn) == SRC_HIDDEN)
|
|
1264
|
+
break;
|
|
1265
|
+
rval = POP_STR();
|
|
1266
|
+
if (sn && SN_TYPE(sn) == SRC_CATCH) {
|
|
1267
|
+
LOCAL_ASSERT(strcmp(rval, catch_cookie) == 0);
|
|
1268
|
+
LOCAL_ASSERT((uintN) js_GetSrcNoteOffset(sn, 0) == ss->top);
|
|
1269
|
+
break;
|
|
1270
|
+
}
|
|
1271
|
+
LOCAL_ASSERT(strcmp(rval, with_cookie) == 0);
|
|
1272
|
+
jp->indent -= 4;
|
|
1273
|
+
js_printf(jp, "\t}\n");
|
|
1274
|
+
break;
|
|
1275
|
+
|
|
1276
|
+
case JSOP_SETRVAL:
|
|
1277
|
+
case JSOP_RETURN:
|
|
1278
|
+
lval = js_CodeSpec[JSOP_RETURN].name;
|
|
1279
|
+
rval = POP_STR();
|
|
1280
|
+
if (*rval != '\0')
|
|
1281
|
+
js_printf(jp, "\t%s %s;\n", lval, rval);
|
|
1282
|
+
else
|
|
1283
|
+
js_printf(jp, "\t%s;\n", lval);
|
|
1284
|
+
todo = -2;
|
|
1285
|
+
break;
|
|
1286
|
+
|
|
1287
|
+
#if JS_HAS_EXCEPTIONS
|
|
1288
|
+
case JSOP_THROW:
|
|
1289
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1290
|
+
todo = -2;
|
|
1291
|
+
if (sn && SN_TYPE(sn) == SRC_HIDDEN)
|
|
1292
|
+
break;
|
|
1293
|
+
rval = POP_STR();
|
|
1294
|
+
js_printf(jp, "\t%s %s;\n", cs->name, rval);
|
|
1295
|
+
break;
|
|
1296
|
+
#endif /* JS_HAS_EXCEPTIONS */
|
|
1297
|
+
|
|
1298
|
+
case JSOP_GOTO:
|
|
1299
|
+
case JSOP_GOTOX:
|
|
1300
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1301
|
+
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
|
|
1302
|
+
case SRC_CONT2LABEL:
|
|
1303
|
+
atom = js_GetAtom(cx, &jp->script->atomMap,
|
|
1304
|
+
(jsatomid) js_GetSrcNoteOffset(sn, 0));
|
|
1305
|
+
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1306
|
+
if (!rval)
|
|
1307
|
+
return JS_FALSE;
|
|
1308
|
+
RETRACT(&ss->sprinter, rval);
|
|
1309
|
+
js_printf(jp, "\tcontinue %s;\n", rval);
|
|
1310
|
+
break;
|
|
1311
|
+
case SRC_CONTINUE:
|
|
1312
|
+
js_printf(jp, "\tcontinue;\n");
|
|
1313
|
+
break;
|
|
1314
|
+
case SRC_BREAK2LABEL:
|
|
1315
|
+
atom = js_GetAtom(cx, &jp->script->atomMap,
|
|
1316
|
+
(jsatomid) js_GetSrcNoteOffset(sn, 0));
|
|
1317
|
+
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1318
|
+
if (!rval)
|
|
1319
|
+
return JS_FALSE;
|
|
1320
|
+
RETRACT(&ss->sprinter, rval);
|
|
1321
|
+
js_printf(jp, "\tbreak %s;\n", rval);
|
|
1322
|
+
break;
|
|
1323
|
+
case SRC_HIDDEN:
|
|
1324
|
+
break;
|
|
1325
|
+
default:
|
|
1326
|
+
js_printf(jp, "\tbreak;\n");
|
|
1327
|
+
break;
|
|
1328
|
+
}
|
|
1329
|
+
todo = -2;
|
|
1330
|
+
break;
|
|
1331
|
+
|
|
1332
|
+
case JSOP_IFEQ:
|
|
1333
|
+
case JSOP_IFEQX:
|
|
1334
|
+
len = GetJumpOffset(pc, pc);
|
|
1335
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1336
|
+
|
|
1337
|
+
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
|
|
1338
|
+
case SRC_IF:
|
|
1339
|
+
case SRC_IF_ELSE:
|
|
1340
|
+
rval = POP_STR();
|
|
1341
|
+
js_printf(jp, "\tif (%s) {\n", rval);
|
|
1342
|
+
jp->indent += 4;
|
|
1343
|
+
if (SN_TYPE(sn) == SRC_IF) {
|
|
1344
|
+
DECOMPILE_CODE(pc + oplen, len - oplen);
|
|
1345
|
+
} else {
|
|
1346
|
+
len = js_GetSrcNoteOffset(sn, 0);
|
|
1347
|
+
DECOMPILE_CODE(pc + oplen, len - oplen);
|
|
1348
|
+
jp->indent -= 4;
|
|
1349
|
+
pc += len;
|
|
1350
|
+
LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
|
|
1351
|
+
oplen = js_CodeSpec[*pc].length;
|
|
1352
|
+
len = GetJumpOffset(pc, pc);
|
|
1353
|
+
js_printf(jp, "\t} else {\n");
|
|
1354
|
+
jp->indent += 4;
|
|
1355
|
+
DECOMPILE_CODE(pc + oplen, len - oplen);
|
|
1356
|
+
}
|
|
1357
|
+
jp->indent -= 4;
|
|
1358
|
+
js_printf(jp, "\t}\n");
|
|
1359
|
+
todo = -2;
|
|
1360
|
+
break;
|
|
1361
|
+
|
|
1362
|
+
case SRC_WHILE:
|
|
1363
|
+
rval = POP_STR();
|
|
1364
|
+
js_printf(jp, "\twhile (%s) {\n", rval);
|
|
1365
|
+
jp->indent += 4;
|
|
1366
|
+
tail = js_GetSrcNoteOffset(sn, 0);
|
|
1367
|
+
DECOMPILE_CODE(pc + oplen, tail - oplen);
|
|
1368
|
+
jp->indent -= 4;
|
|
1369
|
+
js_printf(jp, "\t}\n");
|
|
1370
|
+
todo = -2;
|
|
1371
|
+
break;
|
|
1372
|
+
|
|
1373
|
+
case SRC_COND:
|
|
1374
|
+
xval = JS_strdup(cx, POP_STR());
|
|
1375
|
+
if (!xval)
|
|
1376
|
+
return JS_FALSE;
|
|
1377
|
+
len = js_GetSrcNoteOffset(sn, 0);
|
|
1378
|
+
DECOMPILE_CODE(pc + oplen, len - oplen);
|
|
1379
|
+
lval = JS_strdup(cx, POP_STR());
|
|
1380
|
+
if (!lval) {
|
|
1381
|
+
JS_free(cx, (void *)xval);
|
|
1382
|
+
return JS_FALSE;
|
|
1383
|
+
}
|
|
1384
|
+
pc += len;
|
|
1385
|
+
LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
|
|
1386
|
+
oplen = js_CodeSpec[*pc].length;
|
|
1387
|
+
len = GetJumpOffset(pc, pc);
|
|
1388
|
+
DECOMPILE_CODE(pc + oplen, len - oplen);
|
|
1389
|
+
rval = POP_STR();
|
|
1390
|
+
todo = Sprint(&ss->sprinter, "%s ? %s : %s",
|
|
1391
|
+
xval, lval, rval);
|
|
1392
|
+
JS_free(cx, (void *)xval);
|
|
1393
|
+
JS_free(cx, (void *)lval);
|
|
1394
|
+
break;
|
|
1395
|
+
|
|
1396
|
+
default:
|
|
1397
|
+
break;
|
|
1398
|
+
}
|
|
1399
|
+
break;
|
|
1400
|
+
|
|
1401
|
+
case JSOP_IFNE:
|
|
1402
|
+
case JSOP_IFNEX:
|
|
1403
|
+
#if JS_HAS_DO_WHILE_LOOP
|
|
1404
|
+
/* Currently, this must be a do-while loop's upward branch. */
|
|
1405
|
+
jp->indent -= 4;
|
|
1406
|
+
js_printf(jp, "\t} while (%s);\n", POP_STR());
|
|
1407
|
+
todo = -2;
|
|
1408
|
+
#else
|
|
1409
|
+
JS_ASSERT(0);
|
|
1410
|
+
#endif /* JS_HAS_DO_WHILE_LOOP */
|
|
1411
|
+
break;
|
|
1412
|
+
|
|
1413
|
+
case JSOP_OR:
|
|
1414
|
+
case JSOP_ORX:
|
|
1415
|
+
xval = "||";
|
|
1416
|
+
|
|
1417
|
+
do_logical_connective:
|
|
1418
|
+
/* Top of stack is the first clause in a disjunction (||). */
|
|
1419
|
+
lval = JS_strdup(cx, POP_STR());
|
|
1420
|
+
if (!lval)
|
|
1421
|
+
return JS_FALSE;
|
|
1422
|
+
done = pc + GetJumpOffset(pc, pc);
|
|
1423
|
+
pc += len;
|
|
1424
|
+
len = PTRDIFF(done, pc, jsbytecode);
|
|
1425
|
+
DECOMPILE_CODE(pc, len);
|
|
1426
|
+
rval = POP_STR();
|
|
1427
|
+
if (jp->pretty &&
|
|
1428
|
+
jp->indent + 4 + strlen(lval) + 4 + strlen(rval) > 75) {
|
|
1429
|
+
rval = JS_strdup(cx, rval);
|
|
1430
|
+
if (!rval) {
|
|
1431
|
+
tail = -1;
|
|
1432
|
+
} else {
|
|
1433
|
+
todo = Sprint(&ss->sprinter, "%s %s\n", lval, xval);
|
|
1434
|
+
tail = Sprint(&ss->sprinter, "%*s%s",
|
|
1435
|
+
jp->indent + 4, "", rval);
|
|
1436
|
+
JS_free(cx, (char *)rval);
|
|
1437
|
+
}
|
|
1438
|
+
if (tail < 0)
|
|
1439
|
+
todo = -1;
|
|
1440
|
+
} else {
|
|
1441
|
+
todo = Sprint(&ss->sprinter, "%s %s %s", lval, xval, rval);
|
|
1442
|
+
}
|
|
1443
|
+
JS_free(cx, (char *)lval);
|
|
1444
|
+
break;
|
|
1445
|
+
|
|
1446
|
+
case JSOP_AND:
|
|
1447
|
+
case JSOP_ANDX:
|
|
1448
|
+
xval = "&&";
|
|
1449
|
+
goto do_logical_connective;
|
|
1450
|
+
|
|
1451
|
+
case JSOP_FORARG:
|
|
1452
|
+
atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));
|
|
1453
|
+
LOCAL_ASSERT(atom);
|
|
1454
|
+
goto do_fornameinloop;
|
|
1455
|
+
|
|
1456
|
+
case JSOP_FORVAR:
|
|
1457
|
+
atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));
|
|
1458
|
+
LOCAL_ASSERT(atom);
|
|
1459
|
+
goto do_fornameinloop;
|
|
1460
|
+
|
|
1461
|
+
case JSOP_FORNAME:
|
|
1462
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1463
|
+
|
|
1464
|
+
do_fornameinloop:
|
|
1465
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1466
|
+
xval = NULL;
|
|
1467
|
+
lval = "";
|
|
1468
|
+
goto do_forinloop;
|
|
1469
|
+
|
|
1470
|
+
case JSOP_FORPROP:
|
|
1471
|
+
xval = NULL;
|
|
1472
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1473
|
+
if (!ATOM_IS_IDENTIFIER(atom)) {
|
|
1474
|
+
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
|
|
1475
|
+
(jschar)'\'');
|
|
1476
|
+
if (!xval)
|
|
1477
|
+
return JS_FALSE;
|
|
1478
|
+
atom = NULL;
|
|
1479
|
+
}
|
|
1480
|
+
lval = POP_STR();
|
|
1481
|
+
sn = NULL;
|
|
1482
|
+
|
|
1483
|
+
do_forinloop:
|
|
1484
|
+
pc += oplen;
|
|
1485
|
+
LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
|
|
1486
|
+
oplen = js_CodeSpec[*pc].length;
|
|
1487
|
+
len = GetJumpOffset(pc, pc);
|
|
1488
|
+
sn2 = js_GetSrcNote(jp->script, pc);
|
|
1489
|
+
tail = js_GetSrcNoteOffset(sn2, 0);
|
|
1490
|
+
|
|
1491
|
+
do_forinbody:
|
|
1492
|
+
js_printf(jp, "\tfor (%s%s", VarPrefix(sn), lval);
|
|
1493
|
+
if (atom) {
|
|
1494
|
+
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1495
|
+
if (!xval)
|
|
1496
|
+
return JS_FALSE;
|
|
1497
|
+
RETRACT(&ss->sprinter, xval);
|
|
1498
|
+
js_printf(jp, *lval ? ".%s" : "%s", xval);
|
|
1499
|
+
} else if (xval) {
|
|
1500
|
+
js_printf(jp, "[%s]", xval);
|
|
1501
|
+
}
|
|
1502
|
+
rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]);
|
|
1503
|
+
js_printf(jp, " in %s) {\n", rval);
|
|
1504
|
+
jp->indent += 4;
|
|
1505
|
+
DECOMPILE_CODE(pc + oplen, tail - oplen);
|
|
1506
|
+
jp->indent -= 4;
|
|
1507
|
+
js_printf(jp, "\t}\n");
|
|
1508
|
+
todo = -2;
|
|
1509
|
+
break;
|
|
1510
|
+
|
|
1511
|
+
case JSOP_FORELEM:
|
|
1512
|
+
pc++;
|
|
1513
|
+
LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
|
|
1514
|
+
len = js_CodeSpec[*pc].length;
|
|
1515
|
+
|
|
1516
|
+
/*
|
|
1517
|
+
* Arrange for the JSOP_ENUMELEM case to set tail for use by
|
|
1518
|
+
* do_forinbody: code that uses on it to find the loop-closing
|
|
1519
|
+
* jump (whatever its format, normal or extended), in order to
|
|
1520
|
+
* bound the recursively decompiled loop body.
|
|
1521
|
+
*/
|
|
1522
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1523
|
+
JS_ASSERT(!forelem_tail);
|
|
1524
|
+
forelem_tail = pc + js_GetSrcNoteOffset(sn, 0);
|
|
1525
|
+
|
|
1526
|
+
/*
|
|
1527
|
+
* This gets a little wacky. Only the length of the for loop
|
|
1528
|
+
* body PLUS the element-indexing expression is known here, so
|
|
1529
|
+
* we pass the after-loop pc to the JSOP_ENUMELEM case, which
|
|
1530
|
+
* is immediately below, to decompile that helper bytecode via
|
|
1531
|
+
* the 'forelem_done' local.
|
|
1532
|
+
*
|
|
1533
|
+
* Since a for..in loop can't nest in the head of another for
|
|
1534
|
+
* loop, we can use forelem_{tail,done} singletons to remember
|
|
1535
|
+
* state from JSOP_FORELEM to JSOP_ENUMELEM, thence (via goto)
|
|
1536
|
+
* to label do_forinbody.
|
|
1537
|
+
*/
|
|
1538
|
+
JS_ASSERT(!forelem_done);
|
|
1539
|
+
forelem_done = pc + GetJumpOffset(pc, pc);
|
|
1540
|
+
break;
|
|
1541
|
+
|
|
1542
|
+
case JSOP_ENUMELEM:
|
|
1543
|
+
/*
|
|
1544
|
+
* The stack has the object under the (top) index expression.
|
|
1545
|
+
* The "rval" property id is underneath those two on the stack.
|
|
1546
|
+
* The for loop body net and gross lengths can now be adjusted
|
|
1547
|
+
* to account for the length of the indexing expression that
|
|
1548
|
+
* came after JSOP_FORELEM and before JSOP_ENUMELEM.
|
|
1549
|
+
*/
|
|
1550
|
+
atom = NULL;
|
|
1551
|
+
xval = POP_STR();
|
|
1552
|
+
lval = POP_STR();
|
|
1553
|
+
rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]);
|
|
1554
|
+
JS_ASSERT(forelem_tail > pc);
|
|
1555
|
+
tail = forelem_tail - pc;
|
|
1556
|
+
forelem_tail = NULL;
|
|
1557
|
+
JS_ASSERT(forelem_done > pc);
|
|
1558
|
+
len = forelem_done - pc;
|
|
1559
|
+
forelem_done = NULL;
|
|
1560
|
+
goto do_forinbody;
|
|
1561
|
+
|
|
1562
|
+
case JSOP_DUP2:
|
|
1563
|
+
rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-2]);
|
|
1564
|
+
todo = SprintPut(&ss->sprinter, rval, strlen(rval));
|
|
1565
|
+
if (todo < 0 || !PushOff(ss, todo, ss->opcodes[ss->top-2]))
|
|
1566
|
+
return JS_FALSE;
|
|
1567
|
+
/* FALL THROUGH */
|
|
1568
|
+
|
|
1569
|
+
case JSOP_DUP:
|
|
1570
|
+
rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]);
|
|
1571
|
+
op = ss->opcodes[ss->top-1];
|
|
1572
|
+
todo = SprintPut(&ss->sprinter, rval, strlen(rval));
|
|
1573
|
+
break;
|
|
1574
|
+
|
|
1575
|
+
case JSOP_SETARG:
|
|
1576
|
+
atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));
|
|
1577
|
+
LOCAL_ASSERT(atom);
|
|
1578
|
+
goto do_setname;
|
|
1579
|
+
|
|
1580
|
+
case JSOP_SETVAR:
|
|
1581
|
+
atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));
|
|
1582
|
+
LOCAL_ASSERT(atom);
|
|
1583
|
+
goto do_setname;
|
|
1584
|
+
|
|
1585
|
+
case JSOP_SETCONST:
|
|
1586
|
+
case JSOP_SETNAME:
|
|
1587
|
+
case JSOP_SETGVAR:
|
|
1588
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1589
|
+
do_setname:
|
|
1590
|
+
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1591
|
+
if (!lval)
|
|
1592
|
+
return JS_FALSE;
|
|
1593
|
+
rval = POP_STR();
|
|
1594
|
+
if (op == JSOP_SETNAME)
|
|
1595
|
+
(void) PopOff(ss, op);
|
|
1596
|
+
do_setlval:
|
|
1597
|
+
sn = js_GetSrcNote(jp->script, pc - 1);
|
|
1598
|
+
if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
|
|
1599
|
+
todo = Sprint(&ss->sprinter, "%s %s= %s",
|
|
1600
|
+
lval, js_CodeSpec[lastop].token, rval);
|
|
1601
|
+
} else {
|
|
1602
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1603
|
+
todo = Sprint(&ss->sprinter, "%s%s = %s",
|
|
1604
|
+
VarPrefix(sn), lval, rval);
|
|
1605
|
+
}
|
|
1606
|
+
break;
|
|
1607
|
+
|
|
1608
|
+
case JSOP_NEW:
|
|
1609
|
+
case JSOP_CALL:
|
|
1610
|
+
case JSOP_EVAL:
|
|
1611
|
+
#if JS_HAS_LVALUE_RETURN
|
|
1612
|
+
case JSOP_SETCALL:
|
|
1613
|
+
#endif
|
|
1614
|
+
saveop = op;
|
|
1615
|
+
op = JSOP_NOP; /* turn off parens */
|
|
1616
|
+
argc = GET_ARGC(pc);
|
|
1617
|
+
argv = (char **)
|
|
1618
|
+
JS_malloc(cx, (size_t)(argc + 1) * sizeof *argv);
|
|
1619
|
+
if (!argv)
|
|
1620
|
+
return JS_FALSE;
|
|
1621
|
+
|
|
1622
|
+
ok = JS_TRUE;
|
|
1623
|
+
for (i = argc; i > 0; i--) {
|
|
1624
|
+
argv[i] = JS_strdup(cx, POP_STR());
|
|
1625
|
+
if (!argv[i]) {
|
|
1626
|
+
ok = JS_FALSE;
|
|
1627
|
+
break;
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
/* Skip the JSOP_PUSHOBJ-created empty string. */
|
|
1632
|
+
LOCAL_ASSERT(ss->top >= 2);
|
|
1633
|
+
(void) PopOff(ss, op);
|
|
1634
|
+
|
|
1635
|
+
/* Get the callee's decompiled image in argv[0]. */
|
|
1636
|
+
argv[0] = JS_strdup(cx, POP_STR());
|
|
1637
|
+
if (!argv[i])
|
|
1638
|
+
ok = JS_FALSE;
|
|
1639
|
+
|
|
1640
|
+
lval = "(", rval = ")";
|
|
1641
|
+
if (saveop == JSOP_NEW) {
|
|
1642
|
+
todo = Sprint(&ss->sprinter, "%s %s%s",
|
|
1643
|
+
js_new_str, argv[0], lval);
|
|
1644
|
+
} else {
|
|
1645
|
+
todo = Sprint(&ss->sprinter, "%s%s",
|
|
1646
|
+
argv[0], lval);
|
|
1647
|
+
}
|
|
1648
|
+
if (todo < 0)
|
|
1649
|
+
ok = JS_FALSE;
|
|
1650
|
+
|
|
1651
|
+
for (i = 1; i <= argc; i++) {
|
|
1652
|
+
if (!argv[i] ||
|
|
1653
|
+
Sprint(&ss->sprinter, "%s%s",
|
|
1654
|
+
argv[i], (i < argc) ? ", " : "") < 0) {
|
|
1655
|
+
ok = JS_FALSE;
|
|
1656
|
+
break;
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
if (Sprint(&ss->sprinter, rval) < 0)
|
|
1660
|
+
ok = JS_FALSE;
|
|
1661
|
+
|
|
1662
|
+
for (i = 0; i <= argc; i++) {
|
|
1663
|
+
if (argv[i])
|
|
1664
|
+
JS_free(cx, argv[i]);
|
|
1665
|
+
}
|
|
1666
|
+
JS_free(cx, argv);
|
|
1667
|
+
if (!ok)
|
|
1668
|
+
return JS_FALSE;
|
|
1669
|
+
op = saveop;
|
|
1670
|
+
#if JS_HAS_LVALUE_RETURN
|
|
1671
|
+
if (op == JSOP_SETCALL) {
|
|
1672
|
+
if (!PushOff(ss, todo, op))
|
|
1673
|
+
return JS_FALSE;
|
|
1674
|
+
todo = Sprint(&ss->sprinter, "");
|
|
1675
|
+
}
|
|
1676
|
+
#endif
|
|
1677
|
+
break;
|
|
1678
|
+
|
|
1679
|
+
case JSOP_DELNAME:
|
|
1680
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1681
|
+
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1682
|
+
if (!lval)
|
|
1683
|
+
return JS_FALSE;
|
|
1684
|
+
RETRACT(&ss->sprinter, lval);
|
|
1685
|
+
todo = Sprint(&ss->sprinter, "%s %s", js_delete_str, lval);
|
|
1686
|
+
break;
|
|
1687
|
+
|
|
1688
|
+
case JSOP_DELPROP:
|
|
1689
|
+
GET_ATOM_QUOTE_AND_FMT("%s %s[%s]", "%s %s.%s", rval);
|
|
1690
|
+
lval = POP_STR();
|
|
1691
|
+
todo = Sprint(&ss->sprinter, fmt, js_delete_str, lval, rval);
|
|
1692
|
+
break;
|
|
1693
|
+
|
|
1694
|
+
case JSOP_DELELEM:
|
|
1695
|
+
xval = POP_STR();
|
|
1696
|
+
lval = POP_STR();
|
|
1697
|
+
todo = Sprint(&ss->sprinter, "%s %s[%s]",
|
|
1698
|
+
js_delete_str, lval, xval);
|
|
1699
|
+
break;
|
|
1700
|
+
|
|
1701
|
+
case JSOP_TYPEOF:
|
|
1702
|
+
case JSOP_VOID:
|
|
1703
|
+
rval = POP_STR();
|
|
1704
|
+
todo = Sprint(&ss->sprinter, "%s %s", cs->name, rval);
|
|
1705
|
+
break;
|
|
1706
|
+
|
|
1707
|
+
case JSOP_INCARG:
|
|
1708
|
+
case JSOP_DECARG:
|
|
1709
|
+
atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));
|
|
1710
|
+
LOCAL_ASSERT(atom);
|
|
1711
|
+
goto do_incatom;
|
|
1712
|
+
|
|
1713
|
+
case JSOP_INCVAR:
|
|
1714
|
+
case JSOP_DECVAR:
|
|
1715
|
+
atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));
|
|
1716
|
+
LOCAL_ASSERT(atom);
|
|
1717
|
+
goto do_incatom;
|
|
1718
|
+
|
|
1719
|
+
case JSOP_INCNAME:
|
|
1720
|
+
case JSOP_DECNAME:
|
|
1721
|
+
case JSOP_INCGVAR:
|
|
1722
|
+
case JSOP_DECGVAR:
|
|
1723
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1724
|
+
do_incatom:
|
|
1725
|
+
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1726
|
+
if (!lval)
|
|
1727
|
+
return JS_FALSE;
|
|
1728
|
+
RETRACT(&ss->sprinter, lval);
|
|
1729
|
+
todo = Sprint(&ss->sprinter, "%s%s",
|
|
1730
|
+
js_incop_str[!(cs->format & JOF_INC)], lval);
|
|
1731
|
+
break;
|
|
1732
|
+
|
|
1733
|
+
case JSOP_INCPROP:
|
|
1734
|
+
case JSOP_DECPROP:
|
|
1735
|
+
GET_ATOM_QUOTE_AND_FMT("%s%s[%s]", "%s%s.%s", rval);
|
|
1736
|
+
lval = POP_STR();
|
|
1737
|
+
todo = Sprint(&ss->sprinter, fmt,
|
|
1738
|
+
js_incop_str[!(cs->format & JOF_INC)],
|
|
1739
|
+
lval, rval);
|
|
1740
|
+
break;
|
|
1741
|
+
|
|
1742
|
+
case JSOP_INCELEM:
|
|
1743
|
+
case JSOP_DECELEM:
|
|
1744
|
+
xval = POP_STR();
|
|
1745
|
+
lval = POP_STR();
|
|
1746
|
+
todo = Sprint(&ss->sprinter, "%s%s[%s]",
|
|
1747
|
+
js_incop_str[!(cs->format & JOF_INC)],
|
|
1748
|
+
lval, xval);
|
|
1749
|
+
break;
|
|
1750
|
+
|
|
1751
|
+
case JSOP_ARGINC:
|
|
1752
|
+
case JSOP_ARGDEC:
|
|
1753
|
+
atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));
|
|
1754
|
+
LOCAL_ASSERT(atom);
|
|
1755
|
+
goto do_atominc;
|
|
1756
|
+
|
|
1757
|
+
case JSOP_VARINC:
|
|
1758
|
+
case JSOP_VARDEC:
|
|
1759
|
+
atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));
|
|
1760
|
+
LOCAL_ASSERT(atom);
|
|
1761
|
+
goto do_atominc;
|
|
1762
|
+
|
|
1763
|
+
case JSOP_NAMEINC:
|
|
1764
|
+
case JSOP_NAMEDEC:
|
|
1765
|
+
case JSOP_GVARINC:
|
|
1766
|
+
case JSOP_GVARDEC:
|
|
1767
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1768
|
+
do_atominc:
|
|
1769
|
+
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1770
|
+
if (!lval)
|
|
1771
|
+
return JS_FALSE;
|
|
1772
|
+
todo = STR2OFF(&ss->sprinter, lval);
|
|
1773
|
+
SprintPut(&ss->sprinter,
|
|
1774
|
+
js_incop_str[!(cs->format & JOF_INC)],
|
|
1775
|
+
2);
|
|
1776
|
+
break;
|
|
1777
|
+
|
|
1778
|
+
case JSOP_PROPINC:
|
|
1779
|
+
case JSOP_PROPDEC:
|
|
1780
|
+
GET_ATOM_QUOTE_AND_FMT("%s[%s]%s", "%s.%s%s", rval);
|
|
1781
|
+
lval = POP_STR();
|
|
1782
|
+
todo = Sprint(&ss->sprinter, fmt, lval, rval,
|
|
1783
|
+
js_incop_str[!(cs->format & JOF_INC)]);
|
|
1784
|
+
break;
|
|
1785
|
+
|
|
1786
|
+
case JSOP_ELEMINC:
|
|
1787
|
+
case JSOP_ELEMDEC:
|
|
1788
|
+
xval = POP_STR();
|
|
1789
|
+
lval = POP_STR();
|
|
1790
|
+
todo = Sprint(&ss->sprinter, "%s[%s]%s",
|
|
1791
|
+
lval, xval,
|
|
1792
|
+
js_incop_str[!(cs->format & JOF_INC)]);
|
|
1793
|
+
break;
|
|
1794
|
+
|
|
1795
|
+
case JSOP_GETPROP2:
|
|
1796
|
+
op = JSOP_GETPROP;
|
|
1797
|
+
(void) PopOff(ss, lastop);
|
|
1798
|
+
/* FALL THROUGH */
|
|
1799
|
+
|
|
1800
|
+
case JSOP_GETPROP:
|
|
1801
|
+
GET_ATOM_QUOTE_AND_FMT("%s[%s]", "%s.%s", rval);
|
|
1802
|
+
lval = POP_STR();
|
|
1803
|
+
todo = Sprint(&ss->sprinter, fmt, lval, rval);
|
|
1804
|
+
break;
|
|
1805
|
+
|
|
1806
|
+
case JSOP_SETPROP:
|
|
1807
|
+
GET_ATOM_QUOTE_AND_FMT("%s[%s] %s= %s", "%s.%s %s= %s", xval);
|
|
1808
|
+
rval = POP_STR();
|
|
1809
|
+
lval = POP_STR();
|
|
1810
|
+
sn = js_GetSrcNote(jp->script, pc - 1);
|
|
1811
|
+
todo = Sprint(&ss->sprinter, fmt, lval, xval,
|
|
1812
|
+
(sn && SN_TYPE(sn) == SRC_ASSIGNOP)
|
|
1813
|
+
? js_CodeSpec[lastop].token
|
|
1814
|
+
: "",
|
|
1815
|
+
rval);
|
|
1816
|
+
break;
|
|
1817
|
+
|
|
1818
|
+
case JSOP_GETELEM2:
|
|
1819
|
+
op = JSOP_GETELEM;
|
|
1820
|
+
(void) PopOff(ss, lastop);
|
|
1821
|
+
/* FALL THROUGH */
|
|
1822
|
+
|
|
1823
|
+
case JSOP_GETELEM:
|
|
1824
|
+
op = JSOP_NOP; /* turn off parens */
|
|
1825
|
+
xval = POP_STR();
|
|
1826
|
+
op = JSOP_GETELEM;
|
|
1827
|
+
lval = POP_STR();
|
|
1828
|
+
if (*xval == '\0')
|
|
1829
|
+
todo = Sprint(&ss->sprinter, "%s", lval);
|
|
1830
|
+
else
|
|
1831
|
+
todo = Sprint(&ss->sprinter, "%s[%s]", lval, xval);
|
|
1832
|
+
break;
|
|
1833
|
+
|
|
1834
|
+
case JSOP_SETELEM:
|
|
1835
|
+
op = JSOP_NOP; /* turn off parens */
|
|
1836
|
+
rval = POP_STR();
|
|
1837
|
+
xval = POP_STR();
|
|
1838
|
+
op = JSOP_SETELEM;
|
|
1839
|
+
lval = POP_STR();
|
|
1840
|
+
if (*xval == '\0')
|
|
1841
|
+
goto do_setlval;
|
|
1842
|
+
sn = js_GetSrcNote(jp->script, pc - 1);
|
|
1843
|
+
todo = Sprint(&ss->sprinter, "%s[%s] %s= %s",
|
|
1844
|
+
lval, xval,
|
|
1845
|
+
(sn && SN_TYPE(sn) == SRC_ASSIGNOP)
|
|
1846
|
+
? js_CodeSpec[lastop].token
|
|
1847
|
+
: "",
|
|
1848
|
+
rval);
|
|
1849
|
+
break;
|
|
1850
|
+
|
|
1851
|
+
case JSOP_ARGSUB:
|
|
1852
|
+
i = (jsint) GET_ATOM_INDEX(pc);
|
|
1853
|
+
todo = Sprint(&ss->sprinter, "%s[%d]",
|
|
1854
|
+
js_arguments_str, (int) i);
|
|
1855
|
+
break;
|
|
1856
|
+
|
|
1857
|
+
case JSOP_ARGCNT:
|
|
1858
|
+
todo = Sprint(&ss->sprinter, "%s.%s",
|
|
1859
|
+
js_arguments_str, js_length_str);
|
|
1860
|
+
break;
|
|
1861
|
+
|
|
1862
|
+
case JSOP_GETARG:
|
|
1863
|
+
atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));
|
|
1864
|
+
LOCAL_ASSERT(atom);
|
|
1865
|
+
goto do_name;
|
|
1866
|
+
|
|
1867
|
+
case JSOP_GETVAR:
|
|
1868
|
+
atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));
|
|
1869
|
+
LOCAL_ASSERT(atom);
|
|
1870
|
+
goto do_name;
|
|
1871
|
+
|
|
1872
|
+
case JSOP_NAME:
|
|
1873
|
+
case JSOP_GETGVAR:
|
|
1874
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1875
|
+
do_name:
|
|
1876
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1877
|
+
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
1878
|
+
if (!rval)
|
|
1879
|
+
return JS_FALSE;
|
|
1880
|
+
RETRACT(&ss->sprinter, rval);
|
|
1881
|
+
todo = Sprint(&ss->sprinter, "%s%s", VarPrefix(sn), rval);
|
|
1882
|
+
break;
|
|
1883
|
+
|
|
1884
|
+
case JSOP_UINT16:
|
|
1885
|
+
i = (jsint) GET_ATOM_INDEX(pc);
|
|
1886
|
+
todo = Sprint(&ss->sprinter, "%u", (unsigned) i);
|
|
1887
|
+
break;
|
|
1888
|
+
|
|
1889
|
+
case JSOP_NUMBER:
|
|
1890
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1891
|
+
val = ATOM_KEY(atom);
|
|
1892
|
+
if (JSVAL_IS_INT(val)) {
|
|
1893
|
+
long ival = (long)JSVAL_TO_INT(val);
|
|
1894
|
+
todo = Sprint(&ss->sprinter, "%ld", ival);
|
|
1895
|
+
} else {
|
|
1896
|
+
char buf[DTOSTR_STANDARD_BUFFER_SIZE];
|
|
1897
|
+
char *numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD,
|
|
1898
|
+
0, *JSVAL_TO_DOUBLE(val));
|
|
1899
|
+
if (!numStr) {
|
|
1900
|
+
JS_ReportOutOfMemory(cx);
|
|
1901
|
+
return JS_FALSE;
|
|
1902
|
+
}
|
|
1903
|
+
todo = Sprint(&ss->sprinter, numStr);
|
|
1904
|
+
}
|
|
1905
|
+
break;
|
|
1906
|
+
|
|
1907
|
+
case JSOP_STRING:
|
|
1908
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1909
|
+
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
|
|
1910
|
+
(jschar)'"');
|
|
1911
|
+
if (!rval)
|
|
1912
|
+
return JS_FALSE;
|
|
1913
|
+
todo = STR2OFF(&ss->sprinter, rval);
|
|
1914
|
+
break;
|
|
1915
|
+
|
|
1916
|
+
case JSOP_OBJECT:
|
|
1917
|
+
case JSOP_REGEXP:
|
|
1918
|
+
case JSOP_ANONFUNOBJ:
|
|
1919
|
+
case JSOP_NAMEDFUNOBJ:
|
|
1920
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
1921
|
+
if (op == JSOP_OBJECT || op == JSOP_REGEXP) {
|
|
1922
|
+
if (!js_regexp_toString(cx, ATOM_TO_OBJECT(atom), 0, NULL,
|
|
1923
|
+
&val)) {
|
|
1924
|
+
return JS_FALSE;
|
|
1925
|
+
}
|
|
1926
|
+
} else {
|
|
1927
|
+
if (!js_fun_toString(cx, ATOM_TO_OBJECT(atom),
|
|
1928
|
+
(pc + len < endpc &&
|
|
1929
|
+
pc[len] == JSOP_GROUP)
|
|
1930
|
+
? JS_IN_GROUP_CONTEXT |
|
|
1931
|
+
JS_DONT_PRETTY_PRINT
|
|
1932
|
+
: JS_DONT_PRETTY_PRINT,
|
|
1933
|
+
0, NULL, &val)) {
|
|
1934
|
+
return JS_FALSE;
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
str = JSVAL_TO_STRING(val);
|
|
1938
|
+
todo = SprintPut(&ss->sprinter, JS_GetStringBytes(str),
|
|
1939
|
+
JSSTRING_LENGTH(str));
|
|
1940
|
+
break;
|
|
1941
|
+
|
|
1942
|
+
#if JS_HAS_SWITCH_STATEMENT
|
|
1943
|
+
case JSOP_TABLESWITCH:
|
|
1944
|
+
case JSOP_TABLESWITCHX:
|
|
1945
|
+
{
|
|
1946
|
+
jsbytecode *pc2;
|
|
1947
|
+
ptrdiff_t jmplen, off, off2;
|
|
1948
|
+
jsint j, n, low, high;
|
|
1949
|
+
TableEntry *table;
|
|
1950
|
+
|
|
1951
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
1952
|
+
JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
|
|
1953
|
+
len = js_GetSrcNoteOffset(sn, 0);
|
|
1954
|
+
jmplen = (op == JSOP_TABLESWITCH) ? JUMP_OFFSET_LEN
|
|
1955
|
+
: JUMPX_OFFSET_LEN;
|
|
1956
|
+
pc2 = pc;
|
|
1957
|
+
off = GetJumpOffset(pc, pc2);
|
|
1958
|
+
pc2 += jmplen;
|
|
1959
|
+
low = GET_JUMP_OFFSET(pc2);
|
|
1960
|
+
pc2 += JUMP_OFFSET_LEN;
|
|
1961
|
+
high = GET_JUMP_OFFSET(pc2);
|
|
1962
|
+
pc2 += JUMP_OFFSET_LEN;
|
|
1963
|
+
|
|
1964
|
+
n = high - low + 1;
|
|
1965
|
+
if (n == 0) {
|
|
1966
|
+
table = NULL;
|
|
1967
|
+
j = 0;
|
|
1968
|
+
} else {
|
|
1969
|
+
table = (TableEntry *)
|
|
1970
|
+
JS_malloc(cx, (size_t)n * sizeof *table);
|
|
1971
|
+
if (!table)
|
|
1972
|
+
return JS_FALSE;
|
|
1973
|
+
for (i = j = 0; i < n; i++) {
|
|
1974
|
+
table[j].label = NULL;
|
|
1975
|
+
off2 = GetJumpOffset(pc, pc2);
|
|
1976
|
+
if (off2) {
|
|
1977
|
+
sn = js_GetSrcNote(jp->script, pc2);
|
|
1978
|
+
if (sn) {
|
|
1979
|
+
JS_ASSERT(SN_TYPE(sn) == SRC_LABEL);
|
|
1980
|
+
table[j].label =
|
|
1981
|
+
js_GetAtom(cx, &jp->script->atomMap,
|
|
1982
|
+
(jsatomid)
|
|
1983
|
+
js_GetSrcNoteOffset(sn, 0));
|
|
1984
|
+
}
|
|
1985
|
+
table[j].key = INT_TO_JSVAL(low + i);
|
|
1986
|
+
table[j].offset = off2;
|
|
1987
|
+
table[j].order = j;
|
|
1988
|
+
j++;
|
|
1989
|
+
}
|
|
1990
|
+
pc2 += jmplen;
|
|
1991
|
+
}
|
|
1992
|
+
js_HeapSort(table, (size_t) j, sizeof(TableEntry),
|
|
1993
|
+
CompareOffsets, NULL);
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
ok = DecompileSwitch(ss, table, (uintN)j, pc, len, off,
|
|
1997
|
+
JS_FALSE);
|
|
1998
|
+
JS_free(cx, table);
|
|
1999
|
+
if (!ok)
|
|
2000
|
+
return ok;
|
|
2001
|
+
todo = -2;
|
|
2002
|
+
break;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
case JSOP_LOOKUPSWITCH:
|
|
2006
|
+
case JSOP_LOOKUPSWITCHX:
|
|
2007
|
+
{
|
|
2008
|
+
jsbytecode *pc2;
|
|
2009
|
+
ptrdiff_t jmplen, off, off2;
|
|
2010
|
+
jsatomid npairs, k;
|
|
2011
|
+
TableEntry *table;
|
|
2012
|
+
|
|
2013
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
2014
|
+
JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
|
|
2015
|
+
len = js_GetSrcNoteOffset(sn, 0);
|
|
2016
|
+
jmplen = (op == JSOP_LOOKUPSWITCH) ? JUMP_OFFSET_LEN
|
|
2017
|
+
: JUMPX_OFFSET_LEN;
|
|
2018
|
+
pc2 = pc;
|
|
2019
|
+
off = GetJumpOffset(pc, pc2);
|
|
2020
|
+
pc2 += jmplen;
|
|
2021
|
+
npairs = GET_ATOM_INDEX(pc2);
|
|
2022
|
+
pc2 += ATOM_INDEX_LEN;
|
|
2023
|
+
|
|
2024
|
+
table = (TableEntry *)
|
|
2025
|
+
JS_malloc(cx, (size_t)npairs * sizeof *table);
|
|
2026
|
+
if (!table)
|
|
2027
|
+
return JS_FALSE;
|
|
2028
|
+
for (k = 0; k < npairs; k++) {
|
|
2029
|
+
sn = js_GetSrcNote(jp->script, pc2);
|
|
2030
|
+
if (sn) {
|
|
2031
|
+
JS_ASSERT(SN_TYPE(sn) == SRC_LABEL);
|
|
2032
|
+
table[k].label =
|
|
2033
|
+
js_GetAtom(cx, &jp->script->atomMap, (jsatomid)
|
|
2034
|
+
js_GetSrcNoteOffset(sn, 0));
|
|
2035
|
+
} else {
|
|
2036
|
+
table[k].label = NULL;
|
|
2037
|
+
}
|
|
2038
|
+
atom = GET_ATOM(cx, jp->script, pc2);
|
|
2039
|
+
pc2 += ATOM_INDEX_LEN;
|
|
2040
|
+
off2 = GetJumpOffset(pc, pc2);
|
|
2041
|
+
pc2 += jmplen;
|
|
2042
|
+
table[k].key = ATOM_KEY(atom);
|
|
2043
|
+
table[k].offset = off2;
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
ok = DecompileSwitch(ss, table, (uintN)npairs, pc, len, off,
|
|
2047
|
+
JS_FALSE);
|
|
2048
|
+
JS_free(cx, table);
|
|
2049
|
+
if (!ok)
|
|
2050
|
+
return ok;
|
|
2051
|
+
todo = -2;
|
|
2052
|
+
break;
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
case JSOP_CONDSWITCH:
|
|
2056
|
+
{
|
|
2057
|
+
jsbytecode *pc2;
|
|
2058
|
+
ptrdiff_t off, off2, caseOff;
|
|
2059
|
+
jsint ncases;
|
|
2060
|
+
TableEntry *table;
|
|
2061
|
+
|
|
2062
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
2063
|
+
JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
|
|
2064
|
+
len = js_GetSrcNoteOffset(sn, 0);
|
|
2065
|
+
off = js_GetSrcNoteOffset(sn, 1);
|
|
2066
|
+
|
|
2067
|
+
/*
|
|
2068
|
+
* Count the cases using offsets from switch to first case,
|
|
2069
|
+
* and case to case, stored in srcnote immediates.
|
|
2070
|
+
*/
|
|
2071
|
+
pc2 = pc;
|
|
2072
|
+
off2 = off;
|
|
2073
|
+
for (ncases = 0; off2 != 0; ncases++) {
|
|
2074
|
+
pc2 += off2;
|
|
2075
|
+
JS_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT ||
|
|
2076
|
+
*pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX);
|
|
2077
|
+
if (*pc2 == JSOP_DEFAULT || *pc2 == JSOP_DEFAULTX) {
|
|
2078
|
+
/* End of cases, but count default as a case. */
|
|
2079
|
+
off2 = 0;
|
|
2080
|
+
} else {
|
|
2081
|
+
sn = js_GetSrcNote(jp->script, pc2);
|
|
2082
|
+
JS_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA);
|
|
2083
|
+
off2 = js_GetSrcNoteOffset(sn, 0);
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
/*
|
|
2088
|
+
* Allocate table and rescan the cases using their srcnotes,
|
|
2089
|
+
* stashing each case's delta from switch top in table[i].key,
|
|
2090
|
+
* and the distance to its statements in table[i].offset.
|
|
2091
|
+
*/
|
|
2092
|
+
table = (TableEntry *)
|
|
2093
|
+
JS_malloc(cx, (size_t)ncases * sizeof *table);
|
|
2094
|
+
if (!table)
|
|
2095
|
+
return JS_FALSE;
|
|
2096
|
+
pc2 = pc;
|
|
2097
|
+
off2 = off;
|
|
2098
|
+
for (i = 0; i < ncases; i++) {
|
|
2099
|
+
pc2 += off2;
|
|
2100
|
+
JS_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT ||
|
|
2101
|
+
*pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX);
|
|
2102
|
+
caseOff = pc2 - pc;
|
|
2103
|
+
table[i].key = INT_TO_JSVAL((jsint) caseOff);
|
|
2104
|
+
table[i].offset = caseOff + GetJumpOffset(pc2, pc2);
|
|
2105
|
+
if (*pc2 == JSOP_CASE || *pc2 == JSOP_CASEX) {
|
|
2106
|
+
sn = js_GetSrcNote(jp->script, pc2);
|
|
2107
|
+
JS_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA);
|
|
2108
|
+
off2 = js_GetSrcNoteOffset(sn, 0);
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
/*
|
|
2113
|
+
* Find offset of default code by fetching the default offset
|
|
2114
|
+
* from the end of table. JSOP_CONDSWITCH always has a default
|
|
2115
|
+
* case at the end.
|
|
2116
|
+
*/
|
|
2117
|
+
off = JSVAL_TO_INT(table[ncases-1].key);
|
|
2118
|
+
pc2 = pc + off;
|
|
2119
|
+
off += GetJumpOffset(pc2, pc2);
|
|
2120
|
+
|
|
2121
|
+
ok = DecompileSwitch(ss, table, (uintN)ncases, pc, len, off,
|
|
2122
|
+
JS_TRUE);
|
|
2123
|
+
JS_free(cx, table);
|
|
2124
|
+
if (!ok)
|
|
2125
|
+
return ok;
|
|
2126
|
+
todo = -2;
|
|
2127
|
+
break;
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
case JSOP_CASE:
|
|
2131
|
+
case JSOP_CASEX:
|
|
2132
|
+
{
|
|
2133
|
+
lval = POP_STR();
|
|
2134
|
+
if (!lval)
|
|
2135
|
+
return JS_FALSE;
|
|
2136
|
+
js_printf(jp, "\tcase %s:\n", lval);
|
|
2137
|
+
todo = -2;
|
|
2138
|
+
break;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
#endif /* JS_HAS_SWITCH_STATEMENT */
|
|
2142
|
+
|
|
2143
|
+
#if !JS_BUG_FALLIBLE_EQOPS
|
|
2144
|
+
case JSOP_NEW_EQ:
|
|
2145
|
+
case JSOP_NEW_NE:
|
|
2146
|
+
rval = POP_STR();
|
|
2147
|
+
lval = POP_STR();
|
|
2148
|
+
todo = Sprint(&ss->sprinter, "%s %c%s %s",
|
|
2149
|
+
lval,
|
|
2150
|
+
(op == JSOP_NEW_EQ) ? '=' : '!',
|
|
2151
|
+
#if JS_HAS_TRIPLE_EQOPS
|
|
2152
|
+
JSVERSION_IS_ECMA(cx->version) ? "==" :
|
|
2153
|
+
#endif
|
|
2154
|
+
"=",
|
|
2155
|
+
rval);
|
|
2156
|
+
break;
|
|
2157
|
+
#endif /* !JS_BUG_FALLIBLE_EQOPS */
|
|
2158
|
+
|
|
2159
|
+
#if JS_HAS_LEXICAL_CLOSURE
|
|
2160
|
+
case JSOP_CLOSURE:
|
|
2161
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
2162
|
+
JS_ASSERT(ATOM_IS_OBJECT(atom));
|
|
2163
|
+
goto do_function;
|
|
2164
|
+
#endif /* JS_HAS_LEXICAL_CLOSURE */
|
|
2165
|
+
|
|
2166
|
+
#if JS_HAS_EXPORT_IMPORT
|
|
2167
|
+
case JSOP_EXPORTALL:
|
|
2168
|
+
js_printf(jp, "\texport *\n");
|
|
2169
|
+
todo = -2;
|
|
2170
|
+
break;
|
|
2171
|
+
|
|
2172
|
+
case JSOP_EXPORTNAME:
|
|
2173
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
2174
|
+
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
|
2175
|
+
if (!rval)
|
|
2176
|
+
return JS_FALSE;
|
|
2177
|
+
RETRACT(&ss->sprinter, rval);
|
|
2178
|
+
js_printf(jp, "\texport %s\n", rval);
|
|
2179
|
+
todo = -2;
|
|
2180
|
+
break;
|
|
2181
|
+
|
|
2182
|
+
case JSOP_IMPORTALL:
|
|
2183
|
+
lval = POP_STR();
|
|
2184
|
+
js_printf(jp, "\timport %s.*\n", lval);
|
|
2185
|
+
todo = -2;
|
|
2186
|
+
break;
|
|
2187
|
+
|
|
2188
|
+
case JSOP_IMPORTPROP:
|
|
2189
|
+
GET_ATOM_QUOTE_AND_FMT("\timport %s[%s]\n", "\timport %s.%s\n",
|
|
2190
|
+
rval);
|
|
2191
|
+
lval = POP_STR();
|
|
2192
|
+
js_printf(jp, fmt, lval, rval);
|
|
2193
|
+
todo = -2;
|
|
2194
|
+
break;
|
|
2195
|
+
|
|
2196
|
+
case JSOP_IMPORTELEM:
|
|
2197
|
+
xval = POP_STR();
|
|
2198
|
+
op = JSOP_GETELEM;
|
|
2199
|
+
lval = POP_STR();
|
|
2200
|
+
js_printf(jp, "\timport %s[%s]\n", lval, xval);
|
|
2201
|
+
todo = -2;
|
|
2202
|
+
break;
|
|
2203
|
+
#endif /* JS_HAS_EXPORT_IMPORT */
|
|
2204
|
+
|
|
2205
|
+
case JSOP_TRAP:
|
|
2206
|
+
op = JS_GetTrapOpcode(cx, jp->script, pc);
|
|
2207
|
+
if (op == JSOP_LIMIT)
|
|
2208
|
+
return JS_FALSE;
|
|
2209
|
+
*pc = op;
|
|
2210
|
+
cs = &js_CodeSpec[op];
|
|
2211
|
+
len = cs->length;
|
|
2212
|
+
DECOMPILE_CODE(pc, len);
|
|
2213
|
+
*pc = JSOP_TRAP;
|
|
2214
|
+
todo = -2;
|
|
2215
|
+
break;
|
|
2216
|
+
|
|
2217
|
+
#if JS_HAS_INITIALIZERS
|
|
2218
|
+
case JSOP_NEWINIT:
|
|
2219
|
+
LOCAL_ASSERT(ss->top >= 2);
|
|
2220
|
+
(void) PopOff(ss, op);
|
|
2221
|
+
lval = POP_STR();
|
|
2222
|
+
#if JS_HAS_SHARP_VARS
|
|
2223
|
+
op = (JSOp)pc[len];
|
|
2224
|
+
if (op == JSOP_DEFSHARP) {
|
|
2225
|
+
pc += len;
|
|
2226
|
+
cs = &js_CodeSpec[op];
|
|
2227
|
+
len = cs->length;
|
|
2228
|
+
i = (jsint) GET_ATOM_INDEX(pc);
|
|
2229
|
+
todo = Sprint(&ss->sprinter, "#%u=%c",
|
|
2230
|
+
(unsigned) i,
|
|
2231
|
+
(*lval == 'O') ? '{' : '[');
|
|
2232
|
+
} else
|
|
2233
|
+
#endif /* JS_HAS_SHARP_VARS */
|
|
2234
|
+
{
|
|
2235
|
+
todo = Sprint(&ss->sprinter, (*lval == 'O') ? "{" : "[");
|
|
2236
|
+
}
|
|
2237
|
+
break;
|
|
2238
|
+
|
|
2239
|
+
case JSOP_ENDINIT:
|
|
2240
|
+
rval = POP_STR();
|
|
2241
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
2242
|
+
todo = Sprint(&ss->sprinter, "%s%s%c",
|
|
2243
|
+
rval,
|
|
2244
|
+
(sn && SN_TYPE(sn) == SRC_CONTINUE) ? ", " : "",
|
|
2245
|
+
(*rval == '{') ? '}' : ']');
|
|
2246
|
+
break;
|
|
2247
|
+
|
|
2248
|
+
case JSOP_INITPROP:
|
|
2249
|
+
case JSOP_INITCATCHVAR:
|
|
2250
|
+
atom = GET_ATOM(cx, jp->script, pc);
|
|
2251
|
+
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
|
|
2252
|
+
ATOM_IS_IDENTIFIER(atom) ? 0 : '\'');
|
|
2253
|
+
if (!xval)
|
|
2254
|
+
return JS_FALSE;
|
|
2255
|
+
rval = POP_STR();
|
|
2256
|
+
lval = POP_STR();
|
|
2257
|
+
do_initprop:
|
|
2258
|
+
#ifdef OLD_GETTER_SETTER
|
|
2259
|
+
todo = Sprint(&ss->sprinter, "%s%s%s%s%s:%s",
|
|
2260
|
+
lval,
|
|
2261
|
+
(lval[1] != '\0') ? ", " : "",
|
|
2262
|
+
xval,
|
|
2263
|
+
(lastop == JSOP_GETTER || lastop == JSOP_SETTER)
|
|
2264
|
+
? " " : "",
|
|
2265
|
+
(lastop == JSOP_GETTER) ? js_getter_str :
|
|
2266
|
+
(lastop == JSOP_SETTER) ? js_setter_str :
|
|
2267
|
+
"",
|
|
2268
|
+
rval);
|
|
2269
|
+
#else
|
|
2270
|
+
if (lastop == JSOP_GETTER || lastop == JSOP_SETTER) {
|
|
2271
|
+
todo = Sprint(&ss->sprinter, "%s%s%s %s%s",
|
|
2272
|
+
lval,
|
|
2273
|
+
(lval[1] != '\0') ? ", " : "",
|
|
2274
|
+
(lastop == JSOP_GETTER)
|
|
2275
|
+
? js_get_str : js_set_str,
|
|
2276
|
+
xval,
|
|
2277
|
+
rval + strlen(js_function_str) + 1);
|
|
2278
|
+
} else {
|
|
2279
|
+
todo = Sprint(&ss->sprinter, "%s%s%s:%s",
|
|
2280
|
+
lval,
|
|
2281
|
+
(lval[1] != '\0') ? ", " : "",
|
|
2282
|
+
xval,
|
|
2283
|
+
rval);
|
|
2284
|
+
}
|
|
2285
|
+
#endif
|
|
2286
|
+
break;
|
|
2287
|
+
|
|
2288
|
+
case JSOP_INITELEM:
|
|
2289
|
+
rval = POP_STR();
|
|
2290
|
+
xval = POP_STR();
|
|
2291
|
+
lval = POP_STR();
|
|
2292
|
+
sn = js_GetSrcNote(jp->script, pc);
|
|
2293
|
+
if (sn && SN_TYPE(sn) == SRC_LABEL)
|
|
2294
|
+
goto do_initprop;
|
|
2295
|
+
todo = Sprint(&ss->sprinter, "%s%s%s",
|
|
2296
|
+
lval,
|
|
2297
|
+
(lval[1] != '\0' || *xval != '0') ? ", " : "",
|
|
2298
|
+
rval);
|
|
2299
|
+
break;
|
|
2300
|
+
|
|
2301
|
+
#if JS_HAS_SHARP_VARS
|
|
2302
|
+
case JSOP_DEFSHARP:
|
|
2303
|
+
i = (jsint) GET_ATOM_INDEX(pc);
|
|
2304
|
+
rval = POP_STR();
|
|
2305
|
+
todo = Sprint(&ss->sprinter, "#%u=%s", (unsigned) i, rval);
|
|
2306
|
+
break;
|
|
2307
|
+
|
|
2308
|
+
case JSOP_USESHARP:
|
|
2309
|
+
i = (jsint) GET_ATOM_INDEX(pc);
|
|
2310
|
+
todo = Sprint(&ss->sprinter, "#%u#", (unsigned) i);
|
|
2311
|
+
break;
|
|
2312
|
+
#endif /* JS_HAS_SHARP_VARS */
|
|
2313
|
+
#endif /* JS_HAS_INITIALIZERS */
|
|
2314
|
+
|
|
2315
|
+
#if JS_HAS_DEBUGGER_KEYWORD
|
|
2316
|
+
case JSOP_DEBUGGER:
|
|
2317
|
+
js_printf(jp, "\tdebugger;\n");
|
|
2318
|
+
todo = -2;
|
|
2319
|
+
break;
|
|
2320
|
+
#endif /* JS_HAS_DEBUGGER_KEYWORD */
|
|
2321
|
+
|
|
2322
|
+
default:
|
|
2323
|
+
todo = -2;
|
|
2324
|
+
break;
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
if (todo < 0) {
|
|
2329
|
+
/* -2 means "don't push", -1 means reported error. */
|
|
2330
|
+
if (todo == -1)
|
|
2331
|
+
return JS_FALSE;
|
|
2332
|
+
} else {
|
|
2333
|
+
if (!PushOff(ss, todo, op))
|
|
2334
|
+
return JS_FALSE;
|
|
2335
|
+
}
|
|
2336
|
+
pc += len;
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
/*
|
|
2340
|
+
* Undefine local macros.
|
|
2341
|
+
*/
|
|
2342
|
+
#undef DECOMPILE_CODE
|
|
2343
|
+
#undef POP_STR
|
|
2344
|
+
#undef LOCAL_ASSERT
|
|
2345
|
+
#undef ATOM_IS_IDENTIFIER
|
|
2346
|
+
#undef GET_ATOM_QUOTE_AND_FMT
|
|
2347
|
+
|
|
2348
|
+
return JS_TRUE;
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
|
|
2352
|
+
JSBool
|
|
2353
|
+
js_DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len)
|
|
2354
|
+
{
|
|
2355
|
+
SprintStack ss;
|
|
2356
|
+
JSContext *cx;
|
|
2357
|
+
void *mark, *space;
|
|
2358
|
+
size_t offsetsz, opcodesz;
|
|
2359
|
+
JSBool ok;
|
|
2360
|
+
JSScript *oldscript;
|
|
2361
|
+
char *last;
|
|
2362
|
+
|
|
2363
|
+
/* Initialize a sprinter for use with the offset stack. */
|
|
2364
|
+
ss.printer = jp;
|
|
2365
|
+
cx = jp->sprinter.context;
|
|
2366
|
+
mark = JS_ARENA_MARK(&cx->tempPool);
|
|
2367
|
+
INIT_SPRINTER(cx, &ss.sprinter, &cx->tempPool, PAREN_SLOP);
|
|
2368
|
+
|
|
2369
|
+
/* Allocate the parallel (to avoid padding) offset and opcode stacks. */
|
|
2370
|
+
offsetsz = script->depth * sizeof(ptrdiff_t);
|
|
2371
|
+
opcodesz = script->depth * sizeof(jsbytecode);
|
|
2372
|
+
JS_ARENA_ALLOCATE(space, &cx->tempPool, offsetsz + opcodesz);
|
|
2373
|
+
if (!space) {
|
|
2374
|
+
ok = JS_FALSE;
|
|
2375
|
+
goto out;
|
|
2376
|
+
}
|
|
2377
|
+
ss.offsets = (ptrdiff_t *) space;
|
|
2378
|
+
ss.opcodes = (jsbytecode *) ((char *)space + offsetsz);
|
|
2379
|
+
ss.top = 0;
|
|
2380
|
+
|
|
2381
|
+
/* Call recursive subroutine to do the hard work. */
|
|
2382
|
+
oldscript = jp->script;
|
|
2383
|
+
jp->script = script;
|
|
2384
|
+
ok = Decompile(&ss, pc, len);
|
|
2385
|
+
jp->script = oldscript;
|
|
2386
|
+
|
|
2387
|
+
/* If the given code didn't empty the stack, do it now. */
|
|
2388
|
+
if (ss.top) {
|
|
2389
|
+
do {
|
|
2390
|
+
last = OFF2STR(&ss.sprinter, PopOff(&ss, JSOP_NOP));
|
|
2391
|
+
} while (ss.top);
|
|
2392
|
+
js_printf(jp, "%s", last);
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
out:
|
|
2396
|
+
/* Free all temporary stuff allocated under this call. */
|
|
2397
|
+
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
|
2398
|
+
return ok;
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
JSBool
|
|
2402
|
+
js_DecompileScript(JSPrinter *jp, JSScript *script)
|
|
2403
|
+
{
|
|
2404
|
+
return js_DecompileCode(jp, script, script->code, (uintN)script->length);
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
static const char native_code_str[] = "\t[native code]\n";
|
|
2408
|
+
|
|
2409
|
+
JSBool
|
|
2410
|
+
js_DecompileFunctionBody(JSPrinter *jp, JSFunction *fun)
|
|
2411
|
+
{
|
|
2412
|
+
JSScript *script;
|
|
2413
|
+
JSScope *scope, *save;
|
|
2414
|
+
JSBool ok;
|
|
2415
|
+
|
|
2416
|
+
if (!fun->interpreted) {
|
|
2417
|
+
js_printf(jp, native_code_str);
|
|
2418
|
+
return JS_TRUE;
|
|
2419
|
+
}
|
|
2420
|
+
script = fun->u.script;
|
|
2421
|
+
scope = fun->object ? OBJ_SCOPE(fun->object) : NULL;
|
|
2422
|
+
save = jp->scope;
|
|
2423
|
+
jp->scope = scope;
|
|
2424
|
+
ok = js_DecompileCode(jp, script, script->code, (uintN)script->length);
|
|
2425
|
+
jp->scope = save;
|
|
2426
|
+
return ok;
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
JSBool
|
|
2430
|
+
js_DecompileFunction(JSPrinter *jp, JSFunction *fun)
|
|
2431
|
+
{
|
|
2432
|
+
JSContext *cx;
|
|
2433
|
+
uintN i, nargs, indent;
|
|
2434
|
+
void *mark;
|
|
2435
|
+
JSAtom **params;
|
|
2436
|
+
JSScope *scope, *oldscope;
|
|
2437
|
+
JSScopeProperty *sprop;
|
|
2438
|
+
JSBool ok;
|
|
2439
|
+
|
|
2440
|
+
/*
|
|
2441
|
+
* If pretty, conform to ECMA-262 Edition 3, 15.3.4.2, by decompiling a
|
|
2442
|
+
* FunctionDeclaration. Otherwise, check the JSFUN_LAMBDA flag and force
|
|
2443
|
+
* an expression by parenthesizing.
|
|
2444
|
+
*/
|
|
2445
|
+
if (jp->pretty) {
|
|
2446
|
+
js_puts(jp, "\n");
|
|
2447
|
+
js_printf(jp, "\t");
|
|
2448
|
+
} else {
|
|
2449
|
+
if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
|
|
2450
|
+
js_puts(jp, "(");
|
|
2451
|
+
}
|
|
2452
|
+
if (fun->flags & JSFUN_GETTER)
|
|
2453
|
+
js_printf(jp, "%s ", js_getter_str);
|
|
2454
|
+
else if (fun->flags & JSFUN_SETTER)
|
|
2455
|
+
js_printf(jp, "%s ", js_setter_str);
|
|
2456
|
+
|
|
2457
|
+
js_printf(jp, "%s ", js_function_str);
|
|
2458
|
+
if (fun->atom && !QuoteString(&jp->sprinter, ATOM_TO_STRING(fun->atom), 0))
|
|
2459
|
+
return JS_FALSE;
|
|
2460
|
+
js_puts(jp, "(");
|
|
2461
|
+
|
|
2462
|
+
if (fun->interpreted && fun->object) {
|
|
2463
|
+
/*
|
|
2464
|
+
* Print the parameters.
|
|
2465
|
+
*
|
|
2466
|
+
* This code is complicated by the need to handle duplicate parameter
|
|
2467
|
+
* names, as required by ECMA (bah!). A duplicate parameter is stored
|
|
2468
|
+
* as another node with the same id (the parameter name) but different
|
|
2469
|
+
* shortid (the argument index) along the property tree ancestor line
|
|
2470
|
+
* starting at SCOPE_LAST_PROP(scope). Only the last duplicate param
|
|
2471
|
+
* is mapped by the scope's hash table.
|
|
2472
|
+
*/
|
|
2473
|
+
cx = jp->sprinter.context;
|
|
2474
|
+
nargs = fun->nargs;
|
|
2475
|
+
mark = JS_ARENA_MARK(&cx->tempPool);
|
|
2476
|
+
JS_ARENA_ALLOCATE_CAST(params, JSAtom **, &cx->tempPool,
|
|
2477
|
+
nargs * sizeof(JSAtom *));
|
|
2478
|
+
if (!params) {
|
|
2479
|
+
JS_ReportOutOfMemory(cx);
|
|
2480
|
+
return JS_FALSE;
|
|
2481
|
+
}
|
|
2482
|
+
scope = OBJ_SCOPE(fun->object);
|
|
2483
|
+
for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
|
|
2484
|
+
if (sprop->getter != js_GetArgument)
|
|
2485
|
+
continue;
|
|
2486
|
+
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
|
|
2487
|
+
JS_ASSERT((uintN) sprop->shortid < nargs);
|
|
2488
|
+
JS_ASSERT(!JSVAL_IS_INT(sprop->id));
|
|
2489
|
+
params[(uintN) sprop->shortid] = (JSAtom *) sprop->id;
|
|
2490
|
+
}
|
|
2491
|
+
for (i = 0; i < nargs; i++) {
|
|
2492
|
+
if (i > 0)
|
|
2493
|
+
js_puts(jp, ", ");
|
|
2494
|
+
if (!QuoteString(&jp->sprinter, ATOM_TO_STRING(params[i]), 0))
|
|
2495
|
+
return JS_FALSE;
|
|
2496
|
+
}
|
|
2497
|
+
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
|
2498
|
+
#ifdef __GNUC__
|
|
2499
|
+
} else {
|
|
2500
|
+
scope = NULL;
|
|
2501
|
+
#endif
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
js_printf(jp, ") {\n");
|
|
2505
|
+
indent = jp->indent;
|
|
2506
|
+
jp->indent += 4;
|
|
2507
|
+
if (fun->interpreted && fun->object) {
|
|
2508
|
+
oldscope = jp->scope;
|
|
2509
|
+
jp->scope = scope;
|
|
2510
|
+
ok = js_DecompileScript(jp, fun->u.script);
|
|
2511
|
+
jp->scope = oldscope;
|
|
2512
|
+
if (!ok) {
|
|
2513
|
+
jp->indent = indent;
|
|
2514
|
+
return JS_FALSE;
|
|
2515
|
+
}
|
|
2516
|
+
} else {
|
|
2517
|
+
js_printf(jp, native_code_str);
|
|
2518
|
+
}
|
|
2519
|
+
jp->indent -= 4;
|
|
2520
|
+
js_printf(jp, "\t}");
|
|
2521
|
+
|
|
2522
|
+
if (jp->pretty) {
|
|
2523
|
+
js_puts(jp, "\n");
|
|
2524
|
+
} else {
|
|
2525
|
+
if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
|
|
2526
|
+
js_puts(jp, ")");
|
|
2527
|
+
}
|
|
2528
|
+
return JS_TRUE;
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
JSString *
|
|
2532
|
+
js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
|
|
2533
|
+
JSString *fallback)
|
|
2534
|
+
{
|
|
2535
|
+
JSStackFrame *fp, *down;
|
|
2536
|
+
jsbytecode *pc, *begin, *end, *tmp;
|
|
2537
|
+
jsval *sp, *base, *limit;
|
|
2538
|
+
JSScript *script;
|
|
2539
|
+
JSOp op;
|
|
2540
|
+
const JSCodeSpec *cs;
|
|
2541
|
+
uint32 format, mode;
|
|
2542
|
+
intN depth;
|
|
2543
|
+
jssrcnote *sn;
|
|
2544
|
+
uintN len, off;
|
|
2545
|
+
JSPrinter *jp;
|
|
2546
|
+
JSString *name;
|
|
2547
|
+
|
|
2548
|
+
fp = cx->fp;
|
|
2549
|
+
if (!fp)
|
|
2550
|
+
goto do_fallback;
|
|
2551
|
+
|
|
2552
|
+
/* Try to find sp's generating pc depth slots under it on the stack. */
|
|
2553
|
+
pc = fp->pc;
|
|
2554
|
+
if (spindex == JSDVG_SEARCH_STACK) {
|
|
2555
|
+
if (!pc) {
|
|
2556
|
+
/*
|
|
2557
|
+
* Current frame is native: look under it for a scripted call
|
|
2558
|
+
* in which a decompilable bytecode string that generated the
|
|
2559
|
+
* value as an actual argument might exist.
|
|
2560
|
+
*/
|
|
2561
|
+
JS_ASSERT(!fp->script && !(fp->fun && fp->fun->interpreted));
|
|
2562
|
+
down = fp->down;
|
|
2563
|
+
if (!down)
|
|
2564
|
+
goto do_fallback;
|
|
2565
|
+
script = down->script;
|
|
2566
|
+
base = fp->argv;
|
|
2567
|
+
limit = base + fp->argc;
|
|
2568
|
+
} else {
|
|
2569
|
+
/*
|
|
2570
|
+
* This should be a script activation, either a top-level
|
|
2571
|
+
* script or a scripted function. But be paranoid about calls
|
|
2572
|
+
* to js_DecompileValueGenerator from code that hasn't fully
|
|
2573
|
+
* initialized a (default-all-zeroes) frame.
|
|
2574
|
+
*/
|
|
2575
|
+
script = fp->script;
|
|
2576
|
+
base = fp->spbase;
|
|
2577
|
+
limit = fp->sp;
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
/*
|
|
2581
|
+
* Pure paranoia about default-zeroed frames being active while
|
|
2582
|
+
* js_DecompileValueGenerator is called. It can't hurt much now;
|
|
2583
|
+
* error reporting performance is not an issue.
|
|
2584
|
+
*/
|
|
2585
|
+
if (!script || !base || !limit)
|
|
2586
|
+
goto do_fallback;
|
|
2587
|
+
|
|
2588
|
+
/*
|
|
2589
|
+
* Try to find operand-generating pc depth slots below sp.
|
|
2590
|
+
*
|
|
2591
|
+
* In the native case, we know the arguments have generating pc's
|
|
2592
|
+
* under them, on account of fp->down->script being non-null: all
|
|
2593
|
+
* compiled scripts get depth slots for generating pc's allocated
|
|
2594
|
+
* upon activation, at the top of js_Interpret.
|
|
2595
|
+
*
|
|
2596
|
+
* In the script or scripted function case, the same reasoning
|
|
2597
|
+
* applies to fp rather than to fp->down.
|
|
2598
|
+
*/
|
|
2599
|
+
for (sp = base; sp < limit; sp++) {
|
|
2600
|
+
if (*sp == v) {
|
|
2601
|
+
depth = (intN)script->depth;
|
|
2602
|
+
pc = (jsbytecode *) sp[-depth];
|
|
2603
|
+
break;
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
} else {
|
|
2607
|
+
/*
|
|
2608
|
+
* At this point, pc may or may not be null, i.e., we could be in
|
|
2609
|
+
* a script activation, or we could be in a native frame that was
|
|
2610
|
+
* called by another native function. Check pc and script.
|
|
2611
|
+
*/
|
|
2612
|
+
if (!pc)
|
|
2613
|
+
goto do_fallback;
|
|
2614
|
+
script = fp->script;
|
|
2615
|
+
if (!script)
|
|
2616
|
+
goto do_fallback;
|
|
2617
|
+
|
|
2618
|
+
if (spindex != JSDVG_IGNORE_STACK) {
|
|
2619
|
+
JS_ASSERT(spindex < 0);
|
|
2620
|
+
depth = (intN)script->depth;
|
|
2621
|
+
#if !JS_HAS_NO_SUCH_METHOD
|
|
2622
|
+
JS_ASSERT(-depth <= spindex);
|
|
2623
|
+
#endif
|
|
2624
|
+
spindex -= depth;
|
|
2625
|
+
|
|
2626
|
+
base = (jsval *) cx->stackPool.current->base;
|
|
2627
|
+
limit = (jsval *) cx->stackPool.current->avail;
|
|
2628
|
+
sp = fp->sp + spindex;
|
|
2629
|
+
if (JS_UPTRDIFF(sp, base) < JS_UPTRDIFF(limit, base))
|
|
2630
|
+
pc = (jsbytecode *) *sp;
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
/*
|
|
2635
|
+
* Again, be paranoid, this time about possibly loading an invalid pc
|
|
2636
|
+
* from sp[-(1+depth)].
|
|
2637
|
+
*/
|
|
2638
|
+
if (JS_UPTRDIFF(pc, script->code) >= (jsuword)script->length) {
|
|
2639
|
+
pc = fp->pc;
|
|
2640
|
+
if (!pc)
|
|
2641
|
+
goto do_fallback;
|
|
2642
|
+
}
|
|
2643
|
+
op = (JSOp) *pc;
|
|
2644
|
+
if (op == JSOP_TRAP)
|
|
2645
|
+
op = JS_GetTrapOpcode(cx, script, pc);
|
|
2646
|
+
|
|
2647
|
+
/* XXX handle null as a special case, to avoid calling null "object" */
|
|
2648
|
+
if (op == JSOP_NULL)
|
|
2649
|
+
return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
|
|
2650
|
+
|
|
2651
|
+
cs = &js_CodeSpec[op];
|
|
2652
|
+
format = cs->format;
|
|
2653
|
+
mode = (format & JOF_MODEMASK);
|
|
2654
|
+
|
|
2655
|
+
/* NAME ops are self-contained, but others require left context. */
|
|
2656
|
+
if (mode == JOF_NAME) {
|
|
2657
|
+
begin = pc;
|
|
2658
|
+
} else {
|
|
2659
|
+
sn = js_GetSrcNote(script, pc);
|
|
2660
|
+
if (!sn || SN_TYPE(sn) != SRC_PCBASE)
|
|
2661
|
+
goto do_fallback;
|
|
2662
|
+
begin = pc - js_GetSrcNoteOffset(sn, 0);
|
|
2663
|
+
}
|
|
2664
|
+
end = pc + cs->length;
|
|
2665
|
+
len = PTRDIFF(end, begin, jsbytecode);
|
|
2666
|
+
|
|
2667
|
+
if (format & (JOF_SET | JOF_DEL | JOF_INCDEC | JOF_IMPORT | JOF_FOR)) {
|
|
2668
|
+
tmp = (jsbytecode *) JS_malloc(cx, len * sizeof(jsbytecode));
|
|
2669
|
+
if (!tmp)
|
|
2670
|
+
return NULL;
|
|
2671
|
+
memcpy(tmp, begin, len * sizeof(jsbytecode));
|
|
2672
|
+
if (mode == JOF_NAME) {
|
|
2673
|
+
tmp[0] = JSOP_NAME;
|
|
2674
|
+
} else {
|
|
2675
|
+
/*
|
|
2676
|
+
* We must replace the faulting pc's bytecode with a corresponding
|
|
2677
|
+
* JSOP_GET* code. For JSOP_SET{PROP,ELEM}, we must use the "2nd"
|
|
2678
|
+
* form of JSOP_GET{PROP,ELEM}, to throw away the assignment op's
|
|
2679
|
+
* right-hand operand and decompile it as if it were a GET of its
|
|
2680
|
+
* left-hand operand.
|
|
2681
|
+
*/
|
|
2682
|
+
off = len - cs->length;
|
|
2683
|
+
JS_ASSERT(off == (uintN) PTRDIFF(pc, begin, jsbytecode));
|
|
2684
|
+
if (mode == JOF_PROP) {
|
|
2685
|
+
tmp[off] = (format & JOF_SET) ? JSOP_GETPROP2 : JSOP_GETPROP;
|
|
2686
|
+
} else if (mode == JOF_ELEM) {
|
|
2687
|
+
tmp[off] = (format & JOF_SET) ? JSOP_GETELEM2 : JSOP_GETELEM;
|
|
2688
|
+
} else {
|
|
2689
|
+
/*
|
|
2690
|
+
* A zero mode means precisely that op is uncategorized for our
|
|
2691
|
+
* purposes, so we must write per-op special case code here.
|
|
2692
|
+
*/
|
|
2693
|
+
switch (op) {
|
|
2694
|
+
case JSOP_ENUMELEM:
|
|
2695
|
+
tmp[off] = JSOP_GETELEM;
|
|
2696
|
+
break;
|
|
2697
|
+
#if JS_HAS_LVALUE_RETURN
|
|
2698
|
+
case JSOP_SETCALL:
|
|
2699
|
+
tmp[off] = JSOP_CALL;
|
|
2700
|
+
break;
|
|
2701
|
+
#endif
|
|
2702
|
+
default:
|
|
2703
|
+
JS_ASSERT(0);
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
begin = tmp;
|
|
2708
|
+
} else {
|
|
2709
|
+
/* No need to revise script bytecode. */
|
|
2710
|
+
tmp = NULL;
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2713
|
+
name = NULL;
|
|
2714
|
+
jp = js_NewPrinter(cx, "js_DecompileValueGenerator", 0, JS_FALSE);
|
|
2715
|
+
if (jp) {
|
|
2716
|
+
if (fp->fun && fp->fun->object) {
|
|
2717
|
+
JS_ASSERT(OBJ_IS_NATIVE(fp->fun->object));
|
|
2718
|
+
jp->scope = OBJ_SCOPE(fp->fun->object);
|
|
2719
|
+
}
|
|
2720
|
+
if (js_DecompileCode(jp, script, begin, len))
|
|
2721
|
+
name = js_GetPrinterOutput(jp);
|
|
2722
|
+
}
|
|
2723
|
+
js_DestroyPrinter(jp);
|
|
2724
|
+
if (tmp)
|
|
2725
|
+
JS_free(cx, tmp);
|
|
2726
|
+
return name;
|
|
2727
|
+
|
|
2728
|
+
do_fallback:
|
|
2729
|
+
return fallback ? fallback : js_ValueToString(cx, v);
|
|
2730
|
+
}
|