johnson 1.2.0 → 2.0.0.pre0
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/CHANGELOG.rdoc +8 -0
- data/Manifest.txt +762 -48
- data/README.rdoc +2 -1
- data/Rakefile +90 -18
- data/ext/spidermonkey/conversions.c +9 -2
- data/ext/spidermonkey/ruby_land_proxy.c +1 -1
- data/ext/spidermonkey/runtime.h +1 -1
- data/ext/tracemonkey/context.cc +125 -0
- data/ext/tracemonkey/context.h +19 -0
- data/ext/tracemonkey/conversions.cc +365 -0
- data/ext/tracemonkey/conversions.h +32 -0
- data/ext/tracemonkey/debugger.cc +234 -0
- data/ext/tracemonkey/debugger.h +10 -0
- data/ext/tracemonkey/extconf.rb +37 -0
- data/ext/tracemonkey/extensions.cc +37 -0
- data/ext/tracemonkey/extensions.h +12 -0
- data/ext/tracemonkey/global.cc +40 -0
- data/ext/tracemonkey/global.h +11 -0
- data/ext/tracemonkey/idhash.cc +16 -0
- data/ext/tracemonkey/idhash.h +8 -0
- data/ext/tracemonkey/immutable_node.cc +1199 -0
- data/ext/tracemonkey/immutable_node.cc.erb +559 -0
- data/ext/tracemonkey/immutable_node.h +22 -0
- data/ext/tracemonkey/jroot.h +215 -0
- data/ext/tracemonkey/js_land_proxy.cc +620 -0
- data/ext/tracemonkey/js_land_proxy.h +20 -0
- data/ext/tracemonkey/ruby_land_proxy.cc +618 -0
- data/ext/tracemonkey/ruby_land_proxy.h +38 -0
- data/ext/tracemonkey/runtime.cc +454 -0
- data/ext/tracemonkey/runtime.h +27 -0
- data/ext/tracemonkey/split_global.cc +392 -0
- data/ext/tracemonkey/split_global.h +11 -0
- data/ext/tracemonkey/tracemonkey.cc +23 -0
- data/ext/tracemonkey/tracemonkey.h +32 -0
- data/lib/johnson.rb +12 -4
- data/lib/johnson/error.rb +5 -0
- data/lib/johnson/js/prelude.js +16 -1
- data/lib/johnson/parser.rb +2 -1
- data/lib/johnson/runtime.rb +87 -26
- data/lib/johnson/spidermonkey/runtime.rb +7 -16
- data/lib/johnson/tracemonkey.rb +13 -0
- data/lib/johnson/tracemonkey/context.rb +10 -0
- data/lib/johnson/tracemonkey/debugger.rb +67 -0
- data/lib/johnson/tracemonkey/immutable_node.rb +282 -0
- data/lib/johnson/tracemonkey/js_land_proxy.rb +64 -0
- data/lib/johnson/tracemonkey/mutable_tree_visitor.rb +242 -0
- data/lib/johnson/tracemonkey/ruby_land_proxy.rb +17 -0
- data/lib/johnson/tracemonkey/runtime.rb +80 -0
- data/test/{johnson_test.rb → generic/johnson_test.rb} +1 -1
- data/test/{parser_test.rb → generic/parser_test.rb} +1 -1
- data/test/helper.rb +23 -4
- data/test/johnson/{browser_test.rb → generic/browser_test.rb} +1 -1
- data/test/johnson/{conversions → generic/conversions}/array_test.rb +1 -1
- data/test/johnson/{conversions → generic/conversions}/boolean_test.rb +1 -1
- data/test/johnson/{conversions → generic/conversions}/callable_test.rb +1 -1
- data/test/johnson/{conversions → generic/conversions}/file_test.rb +1 -1
- data/test/johnson/generic/conversions/helper.rb +1 -0
- data/test/johnson/{conversions → generic/conversions}/nil_test.rb +1 -1
- data/test/johnson/{conversions → generic/conversions}/number_test.rb +1 -1
- data/test/johnson/{conversions → generic/conversions}/regexp_test.rb +1 -1
- data/test/johnson/{conversions → generic/conversions}/string_test.rb +1 -1
- data/test/johnson/{conversions → generic/conversions}/struct_test.rb +1 -1
- data/test/johnson/{conversions → generic/conversions}/symbol_test.rb +1 -1
- data/test/johnson/{conversions → generic/conversions}/thread_test.rb +1 -1
- data/test/johnson/{custom_conversions_test.rb → generic/custom_conversions_test.rb} +1 -1
- data/test/johnson/generic/default_test.rb +12 -0
- data/test/johnson/{error_test.rb → generic/error_test.rb} +1 -1
- data/test/johnson/{extensions_test.rb → generic/extensions_test.rb} +1 -1
- data/test/johnson/generic/helper.rb +1 -0
- data/test/johnson/{nodes → generic/nodes}/array_literal_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/array_node_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/binary_node_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/bracket_access_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/delete_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/do_while_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/dot_accessor_test.rb +1 -1
- data/test/johnson/generic/nodes/export_test.rb +11 -0
- data/test/johnson/{nodes → generic/nodes}/for_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/function_test.rb +1 -1
- data/test/johnson/generic/nodes/helper.rb +1 -0
- data/test/johnson/{nodes → generic/nodes}/if_test.rb +16 -6
- data/test/johnson/generic/nodes/import_test.rb +15 -0
- data/test/johnson/{nodes → generic/nodes}/label_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/let_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/object_literal_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/return_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/semi_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/switch_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/ternary_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/throw_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/try_node_test.rb +36 -6
- data/test/johnson/{nodes → generic/nodes}/typeof_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/unary_node_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/void_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/while_test.rb +1 -1
- data/test/johnson/{nodes → generic/nodes}/with_test.rb +1 -1
- data/test/johnson/{prelude_test.rb → generic/prelude_test.rb} +1 -1
- data/test/johnson/{runtime_test.rb → generic/runtime_test.rb} +3 -6
- data/test/johnson/generic/version_test.rb +13 -0
- data/test/johnson/{visitors → generic/visitors}/dot_visitor_test.rb +1 -1
- data/test/johnson/{visitors → generic/visitors}/enumerating_visitor_test.rb +1 -1
- data/test/johnson/generic/visitors/helper.rb +1 -0
- data/test/johnson/spidermonkey/js_land_proxy_test.rb +1 -5
- data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +11 -7
- data/test/johnson/tracemonkey/context_test.rb +21 -0
- data/test/johnson/tracemonkey/immutable_node_test.rb +34 -0
- data/test/johnson/tracemonkey/js_land_proxy_test.rb +273 -0
- data/test/johnson/tracemonkey/ruby_land_proxy_test.rb +274 -0
- data/test/johnson/tracemonkey/runtime_test.rb +41 -0
- data/test/johnson/tracemonkey/split_global_test.rb +32 -0
- data/vendor/spidermonkey/js.pkg +2 -0
- data/vendor/tracemonkey/Makefile.in +668 -0
- data/vendor/tracemonkey/Makefile.ref +483 -0
- data/vendor/tracemonkey/README.html +54 -0
- data/vendor/tracemonkey/SpiderMonkey.rsp +11 -0
- data/vendor/tracemonkey/Y.js +19 -0
- data/vendor/tracemonkey/aclocal.m4 +9 -0
- data/vendor/tracemonkey/bench.sh +5 -0
- data/vendor/tracemonkey/build/autoconf/acoutput-fast.pl +202 -0
- data/vendor/tracemonkey/build/autoconf/altoptions.m4 +154 -0
- data/vendor/tracemonkey/build/autoconf/config.guess +1537 -0
- data/vendor/tracemonkey/build/autoconf/config.sub +1595 -0
- data/vendor/tracemonkey/build/autoconf/install-sh +119 -0
- data/vendor/tracemonkey/build/autoconf/make-makefile +315 -0
- data/vendor/tracemonkey/build/autoconf/match-dir.sh +101 -0
- data/vendor/tracemonkey/build/autoconf/moznbytetype.m4 +136 -0
- data/vendor/tracemonkey/build/autoconf/nspr.m4 +82 -0
- data/vendor/tracemonkey/build/autoconf/pkg.m4 +59 -0
- data/vendor/tracemonkey/build/autoconf/update-makefile.sh +118 -0
- data/vendor/tracemonkey/build/cygwin-wrapper +75 -0
- data/vendor/tracemonkey/build/hcc +111 -0
- data/vendor/tracemonkey/build/hcpp +155 -0
- data/vendor/tracemonkey/build/unix/mddepend.pl +165 -0
- data/vendor/tracemonkey/build/unix/uniq.pl +63 -0
- data/vendor/tracemonkey/build/win32/pgomerge.py +40 -0
- data/vendor/tracemonkey/builtins.tbl +91 -0
- data/vendor/tracemonkey/call.js +13 -0
- data/vendor/tracemonkey/config.mk +206 -0
- data/vendor/tracemonkey/config/Makefile.in +106 -0
- data/vendor/tracemonkey/config/Moz/Milestone.pm +232 -0
- data/vendor/tracemonkey/config/autoconf.mk.in +362 -0
- data/vendor/tracemonkey/config/check-sync-dirs.py +103 -0
- data/vendor/tracemonkey/config/check-sync-exceptions +7 -0
- data/vendor/tracemonkey/config/config.mk +881 -0
- data/vendor/tracemonkey/config/fastcwd.pl +66 -0
- data/vendor/tracemonkey/config/gcc_hidden.h +2 -0
- data/vendor/tracemonkey/config/insure.mk +53 -0
- data/vendor/tracemonkey/config/make-system-wrappers.pl +59 -0
- data/vendor/tracemonkey/config/milestone.pl +112 -0
- data/vendor/tracemonkey/config/milestone.txt +13 -0
- data/vendor/tracemonkey/config/mkdepend/Makefile.in +84 -0
- data/vendor/tracemonkey/config/mkdepend/cppsetup.c +233 -0
- data/vendor/tracemonkey/config/mkdepend/def.h +184 -0
- data/vendor/tracemonkey/config/mkdepend/ifparser.c +551 -0
- data/vendor/tracemonkey/config/mkdepend/ifparser.h +83 -0
- data/vendor/tracemonkey/config/mkdepend/imakemdep.h +733 -0
- data/vendor/tracemonkey/config/mkdepend/include.c +337 -0
- data/vendor/tracemonkey/config/mkdepend/main.c +860 -0
- data/vendor/tracemonkey/config/mkdepend/mkdepend.man +382 -0
- data/vendor/tracemonkey/config/mkdepend/parse.c +686 -0
- data/vendor/tracemonkey/config/mkdepend/pr.c +124 -0
- data/vendor/tracemonkey/config/nfspwd.pl +50 -0
- data/vendor/tracemonkey/config/nsinstall.c +481 -0
- data/vendor/tracemonkey/config/nsinstall.py +155 -0
- data/vendor/tracemonkey/config/pathsub.c +247 -0
- data/vendor/tracemonkey/config/pathsub.h +74 -0
- data/vendor/tracemonkey/config/preprocessor.pl +671 -0
- data/vendor/tracemonkey/config/revdepth-nt.pl +48 -0
- data/vendor/tracemonkey/config/revdepth.pl +51 -0
- data/vendor/tracemonkey/config/rules.mk +2310 -0
- data/vendor/tracemonkey/config/static-checking-config.mk +21 -0
- data/vendor/tracemonkey/config/static-checking.js +92 -0
- data/vendor/tracemonkey/config/string-format.js +61 -0
- data/vendor/tracemonkey/config/system-headers +1035 -0
- data/vendor/tracemonkey/config/version.mk +85 -0
- data/vendor/tracemonkey/config/version_win.pl +442 -0
- data/vendor/tracemonkey/configure +14183 -0
- data/vendor/tracemonkey/configure.in +5363 -0
- data/vendor/tracemonkey/correct.sh +23 -0
- data/vendor/tracemonkey/correct/check-3d-morph.js +55 -0
- data/vendor/tracemonkey/correct/check-3d-raytrace.js +445 -0
- data/vendor/tracemonkey/correct/check-access-binary-trees.js +52 -0
- data/vendor/tracemonkey/correct/check-access-fannkuch.js +66 -0
- data/vendor/tracemonkey/correct/check-access-nbody.js +171 -0
- data/vendor/tracemonkey/correct/check-access-nsieve.js +40 -0
- data/vendor/tracemonkey/correct/check-bitops-3bit-bits-in-byte.js +35 -0
- data/vendor/tracemonkey/correct/check-bitops-bits-in-byte.js +24 -0
- data/vendor/tracemonkey/correct/check-bitops-bitwise-and.js +29 -0
- data/vendor/tracemonkey/correct/check-bitops-nsieve-bits.js +40 -0
- data/vendor/tracemonkey/correct/check-controlflow-recursive.js +27 -0
- data/vendor/tracemonkey/correct/check-date-format-tofte.js +302 -0
- data/vendor/tracemonkey/correct/check-date-format-xparb.js +421 -0
- data/vendor/tracemonkey/correct/check-mont.js +119 -0
- data/vendor/tracemonkey/dtoa.c +3335 -0
- data/vendor/tracemonkey/editline/Makefile.in +55 -0
- data/vendor/tracemonkey/editline/Makefile.ref +143 -0
- data/vendor/tracemonkey/editline/README +83 -0
- data/vendor/tracemonkey/editline/editline.3 +175 -0
- data/vendor/tracemonkey/editline/editline.c +1371 -0
- data/vendor/tracemonkey/editline/editline.h +135 -0
- data/vendor/tracemonkey/editline/sysunix.c +182 -0
- data/vendor/tracemonkey/editline/unix.h +82 -0
- data/vendor/tracemonkey/if.js +13 -0
- data/vendor/tracemonkey/imacro_asm.js.in +396 -0
- data/vendor/tracemonkey/imacros.c.out +1034 -0
- data/vendor/tracemonkey/imacros.jsasm +770 -0
- data/vendor/tracemonkey/javascript-trace.d +73 -0
- data/vendor/tracemonkey/jitstats.tbl +55 -0
- data/vendor/tracemonkey/js-config.h.in +82 -0
- data/vendor/tracemonkey/js-config.in +111 -0
- data/vendor/tracemonkey/js.mdp +0 -0
- data/vendor/tracemonkey/js.msg +312 -0
- data/vendor/tracemonkey/js3240.rc +79 -0
- data/vendor/tracemonkey/jsOS240.def +654 -0
- data/vendor/tracemonkey/jsapi.cpp +6005 -0
- data/vendor/tracemonkey/jsapi.h +2727 -0
- data/vendor/tracemonkey/jsarena.cpp +450 -0
- data/vendor/tracemonkey/jsarena.h +318 -0
- data/vendor/tracemonkey/jsarray.cpp +3664 -0
- data/vendor/tracemonkey/jsarray.h +238 -0
- data/vendor/tracemonkey/jsatom.cpp +1244 -0
- data/vendor/tracemonkey/jsatom.h +493 -0
- data/vendor/tracemonkey/jsbit.h +249 -0
- data/vendor/tracemonkey/jsbool.cpp +184 -0
- data/vendor/tracemonkey/jsbool.h +88 -0
- data/vendor/tracemonkey/jsbuiltins.cpp +415 -0
- data/vendor/tracemonkey/jsbuiltins.h +456 -0
- data/vendor/tracemonkey/jsclist.h +139 -0
- data/vendor/tracemonkey/jscntxt.cpp +1816 -0
- data/vendor/tracemonkey/jscntxt.h +1541 -0
- data/vendor/tracemonkey/jscompat.h +57 -0
- data/vendor/tracemonkey/jsconfig.mk +181 -0
- data/vendor/tracemonkey/jscpucfg.cpp +194 -0
- data/vendor/tracemonkey/jscpucfg.h +91 -0
- data/vendor/tracemonkey/jsdate.cpp +2465 -0
- data/vendor/tracemonkey/jsdate.h +129 -0
- data/vendor/tracemonkey/jsdbgapi.cpp +2017 -0
- data/vendor/tracemonkey/jsdbgapi.h +500 -0
- data/vendor/tracemonkey/jsdhash.cpp +876 -0
- data/vendor/tracemonkey/jsdhash.h +588 -0
- data/vendor/tracemonkey/jsdtoa.cpp +572 -0
- data/vendor/tracemonkey/jsdtoa.h +131 -0
- data/vendor/tracemonkey/jsdtracef.c +318 -0
- data/vendor/tracemonkey/jsdtracef.h +81 -0
- data/vendor/tracemonkey/jsemit.cpp +7292 -0
- data/vendor/tracemonkey/jsemit.h +802 -0
- data/vendor/tracemonkey/jsexn.cpp +1337 -0
- data/vendor/tracemonkey/jsexn.h +96 -0
- data/vendor/tracemonkey/jsfile.cpp +2747 -0
- data/vendor/tracemonkey/jsfile.h +56 -0
- data/vendor/tracemonkey/jsfile.msg +90 -0
- data/vendor/tracemonkey/jsfun.cpp +3089 -0
- data/vendor/tracemonkey/jsfun.h +366 -0
- data/vendor/tracemonkey/jsgc.cpp +3816 -0
- data/vendor/tracemonkey/jsgc.h +429 -0
- data/vendor/tracemonkey/jshash.cpp +477 -0
- data/vendor/tracemonkey/jshash.h +151 -0
- data/vendor/tracemonkey/jsify.pl +483 -0
- data/vendor/tracemonkey/jsinterp.cpp +7441 -0
- data/vendor/tracemonkey/jsinterp.h +666 -0
- data/vendor/tracemonkey/jsinvoke.cpp +42 -0
- data/vendor/tracemonkey/jsiter.cpp +1040 -0
- data/vendor/tracemonkey/jsiter.h +140 -0
- data/vendor/tracemonkey/jskeyword.tbl +124 -0
- data/vendor/tracemonkey/jskwgen.cpp +460 -0
- data/vendor/tracemonkey/jslibmath.h +69 -0
- data/vendor/tracemonkey/jslock.cpp +1512 -0
- data/vendor/tracemonkey/jslock.h +325 -0
- data/vendor/tracemonkey/jslocko.asm +60 -0
- data/vendor/tracemonkey/jslog2.cpp +111 -0
- data/vendor/tracemonkey/jslong.h +167 -0
- data/vendor/tracemonkey/jsmath.cpp +806 -0
- data/vendor/tracemonkey/jsmath.h +63 -0
- data/vendor/tracemonkey/jsnum.cpp +1374 -0
- data/vendor/tracemonkey/jsnum.h +280 -0
- data/vendor/tracemonkey/jsobj.cpp +6165 -0
- data/vendor/tracemonkey/jsobj.h +870 -0
- data/vendor/tracemonkey/json.cpp +1338 -0
- data/vendor/tracemonkey/json.h +108 -0
- data/vendor/tracemonkey/jsopcode.cpp +5484 -0
- data/vendor/tracemonkey/jsopcode.h +434 -0
- data/vendor/tracemonkey/jsopcode.tbl +591 -0
- data/vendor/tracemonkey/jsoplengen.cpp +121 -0
- data/vendor/tracemonkey/jsotypes.h +202 -0
- data/vendor/tracemonkey/jsparse.cpp +9257 -0
- data/vendor/tracemonkey/jsparse.h +900 -0
- data/vendor/tracemonkey/jsprf.cpp +1262 -0
- data/vendor/tracemonkey/jsprf.h +150 -0
- data/vendor/tracemonkey/jsproto.tbl +117 -0
- data/vendor/tracemonkey/jsprvtd.h +366 -0
- data/vendor/tracemonkey/jspubtd.h +585 -0
- data/vendor/tracemonkey/jsregexp.cpp +5051 -0
- data/vendor/tracemonkey/jsregexp.h +199 -0
- data/vendor/tracemonkey/jsreops.tbl +145 -0
- data/vendor/tracemonkey/jsscan.cpp +2040 -0
- data/vendor/tracemonkey/jsscan.h +467 -0
- data/vendor/tracemonkey/jsscope.cpp +1966 -0
- data/vendor/tracemonkey/jsscope.h +487 -0
- data/vendor/tracemonkey/jsscript.cpp +1932 -0
- data/vendor/tracemonkey/jsscript.h +345 -0
- data/vendor/tracemonkey/jsshell.msg +54 -0
- data/vendor/tracemonkey/jsstack.js +167 -0
- data/vendor/tracemonkey/jsstaticcheck.h +69 -0
- data/vendor/tracemonkey/jsstddef.h +87 -0
- data/vendor/tracemonkey/jsstdint.h +96 -0
- data/vendor/tracemonkey/jsstr.cpp +5277 -0
- data/vendor/tracemonkey/jsstr.h +702 -0
- data/vendor/tracemonkey/jstracer.cpp +10991 -0
- data/vendor/tracemonkey/jstracer.h +794 -0
- data/vendor/tracemonkey/jstypes.h +481 -0
- data/vendor/tracemonkey/jsutil.cpp +361 -0
- data/vendor/tracemonkey/jsutil.h +178 -0
- data/vendor/tracemonkey/jsversion.h +243 -0
- data/vendor/tracemonkey/jswince.asm +44 -0
- data/vendor/tracemonkey/jsxdrapi.cpp +800 -0
- data/vendor/tracemonkey/jsxdrapi.h +220 -0
- data/vendor/tracemonkey/jsxml.cpp +8327 -0
- data/vendor/tracemonkey/jsxml.h +305 -0
- data/vendor/tracemonkey/liveconnect/LiveConnect.dsp +157 -0
- data/vendor/tracemonkey/liveconnect/LiveConnectShell.dsp +120 -0
- data/vendor/tracemonkey/liveconnect/LiveConnectShell.dsw +44 -0
- data/vendor/tracemonkey/liveconnect/Makefile.in +105 -0
- data/vendor/tracemonkey/liveconnect/Makefile.ref +169 -0
- data/vendor/tracemonkey/liveconnect/README.html +712 -0
- data/vendor/tracemonkey/liveconnect/_jni/netscape_javascript_JSException.h +14 -0
- data/vendor/tracemonkey/liveconnect/_jni/netscape_javascript_JSObject.h +155 -0
- data/vendor/tracemonkey/liveconnect/classes/Makefile.in +89 -0
- data/vendor/tracemonkey/liveconnect/classes/Makefile.ref +57 -0
- data/vendor/tracemonkey/liveconnect/classes/netscape/Makefile.ref +47 -0
- data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSException.java +140 -0
- data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSObject.java +183 -0
- data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSProxy.java +58 -0
- data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSRunnable.java +70 -0
- data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSUtil.java +59 -0
- data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/Makefile.ref +53 -0
- data/vendor/tracemonkey/liveconnect/config/AIX4.1.mk +45 -0
- data/vendor/tracemonkey/liveconnect/config/AIX4.2.mk +45 -0
- data/vendor/tracemonkey/liveconnect/config/AIX4.3.mk +50 -0
- data/vendor/tracemonkey/liveconnect/config/HP-UXB.10.10.mk +43 -0
- data/vendor/tracemonkey/liveconnect/config/HP-UXB.10.20.mk +43 -0
- data/vendor/tracemonkey/liveconnect/config/HP-UXB.11.00.mk +43 -0
- data/vendor/tracemonkey/liveconnect/config/IRIX6.2.mk +43 -0
- data/vendor/tracemonkey/liveconnect/config/IRIX6.3.mk +43 -0
- data/vendor/tracemonkey/liveconnect/config/IRIX6.5.mk +43 -0
- data/vendor/tracemonkey/liveconnect/config/Linux_All.mk +73 -0
- data/vendor/tracemonkey/liveconnect/config/OSF1V4.0.mk +65 -0
- data/vendor/tracemonkey/liveconnect/config/OSF1V5.0.mk +62 -0
- data/vendor/tracemonkey/liveconnect/config/SunOS5.5.1.mk +55 -0
- data/vendor/tracemonkey/liveconnect/config/SunOS5.6.mk +39 -0
- data/vendor/tracemonkey/liveconnect/config/SunOS5.7.mk +39 -0
- data/vendor/tracemonkey/liveconnect/config/SunOS5.8.mk +39 -0
- data/vendor/tracemonkey/liveconnect/config/WINNT4.0.mk +53 -0
- data/vendor/tracemonkey/liveconnect/jsj.c +886 -0
- data/vendor/tracemonkey/liveconnect/jsj.msg +98 -0
- data/vendor/tracemonkey/liveconnect/jsj_JSObject.c +1377 -0
- data/vendor/tracemonkey/liveconnect/jsj_JavaArray.c +474 -0
- data/vendor/tracemonkey/liveconnect/jsj_JavaClass.c +737 -0
- data/vendor/tracemonkey/liveconnect/jsj_JavaMember.c +191 -0
- data/vendor/tracemonkey/liveconnect/jsj_JavaObject.c +1079 -0
- data/vendor/tracemonkey/liveconnect/jsj_JavaPackage.c +569 -0
- data/vendor/tracemonkey/liveconnect/jsj_array.c +207 -0
- data/vendor/tracemonkey/liveconnect/jsj_class.c +770 -0
- data/vendor/tracemonkey/liveconnect/jsj_convert.c +902 -0
- data/vendor/tracemonkey/liveconnect/jsj_field.c +421 -0
- data/vendor/tracemonkey/liveconnect/jsj_hash.c +488 -0
- data/vendor/tracemonkey/liveconnect/jsj_hash.h +161 -0
- data/vendor/tracemonkey/liveconnect/jsj_method.c +1825 -0
- data/vendor/tracemonkey/liveconnect/jsj_nodl.c +1 -0
- data/vendor/tracemonkey/liveconnect/jsj_private.h +677 -0
- data/vendor/tracemonkey/liveconnect/jsj_simpleapi.c +219 -0
- data/vendor/tracemonkey/liveconnect/jsj_utils.c +513 -0
- data/vendor/tracemonkey/liveconnect/jsjava.h +316 -0
- data/vendor/tracemonkey/liveconnect/netscape_javascript_JSObject.h +155 -0
- data/vendor/tracemonkey/liveconnect/nsCLiveconnect.cpp +785 -0
- data/vendor/tracemonkey/liveconnect/nsCLiveconnect.h +197 -0
- data/vendor/tracemonkey/liveconnect/nsCLiveconnectFactory.cpp +118 -0
- data/vendor/tracemonkey/liveconnect/nsCLiveconnectFactory.h +76 -0
- data/vendor/tracemonkey/liveconnect/nsILiveconnect.h +197 -0
- data/vendor/tracemonkey/liveconnect/nsISecureLiveconnect.h +94 -0
- data/vendor/tracemonkey/liveconnect/nsISecurityContext.h +136 -0
- data/vendor/tracemonkey/lock_SunOS.s +119 -0
- data/vendor/tracemonkey/mandelbrot-results.js +3 -0
- data/vendor/tracemonkey/math-partial-sums.js +32 -0
- data/vendor/tracemonkey/math-trace-tests.js +507 -0
- data/vendor/tracemonkey/md5.js +289 -0
- data/vendor/tracemonkey/nanojit/Assembler.cpp +1984 -0
- data/vendor/tracemonkey/nanojit/Assembler.h +375 -0
- data/vendor/tracemonkey/nanojit/Fragmento.cpp +651 -0
- data/vendor/tracemonkey/nanojit/Fragmento.h +237 -0
- data/vendor/tracemonkey/nanojit/LIR.cpp +2314 -0
- data/vendor/tracemonkey/nanojit/LIR.h +879 -0
- data/vendor/tracemonkey/nanojit/LIRopcode.tbl +252 -0
- data/vendor/tracemonkey/nanojit/Native.h +127 -0
- data/vendor/tracemonkey/nanojit/NativeARM.cpp +1742 -0
- data/vendor/tracemonkey/nanojit/NativeARM.h +844 -0
- data/vendor/tracemonkey/nanojit/NativeSparc.cpp +1130 -0
- data/vendor/tracemonkey/nanojit/NativeSparc.h +948 -0
- data/vendor/tracemonkey/nanojit/NativeThumb.cpp +1322 -0
- data/vendor/tracemonkey/nanojit/NativeThumb.h +525 -0
- data/vendor/tracemonkey/nanojit/Nativei386.cpp +1748 -0
- data/vendor/tracemonkey/nanojit/Nativei386.h +857 -0
- data/vendor/tracemonkey/nanojit/RegAlloc.cpp +183 -0
- data/vendor/tracemonkey/nanojit/RegAlloc.h +95 -0
- data/vendor/tracemonkey/nanojit/TraceTreeDrawer.cpp +306 -0
- data/vendor/tracemonkey/nanojit/TraceTreeDrawer.h +88 -0
- data/vendor/tracemonkey/nanojit/avmplus.cpp +56 -0
- data/vendor/tracemonkey/nanojit/avmplus.h +1016 -0
- data/vendor/tracemonkey/nanojit/nanojit.h +253 -0
- data/vendor/tracemonkey/perfect.js +39 -0
- data/vendor/tracemonkey/plify_jsdhash.sed +35 -0
- data/vendor/tracemonkey/prmjtime.cpp +869 -0
- data/vendor/tracemonkey/prmjtime.h +103 -0
- data/vendor/tracemonkey/ref-config/AIX4.1.mk +65 -0
- data/vendor/tracemonkey/ref-config/AIX4.2.mk +64 -0
- data/vendor/tracemonkey/ref-config/AIX4.3.mk +65 -0
- data/vendor/tracemonkey/ref-config/Darwin.mk +85 -0
- data/vendor/tracemonkey/ref-config/Darwin1.3.mk +81 -0
- data/vendor/tracemonkey/ref-config/Darwin1.4.mk +41 -0
- data/vendor/tracemonkey/ref-config/Darwin5.2.mk +81 -0
- data/vendor/tracemonkey/ref-config/Darwin5.3.mk +81 -0
- data/vendor/tracemonkey/ref-config/Darwin64.mk +72 -0
- data/vendor/tracemonkey/ref-config/HP-UXB.10.10.mk +77 -0
- data/vendor/tracemonkey/ref-config/HP-UXB.10.20.mk +77 -0
- data/vendor/tracemonkey/ref-config/HP-UXB.11.00.mk +80 -0
- data/vendor/tracemonkey/ref-config/IRIX.mk +87 -0
- data/vendor/tracemonkey/ref-config/IRIX5.3.mk +44 -0
- data/vendor/tracemonkey/ref-config/IRIX6.1.mk +44 -0
- data/vendor/tracemonkey/ref-config/IRIX6.2.mk +44 -0
- data/vendor/tracemonkey/ref-config/IRIX6.3.mk +44 -0
- data/vendor/tracemonkey/ref-config/IRIX6.5.mk +44 -0
- data/vendor/tracemonkey/ref-config/Linux_All.mk +105 -0
- data/vendor/tracemonkey/ref-config/Mac_OS10.0.mk +82 -0
- data/vendor/tracemonkey/ref-config/OSF1V4.0.mk +72 -0
- data/vendor/tracemonkey/ref-config/OSF1V5.0.mk +69 -0
- data/vendor/tracemonkey/ref-config/SunOS4.1.4.mk +101 -0
- data/vendor/tracemonkey/ref-config/SunOS5.10.mk +50 -0
- data/vendor/tracemonkey/ref-config/SunOS5.3.mk +91 -0
- data/vendor/tracemonkey/ref-config/SunOS5.4.mk +92 -0
- data/vendor/tracemonkey/ref-config/SunOS5.5.1.mk +44 -0
- data/vendor/tracemonkey/ref-config/SunOS5.5.mk +87 -0
- data/vendor/tracemonkey/ref-config/SunOS5.6.mk +89 -0
- data/vendor/tracemonkey/ref-config/SunOS5.7.mk +44 -0
- data/vendor/tracemonkey/ref-config/SunOS5.8.mk +44 -0
- data/vendor/tracemonkey/ref-config/SunOS5.9.mk +44 -0
- data/vendor/tracemonkey/ref-config/WINNT4.0.mk +118 -0
- data/vendor/tracemonkey/ref-config/WINNT5.0.mk +118 -0
- data/vendor/tracemonkey/ref-config/WINNT5.1.mk +118 -0
- data/vendor/tracemonkey/ref-config/WINNT5.2.mk +118 -0
- data/vendor/tracemonkey/ref-config/WINNT6.0.mk +118 -0
- data/vendor/tracemonkey/ref-config/dgux.mk +64 -0
- data/vendor/tracemonkey/resource.h +15 -0
- data/vendor/tracemonkey/rules.mk +206 -0
- data/vendor/tracemonkey/shell/Makefile.in +72 -0
- data/vendor/tracemonkey/shell/js.cpp +4719 -0
- data/vendor/tracemonkey/t/3d-cube.js +337 -0
- data/vendor/tracemonkey/t/3d-morph.js +54 -0
- data/vendor/tracemonkey/t/3d-raytrace.js +441 -0
- data/vendor/tracemonkey/t/access-binary-trees.js +50 -0
- data/vendor/tracemonkey/t/access-fannkuch.js +66 -0
- data/vendor/tracemonkey/t/access-nbody.js +169 -0
- data/vendor/tracemonkey/t/access-nsieve.js +38 -0
- data/vendor/tracemonkey/t/bitops-3bit-bits-in-byte.js +32 -0
- data/vendor/tracemonkey/t/bitops-bits-in-byte.js +21 -0
- data/vendor/tracemonkey/t/bitops-bitwise-and.js +28 -0
- data/vendor/tracemonkey/t/bitops-nsieve-bits.js +32 -0
- data/vendor/tracemonkey/t/controlflow-recursive.js +25 -0
- data/vendor/tracemonkey/t/crypto-aes.js +422 -0
- data/vendor/tracemonkey/t/crypto-md5.js +286 -0
- data/vendor/tracemonkey/t/crypto-sha1.js +224 -0
- data/vendor/tracemonkey/t/date-format-tofte.js +299 -0
- data/vendor/tracemonkey/t/date-format-xparb.js +417 -0
- data/vendor/tracemonkey/t/math-cordic.js +95 -0
- data/vendor/tracemonkey/t/math-partial-sums.js +33 -0
- data/vendor/tracemonkey/t/math-spectral-norm.js +51 -0
- data/vendor/tracemonkey/t/regexp-dna.js +1712 -0
- data/vendor/tracemonkey/t/string-base64.js +135 -0
- data/vendor/tracemonkey/t/string-fasta.js +85 -0
- data/vendor/tracemonkey/t/string-tagcloud.js +265 -0
- data/vendor/tracemonkey/t/string-unpack-code.js +68 -0
- data/vendor/tracemonkey/t/string-validate-input.js +89 -0
- data/vendor/tracemonkey/time.sh +13 -0
- data/vendor/tracemonkey/trace-test.js +5564 -0
- data/vendor/tracemonkey/v8/base.js +187 -0
- data/vendor/tracemonkey/v8/crypto.js +1689 -0
- data/vendor/tracemonkey/v8/deltablue.js +880 -0
- data/vendor/tracemonkey/v8/earley-boyer.js +4682 -0
- data/vendor/tracemonkey/v8/raytrace.js +3418 -0
- data/vendor/tracemonkey/v8/richards.js +539 -0
- data/vendor/tracemonkey/v8/run-crypto.js +44 -0
- data/vendor/tracemonkey/v8/run-deltablue.js +44 -0
- data/vendor/tracemonkey/v8/run-earley-boyer.js +44 -0
- data/vendor/tracemonkey/v8/run-raytrace.js +44 -0
- data/vendor/tracemonkey/v8/run-richards.js +44 -0
- data/vendor/tracemonkey/v8/run.js +49 -0
- data/vendor/tracemonkey/vprof/readme.txt +93 -0
- data/vendor/tracemonkey/vprof/vprof.cpp +360 -0
- data/vendor/tracemonkey/vprof/vprof.h +245 -0
- data/vendor/tracemonkey/xpconnect/Makefile.in +67 -0
- data/vendor/tracemonkey/xpconnect/crashtests/117307-1.html +20 -0
- data/vendor/tracemonkey/xpconnect/crashtests/193710.html +11 -0
- data/vendor/tracemonkey/xpconnect/crashtests/290162-1.html +5 -0
- data/vendor/tracemonkey/xpconnect/crashtests/326615-1.html +16 -0
- data/vendor/tracemonkey/xpconnect/crashtests/328553-1.html +13 -0
- data/vendor/tracemonkey/xpconnect/crashtests/346258-1.html +12 -0
- data/vendor/tracemonkey/xpconnect/crashtests/346512-1-frame1.xhtml +16 -0
- data/vendor/tracemonkey/xpconnect/crashtests/346512-1-frame2.xhtml +15 -0
- data/vendor/tracemonkey/xpconnect/crashtests/346512-1.xhtml +30 -0
- data/vendor/tracemonkey/xpconnect/crashtests/382133-1.html +3 -0
- data/vendor/tracemonkey/xpconnect/crashtests/386680-1.html +22 -0
- data/vendor/tracemonkey/xpconnect/crashtests/394810-1.html +4 -0
- data/vendor/tracemonkey/xpconnect/crashtests/400349-1.html +20 -0
- data/vendor/tracemonkey/xpconnect/crashtests/403356-1.html +13 -0
- data/vendor/tracemonkey/xpconnect/crashtests/418139-1.svg +22 -0
- data/vendor/tracemonkey/xpconnect/crashtests/420513-1.html +11 -0
- data/vendor/tracemonkey/xpconnect/crashtests/453935-1.html +37 -0
- data/vendor/tracemonkey/xpconnect/crashtests/462926.html +12 -0
- data/vendor/tracemonkey/xpconnect/crashtests/468552-1.html +18 -0
- data/vendor/tracemonkey/xpconnect/crashtests/471366-1.html +12 -0
- data/vendor/tracemonkey/xpconnect/crashtests/475185-1.html +13 -0
- data/vendor/tracemonkey/xpconnect/crashtests/475291-1.html +14 -0
- data/vendor/tracemonkey/xpconnect/crashtests/503286-1.html +23 -0
- data/vendor/tracemonkey/xpconnect/crashtests/crashtests.list +21 -0
- data/vendor/tracemonkey/xpconnect/idl/Makefile.in +78 -0
- data/vendor/tracemonkey/xpconnect/idl/XPCIDispatch.idl +51 -0
- data/vendor/tracemonkey/xpconnect/idl/mozIJSSubScriptLoader.idl +64 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIActiveXSecurityPolicy.idl +67 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIDispatchSupport.idl +119 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIJSContextStack.idl +85 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIJSRuntimeService.idl +51 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIScriptError.idl +102 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIScriptableInterfaces.idl +67 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIXPCScriptNotify.idl +66 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIXPCScriptable.idl +183 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIXPCSecurityManager.idl +114 -0
- data/vendor/tracemonkey/xpconnect/idl/nsIXPConnect.idl +819 -0
- data/vendor/tracemonkey/xpconnect/idl/xpcIJSModuleLoader.idl +95 -0
- data/vendor/tracemonkey/xpconnect/idl/xpcIJSWeakReference.idl +49 -0
- data/vendor/tracemonkey/xpconnect/idl/xpccomponents.idl +254 -0
- data/vendor/tracemonkey/xpconnect/idl/xpcexception.idl +66 -0
- data/vendor/tracemonkey/xpconnect/idl/xpcjsid.idl +83 -0
- data/vendor/tracemonkey/xpconnect/loader/ISO8601DateUtils.jsm +176 -0
- data/vendor/tracemonkey/xpconnect/loader/Makefile.in +63 -0
- data/vendor/tracemonkey/xpconnect/loader/XPCOMUtils.jsm +267 -0
- data/vendor/tracemonkey/xpconnect/loader/mozJSComponentLoader.cpp +1717 -0
- data/vendor/tracemonkey/xpconnect/loader/mozJSComponentLoader.h +172 -0
- data/vendor/tracemonkey/xpconnect/loader/mozJSLoaderConstructors.h +101 -0
- data/vendor/tracemonkey/xpconnect/loader/mozJSSubScriptLoader.cpp +360 -0
- data/vendor/tracemonkey/xpconnect/loader/mozJSSubScriptLoader.h +66 -0
- data/vendor/tracemonkey/xpconnect/public/Makefile.in +54 -0
- data/vendor/tracemonkey/xpconnect/public/nsAXPCNativeCallContext.h +89 -0
- data/vendor/tracemonkey/xpconnect/public/nsAutoJSValHolder.h +168 -0
- data/vendor/tracemonkey/xpconnect/public/xpc_map_end.h +327 -0
- data/vendor/tracemonkey/xpconnect/sample/Makefile.in +71 -0
- data/vendor/tracemonkey/xpconnect/sample/README +39 -0
- data/vendor/tracemonkey/xpconnect/sample/xpcsample1.cpp +337 -0
- data/vendor/tracemonkey/xpconnect/sample/xpcsample1.idl +82 -0
- data/vendor/tracemonkey/xpconnect/sample/xpcsample1.js +21 -0
- data/vendor/tracemonkey/xpconnect/shell/Makefile.in +106 -0
- data/vendor/tracemonkey/xpconnect/shell/jsshell.msg +50 -0
- data/vendor/tracemonkey/xpconnect/shell/xpcshell.cpp +1817 -0
- data/vendor/tracemonkey/xpconnect/shell/xpcshellMacUtils.h +43 -0
- data/vendor/tracemonkey/xpconnect/shell/xpcshellMacUtils.mm +54 -0
- data/vendor/tracemonkey/xpconnect/src/Makefile.in +228 -0
- data/vendor/tracemonkey/xpconnect/src/README +3 -0
- data/vendor/tracemonkey/xpconnect/src/XPCCrossOriginWrapper.cpp +1186 -0
- data/vendor/tracemonkey/xpconnect/src/XPCDispConvert.cpp +593 -0
- data/vendor/tracemonkey/xpconnect/src/XPCDispInlines.h +667 -0
- data/vendor/tracemonkey/xpconnect/src/XPCDispInterface.cpp +383 -0
- data/vendor/tracemonkey/xpconnect/src/XPCDispObject.cpp +516 -0
- data/vendor/tracemonkey/xpconnect/src/XPCDispParamPropJSClass.cpp +223 -0
- data/vendor/tracemonkey/xpconnect/src/XPCDispParams.cpp +103 -0
- data/vendor/tracemonkey/xpconnect/src/XPCDispPrivate.h +1401 -0
- data/vendor/tracemonkey/xpconnect/src/XPCDispTearOff.cpp +547 -0
- data/vendor/tracemonkey/xpconnect/src/XPCDispTypeInfo.cpp +471 -0
- data/vendor/tracemonkey/xpconnect/src/XPCIDispatchClassInfo.cpp +139 -0
- data/vendor/tracemonkey/xpconnect/src/XPCIDispatchExtension.cpp +362 -0
- data/vendor/tracemonkey/xpconnect/src/XPCNativeWrapper.cpp +1350 -0
- data/vendor/tracemonkey/xpconnect/src/XPCNativeWrapper.h +88 -0
- data/vendor/tracemonkey/xpconnect/src/XPCSafeJSObjectWrapper.cpp +1148 -0
- data/vendor/tracemonkey/xpconnect/src/XPCSystemOnlyWrapper.cpp +718 -0
- data/vendor/tracemonkey/xpconnect/src/XPCWrapper.cpp +850 -0
- data/vendor/tracemonkey/xpconnect/src/XPCWrapper.h +394 -0
- data/vendor/tracemonkey/xpconnect/src/dom_quickstubs.qsconf +568 -0
- data/vendor/tracemonkey/xpconnect/src/nsDispatchSupport.cpp +348 -0
- data/vendor/tracemonkey/xpconnect/src/nsScriptError.cpp +201 -0
- data/vendor/tracemonkey/xpconnect/src/nsXPConnect.cpp +2609 -0
- data/vendor/tracemonkey/xpconnect/src/qsgen.py +1487 -0
- data/vendor/tracemonkey/xpconnect/src/xpc.msg +217 -0
- data/vendor/tracemonkey/xpconnect/src/xpcJSWeakReference.cpp +148 -0
- data/vendor/tracemonkey/xpconnect/src/xpcJSWeakReference.h +56 -0
- data/vendor/tracemonkey/xpconnect/src/xpccallcontext.cpp +579 -0
- data/vendor/tracemonkey/xpconnect/src/xpccomponents.cpp +4144 -0
- data/vendor/tracemonkey/xpconnect/src/xpccontext.cpp +115 -0
- data/vendor/tracemonkey/xpconnect/src/xpcconvert.cpp +2298 -0
- data/vendor/tracemonkey/xpconnect/src/xpcdebug.cpp +481 -0
- data/vendor/tracemonkey/xpconnect/src/xpcexception.cpp +502 -0
- data/vendor/tracemonkey/xpconnect/src/xpcforwards.h +114 -0
- data/vendor/tracemonkey/xpconnect/src/xpcinlines.h +772 -0
- data/vendor/tracemonkey/xpconnect/src/xpcjsid.cpp +1025 -0
- data/vendor/tracemonkey/xpconnect/src/xpcjsruntime.cpp +1342 -0
- data/vendor/tracemonkey/xpconnect/src/xpclog.cpp +128 -0
- data/vendor/tracemonkey/xpconnect/src/xpclog.h +101 -0
- data/vendor/tracemonkey/xpconnect/src/xpcmaps.cpp +761 -0
- data/vendor/tracemonkey/xpconnect/src/xpcmaps.h +713 -0
- data/vendor/tracemonkey/xpconnect/src/xpcmodule.cpp +136 -0
- data/vendor/tracemonkey/xpconnect/src/xpcprivate.h +4138 -0
- data/vendor/tracemonkey/xpconnect/src/xpcquickstubs.cpp +1128 -0
- data/vendor/tracemonkey/xpconnect/src/xpcquickstubs.h +480 -0
- data/vendor/tracemonkey/xpconnect/src/xpcruntimesvc.cpp +179 -0
- data/vendor/tracemonkey/xpconnect/src/xpcstack.cpp +342 -0
- data/vendor/tracemonkey/xpconnect/src/xpcstring.cpp +139 -0
- data/vendor/tracemonkey/xpconnect/src/xpcthreadcontext.cpp +599 -0
- data/vendor/tracemonkey/xpconnect/src/xpcthrower.cpp +399 -0
- data/vendor/tracemonkey/xpconnect/src/xpcvariant.cpp +850 -0
- data/vendor/tracemonkey/xpconnect/src/xpcwrappedjs.cpp +670 -0
- data/vendor/tracemonkey/xpconnect/src/xpcwrappedjsclass.cpp +2015 -0
- data/vendor/tracemonkey/xpconnect/src/xpcwrappednative.cpp +3482 -0
- data/vendor/tracemonkey/xpconnect/src/xpcwrappednativeinfo.cpp +945 -0
- data/vendor/tracemonkey/xpconnect/src/xpcwrappednativejsops.cpp +2003 -0
- data/vendor/tracemonkey/xpconnect/src/xpcwrappednativeproto.cpp +302 -0
- data/vendor/tracemonkey/xpconnect/src/xpcwrappednativescope.cpp +991 -0
- data/vendor/tracemonkey/xpconnect/tests/Makefile.in +75 -0
- data/vendor/tracemonkey/xpconnect/tests/TestXPC.cpp +785 -0
- data/vendor/tracemonkey/xpconnect/tests/chrome/Makefile.in +51 -0
- data/vendor/tracemonkey/xpconnect/tests/chrome/test_bug500931.xul +43 -0
- data/vendor/tracemonkey/xpconnect/tests/components/Makefile.in +85 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_array.cpp +388 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_attributes.cpp +305 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_calljs.cpp +135 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_child.cpp +225 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_const.cpp +76 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_domstring.cpp +118 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_echo.cpp +616 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_in.cpp +204 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_inout.cpp +171 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_module.cpp +77 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_multiple.cpp +554 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_noisy.cpp +154 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_out.cpp +335 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_overloaded.cpp +250 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_private.h +192 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_string.cpp +185 -0
- data/vendor/tracemonkey/xpconnect/tests/components/xpctest_variant.cpp +355 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/StdAfx.cpp +12 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/StdAfx.h +28 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCDispUtilities.h +28 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.cpp +86 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.def +9 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.dsp +318 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.dsw +29 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.idl +454 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.rc +145 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispSimple.cpp +44 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispSimple.h +56 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispSimple.rgs +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestArrays.cpp +221 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestArrays.h +53 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestArrays.rgs +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestMethods.cpp +699 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestMethods.h +138 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestMethods.rgs +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestNoIDispatch.cpp +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestNoIDispatch.h +41 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestNoIDispatch.rgs +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestProperties.cpp +256 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestProperties.h +88 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestProperties.rgs +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOff.cpp +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOff.h +43 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOff.rgs +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOn.cpp +29 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOn.h +45 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOn.rgs +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestWrappedJS.cpp +177 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestWrappedJS.h +50 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestWrappedJS.rgs +23 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/resource.h +36 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/Arrays/XPCIDispatchArrayTests.js +54 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/Attributes/XPCIDispatchAttributeTests.js +150 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/General/XPCIDispatchInstantiations.js +122 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/General/XPCStress.js +58 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/Methods/XPCIDispatchMethodTests.js +376 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/shell.js +377 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedJS/General/XPCIDispatchTestWrappedJS.js +76 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedJS/shell.js +377 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/exectests.cmd +1 -0
- data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/jsDriver.pl +1288 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/Makefile.in +61 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest.idl +312 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest2.idl +51 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_attributes.idl +67 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_calljs.idl +59 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_const.idl +61 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_domstring.idl +59 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_in.idl +88 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_inout.idl +86 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_multiple.idl +77 -0
- data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_out.idl +142 -0
- data/vendor/tracemonkey/xpconnect/tests/js/checkid.js +82 -0
- data/vendor/tracemonkey/xpconnect/tests/js/evaluate.js +311 -0
- data/vendor/tracemonkey/xpconnect/tests/js/exceptions-2.js +153 -0
- data/vendor/tracemonkey/xpconnect/tests/js/exceptions-3.js +194 -0
- data/vendor/tracemonkey/xpconnect/tests/js/exceptions-4.js +297 -0
- data/vendor/tracemonkey/xpconnect/tests/js/exceptions-5.js +343 -0
- data/vendor/tracemonkey/xpconnect/tests/js/exceptions.js +230 -0
- data/vendor/tracemonkey/xpconnect/tests/js/javascript.js +96 -0
- data/vendor/tracemonkey/xpconnect/tests/js/multiple-2.js +151 -0
- data/vendor/tracemonkey/xpconnect/tests/js/multiple-3.js +148 -0
- data/vendor/tracemonkey/xpconnect/tests/js/multiple-4.js +152 -0
- data/vendor/tracemonkey/xpconnect/tests/js/multiple.js +137 -0
- data/vendor/tracemonkey/xpconnect/tests/js/notscriptable.js +104 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/simpletest.js +36 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/speed.js +60 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/testxpc.js +464 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/threads.js +74 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/try.js +27 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_array.js +308 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_callcontext.js +68 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_echo.js +636 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_enum_and_sort.js +28 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_enum_constants.js +15 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_enum_create.js +200 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_exceptions.js +167 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_ids.js +135 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_observer.js +36 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_overloaded.js +14 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_primitives.js +141 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_propertybag.js +36 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_variant.js +339 -0
- data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_variant_array.js +30 -0
- data/vendor/tracemonkey/xpconnect/tests/js/readonlyattributes.js +74 -0
- data/vendor/tracemonkey/xpconnect/tests/js/readwriteattributes.js +101 -0
- data/vendor/tracemonkey/xpconnect/tests/js/scriptable.js +120 -0
- data/vendor/tracemonkey/xpconnect/tests/js/testin.js +203 -0
- data/vendor/tracemonkey/xpconnect/tests/js/xpcfun.js +234 -0
- data/vendor/tracemonkey/xpconnect/tests/js/xpctest_primitives.js +200 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/Makefile.in +66 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/bug500931_helper.html +7 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/inner.html +7 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug361111.xul +29 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug384632.html +32 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug390488.html +65 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug393269.html +46 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug396851.html +43 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug428021.html +41 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug446584.html +49 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug448587.html +31 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug462428.html +42 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug478438.html +66 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug484107.html +100 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug484459.html +36 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug500691.html +28 -0
- data/vendor/tracemonkey/xpconnect/tests/mochitest/test_wrappers.html +116 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/bogus_element_type.jsm +1 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/bogus_exports_type.jsm +1 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/bug451678_subscript.js +2 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/component_import.js +144 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/recursive_importA.jsm +44 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/recursive_importB.jsm +45 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/syntax_error.jsm +1 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/test_bogus_files.js +88 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/test_bug408412.js +51 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/test_bug451678.js +52 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/test_bug_442086.js +68 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/test_import.js +127 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/test_js_weak_references.js +63 -0
- data/vendor/tracemonkey/xpconnect/tests/unit/test_recursive_import.js +62 -0
- data/vendor/tracemonkey/xpconnect/tools/Makefile.in +49 -0
- data/vendor/tracemonkey/xpconnect/tools/idl/Makefile.in +53 -0
- data/vendor/tracemonkey/xpconnect/tools/idl/nsIXPCToolsCompiler.idl +60 -0
- data/vendor/tracemonkey/xpconnect/tools/idl/nsIXPCToolsProfiler.idl +57 -0
- data/vendor/tracemonkey/xpconnect/tools/js/CompileJSFiles.js +28 -0
- data/vendor/tracemonkey/xpconnect/tools/js/ListJSFiles.js +18 -0
- data/vendor/tracemonkey/xpconnect/tools/src/Makefile.in +76 -0
- data/vendor/tracemonkey/xpconnect/tools/src/nsXPCToolsCompiler.cpp +161 -0
- data/vendor/tracemonkey/xpconnect/tools/src/nsXPCToolsModule.cpp +65 -0
- data/vendor/tracemonkey/xpconnect/tools/src/nsXPCToolsProfiler.cpp +370 -0
- data/vendor/tracemonkey/xpconnect/tools/src/xpctools_private.h +236 -0
- metadata +782 -107
- data/test/johnson/nodes/export_test.rb +0 -9
- data/test/johnson/nodes/import_test.rb +0 -13
- data/test/johnson/version_test.rb +0 -13
|
@@ -0,0 +1,3482 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
2
|
+
* vim: set ts=8 sw=4 et tw=78:
|
|
3
|
+
*
|
|
4
|
+
* ***** BEGIN LICENSE BLOCK *****
|
|
5
|
+
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
6
|
+
*
|
|
7
|
+
* The contents of this file are subject to the Mozilla Public License Version
|
|
8
|
+
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
9
|
+
* the License. You may obtain a copy of the License at
|
|
10
|
+
* http://www.mozilla.org/MPL/
|
|
11
|
+
*
|
|
12
|
+
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
13
|
+
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
14
|
+
* for the specific language governing rights and limitations under the
|
|
15
|
+
* License.
|
|
16
|
+
*
|
|
17
|
+
* The Original Code is Mozilla Communicator client code, released
|
|
18
|
+
* March 31, 1998.
|
|
19
|
+
*
|
|
20
|
+
* The Initial Developer of the Original Code is
|
|
21
|
+
* Netscape Communications Corporation.
|
|
22
|
+
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
23
|
+
* the Initial Developer. All Rights Reserved.
|
|
24
|
+
*
|
|
25
|
+
* Contributor(s):
|
|
26
|
+
* John Bandhauer <jband@netscape.com> (original author)
|
|
27
|
+
*
|
|
28
|
+
* Alternatively, the contents of this file may be used under the terms of
|
|
29
|
+
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
30
|
+
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
31
|
+
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
32
|
+
* of those above. If you wish to allow use of your version of this file only
|
|
33
|
+
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
34
|
+
* use your version of this file under the terms of the MPL, indicate your
|
|
35
|
+
* decision by deleting the provisions above and replace them with the notice
|
|
36
|
+
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
37
|
+
* the provisions above, a recipient may use your version of this file under
|
|
38
|
+
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
39
|
+
*
|
|
40
|
+
* ***** END LICENSE BLOCK ***** */
|
|
41
|
+
|
|
42
|
+
/* Wrapper object for reflecting native xpcom objects into JavaScript. */
|
|
43
|
+
|
|
44
|
+
#include "xpcprivate.h"
|
|
45
|
+
#include "nsCRT.h"
|
|
46
|
+
#include "XPCNativeWrapper.h"
|
|
47
|
+
#include "XPCWrapper.h"
|
|
48
|
+
#include "nsWrapperCache.h"
|
|
49
|
+
|
|
50
|
+
/***************************************************************************/
|
|
51
|
+
|
|
52
|
+
NS_IMPL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
|
|
53
|
+
|
|
54
|
+
NS_IMETHODIMP
|
|
55
|
+
NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::RootAndUnlinkJSObjects(void *p)
|
|
56
|
+
{
|
|
57
|
+
XPCWrappedNative *tmp = static_cast<XPCWrappedNative*>(p);
|
|
58
|
+
tmp->ExpireWrapper();
|
|
59
|
+
return NS_OK;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
NS_IMETHODIMP
|
|
64
|
+
NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Traverse(void *p,
|
|
65
|
+
nsCycleCollectionTraversalCallback &cb)
|
|
66
|
+
{
|
|
67
|
+
XPCWrappedNative *tmp = static_cast<XPCWrappedNative*>(p);
|
|
68
|
+
if(!tmp->IsValid())
|
|
69
|
+
return NS_OK;
|
|
70
|
+
|
|
71
|
+
#ifdef DEBUG_CC
|
|
72
|
+
char name[72];
|
|
73
|
+
XPCNativeScriptableInfo* si = tmp->GetScriptableInfo();
|
|
74
|
+
if(si)
|
|
75
|
+
JS_snprintf(name, sizeof(name), "XPCWrappedNative (%s)",
|
|
76
|
+
si->GetJSClass()->name);
|
|
77
|
+
else
|
|
78
|
+
JS_snprintf(name, sizeof(name), "XPCWrappedNative");
|
|
79
|
+
|
|
80
|
+
cb.DescribeNode(RefCounted, tmp->mRefCnt.get(), sizeof(XPCWrappedNative),
|
|
81
|
+
name);
|
|
82
|
+
#else
|
|
83
|
+
cb.DescribeNode(RefCounted, tmp->mRefCnt.get());
|
|
84
|
+
#endif
|
|
85
|
+
|
|
86
|
+
if(tmp->mRefCnt.get() > 1) {
|
|
87
|
+
|
|
88
|
+
// If our refcount is > 1, our reference to the flat JS object is
|
|
89
|
+
// considered "strong", and we're going to traverse it.
|
|
90
|
+
//
|
|
91
|
+
// If our refcount is <= 1, our reference to the flat JS object is
|
|
92
|
+
// considered "weak", and we're *not* going to traverse it.
|
|
93
|
+
//
|
|
94
|
+
// This reasoning is in line with the slightly confusing lifecycle rules
|
|
95
|
+
// for XPCWrappedNatives, described in a larger comment below and also
|
|
96
|
+
// on our wiki at http://wiki.mozilla.org/XPConnect_object_wrapping
|
|
97
|
+
|
|
98
|
+
JSObject *obj = nsnull;
|
|
99
|
+
nsresult rv = tmp->GetJSObject(&obj);
|
|
100
|
+
if(NS_SUCCEEDED(rv))
|
|
101
|
+
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, obj);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// XPCWrappedNative keeps its native object alive.
|
|
105
|
+
cb.NoteXPCOMChild(tmp->GetIdentityObject());
|
|
106
|
+
|
|
107
|
+
tmp->NoteTearoffs(cb);
|
|
108
|
+
|
|
109
|
+
return NS_OK;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
void
|
|
113
|
+
XPCWrappedNative::NoteTearoffs(nsCycleCollectionTraversalCallback& cb)
|
|
114
|
+
{
|
|
115
|
+
// Tearoffs hold their native object alive. If their JS object hasn't been
|
|
116
|
+
// finalized yet we'll note the edge between the JS object and the native
|
|
117
|
+
// (see nsXPConnect::Traverse), but if their JS object has been finalized
|
|
118
|
+
// then the tearoff is only reachable through the XPCWrappedNative, so we
|
|
119
|
+
// record an edge here.
|
|
120
|
+
XPCWrappedNativeTearOffChunk* chunk;
|
|
121
|
+
for(chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk)
|
|
122
|
+
{
|
|
123
|
+
XPCWrappedNativeTearOff* to = chunk->mTearOffs;
|
|
124
|
+
for(int i = XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK-1; i >= 0; i--, to++)
|
|
125
|
+
{
|
|
126
|
+
JSObject* jso = to->GetJSObject();
|
|
127
|
+
if(!jso)
|
|
128
|
+
{
|
|
129
|
+
cb.NoteXPCOMChild(to->GetNative());
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
#ifdef XPC_CHECK_CLASSINFO_CLAIMS
|
|
136
|
+
static void DEBUG_CheckClassInfoClaims(XPCWrappedNative* wrapper);
|
|
137
|
+
#else
|
|
138
|
+
#define DEBUG_CheckClassInfoClaims(wrapper) ((void)0)
|
|
139
|
+
#endif
|
|
140
|
+
|
|
141
|
+
#ifdef XPC_TRACK_WRAPPER_STATS
|
|
142
|
+
static int DEBUG_TotalWrappedNativeCount;
|
|
143
|
+
static int DEBUG_TotalLiveWrappedNativeCount;
|
|
144
|
+
static int DEBUG_TotalMaxWrappedNativeCount;
|
|
145
|
+
static int DEBUG_WrappedNativeWithProtoCount;
|
|
146
|
+
static int DEBUG_LiveWrappedNativeWithProtoCount;
|
|
147
|
+
static int DEBUG_MaxWrappedNativeWithProtoCount;
|
|
148
|
+
static int DEBUG_WrappedNativeNoProtoCount;
|
|
149
|
+
static int DEBUG_LiveWrappedNativeNoProtoCount;
|
|
150
|
+
static int DEBUG_MaxWrappedNativeNoProtoCount;
|
|
151
|
+
static int DEBUG_WrappedNativeTotalCalls;
|
|
152
|
+
static int DEBUG_WrappedNativeMethodCalls;
|
|
153
|
+
static int DEBUG_WrappedNativeGetterCalls;
|
|
154
|
+
static int DEBUG_WrappedNativeSetterCalls;
|
|
155
|
+
#define DEBUG_CHUNKS_TO_COUNT 4
|
|
156
|
+
static int DEBUG_WrappedNativeTearOffChunkCounts[DEBUG_CHUNKS_TO_COUNT+1];
|
|
157
|
+
static PRBool DEBUG_DumpedWrapperStats;
|
|
158
|
+
#endif
|
|
159
|
+
|
|
160
|
+
#ifdef DEBUG
|
|
161
|
+
static void DEBUG_TrackNewWrapper(XPCWrappedNative* wrapper)
|
|
162
|
+
{
|
|
163
|
+
#ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
|
|
164
|
+
if(wrapper->GetRuntime())
|
|
165
|
+
wrapper->GetRuntime()->DEBUG_AddWrappedNative(wrapper);
|
|
166
|
+
else
|
|
167
|
+
NS_ERROR("failed to add wrapper");
|
|
168
|
+
#endif
|
|
169
|
+
#ifdef XPC_TRACK_WRAPPER_STATS
|
|
170
|
+
DEBUG_TotalWrappedNativeCount++;
|
|
171
|
+
DEBUG_TotalLiveWrappedNativeCount++;
|
|
172
|
+
if(DEBUG_TotalMaxWrappedNativeCount < DEBUG_TotalLiveWrappedNativeCount)
|
|
173
|
+
DEBUG_TotalMaxWrappedNativeCount = DEBUG_TotalLiveWrappedNativeCount;
|
|
174
|
+
|
|
175
|
+
if(wrapper->HasProto())
|
|
176
|
+
{
|
|
177
|
+
DEBUG_WrappedNativeWithProtoCount++;
|
|
178
|
+
DEBUG_LiveWrappedNativeWithProtoCount++;
|
|
179
|
+
if(DEBUG_MaxWrappedNativeWithProtoCount < DEBUG_LiveWrappedNativeWithProtoCount)
|
|
180
|
+
DEBUG_MaxWrappedNativeWithProtoCount = DEBUG_LiveWrappedNativeWithProtoCount;
|
|
181
|
+
}
|
|
182
|
+
else
|
|
183
|
+
{
|
|
184
|
+
DEBUG_WrappedNativeNoProtoCount++;
|
|
185
|
+
DEBUG_LiveWrappedNativeNoProtoCount++;
|
|
186
|
+
if(DEBUG_MaxWrappedNativeNoProtoCount < DEBUG_LiveWrappedNativeNoProtoCount)
|
|
187
|
+
DEBUG_MaxWrappedNativeNoProtoCount = DEBUG_LiveWrappedNativeNoProtoCount;
|
|
188
|
+
}
|
|
189
|
+
#endif
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
static void DEBUG_TrackDeleteWrapper(XPCWrappedNative* wrapper)
|
|
193
|
+
{
|
|
194
|
+
#ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
|
|
195
|
+
nsXPConnect::GetRuntimeInstance()->DEBUG_RemoveWrappedNative(wrapper);
|
|
196
|
+
#endif
|
|
197
|
+
#ifdef XPC_TRACK_WRAPPER_STATS
|
|
198
|
+
DEBUG_TotalLiveWrappedNativeCount--;
|
|
199
|
+
if(wrapper->HasProto())
|
|
200
|
+
DEBUG_LiveWrappedNativeWithProtoCount--;
|
|
201
|
+
else
|
|
202
|
+
DEBUG_LiveWrappedNativeNoProtoCount--;
|
|
203
|
+
|
|
204
|
+
int extraChunkCount = wrapper->DEBUG_CountOfTearoffChunks() - 1;
|
|
205
|
+
if(extraChunkCount > DEBUG_CHUNKS_TO_COUNT)
|
|
206
|
+
extraChunkCount = DEBUG_CHUNKS_TO_COUNT;
|
|
207
|
+
DEBUG_WrappedNativeTearOffChunkCounts[extraChunkCount]++;
|
|
208
|
+
#endif
|
|
209
|
+
}
|
|
210
|
+
static void DEBUG_TrackWrapperCall(XPCWrappedNative* wrapper,
|
|
211
|
+
XPCWrappedNative::CallMode mode)
|
|
212
|
+
{
|
|
213
|
+
#ifdef XPC_TRACK_WRAPPER_STATS
|
|
214
|
+
DEBUG_WrappedNativeTotalCalls++;
|
|
215
|
+
switch(mode)
|
|
216
|
+
{
|
|
217
|
+
case XPCWrappedNative::CALL_METHOD:
|
|
218
|
+
DEBUG_WrappedNativeMethodCalls++;
|
|
219
|
+
break;
|
|
220
|
+
case XPCWrappedNative::CALL_GETTER:
|
|
221
|
+
DEBUG_WrappedNativeGetterCalls++;
|
|
222
|
+
break;
|
|
223
|
+
case XPCWrappedNative::CALL_SETTER:
|
|
224
|
+
DEBUG_WrappedNativeSetterCalls++;
|
|
225
|
+
break;
|
|
226
|
+
default:
|
|
227
|
+
NS_ERROR("bad value");
|
|
228
|
+
}
|
|
229
|
+
#endif
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
static void DEBUG_TrackShutdownWrapper(XPCWrappedNative* wrapper)
|
|
233
|
+
{
|
|
234
|
+
#ifdef XPC_TRACK_WRAPPER_STATS
|
|
235
|
+
if(!DEBUG_DumpedWrapperStats)
|
|
236
|
+
{
|
|
237
|
+
DEBUG_DumpedWrapperStats = PR_TRUE;
|
|
238
|
+
printf("%d WrappedNatives were constructed. "
|
|
239
|
+
"(%d w/ protos, %d w/o)\n",
|
|
240
|
+
DEBUG_TotalWrappedNativeCount,
|
|
241
|
+
DEBUG_WrappedNativeWithProtoCount,
|
|
242
|
+
DEBUG_WrappedNativeNoProtoCount);
|
|
243
|
+
|
|
244
|
+
printf("%d WrappedNatives max alive at one time. "
|
|
245
|
+
"(%d w/ protos, %d w/o)\n",
|
|
246
|
+
DEBUG_TotalMaxWrappedNativeCount,
|
|
247
|
+
DEBUG_MaxWrappedNativeWithProtoCount,
|
|
248
|
+
DEBUG_MaxWrappedNativeNoProtoCount);
|
|
249
|
+
|
|
250
|
+
printf("%d WrappedNatives alive now. "
|
|
251
|
+
"(%d w/ protos, %d w/o)\n",
|
|
252
|
+
DEBUG_TotalLiveWrappedNativeCount,
|
|
253
|
+
DEBUG_LiveWrappedNativeWithProtoCount,
|
|
254
|
+
DEBUG_LiveWrappedNativeNoProtoCount);
|
|
255
|
+
|
|
256
|
+
printf("%d calls to WrappedNatives. "
|
|
257
|
+
"(%d methods, %d getters, %d setters)\n",
|
|
258
|
+
DEBUG_WrappedNativeTotalCalls,
|
|
259
|
+
DEBUG_WrappedNativeMethodCalls,
|
|
260
|
+
DEBUG_WrappedNativeGetterCalls,
|
|
261
|
+
DEBUG_WrappedNativeSetterCalls);
|
|
262
|
+
|
|
263
|
+
printf("(wrappers / tearoffs): (");
|
|
264
|
+
int i;
|
|
265
|
+
for(i = 0; i < DEBUG_CHUNKS_TO_COUNT; i++)
|
|
266
|
+
{
|
|
267
|
+
printf("%d / %d, ",
|
|
268
|
+
DEBUG_WrappedNativeTearOffChunkCounts[i],
|
|
269
|
+
(i+1) * XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK);
|
|
270
|
+
}
|
|
271
|
+
printf("%d / more)\n", DEBUG_WrappedNativeTearOffChunkCounts[i]);
|
|
272
|
+
}
|
|
273
|
+
#endif
|
|
274
|
+
}
|
|
275
|
+
#else
|
|
276
|
+
#define DEBUG_TrackNewWrapper(wrapper) ((void)0)
|
|
277
|
+
#define DEBUG_TrackDeleteWrapper(wrapper) ((void)0)
|
|
278
|
+
#define DEBUG_TrackWrapperCall(wrapper, mode) ((void)0)
|
|
279
|
+
#define DEBUG_TrackShutdownWrapper(wrapper) ((void)0)
|
|
280
|
+
#endif
|
|
281
|
+
|
|
282
|
+
/***************************************************************************/
|
|
283
|
+
|
|
284
|
+
// static
|
|
285
|
+
nsresult
|
|
286
|
+
XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
|
|
287
|
+
nsISupports* Object,
|
|
288
|
+
XPCWrappedNativeScope* Scope,
|
|
289
|
+
XPCNativeInterface* Interface,
|
|
290
|
+
nsWrapperCache *cache,
|
|
291
|
+
JSBool isGlobal,
|
|
292
|
+
XPCWrappedNative** resultWrapper)
|
|
293
|
+
{
|
|
294
|
+
NS_ASSERTION(!cache || !cache->GetWrapper(),
|
|
295
|
+
"We assume the caller already checked if it could get the "
|
|
296
|
+
"wrapper from the cache.");
|
|
297
|
+
|
|
298
|
+
nsresult rv;
|
|
299
|
+
|
|
300
|
+
#ifdef DEBUG
|
|
301
|
+
NS_ASSERTION(!Scope->GetRuntime()->GetThreadRunningGC(),
|
|
302
|
+
"XPCWrappedNative::GetNewOrUsed called during GC");
|
|
303
|
+
{
|
|
304
|
+
nsWrapperCache *cache2 = nsnull;
|
|
305
|
+
CallQueryInterface(Object, &cache2);
|
|
306
|
+
NS_ASSERTION(!cache == !cache2, "Caller should pass in the cache!");
|
|
307
|
+
}
|
|
308
|
+
#endif
|
|
309
|
+
|
|
310
|
+
nsCOMPtr<nsISupports> identity;
|
|
311
|
+
#ifdef XPC_IDISPATCH_SUPPORT
|
|
312
|
+
// XXX This is done for the benefit of some warped COM implementations
|
|
313
|
+
// where QI(IID_IUnknown, a.b) == QI(IID_IUnknown, a). If someone passes
|
|
314
|
+
// in a pointer that hasn't been QI'd to IDispatch properly this could
|
|
315
|
+
// create multiple wrappers for the same object, creating a fair bit of
|
|
316
|
+
// confusion.
|
|
317
|
+
PRBool isIDispatch = Interface &&
|
|
318
|
+
Interface->GetIID()->Equals(NSID_IDISPATCH);
|
|
319
|
+
if(isIDispatch)
|
|
320
|
+
identity = Object;
|
|
321
|
+
else
|
|
322
|
+
#endif
|
|
323
|
+
identity = do_QueryInterface(Object);
|
|
324
|
+
|
|
325
|
+
if(!identity)
|
|
326
|
+
{
|
|
327
|
+
NS_ERROR("This XPCOM object fails in QueryInterface to nsISupports!");
|
|
328
|
+
return NS_ERROR_FAILURE;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
XPCLock* mapLock = Scope->GetRuntime()->GetMapLock();
|
|
332
|
+
|
|
333
|
+
// We use an AutoMarkingPtr here because it is possible for JS gc to happen
|
|
334
|
+
// after we have Init'd the wrapper but *before* we add it to the hashtable.
|
|
335
|
+
// This would cause the mSet to get collected and we'd later crash. I've
|
|
336
|
+
// *seen* this happen.
|
|
337
|
+
AutoMarkingWrappedNativePtr wrapper(ccx);
|
|
338
|
+
|
|
339
|
+
Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap();
|
|
340
|
+
{ // scoped lock
|
|
341
|
+
XPCAutoLock lock(mapLock);
|
|
342
|
+
wrapper = map->Find(identity);
|
|
343
|
+
if(wrapper)
|
|
344
|
+
wrapper->AddRef();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if(wrapper)
|
|
348
|
+
{
|
|
349
|
+
if(Interface && !wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv))
|
|
350
|
+
{
|
|
351
|
+
NS_RELEASE(wrapper);
|
|
352
|
+
NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
|
|
353
|
+
return rv;
|
|
354
|
+
}
|
|
355
|
+
DEBUG_CheckWrapperThreadSafety(wrapper);
|
|
356
|
+
*resultWrapper = wrapper;
|
|
357
|
+
return NS_OK;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// There is a chance that the object wants to have the self-same JSObject
|
|
361
|
+
// reflection regardless of the scope into which we are reflecting it.
|
|
362
|
+
// Many DOM objects require this. The scriptable helper specifies this
|
|
363
|
+
// in preCreate by indicating a 'parent' of a particular scope.
|
|
364
|
+
//
|
|
365
|
+
// To handle this we need to get the scriptable helper early and ask it.
|
|
366
|
+
// It is possible that we will then end up forwarding this entire call
|
|
367
|
+
// to this same function but with a different scope.
|
|
368
|
+
|
|
369
|
+
// If we are making a wrapper for the nsIClassInfo interface then
|
|
370
|
+
// We *don't* want to have it use the prototype meant for instances
|
|
371
|
+
// of that class.
|
|
372
|
+
JSBool isClassInfo = Interface &&
|
|
373
|
+
Interface->GetIID()->Equals(NS_GET_IID(nsIClassInfo));
|
|
374
|
+
|
|
375
|
+
nsCOMPtr<nsIClassInfo> info;
|
|
376
|
+
|
|
377
|
+
if(!isClassInfo)
|
|
378
|
+
info = do_QueryInterface(identity);
|
|
379
|
+
|
|
380
|
+
#ifdef XPC_IDISPATCH_SUPPORT
|
|
381
|
+
// If this is an IDispatch wrapper and it didn't give us a class info
|
|
382
|
+
// we'll provide a default one
|
|
383
|
+
if(isIDispatch && !info)
|
|
384
|
+
{
|
|
385
|
+
info = dont_AddRef(static_cast<nsIClassInfo*>
|
|
386
|
+
(XPCIDispatchClassInfo::GetSingleton()));
|
|
387
|
+
}
|
|
388
|
+
#endif
|
|
389
|
+
|
|
390
|
+
XPCNativeScriptableCreateInfo sciProto;
|
|
391
|
+
XPCNativeScriptableCreateInfo sciWrapper;
|
|
392
|
+
|
|
393
|
+
// Gather scriptable create info if we are wrapping something
|
|
394
|
+
// other than an nsIClassInfo object. We need to not do this for
|
|
395
|
+
// nsIClassInfo objects because often nsIClassInfo implementations
|
|
396
|
+
// are also nsIXPCScriptable helper implmentations, but the helper
|
|
397
|
+
// code is obviously intended for the implementation of the class
|
|
398
|
+
// described by the nsIClassInfo, not for the class info object
|
|
399
|
+
// itself.
|
|
400
|
+
if(!isClassInfo &&
|
|
401
|
+
NS_FAILED(GatherScriptableCreateInfo(identity, info.get(),
|
|
402
|
+
&sciProto, &sciWrapper)))
|
|
403
|
+
return NS_ERROR_FAILURE;
|
|
404
|
+
|
|
405
|
+
JSObject* parent = Scope->GetGlobalJSObject();
|
|
406
|
+
|
|
407
|
+
jsval newParentVal = JSVAL_NULL;
|
|
408
|
+
XPCMarkableJSVal newParentVal_markable(&newParentVal);
|
|
409
|
+
AutoMarkingJSVal newParentVal_automarker(ccx, &newParentVal_markable);
|
|
410
|
+
JSBool chromeOnly = JS_FALSE;
|
|
411
|
+
|
|
412
|
+
if(sciWrapper.GetFlags().WantPreCreate())
|
|
413
|
+
{
|
|
414
|
+
JSObject* plannedParent = parent;
|
|
415
|
+
nsresult rv = sciWrapper.GetCallback()->PreCreate(identity, ccx,
|
|
416
|
+
parent, &parent);
|
|
417
|
+
if(NS_FAILED(rv))
|
|
418
|
+
return rv;
|
|
419
|
+
|
|
420
|
+
chromeOnly = (rv == NS_SUCCESS_CHROME_ACCESS_ONLY);
|
|
421
|
+
rv = NS_OK;
|
|
422
|
+
|
|
423
|
+
NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(parent),
|
|
424
|
+
"Parent should never be an XPCNativeWrapper here");
|
|
425
|
+
|
|
426
|
+
if(parent != plannedParent)
|
|
427
|
+
{
|
|
428
|
+
XPCWrappedNativeScope* betterScope =
|
|
429
|
+
XPCWrappedNativeScope::FindInJSObjectScope(ccx, parent);
|
|
430
|
+
if(betterScope != Scope)
|
|
431
|
+
return GetNewOrUsed(ccx, identity, betterScope, Interface,
|
|
432
|
+
cache, isGlobal, resultWrapper);
|
|
433
|
+
|
|
434
|
+
newParentVal = OBJECT_TO_JSVAL(parent);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Take the performance hit of checking the hashtable again in case
|
|
438
|
+
// the preCreate call caused the wrapper to get created through some
|
|
439
|
+
// interesting path (the DOM code tends to make this happen sometimes).
|
|
440
|
+
|
|
441
|
+
{ // scoped lock
|
|
442
|
+
XPCAutoLock lock(mapLock);
|
|
443
|
+
wrapper = map->Find(identity);
|
|
444
|
+
if(wrapper)
|
|
445
|
+
wrapper->AddRef();
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if(wrapper)
|
|
449
|
+
{
|
|
450
|
+
if(Interface && !wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv))
|
|
451
|
+
{
|
|
452
|
+
NS_RELEASE(wrapper);
|
|
453
|
+
NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
|
|
454
|
+
return rv;
|
|
455
|
+
}
|
|
456
|
+
DEBUG_CheckWrapperThreadSafety(wrapper);
|
|
457
|
+
*resultWrapper = wrapper;
|
|
458
|
+
return NS_OK;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
AutoMarkingWrappedNativeProtoPtr proto(ccx);
|
|
463
|
+
|
|
464
|
+
// If there is ClassInfo (and we are not building a wrapper for the
|
|
465
|
+
// nsIClassInfo interface) then we use a wrapper that needs a prototype.
|
|
466
|
+
|
|
467
|
+
// Note that the security check happens inside FindTearOff - after the
|
|
468
|
+
// wrapper is actually created, but before JS code can see it.
|
|
469
|
+
|
|
470
|
+
if(info && !isClassInfo)
|
|
471
|
+
{
|
|
472
|
+
proto = XPCWrappedNativeProto::GetNewOrUsed(ccx, Scope, info, &sciProto,
|
|
473
|
+
JS_FALSE, isGlobal);
|
|
474
|
+
if(!proto)
|
|
475
|
+
return NS_ERROR_FAILURE;
|
|
476
|
+
|
|
477
|
+
proto->CacheOffsets(identity);
|
|
478
|
+
|
|
479
|
+
wrapper = new XPCWrappedNative(identity, proto);
|
|
480
|
+
if(!wrapper)
|
|
481
|
+
return NS_ERROR_FAILURE;
|
|
482
|
+
}
|
|
483
|
+
else
|
|
484
|
+
{
|
|
485
|
+
AutoMarkingNativeInterfacePtr iface(ccx, Interface);
|
|
486
|
+
if(!iface)
|
|
487
|
+
iface = XPCNativeInterface::GetISupports(ccx);
|
|
488
|
+
|
|
489
|
+
AutoMarkingNativeSetPtr set(ccx);
|
|
490
|
+
set = XPCNativeSet::GetNewOrUsed(ccx, nsnull, iface, 0);
|
|
491
|
+
|
|
492
|
+
if(!set)
|
|
493
|
+
return NS_ERROR_FAILURE;
|
|
494
|
+
|
|
495
|
+
wrapper = new XPCWrappedNative(identity, Scope, set);
|
|
496
|
+
if(!wrapper)
|
|
497
|
+
return NS_ERROR_FAILURE;
|
|
498
|
+
|
|
499
|
+
DEBUG_ReportShadowedMembers(set, wrapper, nsnull);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
NS_ADDREF(wrapper);
|
|
503
|
+
|
|
504
|
+
NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(parent),
|
|
505
|
+
"XPCNativeWrapper being used to parent XPCWrappedNative?");
|
|
506
|
+
|
|
507
|
+
if(!wrapper->Init(ccx, parent, isGlobal, &sciWrapper))
|
|
508
|
+
{
|
|
509
|
+
NS_RELEASE(wrapper);
|
|
510
|
+
return NS_ERROR_FAILURE;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if(Interface && !wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv))
|
|
514
|
+
{
|
|
515
|
+
// Second reference will be released by the FlatJSObject's finializer.
|
|
516
|
+
wrapper->Release();
|
|
517
|
+
NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
|
|
518
|
+
return rv;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if(chromeOnly)
|
|
522
|
+
wrapper->SetNeedsChromeWrapper();
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
#if DEBUG_xpc_leaks
|
|
526
|
+
{
|
|
527
|
+
char* s = wrapper->ToString(ccx);
|
|
528
|
+
NS_ASSERTION(wrapper->GetFlatJSObject(), "eh?");
|
|
529
|
+
printf("Created wrapped native %s, flat JSObject is %p\n",
|
|
530
|
+
s, (void*)wrapper->GetFlatJSObject());
|
|
531
|
+
if(s)
|
|
532
|
+
JS_smprintf_free(s);
|
|
533
|
+
}
|
|
534
|
+
#endif
|
|
535
|
+
|
|
536
|
+
// Redundant wrapper must be killed outside of the map lock.
|
|
537
|
+
XPCWrappedNative* wrapperToKill = nsnull;
|
|
538
|
+
|
|
539
|
+
{ // scoped lock
|
|
540
|
+
XPCAutoLock lock(mapLock);
|
|
541
|
+
|
|
542
|
+
// Deal with the case where the wrapper got created as a side effect
|
|
543
|
+
// of one of our calls out of this code (or on another thread).
|
|
544
|
+
XPCWrappedNative* wrapper2 = map->Add(wrapper);
|
|
545
|
+
if(!wrapper2)
|
|
546
|
+
{
|
|
547
|
+
NS_ERROR("failed to add our wrapper!");
|
|
548
|
+
wrapperToKill = wrapper;
|
|
549
|
+
wrapper = nsnull;
|
|
550
|
+
}
|
|
551
|
+
else if(wrapper2 != wrapper)
|
|
552
|
+
{
|
|
553
|
+
NS_ADDREF(wrapper2);
|
|
554
|
+
wrapperToKill = wrapper;
|
|
555
|
+
wrapper = wrapper2;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if(wrapperToKill)
|
|
560
|
+
{
|
|
561
|
+
// Second reference will be released by the FlatJSObject's finializer.
|
|
562
|
+
wrapperToKill->Release();
|
|
563
|
+
}
|
|
564
|
+
else if(wrapper)
|
|
565
|
+
{
|
|
566
|
+
if(cache)
|
|
567
|
+
cache->SetWrapper(wrapper);
|
|
568
|
+
|
|
569
|
+
// Our newly created wrapper is the one that we just added to the table.
|
|
570
|
+
// All is well. Call PostCreate as necessary.
|
|
571
|
+
XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
|
|
572
|
+
if(si && si->GetFlags().WantPostCreate())
|
|
573
|
+
{
|
|
574
|
+
rv = si->GetCallback()->
|
|
575
|
+
PostCreate(wrapper, ccx, wrapper->GetFlatJSObject());
|
|
576
|
+
if(NS_FAILED(rv))
|
|
577
|
+
{
|
|
578
|
+
// PostCreate failed and that's Very Bad. We'll remove it from
|
|
579
|
+
// the map and mark it as invalid, but the PostCreate function
|
|
580
|
+
// may have handed the partially-constructed-and-now-invalid
|
|
581
|
+
// wrapper to someone before failing. Or, perhaps worse, the
|
|
582
|
+
// PostCreate call could have triggered code that reentered
|
|
583
|
+
// XPConnect and tried to wrap the same object. In that case
|
|
584
|
+
// *we* hand out the invalid wrapper since it is already in our
|
|
585
|
+
// map :(
|
|
586
|
+
NS_ERROR("PostCreate failed! This is known to cause "
|
|
587
|
+
"inconsistent state for some class types and may even "
|
|
588
|
+
"cause a crash in combination with a JS GC. Fix the "
|
|
589
|
+
"failing PostCreate ASAP!");
|
|
590
|
+
|
|
591
|
+
{ // scoped lock
|
|
592
|
+
XPCAutoLock lock(mapLock);
|
|
593
|
+
map->Remove(wrapper);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// This would be a good place to tell the wrapper not to remove
|
|
597
|
+
// itself from the map when it dies... See bug 429442.
|
|
598
|
+
|
|
599
|
+
if(cache)
|
|
600
|
+
cache->ClearWrapper();
|
|
601
|
+
wrapper->Release();
|
|
602
|
+
return rv;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
if(!wrapper)
|
|
608
|
+
return NS_ERROR_FAILURE;
|
|
609
|
+
|
|
610
|
+
DEBUG_CheckClassInfoClaims(wrapper);
|
|
611
|
+
*resultWrapper = wrapper;
|
|
612
|
+
return NS_OK;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// static
|
|
616
|
+
nsresult
|
|
617
|
+
XPCWrappedNative::GetUsedOnly(XPCCallContext& ccx,
|
|
618
|
+
nsISupports* Object,
|
|
619
|
+
XPCWrappedNativeScope* Scope,
|
|
620
|
+
XPCNativeInterface* Interface,
|
|
621
|
+
XPCWrappedNative** resultWrapper)
|
|
622
|
+
{
|
|
623
|
+
NS_ASSERTION(Object, "XPCWrappedNative::GetUsedOnly was called with a null Object");
|
|
624
|
+
|
|
625
|
+
XPCWrappedNative* wrapper;
|
|
626
|
+
nsWrapperCache* cache = nsnull;
|
|
627
|
+
CallQueryInterface(Object, &cache);
|
|
628
|
+
if(cache)
|
|
629
|
+
{
|
|
630
|
+
wrapper = static_cast<XPCWrappedNative*>(cache->GetWrapper());
|
|
631
|
+
if(!wrapper)
|
|
632
|
+
{
|
|
633
|
+
*resultWrapper = nsnull;
|
|
634
|
+
return NS_OK;
|
|
635
|
+
}
|
|
636
|
+
NS_ADDREF(wrapper);
|
|
637
|
+
}
|
|
638
|
+
else
|
|
639
|
+
{
|
|
640
|
+
nsCOMPtr<nsISupports> identity;
|
|
641
|
+
#ifdef XPC_IDISPATCH_SUPPORT
|
|
642
|
+
// XXX See GetNewOrUsed for more info on this
|
|
643
|
+
if(Interface->GetIID()->Equals(NSID_IDISPATCH))
|
|
644
|
+
identity = Object;
|
|
645
|
+
else
|
|
646
|
+
#endif
|
|
647
|
+
identity = do_QueryInterface(Object);
|
|
648
|
+
|
|
649
|
+
if(!identity)
|
|
650
|
+
{
|
|
651
|
+
NS_ERROR("This XPCOM object fails in QueryInterface to nsISupports!");
|
|
652
|
+
return NS_ERROR_FAILURE;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap();
|
|
656
|
+
|
|
657
|
+
{ // scoped lock
|
|
658
|
+
XPCAutoLock lock(Scope->GetRuntime()->GetMapLock());
|
|
659
|
+
wrapper = map->Find(identity);
|
|
660
|
+
if(!wrapper)
|
|
661
|
+
{
|
|
662
|
+
*resultWrapper = nsnull;
|
|
663
|
+
return NS_OK;
|
|
664
|
+
}
|
|
665
|
+
NS_ADDREF(wrapper);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
nsresult rv;
|
|
670
|
+
if(Interface && !wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv))
|
|
671
|
+
{
|
|
672
|
+
NS_RELEASE(wrapper);
|
|
673
|
+
NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
|
|
674
|
+
return rv;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
*resultWrapper = wrapper;
|
|
678
|
+
return NS_OK;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// This ctor is used if this object will have a proto.
|
|
682
|
+
XPCWrappedNative::XPCWrappedNative(nsISupports* aIdentity,
|
|
683
|
+
XPCWrappedNativeProto* aProto)
|
|
684
|
+
: mMaybeProto(aProto),
|
|
685
|
+
mSet(aProto->GetSet()),
|
|
686
|
+
mFlatJSObject((JSObject*)JSVAL_ONE), // non-null to pass IsValid() test
|
|
687
|
+
mScriptableInfo(nsnull),
|
|
688
|
+
mWrapper(nsnull)
|
|
689
|
+
{
|
|
690
|
+
NS_ADDREF(mIdentity = aIdentity);
|
|
691
|
+
|
|
692
|
+
NS_ASSERTION(mMaybeProto, "bad ctor param");
|
|
693
|
+
NS_ASSERTION(mSet, "bad ctor param");
|
|
694
|
+
|
|
695
|
+
DEBUG_TrackNewWrapper(this);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// This ctor is used if this object will NOT have a proto.
|
|
699
|
+
XPCWrappedNative::XPCWrappedNative(nsISupports* aIdentity,
|
|
700
|
+
XPCWrappedNativeScope* aScope,
|
|
701
|
+
XPCNativeSet* aSet)
|
|
702
|
+
|
|
703
|
+
: mMaybeScope(TagScope(aScope)),
|
|
704
|
+
mSet(aSet),
|
|
705
|
+
mFlatJSObject((JSObject*)JSVAL_ONE), // non-null to pass IsValid() test
|
|
706
|
+
mScriptableInfo(nsnull),
|
|
707
|
+
mWrapper(nsnull)
|
|
708
|
+
{
|
|
709
|
+
NS_ADDREF(mIdentity = aIdentity);
|
|
710
|
+
|
|
711
|
+
NS_ASSERTION(aScope, "bad ctor param");
|
|
712
|
+
NS_ASSERTION(aSet, "bad ctor param");
|
|
713
|
+
|
|
714
|
+
DEBUG_TrackNewWrapper(this);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
XPCWrappedNative::~XPCWrappedNative()
|
|
718
|
+
{
|
|
719
|
+
DEBUG_TrackDeleteWrapper(this);
|
|
720
|
+
|
|
721
|
+
XPCWrappedNativeProto* proto = GetProto();
|
|
722
|
+
|
|
723
|
+
if(mScriptableInfo &&
|
|
724
|
+
(!HasProto() ||
|
|
725
|
+
(proto && proto->GetScriptableInfo() != mScriptableInfo)))
|
|
726
|
+
{
|
|
727
|
+
delete mScriptableInfo;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
XPCWrappedNativeScope *scope = GetScope();
|
|
731
|
+
if(scope)
|
|
732
|
+
{
|
|
733
|
+
Native2WrappedNativeMap* map = scope->GetWrappedNativeMap();
|
|
734
|
+
|
|
735
|
+
// scoped lock
|
|
736
|
+
XPCAutoLock lock(GetRuntime()->GetMapLock());
|
|
737
|
+
|
|
738
|
+
// Post-1.9 we should not remove this wrapper from the map if it is
|
|
739
|
+
// uninitialized.
|
|
740
|
+
map->Remove(this);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if(mIdentity)
|
|
744
|
+
{
|
|
745
|
+
XPCJSRuntime* rt = GetRuntime();
|
|
746
|
+
if(rt && rt->GetDoingFinalization())
|
|
747
|
+
{
|
|
748
|
+
if(!rt->DeferredRelease(mIdentity))
|
|
749
|
+
{
|
|
750
|
+
NS_WARNING("Failed to append object for deferred release.");
|
|
751
|
+
// XXX do we really want to do this???
|
|
752
|
+
NS_RELEASE(mIdentity);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
else
|
|
756
|
+
{
|
|
757
|
+
NS_RELEASE(mIdentity);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// This is factored out so that it can be called publicly
|
|
763
|
+
// static
|
|
764
|
+
nsresult
|
|
765
|
+
XPCWrappedNative::GatherProtoScriptableCreateInfo(
|
|
766
|
+
nsIClassInfo* classInfo,
|
|
767
|
+
XPCNativeScriptableCreateInfo* sciProto)
|
|
768
|
+
{
|
|
769
|
+
NS_ASSERTION(classInfo, "bad param");
|
|
770
|
+
NS_ASSERTION(sciProto && !sciProto->GetCallback(), "bad param");
|
|
771
|
+
|
|
772
|
+
nsCOMPtr<nsISupports> possibleHelper;
|
|
773
|
+
nsresult rv = classInfo->GetHelperForLanguage(
|
|
774
|
+
nsIProgrammingLanguage::JAVASCRIPT,
|
|
775
|
+
getter_AddRefs(possibleHelper));
|
|
776
|
+
if(NS_SUCCEEDED(rv) && possibleHelper)
|
|
777
|
+
{
|
|
778
|
+
nsCOMPtr<nsIXPCScriptable> helper(do_QueryInterface(possibleHelper));
|
|
779
|
+
if(helper)
|
|
780
|
+
{
|
|
781
|
+
JSUint32 flags;
|
|
782
|
+
rv = helper->GetScriptableFlags(&flags);
|
|
783
|
+
if(NS_FAILED(rv))
|
|
784
|
+
flags = 0;
|
|
785
|
+
|
|
786
|
+
sciProto->SetCallback(helper);
|
|
787
|
+
sciProto->SetFlags(flags);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return NS_OK;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// static
|
|
794
|
+
nsresult
|
|
795
|
+
XPCWrappedNative::GatherScriptableCreateInfo(
|
|
796
|
+
nsISupports* obj,
|
|
797
|
+
nsIClassInfo* classInfo,
|
|
798
|
+
XPCNativeScriptableCreateInfo* sciProto,
|
|
799
|
+
XPCNativeScriptableCreateInfo* sciWrapper)
|
|
800
|
+
{
|
|
801
|
+
NS_ASSERTION(sciProto && !sciProto->GetCallback(), "bad param");
|
|
802
|
+
NS_ASSERTION(sciWrapper && !sciWrapper->GetCallback(), "bad param");
|
|
803
|
+
|
|
804
|
+
// Get the class scriptable helper (if present)
|
|
805
|
+
if(classInfo)
|
|
806
|
+
{
|
|
807
|
+
GatherProtoScriptableCreateInfo(classInfo, sciProto);
|
|
808
|
+
|
|
809
|
+
sciWrapper->SetCallback(sciProto->GetCallback());
|
|
810
|
+
sciWrapper->SetFlags(sciProto->GetFlags());
|
|
811
|
+
|
|
812
|
+
if(sciProto->GetFlags().DontAskInstanceForScriptable())
|
|
813
|
+
return NS_OK;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// Do the same for the wrapper specific scriptable
|
|
817
|
+
nsCOMPtr<nsIXPCScriptable> helper(do_QueryInterface(obj));
|
|
818
|
+
if(helper)
|
|
819
|
+
{
|
|
820
|
+
JSUint32 flags;
|
|
821
|
+
nsresult rv = helper->GetScriptableFlags(&flags);
|
|
822
|
+
if(NS_FAILED(rv))
|
|
823
|
+
flags = 0;
|
|
824
|
+
|
|
825
|
+
sciWrapper->SetCallback(helper);
|
|
826
|
+
sciWrapper->SetFlags(flags);
|
|
827
|
+
|
|
828
|
+
// A whole series of assertions to catch bad uses of scriptable flags on
|
|
829
|
+
// the siWrapper...
|
|
830
|
+
|
|
831
|
+
NS_ASSERTION(!(sciWrapper->GetFlags().WantPreCreate() &&
|
|
832
|
+
!sciProto->GetFlags().WantPreCreate()),
|
|
833
|
+
"Can't set WANT_PRECREATE on an instance scriptable "
|
|
834
|
+
"without also setting it on the class scriptable");
|
|
835
|
+
|
|
836
|
+
NS_ASSERTION(!(sciWrapper->GetFlags().DontEnumStaticProps() &&
|
|
837
|
+
!sciProto->GetFlags().DontEnumStaticProps() &&
|
|
838
|
+
sciProto->GetCallback() &&
|
|
839
|
+
!sciProto->GetFlags().DontSharePrototype()),
|
|
840
|
+
"Can't set DONT_ENUM_STATIC_PROPS on an instance scriptable "
|
|
841
|
+
"without also setting it on the class scriptable (if present and shared)");
|
|
842
|
+
|
|
843
|
+
NS_ASSERTION(!(sciWrapper->GetFlags().DontEnumQueryInterface() &&
|
|
844
|
+
!sciProto->GetFlags().DontEnumQueryInterface() &&
|
|
845
|
+
sciProto->GetCallback() &&
|
|
846
|
+
!sciProto->GetFlags().DontSharePrototype()),
|
|
847
|
+
"Can't set DONT_ENUM_QUERY_INTERFACE on an instance scriptable "
|
|
848
|
+
"without also setting it on the class scriptable (if present and shared)");
|
|
849
|
+
|
|
850
|
+
NS_ASSERTION(!(sciWrapper->GetFlags().DontAskInstanceForScriptable() &&
|
|
851
|
+
!sciProto->GetFlags().DontAskInstanceForScriptable()),
|
|
852
|
+
"Can't set DONT_ASK_INSTANCE_FOR_SCRIPTABLE on an instance scriptable "
|
|
853
|
+
"without also setting it on the class scriptable");
|
|
854
|
+
|
|
855
|
+
NS_ASSERTION(!(sciWrapper->GetFlags().ClassInfoInterfacesOnly() &&
|
|
856
|
+
!sciProto->GetFlags().ClassInfoInterfacesOnly() &&
|
|
857
|
+
sciProto->GetCallback() &&
|
|
858
|
+
!sciProto->GetFlags().DontSharePrototype()),
|
|
859
|
+
"Can't set CLASSINFO_INTERFACES_ONLY on an instance scriptable "
|
|
860
|
+
"without also setting it on the class scriptable (if present and shared)");
|
|
861
|
+
|
|
862
|
+
NS_ASSERTION(!(sciWrapper->GetFlags().AllowPropModsDuringResolve() &&
|
|
863
|
+
!sciProto->GetFlags().AllowPropModsDuringResolve() &&
|
|
864
|
+
sciProto->GetCallback() &&
|
|
865
|
+
!sciProto->GetFlags().DontSharePrototype()),
|
|
866
|
+
"Can't set ALLOW_PROP_MODS_DURING_RESOLVE on an instance scriptable "
|
|
867
|
+
"without also setting it on the class scriptable (if present and shared)");
|
|
868
|
+
|
|
869
|
+
NS_ASSERTION(!(sciWrapper->GetFlags().AllowPropModsToPrototype() &&
|
|
870
|
+
!sciProto->GetFlags().AllowPropModsToPrototype() &&
|
|
871
|
+
sciProto->GetCallback() &&
|
|
872
|
+
!sciProto->GetFlags().DontSharePrototype()),
|
|
873
|
+
"Can't set ALLOW_PROP_MODS_TO_PROTOTYPE on an instance scriptable "
|
|
874
|
+
"without also setting it on the class scriptable (if present and shared)");
|
|
875
|
+
|
|
876
|
+
NS_ASSERTION(!(sciWrapper->GetFlags().DontSharePrototype() &&
|
|
877
|
+
!sciProto->GetFlags().DontSharePrototype() &&
|
|
878
|
+
sciProto->GetCallback()),
|
|
879
|
+
"Can't set DONT_SHARE_PROTOTYPE on an instance scriptable "
|
|
880
|
+
"without also setting it on the class scriptable (if present and shared)");
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
return NS_OK;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
void
|
|
887
|
+
XPCWrappedNative::TraceOtherWrapper(JSTracer* trc)
|
|
888
|
+
{
|
|
889
|
+
// Note: This isn't wrapped by a MapLock, however, this is normally called
|
|
890
|
+
// during GC, where nobody should be playing with the wrapper map anyway,
|
|
891
|
+
// so this should be OK.
|
|
892
|
+
JSObject *otherWrapper = GetScope()->GetWrapperMap()->Find(mFlatJSObject);
|
|
893
|
+
if(otherWrapper)
|
|
894
|
+
{
|
|
895
|
+
JS_CALL_OBJECT_TRACER(trc, otherWrapper,
|
|
896
|
+
"XPCWrappedNative::mOtherWrapper");
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
JSBool
|
|
901
|
+
XPCWrappedNative::Init(XPCCallContext& ccx, JSObject* parent, JSBool isGlobal,
|
|
902
|
+
const XPCNativeScriptableCreateInfo* sci)
|
|
903
|
+
{
|
|
904
|
+
// setup our scriptable info...
|
|
905
|
+
|
|
906
|
+
if(sci->GetCallback())
|
|
907
|
+
{
|
|
908
|
+
if(HasProto())
|
|
909
|
+
{
|
|
910
|
+
XPCNativeScriptableInfo* siProto = GetProto()->GetScriptableInfo();
|
|
911
|
+
if(siProto && siProto->GetCallback() == sci->GetCallback())
|
|
912
|
+
mScriptableInfo = siProto;
|
|
913
|
+
}
|
|
914
|
+
if(!mScriptableInfo)
|
|
915
|
+
{
|
|
916
|
+
mScriptableInfo =
|
|
917
|
+
XPCNativeScriptableInfo::Construct(ccx, isGlobal, sci);
|
|
918
|
+
|
|
919
|
+
if(!mScriptableInfo)
|
|
920
|
+
return JS_FALSE;
|
|
921
|
+
|
|
922
|
+
// If we have a one-off proto, then it should share our scriptable.
|
|
923
|
+
// This allows the proto's JSClass callbacks to do the right things
|
|
924
|
+
// (like respecting the DONT_ENUM_STATIC_PROPS flag) w/o requiring
|
|
925
|
+
// scriptable objects to have an nsIClassInfo.
|
|
926
|
+
if(HasProto() && !HasSharedProto())
|
|
927
|
+
GetProto()->SetScriptableInfo(mScriptableInfo);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
XPCNativeScriptableInfo* si = mScriptableInfo;
|
|
931
|
+
|
|
932
|
+
// create our flatJSObject
|
|
933
|
+
|
|
934
|
+
JSClass* jsclazz = si ? si->GetJSClass() : &XPC_WN_NoHelper_JSClass.base;
|
|
935
|
+
|
|
936
|
+
if(isGlobal)
|
|
937
|
+
{
|
|
938
|
+
// Resolving a global object's class can cause us to create a global's
|
|
939
|
+
// JS class without the proper global flags. Notice that here and fix
|
|
940
|
+
// the problem.
|
|
941
|
+
if(!(jsclazz->flags & JSCLASS_IS_GLOBAL))
|
|
942
|
+
jsclazz->flags |= JSCLASS_GLOBAL_FLAGS;
|
|
943
|
+
}
|
|
944
|
+
else
|
|
945
|
+
NS_ASSERTION(!(jsclazz->flags & JSCLASS_IS_GLOBAL),
|
|
946
|
+
"Non-global object has the wrong flags");
|
|
947
|
+
|
|
948
|
+
NS_ASSERTION(jsclazz &&
|
|
949
|
+
jsclazz->name &&
|
|
950
|
+
jsclazz->flags &&
|
|
951
|
+
jsclazz->addProperty &&
|
|
952
|
+
jsclazz->delProperty &&
|
|
953
|
+
jsclazz->getProperty &&
|
|
954
|
+
jsclazz->setProperty &&
|
|
955
|
+
jsclazz->enumerate &&
|
|
956
|
+
jsclazz->resolve &&
|
|
957
|
+
jsclazz->convert &&
|
|
958
|
+
jsclazz->finalize, "bad class");
|
|
959
|
+
|
|
960
|
+
JSObject* protoJSObject = HasProto() ?
|
|
961
|
+
GetProto()->GetJSProtoObject() :
|
|
962
|
+
GetScope()->GetPrototypeNoHelper(ccx);
|
|
963
|
+
|
|
964
|
+
if (!protoJSObject) {
|
|
965
|
+
return JS_FALSE;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
mFlatJSObject = xpc_NewSystemInheritingJSObject(ccx, jsclazz, protoJSObject,
|
|
969
|
+
parent);
|
|
970
|
+
if(!mFlatJSObject)
|
|
971
|
+
return JS_FALSE;
|
|
972
|
+
|
|
973
|
+
// In the current JS engine JS_SetPrivate can't fail. But if it *did*
|
|
974
|
+
// fail then we would not receive our finalizer call and would not be
|
|
975
|
+
// able to properly cleanup. So, if it fails we null out mFlatJSObject
|
|
976
|
+
// to indicate the invalid state of this object and return false.
|
|
977
|
+
if(!JS_SetPrivate(ccx, mFlatJSObject, this))
|
|
978
|
+
{
|
|
979
|
+
mFlatJSObject = nsnull;
|
|
980
|
+
return JS_FALSE;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// This reference will be released when mFlatJSObject is finalized.
|
|
984
|
+
// Since this reference will push the refcount to 2 it will also root
|
|
985
|
+
// mFlatJSObject;
|
|
986
|
+
NS_ASSERTION(1 == mRefCnt, "unexpected refcount value");
|
|
987
|
+
NS_ADDREF(this);
|
|
988
|
+
|
|
989
|
+
if(si && si->GetFlags().WantCreate() &&
|
|
990
|
+
NS_FAILED(si->GetCallback()->Create(this, ccx, mFlatJSObject)))
|
|
991
|
+
{
|
|
992
|
+
return JS_FALSE;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
|
|
996
|
+
mThread = do_GetCurrentThread();
|
|
997
|
+
|
|
998
|
+
if(HasProto() && GetProto()->ClassIsMainThreadOnly() && !NS_IsMainThread())
|
|
999
|
+
DEBUG_ReportWrapperThreadSafetyError(ccx,
|
|
1000
|
+
"MainThread only wrapper created on the wrong thread", this);
|
|
1001
|
+
#endif
|
|
1002
|
+
|
|
1003
|
+
return JS_TRUE;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPCWrappedNative)
|
|
1008
|
+
NS_INTERFACE_MAP_ENTRY(nsIXPConnectWrappedNative)
|
|
1009
|
+
NS_INTERFACE_MAP_ENTRY(nsIXPConnectJSObjectHolder)
|
|
1010
|
+
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPConnectWrappedNative)
|
|
1011
|
+
NS_INTERFACE_MAP_END_THREADSAFE
|
|
1012
|
+
|
|
1013
|
+
NS_IMPL_THREADSAFE_ADDREF(XPCWrappedNative)
|
|
1014
|
+
NS_IMPL_THREADSAFE_RELEASE(XPCWrappedNative)
|
|
1015
|
+
|
|
1016
|
+
/*
|
|
1017
|
+
* Wrapped Native lifetime management is messy!
|
|
1018
|
+
*
|
|
1019
|
+
* - At creation we push the refcount to 2 (only one of which is owned by
|
|
1020
|
+
* the native caller that caused the wrapper creation).
|
|
1021
|
+
* - During the JS GC Mark phase we mark any wrapper with a refcount > 1.
|
|
1022
|
+
* - The *only* thing that can make the wrapper get destroyed is the
|
|
1023
|
+
* finalization of mFlatJSObject. And *that* should only happen if the only
|
|
1024
|
+
* reference is the single extra (internal) reference we hold.
|
|
1025
|
+
*
|
|
1026
|
+
* - The wrapper has a pointer to the nsISupports 'view' of the wrapped native
|
|
1027
|
+
* object i.e... mIdentity. This is held until the wrapper's refcount goes
|
|
1028
|
+
* to zero and the wrapper is released.
|
|
1029
|
+
*
|
|
1030
|
+
* - The wrapper also has 'tearoffs'. It has one tearoff for each interface
|
|
1031
|
+
* that is actually used on the native object. 'Used' means we have either
|
|
1032
|
+
* needed to QueryInterface to verify the availability of that interface
|
|
1033
|
+
* of that we've had to QueryInterface in order to actually make a call
|
|
1034
|
+
* into the wrapped object via the pointer for the given interface.
|
|
1035
|
+
*
|
|
1036
|
+
* - Each tearoff's 'mNative' member (if non-null) indicates one reference
|
|
1037
|
+
* held by our wrapper on the wrapped native for the given interface
|
|
1038
|
+
* associated with the tearoff. If we release that reference then we set
|
|
1039
|
+
* the tearoff's 'mNative' to null.
|
|
1040
|
+
*
|
|
1041
|
+
* - We use the occasion of the JavaScript GCCallback for the JSGC_MARK_END
|
|
1042
|
+
* event to scan the tearoffs of all wrappers for non-null mNative members
|
|
1043
|
+
* that represent unused references. We can tell that a given tearoff's
|
|
1044
|
+
* mNative is unused by noting that no live XPCCallContexts hold a pointer
|
|
1045
|
+
* to the tearoff.
|
|
1046
|
+
*
|
|
1047
|
+
* - As a time/space tradeoff we may decide to not do this scanning on
|
|
1048
|
+
* *every* JavaScript GC. We *do* want to do this *sometimes* because
|
|
1049
|
+
* we want to allow for wrapped native's to do their own tearoff patterns.
|
|
1050
|
+
* So, we want to avoid holding references to interfaces that we don't need.
|
|
1051
|
+
* At the same time, we don't want to be bracketing every call into a
|
|
1052
|
+
* wrapped native object with a QueryInterface/Release pair. And we *never*
|
|
1053
|
+
* make a call into the object except via the correct interface for which
|
|
1054
|
+
* we've QI'd.
|
|
1055
|
+
*
|
|
1056
|
+
* - Each tearoff *can* have a mJSObject whose lazily resolved properties
|
|
1057
|
+
* represent the methods/attributes/constants of that specific interface.
|
|
1058
|
+
* This is optionally reflected into JavaScript as "foo.nsIFoo" when "foo"
|
|
1059
|
+
* is the name of mFlatJSObject and "nsIFoo" is the name of the given
|
|
1060
|
+
* interface associated with the tearoff. When we create the tearoff's
|
|
1061
|
+
* mJSObject we set it's parent to be mFlatJSObject. This way we know that
|
|
1062
|
+
* when mFlatJSObject get's collected there are no outstanding reachable
|
|
1063
|
+
* tearoff mJSObjects. Note that we must clear the private of any lingering
|
|
1064
|
+
* mJSObjects at this point because we have no guarentee of the *order* of
|
|
1065
|
+
* finalization within a given gc cycle.
|
|
1066
|
+
*/
|
|
1067
|
+
|
|
1068
|
+
void
|
|
1069
|
+
XPCWrappedNative::FlatJSObjectFinalized(JSContext *cx)
|
|
1070
|
+
{
|
|
1071
|
+
if(!IsValid())
|
|
1072
|
+
return;
|
|
1073
|
+
|
|
1074
|
+
// Iterate the tearoffs and null out each of their JSObject's privates.
|
|
1075
|
+
// This will keep them from trying to access their pointers to the
|
|
1076
|
+
// dying tearoff object. We can safely assume that those remaining
|
|
1077
|
+
// JSObjects are about to be finalized too.
|
|
1078
|
+
|
|
1079
|
+
XPCWrappedNativeTearOffChunk* chunk;
|
|
1080
|
+
for(chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk)
|
|
1081
|
+
{
|
|
1082
|
+
XPCWrappedNativeTearOff* to = chunk->mTearOffs;
|
|
1083
|
+
for(int i = XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK-1; i >= 0; i--, to++)
|
|
1084
|
+
{
|
|
1085
|
+
JSObject* jso = to->GetJSObject();
|
|
1086
|
+
if(jso)
|
|
1087
|
+
{
|
|
1088
|
+
NS_ASSERTION(JS_IsAboutToBeFinalized(cx, jso), "bad!");
|
|
1089
|
+
JS_SetPrivate(cx, jso, nsnull);
|
|
1090
|
+
to->JSObjectFinalized();
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
// We also need to release any native pointers held...
|
|
1094
|
+
nsISupports* obj = to->GetNative();
|
|
1095
|
+
if(obj)
|
|
1096
|
+
{
|
|
1097
|
+
#ifdef XP_WIN
|
|
1098
|
+
// Try to detect free'd pointer
|
|
1099
|
+
NS_ASSERTION(*(int*)obj != 0xdddddddd, "bad pointer!");
|
|
1100
|
+
NS_ASSERTION(*(int*)obj != 0, "bad pointer!");
|
|
1101
|
+
#endif
|
|
1102
|
+
XPCJSRuntime* rt = GetRuntime();
|
|
1103
|
+
if(rt)
|
|
1104
|
+
{
|
|
1105
|
+
if(!rt->DeferredRelease(obj))
|
|
1106
|
+
{
|
|
1107
|
+
NS_WARNING("Failed to append object for deferred release.");
|
|
1108
|
+
// XXX do we really want to do this???
|
|
1109
|
+
obj->Release();
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
else
|
|
1113
|
+
{
|
|
1114
|
+
obj->Release();
|
|
1115
|
+
}
|
|
1116
|
+
to->SetNative(nsnull);
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
to->SetInterface(nsnull);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
GetScope()->GetWrapperMap()->Remove(mFlatJSObject);
|
|
1124
|
+
|
|
1125
|
+
if(IsWrapperExpired())
|
|
1126
|
+
{
|
|
1127
|
+
GetScope()->GetWrappedNativeMap()->Remove(this);
|
|
1128
|
+
|
|
1129
|
+
XPCWrappedNativeProto* proto = GetProto();
|
|
1130
|
+
|
|
1131
|
+
if(mScriptableInfo &&
|
|
1132
|
+
(!HasProto() ||
|
|
1133
|
+
(proto && proto->GetScriptableInfo() != mScriptableInfo)))
|
|
1134
|
+
{
|
|
1135
|
+
delete mScriptableInfo;
|
|
1136
|
+
mScriptableInfo = nsnull;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
mMaybeScope = nsnull;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
nsWrapperCache *cache = nsnull;
|
|
1143
|
+
CallQueryInterface(mIdentity, &cache);
|
|
1144
|
+
if(cache)
|
|
1145
|
+
cache->ClearWrapper();
|
|
1146
|
+
|
|
1147
|
+
// This makes IsValid return false from now on...
|
|
1148
|
+
mFlatJSObject = nsnull;
|
|
1149
|
+
|
|
1150
|
+
NS_ASSERTION(mIdentity, "bad pointer!");
|
|
1151
|
+
#ifdef XP_WIN
|
|
1152
|
+
// Try to detect free'd pointer
|
|
1153
|
+
NS_ASSERTION(*(int*)mIdentity != 0xdddddddd, "bad pointer!");
|
|
1154
|
+
NS_ASSERTION(*(int*)mIdentity != 0, "bad pointer!");
|
|
1155
|
+
#endif
|
|
1156
|
+
|
|
1157
|
+
// Note that it's not safe to touch mNativeWrapper here since it's
|
|
1158
|
+
// likely that it has already been finalized.
|
|
1159
|
+
|
|
1160
|
+
Release();
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
void
|
|
1164
|
+
XPCWrappedNative::SystemIsBeingShutDown(JSContext* cx)
|
|
1165
|
+
{
|
|
1166
|
+
#ifdef DEBUG_xpc_hacker
|
|
1167
|
+
{
|
|
1168
|
+
printf("Removing root for still-live XPCWrappedNative %p wrapping:\n",
|
|
1169
|
+
static_cast<void*>(this));
|
|
1170
|
+
for(PRUint16 i = 0, i_end = mSet->GetInterfaceCount(); i < i_end; ++i)
|
|
1171
|
+
{
|
|
1172
|
+
nsXPIDLCString name;
|
|
1173
|
+
mSet->GetInterfaceAt(i)->GetInterfaceInfo()
|
|
1174
|
+
->GetName(getter_Copies(name));
|
|
1175
|
+
printf(" %s\n", name.get());
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
#endif
|
|
1179
|
+
DEBUG_TrackShutdownWrapper(this);
|
|
1180
|
+
|
|
1181
|
+
if(!IsValid())
|
|
1182
|
+
return;
|
|
1183
|
+
|
|
1184
|
+
// The long standing strategy is to leak some objects still held at shutdown.
|
|
1185
|
+
// The general problem is that propagating release out of xpconnect at
|
|
1186
|
+
// shutdown time causes a world of problems.
|
|
1187
|
+
|
|
1188
|
+
// We leak mIdentity (see above).
|
|
1189
|
+
|
|
1190
|
+
// short circuit future finalization
|
|
1191
|
+
JS_SetPrivate(cx, mFlatJSObject, nsnull);
|
|
1192
|
+
mFlatJSObject = nsnull; // This makes 'IsValid()' return false.
|
|
1193
|
+
|
|
1194
|
+
XPCWrappedNativeProto* proto = GetProto();
|
|
1195
|
+
|
|
1196
|
+
if(HasProto())
|
|
1197
|
+
proto->SystemIsBeingShutDown(cx);
|
|
1198
|
+
|
|
1199
|
+
if(mScriptableInfo &&
|
|
1200
|
+
(!HasProto() ||
|
|
1201
|
+
(proto && proto->GetScriptableInfo() != mScriptableInfo)))
|
|
1202
|
+
{
|
|
1203
|
+
delete mScriptableInfo;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
// cleanup the tearoffs...
|
|
1207
|
+
|
|
1208
|
+
XPCWrappedNativeTearOffChunk* chunk;
|
|
1209
|
+
for(chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk)
|
|
1210
|
+
{
|
|
1211
|
+
XPCWrappedNativeTearOff* to = chunk->mTearOffs;
|
|
1212
|
+
for(int i = XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK-1; i >= 0; i--, to++)
|
|
1213
|
+
{
|
|
1214
|
+
if(to->GetJSObject())
|
|
1215
|
+
{
|
|
1216
|
+
JS_SetPrivate(cx, to->GetJSObject(), nsnull);
|
|
1217
|
+
#ifdef XPC_IDISPATCH_SUPPORT
|
|
1218
|
+
if(to->IsIDispatch())
|
|
1219
|
+
delete to->GetIDispatchInfo();
|
|
1220
|
+
#endif
|
|
1221
|
+
to->SetJSObject(nsnull);
|
|
1222
|
+
}
|
|
1223
|
+
// We leak the tearoff mNative
|
|
1224
|
+
// (for the same reason we leak mIdentity - see above).
|
|
1225
|
+
to->SetNative(nsnull);
|
|
1226
|
+
to->SetInterface(nsnull);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
if(mFirstChunk.mNextChunk)
|
|
1231
|
+
{
|
|
1232
|
+
delete mFirstChunk.mNextChunk;
|
|
1233
|
+
mFirstChunk.mNextChunk = nsnull;
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/***************************************************************************/
|
|
1238
|
+
|
|
1239
|
+
// static
|
|
1240
|
+
nsresult
|
|
1241
|
+
XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
|
|
1242
|
+
XPCWrappedNativeScope* aOldScope,
|
|
1243
|
+
XPCWrappedNativeScope* aNewScope,
|
|
1244
|
+
JSObject* aNewParent,
|
|
1245
|
+
nsISupports* aCOMObj,
|
|
1246
|
+
XPCWrappedNative** aWrapper)
|
|
1247
|
+
{
|
|
1248
|
+
XPCNativeInterface* iface =
|
|
1249
|
+
XPCNativeInterface::GetISupports(ccx);
|
|
1250
|
+
|
|
1251
|
+
if(!iface)
|
|
1252
|
+
return NS_ERROR_FAILURE;
|
|
1253
|
+
|
|
1254
|
+
nsresult rv;
|
|
1255
|
+
XPCWrappedNative* wrapper;
|
|
1256
|
+
|
|
1257
|
+
rv = XPCWrappedNative::GetUsedOnly(ccx, aCOMObj, aOldScope, iface, &wrapper);
|
|
1258
|
+
if(NS_FAILED(rv))
|
|
1259
|
+
return rv;
|
|
1260
|
+
|
|
1261
|
+
if(!wrapper || !wrapper->IsValid())
|
|
1262
|
+
{
|
|
1263
|
+
NS_IF_RELEASE(wrapper);
|
|
1264
|
+
*aWrapper = nsnull;
|
|
1265
|
+
return NS_OK;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// ReparentWrapperIfFound is really only meant to be called from DOM code
|
|
1269
|
+
// which must happen only on the main thread. Bail if we're on some other
|
|
1270
|
+
// thread or have a non-main-thread-only wrapper.
|
|
1271
|
+
if (!XPCPerThreadData::IsMainThread(ccx) ||
|
|
1272
|
+
(wrapper->GetProto() &&
|
|
1273
|
+
!wrapper->GetProto()->ClassIsMainThreadOnly())) {
|
|
1274
|
+
NS_RELEASE(wrapper);
|
|
1275
|
+
return NS_ERROR_FAILURE;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
if(aOldScope != aNewScope)
|
|
1279
|
+
{
|
|
1280
|
+
// Oh, so now we need to move the wrapper to a different scope.
|
|
1281
|
+
|
|
1282
|
+
// First notify any XOWs.
|
|
1283
|
+
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
|
|
1284
|
+
xpc->UpdateXOWs(ccx, wrapper, nsIXPConnect::XPC_XOW_CLEARSCOPE);
|
|
1285
|
+
|
|
1286
|
+
AutoMarkingWrappedNativeProtoPtr oldProto(ccx);
|
|
1287
|
+
AutoMarkingWrappedNativeProtoPtr newProto(ccx);
|
|
1288
|
+
|
|
1289
|
+
if(wrapper->HasProto())
|
|
1290
|
+
{
|
|
1291
|
+
oldProto = wrapper->GetProto();
|
|
1292
|
+
XPCNativeScriptableInfo *info = oldProto->GetScriptableInfo();
|
|
1293
|
+
XPCNativeScriptableCreateInfo ci(*info);
|
|
1294
|
+
newProto =
|
|
1295
|
+
XPCWrappedNativeProto::GetNewOrUsed(ccx, aNewScope,
|
|
1296
|
+
oldProto->GetClassInfo(),
|
|
1297
|
+
&ci,
|
|
1298
|
+
!oldProto->IsShared(),
|
|
1299
|
+
(info->GetJSClass()->flags & JSCLASS_IS_GLOBAL),
|
|
1300
|
+
oldProto->GetOffsetsMasked());
|
|
1301
|
+
if(!newProto)
|
|
1302
|
+
{
|
|
1303
|
+
NS_RELEASE(wrapper);
|
|
1304
|
+
return NS_ERROR_FAILURE;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
if(!XPC_XOW_WrapperMoved(ccx, wrapper, aNewScope))
|
|
1309
|
+
{
|
|
1310
|
+
NS_RELEASE(wrapper);
|
|
1311
|
+
return NS_ERROR_FAILURE;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap();
|
|
1315
|
+
Native2WrappedNativeMap* newMap = aNewScope->GetWrappedNativeMap();
|
|
1316
|
+
|
|
1317
|
+
{ // scoped lock
|
|
1318
|
+
XPCAutoLock lock(aOldScope->GetRuntime()->GetMapLock());
|
|
1319
|
+
|
|
1320
|
+
oldMap->Remove(wrapper);
|
|
1321
|
+
|
|
1322
|
+
if(wrapper->HasProto())
|
|
1323
|
+
wrapper->SetProto(newProto);
|
|
1324
|
+
|
|
1325
|
+
// If the wrapper has no scriptable or it has a non-shared
|
|
1326
|
+
// scriptable, then we don't need to mess with it.
|
|
1327
|
+
// Otherwise...
|
|
1328
|
+
|
|
1329
|
+
if(wrapper->mScriptableInfo &&
|
|
1330
|
+
wrapper->mScriptableInfo == oldProto->GetScriptableInfo())
|
|
1331
|
+
{
|
|
1332
|
+
// The new proto had better have the same JSClass stuff as the
|
|
1333
|
+
// old one! We maintain a runtime wide unique map of this stuff.
|
|
1334
|
+
// So, if these don't match then the caller is doing something
|
|
1335
|
+
// bad here.
|
|
1336
|
+
|
|
1337
|
+
NS_ASSERTION(
|
|
1338
|
+
oldProto->GetScriptableInfo()->GetScriptableShared() ==
|
|
1339
|
+
newProto->GetScriptableInfo()->GetScriptableShared(),
|
|
1340
|
+
"Changing proto is also changing JSObject Classname or "
|
|
1341
|
+
"helper's nsIXPScriptable flags. This is not allowed!");
|
|
1342
|
+
|
|
1343
|
+
wrapper->mScriptableInfo = newProto->GetScriptableInfo();
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
NS_ASSERTION(!newMap->Find(wrapper->GetIdentityObject()),
|
|
1347
|
+
"wrapper already in new scope!");
|
|
1348
|
+
|
|
1349
|
+
(void) newMap->Add(wrapper);
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
// We only try to fixup the __proto__ JSObject if the wrapper
|
|
1353
|
+
// is directly using that of its XPCWrappedNativeProto.
|
|
1354
|
+
|
|
1355
|
+
if(wrapper->HasProto() &&
|
|
1356
|
+
STOBJ_GET_PROTO(wrapper->GetFlatJSObject()) ==
|
|
1357
|
+
oldProto->GetJSProtoObject())
|
|
1358
|
+
{
|
|
1359
|
+
if(!JS_SetPrototype(ccx, wrapper->GetFlatJSObject(),
|
|
1360
|
+
newProto->GetJSProtoObject()))
|
|
1361
|
+
{
|
|
1362
|
+
// this is bad, very bad
|
|
1363
|
+
NS_ERROR("JS_SetPrototype failed");
|
|
1364
|
+
NS_RELEASE(wrapper);
|
|
1365
|
+
return NS_ERROR_FAILURE;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
else
|
|
1369
|
+
{
|
|
1370
|
+
NS_WARNING("Moving XPConnect wrappedNative to new scope, "
|
|
1371
|
+
"but can't fixup __proto__");
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
// Now we can just fix up the parent and return the wrapper
|
|
1376
|
+
|
|
1377
|
+
if(!JS_SetParent(ccx, wrapper->GetFlatJSObject(), aNewParent))
|
|
1378
|
+
{
|
|
1379
|
+
NS_RELEASE(wrapper);
|
|
1380
|
+
return NS_ERROR_FAILURE;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
*aWrapper = wrapper;
|
|
1384
|
+
return NS_OK;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
#define IS_TEAROFF_CLASS(clazz) \
|
|
1388
|
+
((clazz) == &XPC_WN_Tearoff_JSClass)
|
|
1389
|
+
|
|
1390
|
+
// static
|
|
1391
|
+
XPCWrappedNative*
|
|
1392
|
+
XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx,
|
|
1393
|
+
JSObject* obj,
|
|
1394
|
+
JSObject* funobj,
|
|
1395
|
+
JSObject** pobj2,
|
|
1396
|
+
XPCWrappedNativeTearOff** pTearOff)
|
|
1397
|
+
{
|
|
1398
|
+
NS_PRECONDITION(obj, "bad param");
|
|
1399
|
+
|
|
1400
|
+
JSObject* cur;
|
|
1401
|
+
|
|
1402
|
+
XPCWrappedNativeProto* proto = nsnull;
|
|
1403
|
+
nsIClassInfo* protoClassInfo = nsnull;
|
|
1404
|
+
|
|
1405
|
+
// If we were passed a function object then we need to find the correct
|
|
1406
|
+
// wrapper out of those that might be in the callee obj's proto chain.
|
|
1407
|
+
|
|
1408
|
+
if(funobj)
|
|
1409
|
+
{
|
|
1410
|
+
JSObject* funObjParent = STOBJ_GET_PARENT(funobj);
|
|
1411
|
+
NS_ASSERTION(funObjParent, "funobj has no parent");
|
|
1412
|
+
|
|
1413
|
+
JSClass* funObjParentClass = STOBJ_GET_CLASS(funObjParent);
|
|
1414
|
+
|
|
1415
|
+
if(IS_PROTO_CLASS(funObjParentClass))
|
|
1416
|
+
{
|
|
1417
|
+
NS_ASSERTION(STOBJ_GET_PARENT(funObjParent), "funobj's parent (proto) is global");
|
|
1418
|
+
proto = (XPCWrappedNativeProto*) xpc_GetJSPrivate(funObjParent);
|
|
1419
|
+
if(proto)
|
|
1420
|
+
protoClassInfo = proto->GetClassInfo();
|
|
1421
|
+
}
|
|
1422
|
+
else if(IS_WRAPPER_CLASS(funObjParentClass))
|
|
1423
|
+
{
|
|
1424
|
+
cur = funObjParent;
|
|
1425
|
+
goto return_wrapper;
|
|
1426
|
+
}
|
|
1427
|
+
else if(IS_TEAROFF_CLASS(funObjParentClass))
|
|
1428
|
+
{
|
|
1429
|
+
NS_ASSERTION(STOBJ_GET_PARENT(funObjParent), "funobj's parent (tearoff) is global");
|
|
1430
|
+
cur = funObjParent;
|
|
1431
|
+
goto return_tearoff;
|
|
1432
|
+
}
|
|
1433
|
+
else
|
|
1434
|
+
{
|
|
1435
|
+
NS_ERROR("function object has parent of unknown class!");
|
|
1436
|
+
return nsnull;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
for(cur = obj; cur; cur = STOBJ_GET_PROTO(cur))
|
|
1441
|
+
{
|
|
1442
|
+
// this is on two lines to make the compiler happy given the goto.
|
|
1443
|
+
JSClass* clazz;
|
|
1444
|
+
clazz = STOBJ_GET_CLASS(cur);
|
|
1445
|
+
|
|
1446
|
+
if(IS_WRAPPER_CLASS(clazz))
|
|
1447
|
+
{
|
|
1448
|
+
return_wrapper:
|
|
1449
|
+
XPCWrappedNative* wrapper =
|
|
1450
|
+
(XPCWrappedNative*) xpc_GetJSPrivate(cur);
|
|
1451
|
+
if(proto && proto != wrapper->GetProto() &&
|
|
1452
|
+
(proto->GetScope() != wrapper->GetScope() ||
|
|
1453
|
+
!protoClassInfo || !wrapper->GetProto() ||
|
|
1454
|
+
protoClassInfo != wrapper->GetProto()->GetClassInfo()))
|
|
1455
|
+
continue;
|
|
1456
|
+
if(pobj2)
|
|
1457
|
+
*pobj2 = cur;
|
|
1458
|
+
return wrapper;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
if(IS_TEAROFF_CLASS(clazz))
|
|
1462
|
+
{
|
|
1463
|
+
return_tearoff:
|
|
1464
|
+
XPCWrappedNative* wrapper =
|
|
1465
|
+
(XPCWrappedNative*) xpc_GetJSPrivate(STOBJ_GET_PARENT(cur));
|
|
1466
|
+
if(proto && proto != wrapper->GetProto() &&
|
|
1467
|
+
(proto->GetScope() != wrapper->GetScope() ||
|
|
1468
|
+
!protoClassInfo || !wrapper->GetProto() ||
|
|
1469
|
+
protoClassInfo != wrapper->GetProto()->GetClassInfo()))
|
|
1470
|
+
continue;
|
|
1471
|
+
if(pobj2)
|
|
1472
|
+
*pobj2 = cur;
|
|
1473
|
+
XPCWrappedNativeTearOff* to =
|
|
1474
|
+
(XPCWrappedNativeTearOff*) xpc_GetJSPrivate(cur);
|
|
1475
|
+
if(!to)
|
|
1476
|
+
return nsnull;
|
|
1477
|
+
if(pTearOff)
|
|
1478
|
+
*pTearOff = to;
|
|
1479
|
+
return wrapper;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
// Unwrap any wrapper wrappers.
|
|
1483
|
+
JSObject *unsafeObj;
|
|
1484
|
+
if((unsafeObj = XPCWrapper::Unwrap(cx, cur)))
|
|
1485
|
+
return GetWrappedNativeOfJSObject(cx, unsafeObj, funobj, pobj2,
|
|
1486
|
+
pTearOff);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
// If we didn't find a wrapper using the given funobj and obj, try
|
|
1490
|
+
// again with obj's outer object, if it's got one.
|
|
1491
|
+
|
|
1492
|
+
JSClass *clazz = STOBJ_GET_CLASS(obj);
|
|
1493
|
+
|
|
1494
|
+
if((clazz->flags & JSCLASS_IS_EXTENDED) &&
|
|
1495
|
+
((JSExtendedClass*)clazz)->outerObject)
|
|
1496
|
+
{
|
|
1497
|
+
JSObject *outer = ((JSExtendedClass*)clazz)->outerObject(cx, obj);
|
|
1498
|
+
|
|
1499
|
+
// Protect against infinite recursion through XOWs.
|
|
1500
|
+
JSObject *unsafeObj;
|
|
1501
|
+
clazz = STOBJ_GET_CLASS(outer);
|
|
1502
|
+
if(clazz == &sXPC_XOW_JSClass.base &&
|
|
1503
|
+
(unsafeObj = XPCWrapper::UnwrapXOW(cx, outer)))
|
|
1504
|
+
{
|
|
1505
|
+
outer = unsafeObj;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
if(outer && outer != obj)
|
|
1509
|
+
return GetWrappedNativeOfJSObject(cx, outer, funobj, pobj2,
|
|
1510
|
+
pTearOff);
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
if(pobj2)
|
|
1514
|
+
*pobj2 = nsnull;
|
|
1515
|
+
return nsnull;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
JSBool
|
|
1519
|
+
XPCWrappedNative::ExtendSet(XPCCallContext& ccx, XPCNativeInterface* aInterface)
|
|
1520
|
+
{
|
|
1521
|
+
// This is only called while locked (during XPCWrappedNative::FindTearOff).
|
|
1522
|
+
|
|
1523
|
+
if(!mSet->HasInterface(aInterface))
|
|
1524
|
+
{
|
|
1525
|
+
AutoMarkingNativeSetPtr newSet(ccx);
|
|
1526
|
+
newSet = XPCNativeSet::GetNewOrUsed(ccx, mSet, aInterface,
|
|
1527
|
+
mSet->GetInterfaceCount());
|
|
1528
|
+
if(!newSet)
|
|
1529
|
+
return JS_FALSE;
|
|
1530
|
+
|
|
1531
|
+
mSet = newSet;
|
|
1532
|
+
|
|
1533
|
+
DEBUG_ReportShadowedMembers(newSet, this, GetProto());
|
|
1534
|
+
}
|
|
1535
|
+
return JS_TRUE;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
XPCWrappedNativeTearOff*
|
|
1539
|
+
XPCWrappedNative::LocateTearOff(XPCCallContext& ccx,
|
|
1540
|
+
XPCNativeInterface* aInterface)
|
|
1541
|
+
{
|
|
1542
|
+
XPCAutoLock al(GetLock()); // hold the lock throughout
|
|
1543
|
+
|
|
1544
|
+
for(
|
|
1545
|
+
XPCWrappedNativeTearOffChunk* chunk = &mFirstChunk;
|
|
1546
|
+
chunk != nsnull;
|
|
1547
|
+
chunk = chunk->mNextChunk)
|
|
1548
|
+
{
|
|
1549
|
+
XPCWrappedNativeTearOff* tearOff = chunk->mTearOffs;
|
|
1550
|
+
XPCWrappedNativeTearOff* const end = tearOff +
|
|
1551
|
+
XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK;
|
|
1552
|
+
for(
|
|
1553
|
+
tearOff = chunk->mTearOffs;
|
|
1554
|
+
tearOff < end;
|
|
1555
|
+
tearOff++)
|
|
1556
|
+
{
|
|
1557
|
+
if(tearOff->GetInterface() == aInterface)
|
|
1558
|
+
{
|
|
1559
|
+
return tearOff;
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
return nsnull;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
XPCWrappedNativeTearOff*
|
|
1567
|
+
XPCWrappedNative::FindTearOff(XPCCallContext& ccx,
|
|
1568
|
+
XPCNativeInterface* aInterface,
|
|
1569
|
+
JSBool needJSObject /* = JS_FALSE */,
|
|
1570
|
+
nsresult* pError /* = nsnull */)
|
|
1571
|
+
{
|
|
1572
|
+
XPCAutoLock al(GetLock()); // hold the lock throughout
|
|
1573
|
+
|
|
1574
|
+
nsresult rv = NS_OK;
|
|
1575
|
+
XPCWrappedNativeTearOff* to;
|
|
1576
|
+
XPCWrappedNativeTearOff* firstAvailable = nsnull;
|
|
1577
|
+
|
|
1578
|
+
XPCWrappedNativeTearOffChunk* lastChunk;
|
|
1579
|
+
XPCWrappedNativeTearOffChunk* chunk;
|
|
1580
|
+
for(lastChunk = chunk = &mFirstChunk;
|
|
1581
|
+
chunk;
|
|
1582
|
+
lastChunk = chunk, chunk = chunk->mNextChunk)
|
|
1583
|
+
{
|
|
1584
|
+
to = chunk->mTearOffs;
|
|
1585
|
+
XPCWrappedNativeTearOff* const end = chunk->mTearOffs +
|
|
1586
|
+
XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK;
|
|
1587
|
+
for(
|
|
1588
|
+
to = chunk->mTearOffs;
|
|
1589
|
+
to < end;
|
|
1590
|
+
to++)
|
|
1591
|
+
{
|
|
1592
|
+
if(to->GetInterface() == aInterface)
|
|
1593
|
+
{
|
|
1594
|
+
if(needJSObject && !to->GetJSObject())
|
|
1595
|
+
{
|
|
1596
|
+
AutoMarkingWrappedNativeTearOffPtr tearoff(ccx, to);
|
|
1597
|
+
rv = InitTearOffJSObject(ccx, to);
|
|
1598
|
+
// During shutdown, we don't sweep tearoffs. So make sure
|
|
1599
|
+
// to unmark manually in case the auto-marker marked us.
|
|
1600
|
+
// We shouldn't ever be getting here _during_ our
|
|
1601
|
+
// Mark/Sweep cycle, so this should be safe.
|
|
1602
|
+
to->Unmark();
|
|
1603
|
+
if(NS_FAILED(rv))
|
|
1604
|
+
to = nsnull;
|
|
1605
|
+
}
|
|
1606
|
+
goto return_result;
|
|
1607
|
+
}
|
|
1608
|
+
if(!firstAvailable && to->IsAvailable())
|
|
1609
|
+
firstAvailable = to;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
to = firstAvailable;
|
|
1614
|
+
|
|
1615
|
+
if(!to)
|
|
1616
|
+
{
|
|
1617
|
+
XPCWrappedNativeTearOffChunk* newChunk =
|
|
1618
|
+
new XPCWrappedNativeTearOffChunk();
|
|
1619
|
+
if(!newChunk)
|
|
1620
|
+
{
|
|
1621
|
+
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
1622
|
+
goto return_result;
|
|
1623
|
+
}
|
|
1624
|
+
lastChunk->mNextChunk = newChunk;
|
|
1625
|
+
to = newChunk->mTearOffs;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
{
|
|
1629
|
+
// Scope keeps |tearoff| from leaking across the return_result: label
|
|
1630
|
+
AutoMarkingWrappedNativeTearOffPtr tearoff(ccx, to);
|
|
1631
|
+
rv = InitTearOff(ccx, to, aInterface, needJSObject);
|
|
1632
|
+
// During shutdown, we don't sweep tearoffs. So make sure to unmark
|
|
1633
|
+
// manually in case the auto-marker marked us. We shouldn't ever be
|
|
1634
|
+
// getting here _during_ our Mark/Sweep cycle, so this should be safe.
|
|
1635
|
+
to->Unmark();
|
|
1636
|
+
if(NS_FAILED(rv))
|
|
1637
|
+
to = nsnull;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
return_result:
|
|
1641
|
+
|
|
1642
|
+
if(pError)
|
|
1643
|
+
*pError = rv;
|
|
1644
|
+
return to;
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
nsresult
|
|
1648
|
+
XPCWrappedNative::InitTearOff(XPCCallContext& ccx,
|
|
1649
|
+
XPCWrappedNativeTearOff* aTearOff,
|
|
1650
|
+
XPCNativeInterface* aInterface,
|
|
1651
|
+
JSBool needJSObject)
|
|
1652
|
+
{
|
|
1653
|
+
// This is only called while locked (during XPCWrappedNative::FindTearOff).
|
|
1654
|
+
|
|
1655
|
+
// Determine if the object really does this interface...
|
|
1656
|
+
|
|
1657
|
+
const nsIID* iid = aInterface->GetIID();
|
|
1658
|
+
nsISupports* identity = GetIdentityObject();
|
|
1659
|
+
nsISupports* obj;
|
|
1660
|
+
|
|
1661
|
+
// If the scriptable helper forbids us from reflecting additional
|
|
1662
|
+
// interfaces, then don't even try the QI, just fail.
|
|
1663
|
+
if(mScriptableInfo &&
|
|
1664
|
+
mScriptableInfo->GetFlags().ClassInfoInterfacesOnly() &&
|
|
1665
|
+
!mSet->HasInterface(aInterface) &&
|
|
1666
|
+
!mSet->HasInterfaceWithAncestor(aInterface))
|
|
1667
|
+
{
|
|
1668
|
+
return NS_ERROR_NO_INTERFACE;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
// We are about to call out to unlock and other code.
|
|
1672
|
+
// So protect our intended tearoff.
|
|
1673
|
+
|
|
1674
|
+
aTearOff->SetReserved();
|
|
1675
|
+
|
|
1676
|
+
{ // scoped *un*lock
|
|
1677
|
+
XPCAutoUnlock unlock(GetLock());
|
|
1678
|
+
|
|
1679
|
+
if(NS_FAILED(identity->QueryInterface(*iid, (void**)&obj)) || !obj)
|
|
1680
|
+
{
|
|
1681
|
+
aTearOff->SetInterface(nsnull);
|
|
1682
|
+
return NS_ERROR_NO_INTERFACE;
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
// Guard against trying to build a tearoff for a shared nsIClassInfo.
|
|
1686
|
+
if(iid->Equals(NS_GET_IID(nsIClassInfo)))
|
|
1687
|
+
{
|
|
1688
|
+
nsCOMPtr<nsISupports> alternate_identity(do_QueryInterface(obj));
|
|
1689
|
+
if(alternate_identity.get() != identity)
|
|
1690
|
+
{
|
|
1691
|
+
NS_RELEASE(obj);
|
|
1692
|
+
aTearOff->SetInterface(nsnull);
|
|
1693
|
+
return NS_ERROR_NO_INTERFACE;
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
// Guard against trying to build a tearoff for an interface that is
|
|
1698
|
+
// aggregated and is implemented as a nsIXPConnectWrappedJS using this
|
|
1699
|
+
// self-same JSObject. The XBL system does this. If we mutate the set
|
|
1700
|
+
// of this wrapper then we will shadow the method that XBL has added to
|
|
1701
|
+
// the JSObject that it has inserted in the JS proto chain between our
|
|
1702
|
+
// JSObject and our XPCWrappedNativeProto's JSObject. If we let this
|
|
1703
|
+
// set mutation happen then the interface's methods will be added to
|
|
1704
|
+
// our JSObject, but calls on those methods will get routed up to
|
|
1705
|
+
// native code and into the wrappedJS - which will do a method lookup
|
|
1706
|
+
// on *our* JSObject and find the same method and make another call
|
|
1707
|
+
// into an infinite loop.
|
|
1708
|
+
// see: http://bugzilla.mozilla.org/show_bug.cgi?id=96725
|
|
1709
|
+
|
|
1710
|
+
// The code in this block also does a check for the double wrapped
|
|
1711
|
+
// nsIPropertyBag case.
|
|
1712
|
+
|
|
1713
|
+
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS(do_QueryInterface(obj));
|
|
1714
|
+
if(wrappedJS)
|
|
1715
|
+
{
|
|
1716
|
+
JSObject* jso = nsnull;
|
|
1717
|
+
if(NS_SUCCEEDED(wrappedJS->GetJSObject(&jso)) &&
|
|
1718
|
+
jso == GetFlatJSObject())
|
|
1719
|
+
{
|
|
1720
|
+
// The implementing JSObject is the same as ours! Just say OK
|
|
1721
|
+
// without actually extending the set.
|
|
1722
|
+
//
|
|
1723
|
+
// XXX It is a little cheesy to have FindTearOff return an
|
|
1724
|
+
// 'empty' tearoff. But this is the centralized place to do the
|
|
1725
|
+
// QI activities on the underlying object. *And* most caller to
|
|
1726
|
+
// FindTearOff only look for a non-null result and ignore the
|
|
1727
|
+
// actual tearoff returned. The only callers that do use the
|
|
1728
|
+
// returned tearoff make sure to check for either a non-null
|
|
1729
|
+
// JSObject or a matching Interface before proceeding.
|
|
1730
|
+
// I think we can get away with this bit of ugliness.
|
|
1731
|
+
|
|
1732
|
+
#ifdef DEBUG_xpc_hacker
|
|
1733
|
+
{
|
|
1734
|
+
// I want to make sure this only happens in xbl-like cases.
|
|
1735
|
+
// So, some debug code to verify that there is at least
|
|
1736
|
+
// *some* object between our JSObject and its inital proto.
|
|
1737
|
+
// XXX This is a pretty funky test. Someone might hack it
|
|
1738
|
+
// a bit if false positives start showing up. Note that
|
|
1739
|
+
// this is only going to run for the few people in the
|
|
1740
|
+
// DEBUG_xpc_hacker list.
|
|
1741
|
+
if(HasProto())
|
|
1742
|
+
{
|
|
1743
|
+
JSObject* proto = nsnull;
|
|
1744
|
+
JSObject* our_proto = GetProto()->GetJSProtoObject();
|
|
1745
|
+
|
|
1746
|
+
proto = STOBJ_GET_PROTO(jso);
|
|
1747
|
+
|
|
1748
|
+
NS_ASSERTION(proto && proto != our_proto,
|
|
1749
|
+
"!!! xpconnect/xbl check - wrapper has no special proto");
|
|
1750
|
+
|
|
1751
|
+
PRBool found_our_proto = PR_FALSE;
|
|
1752
|
+
while(proto && !found_our_proto) {
|
|
1753
|
+
proto = STOBJ_GET_PROTO(proto);
|
|
1754
|
+
|
|
1755
|
+
found_our_proto = proto == our_proto;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
NS_ASSERTION(found_our_proto,
|
|
1759
|
+
"!!! xpconnect/xbl check - wrapper has extra proto");
|
|
1760
|
+
}
|
|
1761
|
+
else
|
|
1762
|
+
{
|
|
1763
|
+
NS_WARNING("!!! xpconnect/xbl check - wrapper has no proto");
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
#endif
|
|
1767
|
+
NS_RELEASE(obj);
|
|
1768
|
+
aTearOff->SetInterface(nsnull);
|
|
1769
|
+
return NS_OK;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
// Decide whether or not to expose nsIPropertyBag to calling
|
|
1773
|
+
// JS code in the double wrapped case.
|
|
1774
|
+
//
|
|
1775
|
+
// Our rule here is that when JSObjects are double wrapped and
|
|
1776
|
+
// exposed to other JSObjects then the nsIPropertyBag interface
|
|
1777
|
+
// is only exposed on an 'opt-in' basis; i.e. if the underlying
|
|
1778
|
+
// JSObject wants other JSObjects to be able to see this interface
|
|
1779
|
+
// then it must implement QueryInterface and not throw an exception
|
|
1780
|
+
// when asked for nsIPropertyBag. It need not actually *implement*
|
|
1781
|
+
// nsIPropertyBag - xpconnect will do that work.
|
|
1782
|
+
|
|
1783
|
+
nsXPCWrappedJSClass* clazz;
|
|
1784
|
+
if(iid->Equals(NS_GET_IID(nsIPropertyBag)) && jso &&
|
|
1785
|
+
NS_SUCCEEDED(nsXPCWrappedJSClass::GetNewOrUsed(ccx,*iid,&clazz))&&
|
|
1786
|
+
clazz)
|
|
1787
|
+
{
|
|
1788
|
+
JSObject* answer =
|
|
1789
|
+
clazz->CallQueryInterfaceOnJSObject(ccx, jso, *iid);
|
|
1790
|
+
NS_RELEASE(clazz);
|
|
1791
|
+
if(!answer)
|
|
1792
|
+
{
|
|
1793
|
+
NS_RELEASE(obj);
|
|
1794
|
+
aTearOff->SetInterface(nsnull);
|
|
1795
|
+
return NS_ERROR_NO_INTERFACE;
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
nsIXPCSecurityManager* sm;
|
|
1801
|
+
sm = ccx.GetXPCContext()->GetAppropriateSecurityManager(
|
|
1802
|
+
nsIXPCSecurityManager::HOOK_CREATE_WRAPPER);
|
|
1803
|
+
if(sm && NS_FAILED(sm->
|
|
1804
|
+
CanCreateWrapper(ccx, *iid, identity,
|
|
1805
|
+
GetClassInfo(), GetSecurityInfoAddr())))
|
|
1806
|
+
{
|
|
1807
|
+
// the security manager vetoed. It should have set an exception.
|
|
1808
|
+
NS_RELEASE(obj);
|
|
1809
|
+
aTearOff->SetInterface(nsnull);
|
|
1810
|
+
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
// We are relocked from here on...
|
|
1814
|
+
|
|
1815
|
+
// If this is not already in our set we need to extend our set.
|
|
1816
|
+
// Note: we do not cache the result of the previous call to HasInterface()
|
|
1817
|
+
// because we unlocked and called out in the interim and the result of the
|
|
1818
|
+
// previous call might not be correct anymore.
|
|
1819
|
+
|
|
1820
|
+
if(!mSet->HasInterface(aInterface) && !ExtendSet(ccx, aInterface))
|
|
1821
|
+
{
|
|
1822
|
+
NS_RELEASE(obj);
|
|
1823
|
+
aTearOff->SetInterface(nsnull);
|
|
1824
|
+
return NS_ERROR_NO_INTERFACE;
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
aTearOff->SetInterface(aInterface);
|
|
1828
|
+
aTearOff->SetNative(obj);
|
|
1829
|
+
#ifdef XPC_IDISPATCH_SUPPORT
|
|
1830
|
+
// Are we building a tearoff for IDispatch?
|
|
1831
|
+
if(iid->Equals(NSID_IDISPATCH))
|
|
1832
|
+
{
|
|
1833
|
+
aTearOff->SetIDispatch(ccx);
|
|
1834
|
+
}
|
|
1835
|
+
#endif
|
|
1836
|
+
if(needJSObject && !InitTearOffJSObject(ccx, aTearOff))
|
|
1837
|
+
return NS_ERROR_OUT_OF_MEMORY;
|
|
1838
|
+
|
|
1839
|
+
return NS_OK;
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
JSBool
|
|
1843
|
+
XPCWrappedNative::InitTearOffJSObject(XPCCallContext& ccx,
|
|
1844
|
+
XPCWrappedNativeTearOff* to)
|
|
1845
|
+
{
|
|
1846
|
+
// This is only called while locked (during XPCWrappedNative::FindTearOff).
|
|
1847
|
+
|
|
1848
|
+
JSObject* obj =
|
|
1849
|
+
xpc_NewSystemInheritingJSObject(ccx, &XPC_WN_Tearoff_JSClass,
|
|
1850
|
+
GetScope()->GetPrototypeJSObject(),
|
|
1851
|
+
mFlatJSObject);
|
|
1852
|
+
|
|
1853
|
+
if(!obj || !JS_SetPrivate(ccx, obj, to))
|
|
1854
|
+
return JS_FALSE;
|
|
1855
|
+
|
|
1856
|
+
to->SetJSObject(obj);
|
|
1857
|
+
return JS_TRUE;
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
/***************************************************************************/
|
|
1861
|
+
|
|
1862
|
+
static JSBool Throw(uintN errNum, XPCCallContext& ccx)
|
|
1863
|
+
{
|
|
1864
|
+
XPCThrower::Throw(errNum, ccx);
|
|
1865
|
+
return JS_FALSE;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
enum SizeMode {GET_SIZE, GET_LENGTH};
|
|
1869
|
+
|
|
1870
|
+
/***************************************************************************/
|
|
1871
|
+
|
|
1872
|
+
static JSBool
|
|
1873
|
+
GetArraySizeFromParam(XPCCallContext& ccx,
|
|
1874
|
+
nsIInterfaceInfo* ifaceInfo,
|
|
1875
|
+
const nsXPTMethodInfo* methodInfo,
|
|
1876
|
+
const nsXPTParamInfo& paramInfo,
|
|
1877
|
+
uint16 vtblIndex,
|
|
1878
|
+
uint8 paramIndex,
|
|
1879
|
+
SizeMode mode,
|
|
1880
|
+
nsXPTCVariant* dispatchParams,
|
|
1881
|
+
JSUint32* result)
|
|
1882
|
+
{
|
|
1883
|
+
uint8 argnum;
|
|
1884
|
+
nsresult rv;
|
|
1885
|
+
|
|
1886
|
+
// XXX fixup the various exceptions that are thrown
|
|
1887
|
+
|
|
1888
|
+
if(mode == GET_SIZE)
|
|
1889
|
+
rv = ifaceInfo->GetSizeIsArgNumberForParam(vtblIndex, ¶mInfo, 0, &argnum);
|
|
1890
|
+
else
|
|
1891
|
+
rv = ifaceInfo->GetLengthIsArgNumberForParam(vtblIndex, ¶mInfo, 0, &argnum);
|
|
1892
|
+
if(NS_FAILED(rv))
|
|
1893
|
+
return Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, ccx);
|
|
1894
|
+
|
|
1895
|
+
const nsXPTParamInfo& arg_param = methodInfo->GetParam(argnum);
|
|
1896
|
+
const nsXPTType& arg_type = arg_param.GetType();
|
|
1897
|
+
|
|
1898
|
+
// The xpidl compiler ensures this. We reaffirm it for safety.
|
|
1899
|
+
if(arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_U32)
|
|
1900
|
+
return Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, ccx);
|
|
1901
|
+
|
|
1902
|
+
*result = dispatchParams[argnum].val.u32;
|
|
1903
|
+
|
|
1904
|
+
return JS_TRUE;
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
|
|
1908
|
+
static JSBool
|
|
1909
|
+
GetInterfaceTypeFromParam(XPCCallContext& ccx,
|
|
1910
|
+
nsIInterfaceInfo* ifaceInfo,
|
|
1911
|
+
const nsXPTMethodInfo* methodInfo,
|
|
1912
|
+
const nsXPTParamInfo& paramInfo,
|
|
1913
|
+
uint16 vtblIndex,
|
|
1914
|
+
uint8 paramIndex,
|
|
1915
|
+
const nsXPTType& datum_type,
|
|
1916
|
+
nsXPTCVariant* dispatchParams,
|
|
1917
|
+
nsID* result)
|
|
1918
|
+
{
|
|
1919
|
+
uint8 argnum;
|
|
1920
|
+
nsresult rv;
|
|
1921
|
+
uint8 type_tag = datum_type.TagPart();
|
|
1922
|
+
|
|
1923
|
+
// XXX fixup the various exceptions that are thrown
|
|
1924
|
+
|
|
1925
|
+
if(type_tag == nsXPTType::T_INTERFACE)
|
|
1926
|
+
{
|
|
1927
|
+
rv = ifaceInfo->GetIIDForParamNoAlloc(vtblIndex, ¶mInfo, result);
|
|
1928
|
+
if(NS_FAILED(rv))
|
|
1929
|
+
return ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO, paramIndex, ccx);
|
|
1930
|
+
}
|
|
1931
|
+
else if(type_tag == nsXPTType::T_INTERFACE_IS)
|
|
1932
|
+
{
|
|
1933
|
+
rv = ifaceInfo->GetInterfaceIsArgNumberForParam(vtblIndex, ¶mInfo, &argnum);
|
|
1934
|
+
if(NS_FAILED(rv))
|
|
1935
|
+
return Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, ccx);
|
|
1936
|
+
|
|
1937
|
+
const nsXPTParamInfo& arg_param = methodInfo->GetParam(argnum);
|
|
1938
|
+
const nsXPTType& arg_type = arg_param.GetType();
|
|
1939
|
+
|
|
1940
|
+
// The xpidl compiler ensures this. We reaffirm it for safety.
|
|
1941
|
+
if(!arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_IID)
|
|
1942
|
+
return ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO, paramIndex, ccx);
|
|
1943
|
+
|
|
1944
|
+
nsID* p = (nsID*) dispatchParams[argnum].val.p;
|
|
1945
|
+
if(!p)
|
|
1946
|
+
return ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO, paramIndex, ccx);
|
|
1947
|
+
*result = *p;
|
|
1948
|
+
}
|
|
1949
|
+
return JS_TRUE;
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
/***************************************************************************/
|
|
1953
|
+
|
|
1954
|
+
// static
|
|
1955
|
+
NS_SUPPRESS_STACK_CHECK JSBool
|
|
1956
|
+
XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
|
1957
|
+
CallMode mode /*= CALL_METHOD */)
|
|
1958
|
+
{
|
|
1959
|
+
NS_ASSERTION(ccx.GetXPCContext()->CallerTypeIsJavaScript(),
|
|
1960
|
+
"Native caller for XPCWrappedNative::CallMethod?");
|
|
1961
|
+
|
|
1962
|
+
nsresult rv = ccx.CanCallNow();
|
|
1963
|
+
if(NS_FAILED(rv))
|
|
1964
|
+
{
|
|
1965
|
+
// If the security manager is complaining then this is not really an
|
|
1966
|
+
// internal error in xpconnect. So, no reason to botch the assertion.
|
|
1967
|
+
NS_ASSERTION(rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO,
|
|
1968
|
+
"hmm? CanCallNow failed in XPCWrappedNative::CallMethod. "
|
|
1969
|
+
"We are finding out about this late!");
|
|
1970
|
+
return Throw(rv, ccx);
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
DEBUG_TrackWrapperCall(ccx.GetWrapper(), mode);
|
|
1974
|
+
|
|
1975
|
+
// From here on ALL exits are through 'goto done;'
|
|
1976
|
+
|
|
1977
|
+
#define PARAM_BUFFER_COUNT 8
|
|
1978
|
+
|
|
1979
|
+
nsXPTCVariant paramBuffer[PARAM_BUFFER_COUNT];
|
|
1980
|
+
|
|
1981
|
+
// Reserve space on the stack for one nsAutoString. We don't want
|
|
1982
|
+
// the string itself to be declared on the stack as that would
|
|
1983
|
+
// make the ctor and dtors run for each pass through this code,
|
|
1984
|
+
// and they're only needed in a fraction of all the calls that
|
|
1985
|
+
// come through here.
|
|
1986
|
+
char autoString[sizeof(nsAutoString)];
|
|
1987
|
+
PRBool autoStringUsed = PR_FALSE;
|
|
1988
|
+
|
|
1989
|
+
JSBool retval = JS_FALSE;
|
|
1990
|
+
|
|
1991
|
+
nsXPTCVariant* dispatchParams = nsnull;
|
|
1992
|
+
uint8 i;
|
|
1993
|
+
const nsXPTMethodInfo* methodInfo;
|
|
1994
|
+
uint8 requiredArgs;
|
|
1995
|
+
uint8 paramCount;
|
|
1996
|
+
jsval src;
|
|
1997
|
+
nsresult invokeResult;
|
|
1998
|
+
nsID param_iid;
|
|
1999
|
+
uintN err;
|
|
2000
|
+
nsIXPCSecurityManager* sm;
|
|
2001
|
+
JSBool foundDependentParam;
|
|
2002
|
+
|
|
2003
|
+
XPCJSRuntime* rt = ccx.GetRuntime();
|
|
2004
|
+
XPCContext* xpcc = ccx.GetXPCContext();
|
|
2005
|
+
nsISupports* callee = ccx.GetTearOff()->GetNative();
|
|
2006
|
+
XPCPerThreadData* tls = ccx.GetThreadData();
|
|
2007
|
+
uint16 vtblIndex = ccx.GetMethodIndex();
|
|
2008
|
+
nsIInterfaceInfo* ifaceInfo = ccx.GetInterface()->GetInterfaceInfo();
|
|
2009
|
+
jsval name = ccx.GetMember()->GetName();
|
|
2010
|
+
jsval* argv = ccx.GetArgv();
|
|
2011
|
+
PRUint32 argc = ccx.GetArgc();
|
|
2012
|
+
|
|
2013
|
+
ccx.SetRetVal(JSVAL_VOID);
|
|
2014
|
+
|
|
2015
|
+
tls->SetException(nsnull);
|
|
2016
|
+
xpcc->SetLastResult(NS_ERROR_UNEXPECTED);
|
|
2017
|
+
|
|
2018
|
+
// set up the method index and do the security check if needed
|
|
2019
|
+
|
|
2020
|
+
PRUint32 secFlag;
|
|
2021
|
+
PRUint32 secAction;
|
|
2022
|
+
|
|
2023
|
+
switch(mode)
|
|
2024
|
+
{
|
|
2025
|
+
case CALL_METHOD:
|
|
2026
|
+
secFlag = nsIXPCSecurityManager::HOOK_CALL_METHOD;
|
|
2027
|
+
secAction = nsIXPCSecurityManager::ACCESS_CALL_METHOD;
|
|
2028
|
+
break;
|
|
2029
|
+
case CALL_GETTER:
|
|
2030
|
+
secFlag = nsIXPCSecurityManager::HOOK_GET_PROPERTY;
|
|
2031
|
+
secAction = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
|
|
2032
|
+
break;
|
|
2033
|
+
case CALL_SETTER:
|
|
2034
|
+
secFlag = nsIXPCSecurityManager::HOOK_SET_PROPERTY;
|
|
2035
|
+
secAction = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
|
|
2036
|
+
break;
|
|
2037
|
+
default:
|
|
2038
|
+
NS_ASSERTION(0,"bad value");
|
|
2039
|
+
return JS_FALSE;
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
sm = xpcc->GetAppropriateSecurityManager(secFlag);
|
|
2043
|
+
if(sm && NS_FAILED(sm->CanAccess(secAction, &ccx, ccx,
|
|
2044
|
+
ccx.GetFlattenedJSObject(),
|
|
2045
|
+
ccx.GetWrapper()->GetIdentityObject(),
|
|
2046
|
+
ccx.GetWrapper()->GetClassInfo(), name,
|
|
2047
|
+
ccx.GetWrapper()->GetSecurityInfoAddr())))
|
|
2048
|
+
{
|
|
2049
|
+
// the security manager vetoed. It should have set an exception.
|
|
2050
|
+
return JS_FALSE;
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
// fast-path QueryInterface: we already know the signature and can avoid a
|
|
2054
|
+
// lot of work
|
|
2055
|
+
if(vtblIndex == 0)
|
|
2056
|
+
{
|
|
2057
|
+
if(argc < 1)
|
|
2058
|
+
{
|
|
2059
|
+
Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, ccx);
|
|
2060
|
+
return JS_FALSE;
|
|
2061
|
+
}
|
|
2062
|
+
const nsID* iid;
|
|
2063
|
+
JSObject* obj;
|
|
2064
|
+
if(!JSVAL_IS_OBJECT(argv[0]) ||
|
|
2065
|
+
(!(obj = JSVAL_TO_OBJECT(argv[0]))) ||
|
|
2066
|
+
(!(iid = xpc_JSObjectToID(ccx, obj))))
|
|
2067
|
+
{
|
|
2068
|
+
ThrowBadParam(NS_ERROR_XPC_BAD_CONVERT_JS, 0, ccx);
|
|
2069
|
+
return JS_FALSE;
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
nsISupports* qiresult = nsnull;
|
|
2073
|
+
{
|
|
2074
|
+
AutoJSSuspendNonMainThreadRequest req(ccx.GetJSContext());
|
|
2075
|
+
invokeResult = callee->QueryInterface(*iid, (void**) &qiresult);
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
xpcc->SetLastResult(invokeResult);
|
|
2079
|
+
|
|
2080
|
+
if(NS_FAILED(invokeResult))
|
|
2081
|
+
{
|
|
2082
|
+
ThrowBadResult(invokeResult, ccx);
|
|
2083
|
+
return JS_FALSE;
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
jsval v = JSVAL_NULL;
|
|
2087
|
+
retval = XPCConvert::NativeData2JS(ccx, &v, &qiresult,
|
|
2088
|
+
nsXPTType::T_INTERFACE_IS | XPT_TDP_POINTER,
|
|
2089
|
+
iid, ccx.GetCurrentJSObject(), &err);
|
|
2090
|
+
NS_IF_RELEASE(qiresult);
|
|
2091
|
+
|
|
2092
|
+
if(!retval)
|
|
2093
|
+
{
|
|
2094
|
+
ThrowBadParam(err, 0, ccx);
|
|
2095
|
+
return JS_FALSE;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
ccx.SetRetVal(v);
|
|
2099
|
+
return JS_TRUE;
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
if(NS_FAILED(ifaceInfo->GetMethodInfo(vtblIndex, &methodInfo)))
|
|
2103
|
+
{
|
|
2104
|
+
Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, ccx);
|
|
2105
|
+
goto done;
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
|
|
2109
|
+
paramCount = methodInfo->GetParamCount();
|
|
2110
|
+
requiredArgs = paramCount;
|
|
2111
|
+
if(paramCount && methodInfo->GetParam(paramCount-1).IsRetval())
|
|
2112
|
+
requiredArgs--;
|
|
2113
|
+
if(argc < requiredArgs)
|
|
2114
|
+
{
|
|
2115
|
+
// skip over any optional arguments
|
|
2116
|
+
while(requiredArgs && methodInfo->GetParam(requiredArgs-1).IsOptional())
|
|
2117
|
+
requiredArgs--;
|
|
2118
|
+
|
|
2119
|
+
if(argc < requiredArgs) {
|
|
2120
|
+
Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, ccx);
|
|
2121
|
+
goto done;
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
// setup variant array pointer
|
|
2126
|
+
if(paramCount > PARAM_BUFFER_COUNT)
|
|
2127
|
+
{
|
|
2128
|
+
if(!(dispatchParams = new nsXPTCVariant[paramCount]))
|
|
2129
|
+
{
|
|
2130
|
+
JS_ReportOutOfMemory(ccx);
|
|
2131
|
+
goto done;
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
else
|
|
2135
|
+
dispatchParams = paramBuffer;
|
|
2136
|
+
|
|
2137
|
+
// iterate through the params to clear flags (for safe cleanup later)
|
|
2138
|
+
for(i = 0; i < paramCount; i++)
|
|
2139
|
+
{
|
|
2140
|
+
nsXPTCVariant* dp = &dispatchParams[i];
|
|
2141
|
+
dp->ClearFlags();
|
|
2142
|
+
dp->val.p = nsnull;
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
// Iterate through the params doing conversions of independent params only.
|
|
2146
|
+
// When we later convert the dependent params (if any) we will know that
|
|
2147
|
+
// the params upon which they depend will have already been converted -
|
|
2148
|
+
// regardless of ordering.
|
|
2149
|
+
foundDependentParam = JS_FALSE;
|
|
2150
|
+
for(i = 0; i < paramCount; i++)
|
|
2151
|
+
{
|
|
2152
|
+
JSBool useAllocator = JS_FALSE;
|
|
2153
|
+
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
|
2154
|
+
const nsXPTType& type = paramInfo.GetType();
|
|
2155
|
+
uint8 type_tag = type.TagPart();
|
|
2156
|
+
|
|
2157
|
+
if(type.IsDependent())
|
|
2158
|
+
{
|
|
2159
|
+
foundDependentParam = JS_TRUE;
|
|
2160
|
+
continue;
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
nsXPTCVariant* dp = &dispatchParams[i];
|
|
2164
|
+
dp->type = type;
|
|
2165
|
+
|
|
2166
|
+
if(type_tag == nsXPTType::T_INTERFACE)
|
|
2167
|
+
{
|
|
2168
|
+
dp->SetValIsInterface();
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
// set 'src' to be the object from which we get the value and
|
|
2172
|
+
// prepare for out param
|
|
2173
|
+
|
|
2174
|
+
if((paramInfo.IsOut() || paramInfo.IsDipper()) &&
|
|
2175
|
+
!paramInfo.IsRetval()) {
|
|
2176
|
+
NS_ASSERTION(i < argc || paramInfo.IsOptional(),
|
|
2177
|
+
"Expected either enough arguments or an optional argument");
|
|
2178
|
+
jsval arg = i < argc ? argv[i] : JSVAL_NULL;
|
|
2179
|
+
if(JSVAL_IS_PRIMITIVE(arg) ||
|
|
2180
|
+
!JS_GetPropertyById(ccx, JSVAL_TO_OBJECT(arg),
|
|
2181
|
+
rt->GetStringID(XPCJSRuntime::IDX_VALUE),
|
|
2182
|
+
&src))
|
|
2183
|
+
{
|
|
2184
|
+
ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, i, ccx);
|
|
2185
|
+
goto done;
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
if(paramInfo.IsOut())
|
|
2190
|
+
{
|
|
2191
|
+
dp->SetPtrIsData();
|
|
2192
|
+
dp->ptr = &dp->val;
|
|
2193
|
+
|
|
2194
|
+
if(type.IsPointer() &&
|
|
2195
|
+
type_tag != nsXPTType::T_INTERFACE &&
|
|
2196
|
+
!paramInfo.IsShared())
|
|
2197
|
+
{
|
|
2198
|
+
useAllocator = JS_TRUE;
|
|
2199
|
+
dp->SetValIsAllocated();
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
if(!paramInfo.IsIn())
|
|
2203
|
+
continue;
|
|
2204
|
+
}
|
|
2205
|
+
else
|
|
2206
|
+
{
|
|
2207
|
+
if(type.IsPointer())
|
|
2208
|
+
{
|
|
2209
|
+
switch(type_tag)
|
|
2210
|
+
{
|
|
2211
|
+
case nsXPTType::T_IID:
|
|
2212
|
+
dp->SetValIsAllocated();
|
|
2213
|
+
useAllocator = JS_TRUE;
|
|
2214
|
+
break;
|
|
2215
|
+
|
|
2216
|
+
case nsXPTType::T_ASTRING:
|
|
2217
|
+
// Fall through to the T_DOMSTRING case
|
|
2218
|
+
|
|
2219
|
+
case nsXPTType::T_DOMSTRING:
|
|
2220
|
+
if(paramInfo.IsDipper())
|
|
2221
|
+
{
|
|
2222
|
+
// Is an 'out' DOMString. Make a new nsAString
|
|
2223
|
+
// now and then continue in order to skip the call to
|
|
2224
|
+
// JSData2Native
|
|
2225
|
+
|
|
2226
|
+
if(!autoStringUsed)
|
|
2227
|
+
{
|
|
2228
|
+
// Our stack space for an nsAutoString is
|
|
2229
|
+
// still available, initialize the string
|
|
2230
|
+
// object (using placement new) and use
|
|
2231
|
+
// it.
|
|
2232
|
+
nsAutoString *s = (nsAutoString*)&autoString;
|
|
2233
|
+
new (s) nsAutoString();
|
|
2234
|
+
autoStringUsed = PR_TRUE;
|
|
2235
|
+
|
|
2236
|
+
// Don't call SetValIsDOMString because we don't
|
|
2237
|
+
// want to delete this pointer.
|
|
2238
|
+
dp->val.p = s;
|
|
2239
|
+
continue;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
dp->SetValIsDOMString();
|
|
2243
|
+
if(!(dp->val.p = new nsAutoString()))
|
|
2244
|
+
{
|
|
2245
|
+
JS_ReportOutOfMemory(ccx);
|
|
2246
|
+
goto done;
|
|
2247
|
+
}
|
|
2248
|
+
continue;
|
|
2249
|
+
}
|
|
2250
|
+
// else...
|
|
2251
|
+
|
|
2252
|
+
// Is an 'in' DOMString. Set 'useAllocator' to indicate
|
|
2253
|
+
// that JSData2Native should allocate a new
|
|
2254
|
+
// nsAString.
|
|
2255
|
+
dp->SetValIsDOMString();
|
|
2256
|
+
useAllocator = JS_TRUE;
|
|
2257
|
+
break;
|
|
2258
|
+
|
|
2259
|
+
case nsXPTType::T_UTF8STRING:
|
|
2260
|
+
// Fall through to the C string case for now...
|
|
2261
|
+
case nsXPTType::T_CSTRING:
|
|
2262
|
+
dp->SetValIsCString();
|
|
2263
|
+
if(paramInfo.IsDipper())
|
|
2264
|
+
{
|
|
2265
|
+
// Is an 'out' CString.
|
|
2266
|
+
if(!(dp->val.p = new nsCString()))
|
|
2267
|
+
{
|
|
2268
|
+
JS_ReportOutOfMemory(ccx);
|
|
2269
|
+
goto done;
|
|
2270
|
+
}
|
|
2271
|
+
continue;
|
|
2272
|
+
}
|
|
2273
|
+
// else ...
|
|
2274
|
+
// Is an 'in' CString.
|
|
2275
|
+
useAllocator = JS_TRUE;
|
|
2276
|
+
break;
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
// Do this *after* the above because in the case where we have a
|
|
2281
|
+
// "T_DOMSTRING && IsDipper()" then arg might be null since this
|
|
2282
|
+
// is really an 'out' param masquerading as an 'in' param.
|
|
2283
|
+
NS_ASSERTION(i < argc || paramInfo.IsOptional(),
|
|
2284
|
+
"Expected either enough arguments or an optional argument");
|
|
2285
|
+
src = i < argc ? argv[i] : JSVAL_NULL;
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
if(type_tag == nsXPTType::T_INTERFACE &&
|
|
2289
|
+
NS_FAILED(ifaceInfo->GetIIDForParamNoAlloc(vtblIndex, ¶mInfo,
|
|
2290
|
+
¶m_iid)))
|
|
2291
|
+
{
|
|
2292
|
+
ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO, i, ccx);
|
|
2293
|
+
goto done;
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
if(!XPCConvert::JSData2Native(ccx, &dp->val, src, type,
|
|
2297
|
+
useAllocator, ¶m_iid, &err))
|
|
2298
|
+
{
|
|
2299
|
+
ThrowBadParam(err, i, ccx);
|
|
2300
|
+
goto done;
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
// if any params were dependent, then we must iterate again to convert them.
|
|
2305
|
+
if(foundDependentParam)
|
|
2306
|
+
{
|
|
2307
|
+
for(i = 0; i < paramCount; i++)
|
|
2308
|
+
{
|
|
2309
|
+
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
|
2310
|
+
const nsXPTType& type = paramInfo.GetType();
|
|
2311
|
+
|
|
2312
|
+
if(!type.IsDependent())
|
|
2313
|
+
continue;
|
|
2314
|
+
|
|
2315
|
+
nsXPTType datum_type;
|
|
2316
|
+
JSUint32 array_count;
|
|
2317
|
+
JSUint32 array_capacity;
|
|
2318
|
+
JSBool useAllocator = JS_FALSE;
|
|
2319
|
+
PRBool isArray = type.IsArray();
|
|
2320
|
+
|
|
2321
|
+
PRBool isSizedString = isArray ?
|
|
2322
|
+
JS_FALSE :
|
|
2323
|
+
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
|
2324
|
+
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
|
2325
|
+
|
|
2326
|
+
nsXPTCVariant* dp = &dispatchParams[i];
|
|
2327
|
+
dp->type = type;
|
|
2328
|
+
|
|
2329
|
+
if(isArray)
|
|
2330
|
+
{
|
|
2331
|
+
dp->SetValIsArray();
|
|
2332
|
+
|
|
2333
|
+
if(NS_FAILED(ifaceInfo->GetTypeForParam(vtblIndex, ¶mInfo, 1,
|
|
2334
|
+
&datum_type)))
|
|
2335
|
+
{
|
|
2336
|
+
Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, ccx);
|
|
2337
|
+
goto done;
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
else
|
|
2341
|
+
datum_type = type;
|
|
2342
|
+
|
|
2343
|
+
if(datum_type.IsInterfacePointer())
|
|
2344
|
+
{
|
|
2345
|
+
dp->SetValIsInterface();
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
// set 'src' to be the object from which we get the value and
|
|
2349
|
+
// prepare for out param
|
|
2350
|
+
|
|
2351
|
+
if(paramInfo.IsOut())
|
|
2352
|
+
{
|
|
2353
|
+
dp->SetPtrIsData();
|
|
2354
|
+
dp->ptr = &dp->val;
|
|
2355
|
+
|
|
2356
|
+
if(!paramInfo.IsRetval()) {
|
|
2357
|
+
NS_ASSERTION(i < argc || paramInfo.IsOptional(),
|
|
2358
|
+
"Expected either enough arguments or an optional argument");
|
|
2359
|
+
jsval arg = i < argc ? argv[i] : JSVAL_NULL;
|
|
2360
|
+
if(JSVAL_IS_PRIMITIVE(arg) ||
|
|
2361
|
+
!JS_GetPropertyById(ccx, JSVAL_TO_OBJECT(arg),
|
|
2362
|
+
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &src))
|
|
2363
|
+
{
|
|
2364
|
+
ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, i, ccx);
|
|
2365
|
+
goto done;
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
if(datum_type.IsPointer() &&
|
|
2370
|
+
!datum_type.IsInterfacePointer() &&
|
|
2371
|
+
(isArray || !paramInfo.IsShared()))
|
|
2372
|
+
{
|
|
2373
|
+
useAllocator = JS_TRUE;
|
|
2374
|
+
dp->SetValIsAllocated();
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
if(!paramInfo.IsIn())
|
|
2378
|
+
continue;
|
|
2379
|
+
}
|
|
2380
|
+
else
|
|
2381
|
+
{
|
|
2382
|
+
NS_ASSERTION(i < argc || paramInfo.IsOptional(),
|
|
2383
|
+
"Expected either enough arguments or an optional argument");
|
|
2384
|
+
src = i < argc ? argv[i] : JSVAL_NULL;
|
|
2385
|
+
|
|
2386
|
+
if(datum_type.IsPointer() &&
|
|
2387
|
+
datum_type.TagPart() == nsXPTType::T_IID)
|
|
2388
|
+
{
|
|
2389
|
+
useAllocator = JS_TRUE;
|
|
2390
|
+
dp->SetValIsAllocated();
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2394
|
+
if(datum_type.IsInterfacePointer() &&
|
|
2395
|
+
!GetInterfaceTypeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
|
|
2396
|
+
vtblIndex, i, datum_type,
|
|
2397
|
+
dispatchParams, ¶m_iid))
|
|
2398
|
+
goto done;
|
|
2399
|
+
|
|
2400
|
+
if(isArray || isSizedString)
|
|
2401
|
+
{
|
|
2402
|
+
if(!GetArraySizeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
|
|
2403
|
+
vtblIndex, i, GET_SIZE,
|
|
2404
|
+
dispatchParams, &array_capacity)||
|
|
2405
|
+
!GetArraySizeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
|
|
2406
|
+
vtblIndex, i, GET_LENGTH,
|
|
2407
|
+
dispatchParams, &array_count))
|
|
2408
|
+
goto done;
|
|
2409
|
+
|
|
2410
|
+
if(isArray)
|
|
2411
|
+
{
|
|
2412
|
+
if(array_count &&
|
|
2413
|
+
!XPCConvert::JSArray2Native(ccx, (void**)&dp->val, src,
|
|
2414
|
+
array_count, array_capacity,
|
|
2415
|
+
datum_type,
|
|
2416
|
+
useAllocator,
|
|
2417
|
+
¶m_iid, &err))
|
|
2418
|
+
{
|
|
2419
|
+
// XXX need exception scheme for arrays to indicate bad element
|
|
2420
|
+
ThrowBadParam(err, i, ccx);
|
|
2421
|
+
goto done;
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
else // if(isSizedString)
|
|
2425
|
+
{
|
|
2426
|
+
if(!XPCConvert::JSStringWithSize2Native(ccx,
|
|
2427
|
+
(void*)&dp->val,
|
|
2428
|
+
src,
|
|
2429
|
+
array_count, array_capacity,
|
|
2430
|
+
datum_type, useAllocator,
|
|
2431
|
+
&err))
|
|
2432
|
+
{
|
|
2433
|
+
ThrowBadParam(err, i, ccx);
|
|
2434
|
+
goto done;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
else
|
|
2439
|
+
{
|
|
2440
|
+
if(!XPCConvert::JSData2Native(ccx, &dp->val, src, type,
|
|
2441
|
+
useAllocator, ¶m_iid,
|
|
2442
|
+
&err))
|
|
2443
|
+
{
|
|
2444
|
+
ThrowBadParam(err, i, ccx);
|
|
2445
|
+
goto done;
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
|
|
2452
|
+
// do the invoke
|
|
2453
|
+
{
|
|
2454
|
+
AutoJSSuspendNonMainThreadRequest req(ccx.GetJSContext());
|
|
2455
|
+
invokeResult = NS_InvokeByIndex(callee, vtblIndex, paramCount,
|
|
2456
|
+
dispatchParams);
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
xpcc->SetLastResult(invokeResult);
|
|
2460
|
+
|
|
2461
|
+
if(NS_FAILED(invokeResult))
|
|
2462
|
+
{
|
|
2463
|
+
ThrowBadResult(invokeResult, ccx);
|
|
2464
|
+
goto done;
|
|
2465
|
+
}
|
|
2466
|
+
else if(JS_IsExceptionPending(ccx))
|
|
2467
|
+
{
|
|
2468
|
+
goto done;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
// now we iterate through the native params to gather and convert results
|
|
2472
|
+
for(i = 0; i < paramCount; i++)
|
|
2473
|
+
{
|
|
2474
|
+
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
|
2475
|
+
if(!paramInfo.IsOut() && !paramInfo.IsDipper())
|
|
2476
|
+
continue;
|
|
2477
|
+
|
|
2478
|
+
const nsXPTType& type = paramInfo.GetType();
|
|
2479
|
+
nsXPTCVariant* dp = &dispatchParams[i];
|
|
2480
|
+
jsval v = JSVAL_NULL;
|
|
2481
|
+
AUTO_MARK_JSVAL(ccx, &v);
|
|
2482
|
+
JSUint32 array_count;
|
|
2483
|
+
nsXPTType datum_type;
|
|
2484
|
+
PRBool isArray = type.IsArray();
|
|
2485
|
+
PRBool isSizedString = isArray ?
|
|
2486
|
+
JS_FALSE :
|
|
2487
|
+
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
|
2488
|
+
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
|
2489
|
+
|
|
2490
|
+
if(isArray)
|
|
2491
|
+
{
|
|
2492
|
+
if(NS_FAILED(ifaceInfo->GetTypeForParam(vtblIndex, ¶mInfo, 1,
|
|
2493
|
+
&datum_type)))
|
|
2494
|
+
{
|
|
2495
|
+
Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, ccx);
|
|
2496
|
+
goto done;
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
else
|
|
2500
|
+
datum_type = type;
|
|
2501
|
+
|
|
2502
|
+
if(isArray || isSizedString)
|
|
2503
|
+
{
|
|
2504
|
+
if(!GetArraySizeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
|
|
2505
|
+
vtblIndex, i, GET_LENGTH, dispatchParams,
|
|
2506
|
+
&array_count))
|
|
2507
|
+
goto done;
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
if(datum_type.IsInterfacePointer() &&
|
|
2511
|
+
!GetInterfaceTypeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
|
|
2512
|
+
vtblIndex, i, datum_type, dispatchParams,
|
|
2513
|
+
¶m_iid))
|
|
2514
|
+
goto done;
|
|
2515
|
+
|
|
2516
|
+
if(isArray)
|
|
2517
|
+
{
|
|
2518
|
+
if(!XPCConvert::NativeArray2JS(ccx, &v, (const void**)&dp->val,
|
|
2519
|
+
datum_type, ¶m_iid,
|
|
2520
|
+
array_count, ccx.GetCurrentJSObject(),
|
|
2521
|
+
&err))
|
|
2522
|
+
{
|
|
2523
|
+
// XXX need exception scheme for arrays to indicate bad element
|
|
2524
|
+
ThrowBadParam(err, i, ccx);
|
|
2525
|
+
goto done;
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
else if(isSizedString)
|
|
2529
|
+
{
|
|
2530
|
+
if(!XPCConvert::NativeStringWithSize2JS(ccx, &v,
|
|
2531
|
+
(const void*)&dp->val,
|
|
2532
|
+
datum_type,
|
|
2533
|
+
array_count, &err))
|
|
2534
|
+
{
|
|
2535
|
+
ThrowBadParam(err, i, ccx);
|
|
2536
|
+
goto done;
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
else
|
|
2540
|
+
{
|
|
2541
|
+
if(!XPCConvert::NativeData2JS(ccx, &v, &dp->val, datum_type,
|
|
2542
|
+
¶m_iid,
|
|
2543
|
+
ccx.GetCurrentJSObject(), &err))
|
|
2544
|
+
{
|
|
2545
|
+
ThrowBadParam(err, i, ccx);
|
|
2546
|
+
goto done;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
|
|
2550
|
+
if(paramInfo.IsRetval())
|
|
2551
|
+
{
|
|
2552
|
+
if(!ccx.GetReturnValueWasSet())
|
|
2553
|
+
ccx.SetRetVal(v);
|
|
2554
|
+
}
|
|
2555
|
+
else if(i < argc)
|
|
2556
|
+
{
|
|
2557
|
+
// we actually assured this before doing the invoke
|
|
2558
|
+
NS_ASSERTION(JSVAL_IS_OBJECT(argv[i]), "out var is not object");
|
|
2559
|
+
if(!JS_SetPropertyById(ccx, JSVAL_TO_OBJECT(argv[i]),
|
|
2560
|
+
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &v))
|
|
2561
|
+
{
|
|
2562
|
+
ThrowBadParam(NS_ERROR_XPC_CANT_SET_OUT_VAL, i, ccx);
|
|
2563
|
+
goto done;
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
else
|
|
2567
|
+
{
|
|
2568
|
+
NS_ASSERTION(paramInfo.IsOptional(),
|
|
2569
|
+
"Expected either enough arguments or an optional argument");
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
retval = JS_TRUE;
|
|
2574
|
+
done:
|
|
2575
|
+
// iterate through the params (again!) and clean up
|
|
2576
|
+
// any alloc'd stuff and release wrappers of params
|
|
2577
|
+
if(dispatchParams)
|
|
2578
|
+
{
|
|
2579
|
+
for(i = 0; i < paramCount; i++)
|
|
2580
|
+
{
|
|
2581
|
+
nsXPTCVariant* dp = &dispatchParams[i];
|
|
2582
|
+
void* p = dp->val.p;
|
|
2583
|
+
if(!p)
|
|
2584
|
+
continue;
|
|
2585
|
+
|
|
2586
|
+
if(dp->IsValArray())
|
|
2587
|
+
{
|
|
2588
|
+
// going to have to cleanup the array and perhaps its contents
|
|
2589
|
+
if(dp->IsValAllocated() || dp->IsValInterface())
|
|
2590
|
+
{
|
|
2591
|
+
// we need to figure out how many elements are present.
|
|
2592
|
+
JSUint32 array_count;
|
|
2593
|
+
|
|
2594
|
+
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
|
2595
|
+
if(!GetArraySizeFromParam(ccx, ifaceInfo, methodInfo,
|
|
2596
|
+
paramInfo, vtblIndex,
|
|
2597
|
+
i, GET_LENGTH, dispatchParams,
|
|
2598
|
+
&array_count))
|
|
2599
|
+
{
|
|
2600
|
+
NS_ASSERTION(0,"failed to get array length, we'll leak here");
|
|
2601
|
+
continue;
|
|
2602
|
+
}
|
|
2603
|
+
if(dp->IsValAllocated())
|
|
2604
|
+
{
|
|
2605
|
+
void** a = (void**)p;
|
|
2606
|
+
for(JSUint32 k = 0; k < array_count; k++)
|
|
2607
|
+
{
|
|
2608
|
+
void* o = a[k];
|
|
2609
|
+
if(o) nsMemory::Free(o);
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
else // if(dp->IsValInterface())
|
|
2613
|
+
{
|
|
2614
|
+
nsISupports** a = (nsISupports**)p;
|
|
2615
|
+
for(JSUint32 k = 0; k < array_count; k++)
|
|
2616
|
+
{
|
|
2617
|
+
nsISupports* o = a[k];
|
|
2618
|
+
NS_IF_RELEASE(o);
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
// always free the array itself
|
|
2623
|
+
nsMemory::Free(p);
|
|
2624
|
+
}
|
|
2625
|
+
else if(dp->IsValAllocated())
|
|
2626
|
+
nsMemory::Free(p);
|
|
2627
|
+
else if(dp->IsValInterface())
|
|
2628
|
+
((nsISupports*)p)->Release();
|
|
2629
|
+
else if(dp->IsValDOMString())
|
|
2630
|
+
ccx.DeleteString((nsAString*)p);
|
|
2631
|
+
else if(dp->IsValUTF8String())
|
|
2632
|
+
delete (nsCString*) p;
|
|
2633
|
+
else if(dp->IsValCString())
|
|
2634
|
+
delete (nsCString*) p;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
if (autoStringUsed) {
|
|
2639
|
+
// Our stack based nsAutoString was used, clean it up.
|
|
2640
|
+
|
|
2641
|
+
nsAutoString *s = (nsAutoString*)&autoString;
|
|
2642
|
+
|
|
2643
|
+
s->~nsAutoString();
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
if(dispatchParams && dispatchParams != paramBuffer)
|
|
2647
|
+
delete [] dispatchParams;
|
|
2648
|
+
|
|
2649
|
+
return retval;
|
|
2650
|
+
}
|
|
2651
|
+
|
|
2652
|
+
/***************************************************************************/
|
|
2653
|
+
// interface methods
|
|
2654
|
+
|
|
2655
|
+
/* readonly attribute JSObjectPtr JSObject; */
|
|
2656
|
+
NS_IMETHODIMP XPCWrappedNative::GetJSObject(JSObject * *aJSObject)
|
|
2657
|
+
{
|
|
2658
|
+
*aJSObject = mFlatJSObject;
|
|
2659
|
+
return NS_OK;
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
/* readonly attribute nsISupports Native; */
|
|
2663
|
+
NS_IMETHODIMP XPCWrappedNative::GetNative(nsISupports * *aNative)
|
|
2664
|
+
{
|
|
2665
|
+
// No need to QI here, we already have the correct nsISupports
|
|
2666
|
+
// vtable.
|
|
2667
|
+
*aNative = mIdentity;
|
|
2668
|
+
NS_ADDREF(*aNative);
|
|
2669
|
+
return NS_OK;
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
/* readonly attribute JSObjectPtr JSObjectPrototype; */
|
|
2673
|
+
NS_IMETHODIMP XPCWrappedNative::GetJSObjectPrototype(JSObject * *aJSObjectPrototype)
|
|
2674
|
+
{
|
|
2675
|
+
*aJSObjectPrototype = HasProto() ?
|
|
2676
|
+
GetProto()->GetJSProtoObject() : GetFlatJSObject();
|
|
2677
|
+
return NS_OK;
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
#ifndef XPCONNECT_STANDALONE
|
|
2681
|
+
nsIPrincipal*
|
|
2682
|
+
XPCWrappedNative::GetObjectPrincipal() const
|
|
2683
|
+
{
|
|
2684
|
+
nsIPrincipal* principal = GetScope()->GetPrincipal();
|
|
2685
|
+
#ifdef DEBUG
|
|
2686
|
+
nsCOMPtr<nsIScriptObjectPrincipal> objPrin(do_QueryInterface(mIdentity));
|
|
2687
|
+
NS_ASSERTION(!objPrin || objPrin->GetPrincipal() == principal,
|
|
2688
|
+
"Principal mismatch. Expect bad things to happen");
|
|
2689
|
+
#endif
|
|
2690
|
+
return principal;
|
|
2691
|
+
}
|
|
2692
|
+
#endif
|
|
2693
|
+
|
|
2694
|
+
/* readonly attribute nsIXPConnect XPConnect; */
|
|
2695
|
+
NS_IMETHODIMP XPCWrappedNative::GetXPConnect(nsIXPConnect * *aXPConnect)
|
|
2696
|
+
{
|
|
2697
|
+
if(IsValid())
|
|
2698
|
+
{
|
|
2699
|
+
nsIXPConnect* temp = GetRuntime()->GetXPConnect();
|
|
2700
|
+
NS_IF_ADDREF(temp);
|
|
2701
|
+
*aXPConnect = temp;
|
|
2702
|
+
}
|
|
2703
|
+
else
|
|
2704
|
+
*aXPConnect = nsnull;
|
|
2705
|
+
return NS_OK;
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
/* XPCNativeInterface FindInterfaceWithMember (in JSVal name); */
|
|
2709
|
+
NS_IMETHODIMP XPCWrappedNative::FindInterfaceWithMember(jsval name, nsIInterfaceInfo * *_retval)
|
|
2710
|
+
{
|
|
2711
|
+
XPCNativeInterface* iface;
|
|
2712
|
+
XPCNativeMember* member;
|
|
2713
|
+
|
|
2714
|
+
if(GetSet()->FindMember(name, &member, &iface) && iface)
|
|
2715
|
+
{
|
|
2716
|
+
nsIInterfaceInfo* temp = iface->GetInterfaceInfo();
|
|
2717
|
+
NS_IF_ADDREF(temp);
|
|
2718
|
+
*_retval = temp;
|
|
2719
|
+
}
|
|
2720
|
+
else
|
|
2721
|
+
*_retval = nsnull;
|
|
2722
|
+
return NS_OK;
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
/* XPCNativeInterface FindInterfaceWithName (in JSVal name); */
|
|
2726
|
+
NS_IMETHODIMP XPCWrappedNative::FindInterfaceWithName(jsval name, nsIInterfaceInfo * *_retval)
|
|
2727
|
+
{
|
|
2728
|
+
XPCNativeInterface* iface = GetSet()->FindNamedInterface(name);
|
|
2729
|
+
if(iface)
|
|
2730
|
+
{
|
|
2731
|
+
nsIInterfaceInfo* temp = iface->GetInterfaceInfo();
|
|
2732
|
+
NS_IF_ADDREF(temp);
|
|
2733
|
+
*_retval = temp;
|
|
2734
|
+
}
|
|
2735
|
+
else
|
|
2736
|
+
*_retval = nsnull;
|
|
2737
|
+
return NS_OK;
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2740
|
+
inline nsresult UnexpectedFailure(nsresult rv)
|
|
2741
|
+
{
|
|
2742
|
+
NS_ERROR("This is not supposed to fail!");
|
|
2743
|
+
return rv;
|
|
2744
|
+
}
|
|
2745
|
+
|
|
2746
|
+
/* void refreshPrototype (); */
|
|
2747
|
+
NS_IMETHODIMP XPCWrappedNative::RefreshPrototype()
|
|
2748
|
+
{
|
|
2749
|
+
XPCCallContext ccx(NATIVE_CALLER);
|
|
2750
|
+
if(!ccx.IsValid())
|
|
2751
|
+
return UnexpectedFailure(NS_ERROR_FAILURE);
|
|
2752
|
+
|
|
2753
|
+
if(!HasProto())
|
|
2754
|
+
return NS_OK;
|
|
2755
|
+
|
|
2756
|
+
if(!GetFlatJSObject())
|
|
2757
|
+
return UnexpectedFailure(NS_ERROR_FAILURE);
|
|
2758
|
+
|
|
2759
|
+
AutoMarkingWrappedNativeProtoPtr oldProto(ccx);
|
|
2760
|
+
AutoMarkingWrappedNativeProtoPtr newProto(ccx);
|
|
2761
|
+
|
|
2762
|
+
oldProto = GetProto();
|
|
2763
|
+
|
|
2764
|
+
XPCNativeScriptableInfo *info = oldProto->GetScriptableInfo();
|
|
2765
|
+
XPCNativeScriptableCreateInfo ci(*info);
|
|
2766
|
+
newProto = XPCWrappedNativeProto::GetNewOrUsed(ccx, oldProto->GetScope(),
|
|
2767
|
+
oldProto->GetClassInfo(),
|
|
2768
|
+
&ci,
|
|
2769
|
+
!oldProto->IsShared(),
|
|
2770
|
+
(info->GetJSClass()->flags & JSCLASS_IS_GLOBAL),
|
|
2771
|
+
oldProto->GetOffsetsMasked());
|
|
2772
|
+
if(!newProto)
|
|
2773
|
+
return UnexpectedFailure(NS_ERROR_FAILURE);
|
|
2774
|
+
|
|
2775
|
+
// If nothing needs to change then we're done.
|
|
2776
|
+
|
|
2777
|
+
if(newProto.get() == oldProto.get())
|
|
2778
|
+
return NS_OK;
|
|
2779
|
+
|
|
2780
|
+
if(!JS_SetPrototype(ccx, GetFlatJSObject(), newProto->GetJSProtoObject()))
|
|
2781
|
+
return UnexpectedFailure(NS_ERROR_FAILURE);
|
|
2782
|
+
|
|
2783
|
+
SetProto(newProto);
|
|
2784
|
+
|
|
2785
|
+
if(mScriptableInfo == oldProto->GetScriptableInfo())
|
|
2786
|
+
mScriptableInfo = newProto->GetScriptableInfo();
|
|
2787
|
+
|
|
2788
|
+
return NS_OK;
|
|
2789
|
+
}
|
|
2790
|
+
|
|
2791
|
+
NS_IMETHODIMP XPCWrappedNative::GetSecurityInfoAddress(void*** securityInfoAddrPtr)
|
|
2792
|
+
{
|
|
2793
|
+
NS_ENSURE_ARG_POINTER(securityInfoAddrPtr);
|
|
2794
|
+
*securityInfoAddrPtr = GetSecurityInfoAddr();
|
|
2795
|
+
return NS_OK;
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
/* void debugDump (in short depth); */
|
|
2799
|
+
NS_IMETHODIMP XPCWrappedNative::DebugDump(PRInt16 depth)
|
|
2800
|
+
{
|
|
2801
|
+
#ifdef DEBUG
|
|
2802
|
+
depth-- ;
|
|
2803
|
+
XPC_LOG_ALWAYS(("XPCWrappedNative @ %x with mRefCnt = %d", this, mRefCnt.get()));
|
|
2804
|
+
XPC_LOG_INDENT();
|
|
2805
|
+
|
|
2806
|
+
if(HasProto())
|
|
2807
|
+
{
|
|
2808
|
+
XPCWrappedNativeProto* proto = GetProto();
|
|
2809
|
+
if(depth && proto)
|
|
2810
|
+
proto->DebugDump(depth);
|
|
2811
|
+
else
|
|
2812
|
+
XPC_LOG_ALWAYS(("mMaybeProto @ %x", proto));
|
|
2813
|
+
}
|
|
2814
|
+
else
|
|
2815
|
+
XPC_LOG_ALWAYS(("Scope @ %x", GetScope()));
|
|
2816
|
+
|
|
2817
|
+
if(depth && mSet)
|
|
2818
|
+
mSet->DebugDump(depth);
|
|
2819
|
+
else
|
|
2820
|
+
XPC_LOG_ALWAYS(("mSet @ %x", mSet));
|
|
2821
|
+
|
|
2822
|
+
XPC_LOG_ALWAYS(("mFlatJSObject of %x", mFlatJSObject));
|
|
2823
|
+
XPC_LOG_ALWAYS(("mIdentity of %x", mIdentity));
|
|
2824
|
+
XPC_LOG_ALWAYS(("mScriptableInfo @ %x", mScriptableInfo));
|
|
2825
|
+
|
|
2826
|
+
if(depth && mScriptableInfo)
|
|
2827
|
+
{
|
|
2828
|
+
XPC_LOG_INDENT();
|
|
2829
|
+
XPC_LOG_ALWAYS(("mScriptable @ %x", mScriptableInfo->GetCallback()));
|
|
2830
|
+
XPC_LOG_ALWAYS(("mFlags of %x", (PRUint32)mScriptableInfo->GetFlags()));
|
|
2831
|
+
XPC_LOG_ALWAYS(("mJSClass @ %x", mScriptableInfo->GetJSClass()));
|
|
2832
|
+
XPC_LOG_OUTDENT();
|
|
2833
|
+
}
|
|
2834
|
+
XPC_LOG_OUTDENT();
|
|
2835
|
+
#endif
|
|
2836
|
+
return NS_OK;
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2839
|
+
/***************************************************************************/
|
|
2840
|
+
|
|
2841
|
+
char*
|
|
2842
|
+
XPCWrappedNative::ToString(XPCCallContext& ccx,
|
|
2843
|
+
XPCWrappedNativeTearOff* to /* = nsnull */ ) const
|
|
2844
|
+
{
|
|
2845
|
+
#ifdef DEBUG
|
|
2846
|
+
# define FMT_ADDR " @ 0x%p"
|
|
2847
|
+
# define FMT_STR(str) str
|
|
2848
|
+
# define PARAM_ADDR(w) , w
|
|
2849
|
+
#else
|
|
2850
|
+
# define FMT_ADDR ""
|
|
2851
|
+
# define FMT_STR(str)
|
|
2852
|
+
# define PARAM_ADDR(w)
|
|
2853
|
+
#endif
|
|
2854
|
+
|
|
2855
|
+
char* sz = nsnull;
|
|
2856
|
+
char* name = nsnull;
|
|
2857
|
+
|
|
2858
|
+
XPCNativeScriptableInfo* si = GetScriptableInfo();
|
|
2859
|
+
if(si)
|
|
2860
|
+
name = JS_smprintf("%s", si->GetJSClass()->name);
|
|
2861
|
+
if(to)
|
|
2862
|
+
{
|
|
2863
|
+
const char* fmt = name ? " (%s)" : "%s";
|
|
2864
|
+
name = JS_sprintf_append(name, fmt,
|
|
2865
|
+
to->GetInterface()->GetNameString());
|
|
2866
|
+
}
|
|
2867
|
+
else if(!name)
|
|
2868
|
+
{
|
|
2869
|
+
XPCNativeSet* set = GetSet();
|
|
2870
|
+
XPCNativeInterface** array = set->GetInterfaceArray();
|
|
2871
|
+
PRUint16 count = set->GetInterfaceCount();
|
|
2872
|
+
|
|
2873
|
+
if(count == 1)
|
|
2874
|
+
name = JS_sprintf_append(name, "%s", array[0]->GetNameString());
|
|
2875
|
+
else if(count == 2 &&
|
|
2876
|
+
array[0] == XPCNativeInterface::GetISupports(ccx))
|
|
2877
|
+
{
|
|
2878
|
+
name = JS_sprintf_append(name, "%s", array[1]->GetNameString());
|
|
2879
|
+
}
|
|
2880
|
+
else
|
|
2881
|
+
{
|
|
2882
|
+
for(PRUint16 i = 0; i < count; i++)
|
|
2883
|
+
{
|
|
2884
|
+
const char* fmt = (i == 0) ?
|
|
2885
|
+
"(%s" : (i == count-1) ?
|
|
2886
|
+
", %s)" : ", %s";
|
|
2887
|
+
name = JS_sprintf_append(name, fmt,
|
|
2888
|
+
array[i]->GetNameString());
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2893
|
+
if(!name)
|
|
2894
|
+
{
|
|
2895
|
+
return nsnull;
|
|
2896
|
+
}
|
|
2897
|
+
const char* fmt = "[xpconnect wrapped %s" FMT_ADDR FMT_STR(" (native")
|
|
2898
|
+
FMT_ADDR FMT_STR(")") "]";
|
|
2899
|
+
if(si)
|
|
2900
|
+
{
|
|
2901
|
+
fmt = "[object %s" FMT_ADDR FMT_STR(" (native") FMT_ADDR FMT_STR(")") "]";
|
|
2902
|
+
}
|
|
2903
|
+
sz = JS_smprintf(fmt, name PARAM_ADDR(this) PARAM_ADDR(mIdentity));
|
|
2904
|
+
|
|
2905
|
+
JS_smprintf_free(name);
|
|
2906
|
+
|
|
2907
|
+
|
|
2908
|
+
return sz;
|
|
2909
|
+
|
|
2910
|
+
#undef FMT_ADDR
|
|
2911
|
+
#undef PARAM_ADDR
|
|
2912
|
+
}
|
|
2913
|
+
|
|
2914
|
+
/***************************************************************************/
|
|
2915
|
+
|
|
2916
|
+
#ifdef XPC_DETECT_LEADING_UPPERCASE_ACCESS_ERRORS
|
|
2917
|
+
// static
|
|
2918
|
+
void
|
|
2919
|
+
XPCWrappedNative::HandlePossibleNameCaseError(JSContext* cx,
|
|
2920
|
+
XPCNativeSet* set,
|
|
2921
|
+
XPCNativeInterface* iface,
|
|
2922
|
+
jsval name)
|
|
2923
|
+
{
|
|
2924
|
+
XPCCallContext ccx(JS_CALLER, cx);
|
|
2925
|
+
HandlePossibleNameCaseError(ccx, set, iface, name);
|
|
2926
|
+
}
|
|
2927
|
+
|
|
2928
|
+
// static
|
|
2929
|
+
void
|
|
2930
|
+
XPCWrappedNative::HandlePossibleNameCaseError(XPCCallContext& ccx,
|
|
2931
|
+
XPCNativeSet* set,
|
|
2932
|
+
XPCNativeInterface* iface,
|
|
2933
|
+
jsval name)
|
|
2934
|
+
{
|
|
2935
|
+
if(!ccx.IsValid())
|
|
2936
|
+
return;
|
|
2937
|
+
|
|
2938
|
+
JSString* oldJSStr;
|
|
2939
|
+
JSString* newJSStr;
|
|
2940
|
+
PRUnichar* oldStr;
|
|
2941
|
+
PRUnichar* newStr;
|
|
2942
|
+
XPCNativeMember* member;
|
|
2943
|
+
XPCNativeInterface* localIface;
|
|
2944
|
+
|
|
2945
|
+
/* PRUnichar->char->PRUnichar hack is to avoid pulling in i18n code. */
|
|
2946
|
+
if(JSVAL_IS_STRING(name) &&
|
|
2947
|
+
nsnull != (oldJSStr = JSVAL_TO_STRING(name)) &&
|
|
2948
|
+
nsnull != (oldStr = (PRUnichar*) JS_GetStringChars(oldJSStr)) &&
|
|
2949
|
+
oldStr[0] != 0 &&
|
|
2950
|
+
oldStr[0] >> 8 == 0 &&
|
|
2951
|
+
nsCRT::IsUpper((char)oldStr[0]) &&
|
|
2952
|
+
nsnull != (newStr = nsCRT::strdup(oldStr)))
|
|
2953
|
+
{
|
|
2954
|
+
newStr[0] = (PRUnichar) nsCRT::ToLower((char)newStr[0]);
|
|
2955
|
+
newJSStr = JS_NewUCStringCopyZ(ccx, (const jschar*)newStr);
|
|
2956
|
+
nsCRT::free(newStr);
|
|
2957
|
+
if(newJSStr && (set ?
|
|
2958
|
+
set->FindMember(STRING_TO_JSVAL(newJSStr), &member, &localIface) :
|
|
2959
|
+
NS_PTR_TO_INT32(iface->FindMember(STRING_TO_JSVAL(newJSStr)))))
|
|
2960
|
+
{
|
|
2961
|
+
// found it!
|
|
2962
|
+
const char* ifaceName = set ?
|
|
2963
|
+
localIface->GetNameString() :
|
|
2964
|
+
iface->GetNameString();
|
|
2965
|
+
const char* goodName = JS_GetStringBytes(newJSStr);
|
|
2966
|
+
const char* badName = JS_GetStringBytes(oldJSStr);
|
|
2967
|
+
char* locationStr = nsnull;
|
|
2968
|
+
|
|
2969
|
+
nsIException* e = nsnull;
|
|
2970
|
+
nsXPCException::NewException("", NS_OK, nsnull, nsnull, &e);
|
|
2971
|
+
|
|
2972
|
+
if(e)
|
|
2973
|
+
{
|
|
2974
|
+
nsresult rv;
|
|
2975
|
+
nsCOMPtr<nsIStackFrame> loc = nsnull;
|
|
2976
|
+
rv = e->GetLocation(getter_AddRefs(loc));
|
|
2977
|
+
if(NS_SUCCEEDED(rv) && loc) {
|
|
2978
|
+
loc->ToString(&locationStr); // failure here leaves it nsnull.
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2982
|
+
if(locationStr && ifaceName && goodName && badName )
|
|
2983
|
+
{
|
|
2984
|
+
printf("**************************************************\n"
|
|
2985
|
+
"ERROR: JS code at [%s]\n"
|
|
2986
|
+
"tried to access nonexistent property called\n"
|
|
2987
|
+
"\'%s\' on interface of type \'%s\'.\n"
|
|
2988
|
+
"That interface does however have a property called\n"
|
|
2989
|
+
"\'%s\'. Did you mean to access that lowercase property?\n"
|
|
2990
|
+
"Please fix the JS code as appropriate.\n"
|
|
2991
|
+
"**************************************************\n",
|
|
2992
|
+
locationStr, badName, ifaceName, goodName);
|
|
2993
|
+
}
|
|
2994
|
+
if(locationStr)
|
|
2995
|
+
nsMemory::Free(locationStr);
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
#endif
|
|
3000
|
+
|
|
3001
|
+
#ifdef XPC_CHECK_CLASSINFO_CLAIMS
|
|
3002
|
+
static void DEBUG_CheckClassInfoClaims(XPCWrappedNative* wrapper)
|
|
3003
|
+
{
|
|
3004
|
+
if(!wrapper || !wrapper->GetClassInfo())
|
|
3005
|
+
return;
|
|
3006
|
+
|
|
3007
|
+
nsISupports* obj = wrapper->GetIdentityObject();
|
|
3008
|
+
XPCNativeSet* set = wrapper->GetSet();
|
|
3009
|
+
PRUint16 count = set->GetInterfaceCount();
|
|
3010
|
+
for(PRUint16 i = 0; i < count; i++)
|
|
3011
|
+
{
|
|
3012
|
+
nsIClassInfo* clsInfo = wrapper->GetClassInfo();
|
|
3013
|
+
XPCNativeInterface* iface = set->GetInterfaceAt(i);
|
|
3014
|
+
nsIInterfaceInfo* info = iface->GetInterfaceInfo();
|
|
3015
|
+
const nsIID* iid;
|
|
3016
|
+
nsISupports* ptr;
|
|
3017
|
+
|
|
3018
|
+
info->GetIIDShared(&iid);
|
|
3019
|
+
nsresult rv = obj->QueryInterface(*iid, (void**)&ptr);
|
|
3020
|
+
if(NS_SUCCEEDED(rv))
|
|
3021
|
+
{
|
|
3022
|
+
NS_RELEASE(ptr);
|
|
3023
|
+
continue;
|
|
3024
|
+
}
|
|
3025
|
+
if(rv == NS_ERROR_OUT_OF_MEMORY)
|
|
3026
|
+
continue;
|
|
3027
|
+
|
|
3028
|
+
// Houston, We have a problem...
|
|
3029
|
+
|
|
3030
|
+
char* className = nsnull;
|
|
3031
|
+
char* contractID = nsnull;
|
|
3032
|
+
const char* interfaceName;
|
|
3033
|
+
|
|
3034
|
+
info->GetNameShared(&interfaceName);
|
|
3035
|
+
clsInfo->GetContractID(&contractID);
|
|
3036
|
+
if(wrapper->GetScriptableInfo())
|
|
3037
|
+
{
|
|
3038
|
+
wrapper->GetScriptableInfo()->GetCallback()->
|
|
3039
|
+
GetClassName(&className);
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
|
|
3043
|
+
printf("\n!!! Object's nsIClassInfo lies about its interfaces!!!\n"
|
|
3044
|
+
" classname: %s \n"
|
|
3045
|
+
" contractid: %s \n"
|
|
3046
|
+
" unimplemented interface name: %s\n\n",
|
|
3047
|
+
className ? className : "<unknown>",
|
|
3048
|
+
contractID ? contractID : "<unknown>",
|
|
3049
|
+
interfaceName);
|
|
3050
|
+
|
|
3051
|
+
#ifdef XPC_ASSERT_CLASSINFO_CLAIMS
|
|
3052
|
+
NS_ERROR("Fix this QueryInterface or nsIClassInfo");
|
|
3053
|
+
#endif
|
|
3054
|
+
|
|
3055
|
+
if(className)
|
|
3056
|
+
nsMemory::Free(className);
|
|
3057
|
+
if(contractID)
|
|
3058
|
+
nsMemory::Free(contractID);
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
#endif
|
|
3062
|
+
|
|
3063
|
+
#ifdef XPC_REPORT_SHADOWED_WRAPPED_NATIVE_MEMBERS
|
|
3064
|
+
static void DEBUG_PrintShadowObjectInfo(const char* header,
|
|
3065
|
+
XPCNativeSet* set,
|
|
3066
|
+
XPCWrappedNative* wrapper,
|
|
3067
|
+
XPCWrappedNativeProto* proto)
|
|
3068
|
+
|
|
3069
|
+
{
|
|
3070
|
+
if(header)
|
|
3071
|
+
printf("%s\n", header);
|
|
3072
|
+
|
|
3073
|
+
printf(" XPCNativeSet @ 0x%p for the class:\n", (void*)set);
|
|
3074
|
+
|
|
3075
|
+
char* className = nsnull;
|
|
3076
|
+
char* contractID = nsnull;
|
|
3077
|
+
|
|
3078
|
+
nsIClassInfo* clsInfo = proto ? proto->GetClassInfo() : nsnull;
|
|
3079
|
+
if(clsInfo)
|
|
3080
|
+
clsInfo->GetContractID(&contractID);
|
|
3081
|
+
|
|
3082
|
+
XPCNativeScriptableInfo* si = wrapper ?
|
|
3083
|
+
wrapper->GetScriptableInfo() :
|
|
3084
|
+
proto->GetScriptableInfo();
|
|
3085
|
+
if(si)
|
|
3086
|
+
si->GetCallback()->GetClassName(&className);
|
|
3087
|
+
|
|
3088
|
+
printf(" classname: %s \n"
|
|
3089
|
+
" contractid: %s \n",
|
|
3090
|
+
className ? className : "<unknown>",
|
|
3091
|
+
contractID ? contractID : "<unknown>");
|
|
3092
|
+
|
|
3093
|
+
if(className)
|
|
3094
|
+
nsMemory::Free(className);
|
|
3095
|
+
if(contractID)
|
|
3096
|
+
nsMemory::Free(contractID);
|
|
3097
|
+
|
|
3098
|
+
printf(" claims to implement interfaces:\n");
|
|
3099
|
+
|
|
3100
|
+
PRUint16 count = set->GetInterfaceCount();
|
|
3101
|
+
for(PRUint16 i = 0; i < count; i++)
|
|
3102
|
+
{
|
|
3103
|
+
XPCNativeInterface* iface = set->GetInterfaceAt(i);
|
|
3104
|
+
nsIInterfaceInfo* info = iface->GetInterfaceInfo();
|
|
3105
|
+
const char* interfaceName;
|
|
3106
|
+
info->GetNameShared(&interfaceName);
|
|
3107
|
+
printf(" %s\n", interfaceName);
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
|
|
3111
|
+
static void ReportSingleMember(jsval ifaceName,
|
|
3112
|
+
jsval memberName)
|
|
3113
|
+
{
|
|
3114
|
+
if(JSVAL_IS_STRING(memberName))
|
|
3115
|
+
printf("%s::%s", JS_GetStringBytes(JSVAL_TO_STRING(ifaceName)),
|
|
3116
|
+
JS_GetStringBytes(JSVAL_TO_STRING(memberName)));
|
|
3117
|
+
else
|
|
3118
|
+
printf("%s", JS_GetStringBytes(JSVAL_TO_STRING(ifaceName)));
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
static void ShowHeader(JSBool* printedHeader,
|
|
3122
|
+
const char* header,
|
|
3123
|
+
XPCNativeSet* set,
|
|
3124
|
+
XPCWrappedNative* wrapper,
|
|
3125
|
+
XPCWrappedNativeProto* proto)
|
|
3126
|
+
{
|
|
3127
|
+
if(!*printedHeader)
|
|
3128
|
+
{
|
|
3129
|
+
DEBUG_PrintShadowObjectInfo(header, set, wrapper, proto);
|
|
3130
|
+
*printedHeader = JS_TRUE;
|
|
3131
|
+
}
|
|
3132
|
+
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3135
|
+
static void ShowOneShadow(jsval ifaceName1,
|
|
3136
|
+
jsval memberName1,
|
|
3137
|
+
jsval ifaceName2,
|
|
3138
|
+
jsval memberName2)
|
|
3139
|
+
{
|
|
3140
|
+
ReportSingleMember(ifaceName1, memberName1);
|
|
3141
|
+
printf(" shadows ");
|
|
3142
|
+
ReportSingleMember(ifaceName2, memberName2);
|
|
3143
|
+
printf("\n");
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3146
|
+
static void ShowDuplicateInterface(jsval ifaceName)
|
|
3147
|
+
{
|
|
3148
|
+
printf(" ! %s appears twice in the nsIClassInfo interface set!\n",
|
|
3149
|
+
JS_GetStringBytes(JSVAL_TO_STRING(ifaceName)));
|
|
3150
|
+
}
|
|
3151
|
+
|
|
3152
|
+
static JSBool InterfacesAreRelated(XPCNativeInterface* iface1,
|
|
3153
|
+
XPCNativeInterface* iface2)
|
|
3154
|
+
{
|
|
3155
|
+
nsIInterfaceInfo* info1 = iface1->GetInterfaceInfo();
|
|
3156
|
+
nsIInterfaceInfo* info2 = iface2->GetInterfaceInfo();
|
|
3157
|
+
|
|
3158
|
+
NS_ASSERTION(info1 != info2, "should not have different iface!");
|
|
3159
|
+
|
|
3160
|
+
PRBool match;
|
|
3161
|
+
|
|
3162
|
+
return
|
|
3163
|
+
(NS_SUCCEEDED(info1->HasAncestor(iface2->GetIID(), &match)) && match) ||
|
|
3164
|
+
(NS_SUCCEEDED(info2->HasAncestor(iface1->GetIID(), &match)) && match);
|
|
3165
|
+
}
|
|
3166
|
+
|
|
3167
|
+
static JSBool MembersAreTheSame(XPCNativeInterface* iface1,
|
|
3168
|
+
PRUint16 memberIndex1,
|
|
3169
|
+
XPCNativeInterface* iface2,
|
|
3170
|
+
PRUint16 memberIndex2)
|
|
3171
|
+
{
|
|
3172
|
+
nsIInterfaceInfo* info1 = iface1->GetInterfaceInfo();
|
|
3173
|
+
nsIInterfaceInfo* info2 = iface2->GetInterfaceInfo();
|
|
3174
|
+
|
|
3175
|
+
XPCNativeMember* member1 = iface1->GetMemberAt(memberIndex1);
|
|
3176
|
+
XPCNativeMember* member2 = iface2->GetMemberAt(memberIndex2);
|
|
3177
|
+
|
|
3178
|
+
PRUint16 index1 = member1->GetIndex();
|
|
3179
|
+
PRUint16 index2 = member2->GetIndex();
|
|
3180
|
+
|
|
3181
|
+
// If they are both constants, then we'll just be sure that they are equivalent.
|
|
3182
|
+
|
|
3183
|
+
if(member1->IsConstant())
|
|
3184
|
+
{
|
|
3185
|
+
if(!member2->IsConstant())
|
|
3186
|
+
return JS_FALSE;
|
|
3187
|
+
|
|
3188
|
+
const nsXPTConstant* constant1;
|
|
3189
|
+
const nsXPTConstant* constant2;
|
|
3190
|
+
|
|
3191
|
+
return NS_SUCCEEDED(info1->GetConstant(index1, &constant1)) &&
|
|
3192
|
+
NS_SUCCEEDED(info2->GetConstant(index2, &constant2)) &&
|
|
3193
|
+
constant1->GetType() == constant2->GetType() &&
|
|
3194
|
+
constant1->GetValue() == constant2->GetValue();
|
|
3195
|
+
}
|
|
3196
|
+
|
|
3197
|
+
// Else we make sure they are of the same 'type' and return true only if
|
|
3198
|
+
// they are inherited from the same interface.
|
|
3199
|
+
|
|
3200
|
+
if(member1->IsMethod() != member2->IsMethod() ||
|
|
3201
|
+
member1->IsWritableAttribute() != member2->IsWritableAttribute() ||
|
|
3202
|
+
member1->IsReadOnlyAttribute() != member2->IsReadOnlyAttribute())
|
|
3203
|
+
{
|
|
3204
|
+
return JS_FALSE;
|
|
3205
|
+
}
|
|
3206
|
+
|
|
3207
|
+
const nsXPTMethodInfo* mi1;
|
|
3208
|
+
const nsXPTMethodInfo* mi2;
|
|
3209
|
+
|
|
3210
|
+
return NS_SUCCEEDED(info1->GetMethodInfo(index1, &mi1)) &&
|
|
3211
|
+
NS_SUCCEEDED(info2->GetMethodInfo(index2, &mi2)) &&
|
|
3212
|
+
mi1 == mi2;
|
|
3213
|
+
}
|
|
3214
|
+
|
|
3215
|
+
void DEBUG_ReportShadowedMembers(XPCNativeSet* set,
|
|
3216
|
+
XPCWrappedNative* wrapper,
|
|
3217
|
+
XPCWrappedNativeProto* proto)
|
|
3218
|
+
{
|
|
3219
|
+
// NOTE: Either wrapper or proto could be null...
|
|
3220
|
+
|
|
3221
|
+
if(!(proto || wrapper) || !set || set->GetInterfaceCount() < 2)
|
|
3222
|
+
return;
|
|
3223
|
+
|
|
3224
|
+
NS_ASSERTION(proto || wrapper, "bad param!");
|
|
3225
|
+
XPCJSRuntime* rt = proto ? proto->GetRuntime() : wrapper->GetRuntime();
|
|
3226
|
+
|
|
3227
|
+
// a quicky hack to avoid reporting info for the same set too often
|
|
3228
|
+
static int nextSeenSet = 0;
|
|
3229
|
+
static const int MAX_SEEN_SETS = 128;
|
|
3230
|
+
static XPCNativeSet* SeenSets[MAX_SEEN_SETS];
|
|
3231
|
+
for(int seen = 0; seen < MAX_SEEN_SETS; seen++)
|
|
3232
|
+
if(set == SeenSets[seen])
|
|
3233
|
+
return;
|
|
3234
|
+
SeenSets[nextSeenSet] = set;
|
|
3235
|
+
|
|
3236
|
+
#ifdef off_DEBUG_jband
|
|
3237
|
+
static int seenCount = 0;
|
|
3238
|
+
printf("--- adding SeenSets[%d] = 0x%p\n", nextSeenSet, set);
|
|
3239
|
+
DEBUG_PrintShadowObjectInfo(nsnull, set, wrapper, proto);
|
|
3240
|
+
#endif
|
|
3241
|
+
int localNext = nextSeenSet+1;
|
|
3242
|
+
nextSeenSet = localNext < MAX_SEEN_SETS ? localNext : 0;
|
|
3243
|
+
|
|
3244
|
+
XPCNativeScriptableInfo* si = wrapper ?
|
|
3245
|
+
wrapper->GetScriptableInfo() :
|
|
3246
|
+
proto->GetScriptableInfo();
|
|
3247
|
+
|
|
3248
|
+
// We just want to skip some classes...
|
|
3249
|
+
if(si)
|
|
3250
|
+
{
|
|
3251
|
+
// Add any classnames to skip to this (null terminated) array...
|
|
3252
|
+
static const char* skipClasses[] = {
|
|
3253
|
+
"Window",
|
|
3254
|
+
"HTMLDocument",
|
|
3255
|
+
"HTMLCollection",
|
|
3256
|
+
"Event",
|
|
3257
|
+
"ChromeWindow",
|
|
3258
|
+
nsnull
|
|
3259
|
+
};
|
|
3260
|
+
|
|
3261
|
+
static PRBool warned = JS_FALSE;
|
|
3262
|
+
if(!warned)
|
|
3263
|
+
{
|
|
3264
|
+
printf("!!! XPConnect won't warn about Shadowed Members of...\n ");
|
|
3265
|
+
for(const char** name = skipClasses; *name; name++)
|
|
3266
|
+
printf("%s %s", name == skipClasses ? "" : ",", *name);
|
|
3267
|
+
printf("\n");
|
|
3268
|
+
warned = JS_TRUE;
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
PRBool quit = JS_FALSE;
|
|
3272
|
+
char* className = nsnull;
|
|
3273
|
+
si->GetCallback()->GetClassName(&className);
|
|
3274
|
+
if(className)
|
|
3275
|
+
{
|
|
3276
|
+
for(const char** name = skipClasses; *name; name++)
|
|
3277
|
+
{
|
|
3278
|
+
if(!strcmp(*name, className))
|
|
3279
|
+
{
|
|
3280
|
+
quit = JS_TRUE;
|
|
3281
|
+
break;
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
nsMemory::Free(className);
|
|
3285
|
+
}
|
|
3286
|
+
if(quit)
|
|
3287
|
+
return;
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3290
|
+
const char header[] =
|
|
3291
|
+
"!!!Object wrapped by XPConnect has members whose names shadow each other!!!";
|
|
3292
|
+
|
|
3293
|
+
JSBool printedHeader = JS_FALSE;
|
|
3294
|
+
|
|
3295
|
+
jsval QIName = rt->GetStringJSVal(XPCJSRuntime::IDX_QUERY_INTERFACE);
|
|
3296
|
+
|
|
3297
|
+
PRUint16 ifaceCount = set->GetInterfaceCount();
|
|
3298
|
+
PRUint16 i, j, k, m;
|
|
3299
|
+
|
|
3300
|
+
// First look for duplicate interface entries
|
|
3301
|
+
|
|
3302
|
+
for(i = 0; i < ifaceCount; i++)
|
|
3303
|
+
{
|
|
3304
|
+
XPCNativeInterface* ifaceOuter = set->GetInterfaceAt(i);
|
|
3305
|
+
for(k = i+1; k < ifaceCount; k++)
|
|
3306
|
+
{
|
|
3307
|
+
XPCNativeInterface* ifaceInner = set->GetInterfaceAt(k);
|
|
3308
|
+
if(ifaceInner == ifaceOuter)
|
|
3309
|
+
{
|
|
3310
|
+
ShowHeader(&printedHeader, header, set, wrapper, proto);
|
|
3311
|
+
ShowDuplicateInterface(ifaceOuter->GetName());
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
|
|
3316
|
+
// Now scan for shadowing names
|
|
3317
|
+
|
|
3318
|
+
for(i = 0; i < ifaceCount; i++)
|
|
3319
|
+
{
|
|
3320
|
+
XPCNativeInterface* ifaceOuter = set->GetInterfaceAt(i);
|
|
3321
|
+
jsval ifaceOuterName = ifaceOuter->GetName();
|
|
3322
|
+
|
|
3323
|
+
PRUint16 memberCountOuter = ifaceOuter->GetMemberCount();
|
|
3324
|
+
for(j = 0; j < memberCountOuter; j++)
|
|
3325
|
+
{
|
|
3326
|
+
XPCNativeMember* memberOuter = ifaceOuter->GetMemberAt(j);
|
|
3327
|
+
jsval memberOuterName = memberOuter->GetName();
|
|
3328
|
+
|
|
3329
|
+
if(memberOuterName == QIName)
|
|
3330
|
+
continue;
|
|
3331
|
+
|
|
3332
|
+
for(k = i+1; k < ifaceCount; k++)
|
|
3333
|
+
{
|
|
3334
|
+
XPCNativeInterface* ifaceInner = set->GetInterfaceAt(k);
|
|
3335
|
+
jsval ifaceInnerName = ifaceInner->GetName();
|
|
3336
|
+
|
|
3337
|
+
// Reported elsewhere.
|
|
3338
|
+
if(ifaceInner == ifaceOuter)
|
|
3339
|
+
continue;
|
|
3340
|
+
|
|
3341
|
+
// We consider this not worth reporting because callers will
|
|
3342
|
+
// almost certainly be getting what they expect.
|
|
3343
|
+
if(InterfacesAreRelated(ifaceInner, ifaceOuter))
|
|
3344
|
+
continue;
|
|
3345
|
+
|
|
3346
|
+
if(ifaceInnerName == memberOuterName)
|
|
3347
|
+
{
|
|
3348
|
+
ShowHeader(&printedHeader, header, set, wrapper, proto);
|
|
3349
|
+
ShowOneShadow(ifaceInnerName, JSVAL_NULL,
|
|
3350
|
+
ifaceOuterName, memberOuterName);
|
|
3351
|
+
}
|
|
3352
|
+
|
|
3353
|
+
PRUint16 memberCountInner = ifaceInner->GetMemberCount();
|
|
3354
|
+
|
|
3355
|
+
for(m = 0; m < memberCountInner; m++)
|
|
3356
|
+
{
|
|
3357
|
+
XPCNativeMember* memberInner = ifaceInner->GetMemberAt(m);
|
|
3358
|
+
jsval memberInnerName = memberInner->GetName();
|
|
3359
|
+
|
|
3360
|
+
if(memberInnerName == QIName)
|
|
3361
|
+
continue;
|
|
3362
|
+
|
|
3363
|
+
if(memberOuterName == memberInnerName &&
|
|
3364
|
+
!MembersAreTheSame(ifaceOuter, j, ifaceInner, m))
|
|
3365
|
+
|
|
3366
|
+
{
|
|
3367
|
+
ShowHeader(&printedHeader, header, set, wrapper, proto);
|
|
3368
|
+
ShowOneShadow(ifaceOuterName, memberOuterName,
|
|
3369
|
+
ifaceInnerName, memberInnerName);
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
#endif
|
|
3377
|
+
|
|
3378
|
+
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
|
|
3379
|
+
void DEBUG_ReportWrapperThreadSafetyError(XPCCallContext& ccx,
|
|
3380
|
+
const char* msg,
|
|
3381
|
+
const XPCWrappedNative* wrapper)
|
|
3382
|
+
{
|
|
3383
|
+
XPCPerThreadData* tls = ccx.GetThreadData();
|
|
3384
|
+
if(1 != tls->IncrementWrappedNativeThreadsafetyReportDepth())
|
|
3385
|
+
return;
|
|
3386
|
+
|
|
3387
|
+
printf("---------------------------------------------------------------\n");
|
|
3388
|
+
printf("!!!!! XPConnect wrapper thread use error...\n");
|
|
3389
|
+
|
|
3390
|
+
char* wrapperDump = wrapper->ToString(ccx);
|
|
3391
|
+
if(wrapperDump)
|
|
3392
|
+
{
|
|
3393
|
+
printf(" %s\n wrapper: %s\n", msg, wrapperDump);
|
|
3394
|
+
JS_smprintf_free(wrapperDump);
|
|
3395
|
+
}
|
|
3396
|
+
else
|
|
3397
|
+
printf(" %s\n wrapper @ 0x%p\n", msg, (void *)wrapper);
|
|
3398
|
+
|
|
3399
|
+
printf(" JS call stack...\n");
|
|
3400
|
+
xpc_DumpJSStack(ccx, JS_TRUE, JS_TRUE, JS_TRUE);
|
|
3401
|
+
printf("---------------------------------------------------------------\n");
|
|
3402
|
+
|
|
3403
|
+
tls->ClearWrappedNativeThreadsafetyReportDepth();
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3406
|
+
void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper)
|
|
3407
|
+
{
|
|
3408
|
+
XPCWrappedNativeProto* proto = wrapper->GetProto();
|
|
3409
|
+
if(proto && proto->ClassIsThreadSafe())
|
|
3410
|
+
return;
|
|
3411
|
+
|
|
3412
|
+
PRBool val;
|
|
3413
|
+
if(proto && proto->ClassIsMainThreadOnly())
|
|
3414
|
+
{
|
|
3415
|
+
if(!NS_IsMainThread())
|
|
3416
|
+
{
|
|
3417
|
+
XPCCallContext ccx(NATIVE_CALLER);
|
|
3418
|
+
DEBUG_ReportWrapperThreadSafetyError(ccx,
|
|
3419
|
+
"Main Thread Only wrapper accessed on another thread", wrapper);
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
else if(NS_SUCCEEDED(wrapper->mThread->IsOnCurrentThread(&val)) && !val)
|
|
3423
|
+
{
|
|
3424
|
+
XPCCallContext ccx(NATIVE_CALLER);
|
|
3425
|
+
DEBUG_ReportWrapperThreadSafetyError(ccx,
|
|
3426
|
+
"XPConnect WrappedNative is being accessed on multiple threads but "
|
|
3427
|
+
"the underlying native xpcom object does not have a "
|
|
3428
|
+
"nsIClassInfo with the 'THREADSAFE' flag set", wrapper);
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
#endif
|
|
3432
|
+
|
|
3433
|
+
NS_IMPL_THREADSAFE_ISUPPORTS1(XPCJSObjectHolder, nsIXPConnectJSObjectHolder)
|
|
3434
|
+
|
|
3435
|
+
NS_IMETHODIMP
|
|
3436
|
+
XPCJSObjectHolder::GetJSObject(JSObject** aJSObj)
|
|
3437
|
+
{
|
|
3438
|
+
NS_PRECONDITION(aJSObj, "bad param");
|
|
3439
|
+
NS_PRECONDITION(mJSObj, "bad object state");
|
|
3440
|
+
*aJSObj = mJSObj;
|
|
3441
|
+
return NS_OK;
|
|
3442
|
+
}
|
|
3443
|
+
|
|
3444
|
+
XPCJSObjectHolder::XPCJSObjectHolder(XPCCallContext& ccx, JSObject* obj)
|
|
3445
|
+
: mJSObj(obj)
|
|
3446
|
+
{
|
|
3447
|
+
ccx.GetRuntime()->AddObjectHolderRoot(this);
|
|
3448
|
+
}
|
|
3449
|
+
|
|
3450
|
+
XPCJSObjectHolder::~XPCJSObjectHolder()
|
|
3451
|
+
{
|
|
3452
|
+
RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetJSRuntime());
|
|
3453
|
+
}
|
|
3454
|
+
|
|
3455
|
+
void
|
|
3456
|
+
XPCJSObjectHolder::TraceJS(JSTracer *trc)
|
|
3457
|
+
{
|
|
3458
|
+
JS_SET_TRACING_DETAILS(trc, PrintTraceName, this, 0);
|
|
3459
|
+
JS_CallTracer(trc, mJSObj, JSTRACE_OBJECT);
|
|
3460
|
+
}
|
|
3461
|
+
|
|
3462
|
+
#ifdef DEBUG
|
|
3463
|
+
// static
|
|
3464
|
+
void
|
|
3465
|
+
XPCJSObjectHolder::PrintTraceName(JSTracer* trc, char *buf, size_t bufsize)
|
|
3466
|
+
{
|
|
3467
|
+
JS_snprintf(buf, bufsize, "XPCJSObjectHolder[0x%p].mJSObj",
|
|
3468
|
+
trc->debugPrintArg);
|
|
3469
|
+
}
|
|
3470
|
+
#endif
|
|
3471
|
+
|
|
3472
|
+
// static
|
|
3473
|
+
XPCJSObjectHolder*
|
|
3474
|
+
XPCJSObjectHolder::newHolder(XPCCallContext& ccx, JSObject* obj)
|
|
3475
|
+
{
|
|
3476
|
+
if(!obj)
|
|
3477
|
+
{
|
|
3478
|
+
NS_ASSERTION(0, "bad param");
|
|
3479
|
+
return nsnull;
|
|
3480
|
+
}
|
|
3481
|
+
return new XPCJSObjectHolder(ccx, obj);
|
|
3482
|
+
}
|