BindingUtils.h 105 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef mozilla_dom_BindingUtils_h__
  6. #define mozilla_dom_BindingUtils_h__
  7. #include "jsfriendapi.h"
  8. #include "jswrapper.h"
  9. #include "js/Conversions.h"
  10. #include "mozilla/ArrayUtils.h"
  11. #include "mozilla/Alignment.h"
  12. #include "mozilla/Array.h"
  13. #include "mozilla/Assertions.h"
  14. #include "mozilla/CycleCollectedJSContext.h"
  15. #include "mozilla/DeferredFinalize.h"
  16. #include "mozilla/dom/BindingDeclarations.h"
  17. #include "mozilla/dom/CallbackObject.h"
  18. #include "mozilla/dom/DOMJSClass.h"
  19. #include "mozilla/dom/DOMJSProxyHandler.h"
  20. #include "mozilla/dom/Exceptions.h"
  21. #include "mozilla/dom/NonRefcountedDOMObject.h"
  22. #include "mozilla/dom/Nullable.h"
  23. #include "mozilla/dom/RootedDictionary.h"
  24. #include "mozilla/SegmentedVector.h"
  25. #include "mozilla/dom/workers/Workers.h"
  26. #include "mozilla/ErrorResult.h"
  27. #include "mozilla/Likely.h"
  28. #include "mozilla/MemoryReporting.h"
  29. #include "nsAutoPtr.h"
  30. #include "nsIDocument.h"
  31. #include "nsIGlobalObject.h"
  32. #include "nsIXPConnect.h"
  33. #include "nsJSUtils.h"
  34. #include "nsISupportsImpl.h"
  35. #include "qsObjectHelper.h"
  36. #include "xpcpublic.h"
  37. #include "nsIVariant.h"
  38. #include "mozilla/dom/FakeString.h"
  39. #include "nsWrapperCacheInlines.h"
  40. class nsGenericHTMLElement;
  41. class nsIJSID;
  42. namespace mozilla {
  43. enum UseCounter : int16_t;
  44. namespace dom {
  45. class CustomElementReactionsStack;
  46. template<typename KeyType, typename ValueType> class Record;
  47. nsresult
  48. UnwrapArgImpl(JS::Handle<JSObject*> src, const nsIID& iid, void** ppArg);
  49. nsresult
  50. UnwrapWindowProxyImpl(JS::Handle<JSObject*> src, nsPIDOMWindowOuter** ppArg);
  51. /** Convert a jsval to an XPCOM pointer. Caller must not assume that src will
  52. keep the XPCOM pointer rooted. */
  53. template <class Interface>
  54. inline nsresult
  55. UnwrapArg(JS::Handle<JSObject*> src, Interface** ppArg)
  56. {
  57. return UnwrapArgImpl(src, NS_GET_TEMPLATE_IID(Interface),
  58. reinterpret_cast<void**>(ppArg));
  59. }
  60. template <>
  61. inline nsresult
  62. UnwrapArg<nsPIDOMWindowOuter>(JS::Handle<JSObject*> src, nsPIDOMWindowOuter** ppArg)
  63. {
  64. return UnwrapWindowProxyImpl(src, ppArg);
  65. }
  66. nsresult
  67. UnwrapXPConnectImpl(JSContext* cx, JS::MutableHandle<JS::Value> src,
  68. const nsIID& iid, void** ppArg);
  69. /*
  70. * Convert a jsval being used as a Web IDL interface implementation to an XPCOM
  71. * pointer; this is only used for Web IDL interfaces that specify
  72. * hasXPConnectImpls. This is not the same as UnwrapArg because caller _can_
  73. * assume that if unwrapping succeeds "val" will be updated so it's rooting the
  74. * XPCOM pointer. Also, UnwrapXPConnect doesn't need to worry about doing
  75. * XPCWrappedJS things.
  76. *
  77. * val must be an ObjectValue.
  78. */
  79. template<class Interface>
  80. inline nsresult
  81. UnwrapXPConnect(JSContext* cx, JS::MutableHandle<JS::Value> val,
  82. Interface** ppThis)
  83. {
  84. return UnwrapXPConnectImpl(cx, val, NS_GET_TEMPLATE_IID(Interface),
  85. reinterpret_cast<void**>(ppThis));
  86. }
  87. bool
  88. ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
  89. bool aSecurityError, const char* aInterfaceName);
  90. bool
  91. ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
  92. bool aSecurityError, prototypes::ID aProtoId);
  93. // Returns true if the JSClass is used for DOM objects.
  94. inline bool
  95. IsDOMClass(const JSClass* clasp)
  96. {
  97. return clasp->flags & JSCLASS_IS_DOMJSCLASS;
  98. }
  99. inline bool
  100. IsDOMClass(const js::Class* clasp)
  101. {
  102. return IsDOMClass(Jsvalify(clasp));
  103. }
  104. // Return true if the JSClass is used for non-proxy DOM objects.
  105. inline bool
  106. IsNonProxyDOMClass(const js::Class* clasp)
  107. {
  108. return IsDOMClass(clasp) && !clasp->isProxy();
  109. }
  110. inline bool
  111. IsNonProxyDOMClass(const JSClass* clasp)
  112. {
  113. return IsNonProxyDOMClass(js::Valueify(clasp));
  114. }
  115. // Returns true if the JSClass is used for DOM interface and interface
  116. // prototype objects.
  117. inline bool
  118. IsDOMIfaceAndProtoClass(const JSClass* clasp)
  119. {
  120. return clasp->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS;
  121. }
  122. inline bool
  123. IsDOMIfaceAndProtoClass(const js::Class* clasp)
  124. {
  125. return IsDOMIfaceAndProtoClass(Jsvalify(clasp));
  126. }
  127. static_assert(DOM_OBJECT_SLOT == 0,
  128. "DOM_OBJECT_SLOT doesn't match the proxy private slot. "
  129. "Expect bad things");
  130. template <class T>
  131. inline T*
  132. UnwrapDOMObject(JSObject* obj)
  133. {
  134. MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj)),
  135. "Don't pass non-DOM objects to this function");
  136. JS::Value val = js::GetReservedOrProxyPrivateSlot(obj, DOM_OBJECT_SLOT);
  137. return static_cast<T*>(val.toPrivate());
  138. }
  139. template <class T>
  140. inline T*
  141. UnwrapPossiblyNotInitializedDOMObject(JSObject* obj)
  142. {
  143. // This is used by the OjectMoved JSClass hook which can be called before
  144. // JS_NewObject has returned and so before we have a chance to set
  145. // DOM_OBJECT_SLOT to anything useful.
  146. MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj)),
  147. "Don't pass non-DOM objects to this function");
  148. JS::Value val = js::GetReservedOrProxyPrivateSlot(obj, DOM_OBJECT_SLOT);
  149. if (val.isUndefined()) {
  150. return nullptr;
  151. }
  152. return static_cast<T*>(val.toPrivate());
  153. }
  154. inline const DOMJSClass*
  155. GetDOMClass(const js::Class* clasp)
  156. {
  157. return IsDOMClass(clasp) ? DOMJSClass::FromJSClass(clasp) : nullptr;
  158. }
  159. inline const DOMJSClass*
  160. GetDOMClass(JSObject* obj)
  161. {
  162. return GetDOMClass(js::GetObjectClass(obj));
  163. }
  164. inline nsISupports*
  165. UnwrapDOMObjectToISupports(JSObject* aObject)
  166. {
  167. const DOMJSClass* clasp = GetDOMClass(aObject);
  168. if (!clasp || !clasp->mDOMObjectIsISupports) {
  169. return nullptr;
  170. }
  171. return UnwrapPossiblyNotInitializedDOMObject<nsISupports>(aObject);
  172. }
  173. inline bool
  174. IsDOMObject(JSObject* obj)
  175. {
  176. return IsDOMClass(js::GetObjectClass(obj));
  177. }
  178. // There are two valid ways to use UNWRAP_OBJECT: Either obj needs to
  179. // be a MutableHandle<JSObject*>, or value needs to be a strong-reference
  180. // smart pointer type (OwningNonNull or RefPtr or nsCOMPtr), in which case obj
  181. // can be anything that converts to JSObject*.
  182. #define UNWRAP_OBJECT(Interface, obj, value) \
  183. mozilla::dom::UnwrapObject<mozilla::dom::prototypes::id::Interface, \
  184. mozilla::dom::Interface##Binding::NativeType>(obj, value)
  185. // Test whether the given object is an instance of the given interface.
  186. #define IS_INSTANCE_OF(Interface, obj) \
  187. mozilla::dom::IsInstanceOf<mozilla::dom::prototypes::id::Interface, \
  188. mozilla::dom::Interface##Binding::NativeType>(obj)
  189. // Unwrap the given non-wrapper object. This can be used with any obj that
  190. // converts to JSObject*; as long as that JSObject* is live the return value
  191. // will be valid.
  192. #define UNWRAP_NON_WRAPPER_OBJECT(Interface, obj, value) \
  193. mozilla::dom::UnwrapNonWrapperObject<mozilla::dom::prototypes::id::Interface, \
  194. mozilla::dom::Interface##Binding::NativeType>(obj, value)
  195. // Some callers don't want to set an exception when unwrapping fails
  196. // (for example, overload resolution uses unwrapping to tell what sort
  197. // of thing it's looking at).
  198. // U must be something that a T* can be assigned to (e.g. T* or an RefPtr<T>).
  199. //
  200. // The obj argument will be mutated to point to CheckedUnwrap of itself if the
  201. // passed-in value is not a DOM object and CheckedUnwrap succeeds.
  202. //
  203. // If mayBeWrapper is true, there are three valid ways to invoke
  204. // UnwrapObjectInternal: Either obj needs to be a class wrapping a
  205. // MutableHandle<JSObject*>, with an assignment operator that sets the handle to
  206. // the given object, or U needs to be a strong-reference smart pointer type
  207. // (OwningNonNull or RefPtr or nsCOMPtr), or the value being stored in "value"
  208. // must not escape past being tested for falsiness immediately after the
  209. // UnwrapObjectInternal call.
  210. //
  211. // If mayBeWrapper is false, obj can just be a JSObject*, and U anything that a
  212. // T* can be assigned to.
  213. namespace binding_detail {
  214. template <class T, bool mayBeWrapper, typename U, typename V>
  215. MOZ_ALWAYS_INLINE nsresult
  216. UnwrapObjectInternal(V& obj, U& value, prototypes::ID protoID,
  217. uint32_t protoDepth)
  218. {
  219. /* First check to see whether we have a DOM object */
  220. const DOMJSClass* domClass = GetDOMClass(obj);
  221. if (domClass) {
  222. /* This object is a DOM object. Double-check that it is safely
  223. castable to T by checking whether it claims to inherit from the
  224. class identified by protoID. */
  225. if (domClass->mInterfaceChain[protoDepth] == protoID) {
  226. value = UnwrapDOMObject<T>(obj);
  227. return NS_OK;
  228. }
  229. }
  230. /* Maybe we have a security wrapper or outer window? */
  231. if (!mayBeWrapper || !js::IsWrapper(obj)) {
  232. /* Not a DOM object, not a wrapper, just bail */
  233. return NS_ERROR_XPC_BAD_CONVERT_JS;
  234. }
  235. JSObject* unwrappedObj =
  236. js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
  237. if (!unwrappedObj) {
  238. return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
  239. }
  240. MOZ_ASSERT(!js::IsWrapper(unwrappedObj));
  241. // Recursive call is OK, because now we're using false for mayBeWrapper and
  242. // we never reach this code if that boolean is false, so can't keep calling
  243. // ourselves.
  244. //
  245. // Unwrap into a temporary pointer, because in general unwrapping into
  246. // something of type U might trigger GC (e.g. release the value currently
  247. // stored in there, with arbitrary consequences) and invalidate the
  248. // "unwrappedObj" pointer.
  249. T* tempValue;
  250. nsresult rv = UnwrapObjectInternal<T, false>(unwrappedObj, tempValue,
  251. protoID, protoDepth);
  252. if (NS_SUCCEEDED(rv)) {
  253. // It's very important to not update "obj" with the "unwrappedObj" value
  254. // until we know the unwrap has succeeded. Otherwise, in a situation in
  255. // which we have an overload of object and primitive we could end up
  256. // converting to the primitive from the unwrappedObj, whereas we want to do
  257. // it from the original object.
  258. obj = unwrappedObj;
  259. // And now assign to "value"; at this point we don't care if a GC happens
  260. // and invalidates unwrappedObj.
  261. value = tempValue;
  262. return NS_OK;
  263. }
  264. /* It's the wrong sort of DOM object */
  265. return NS_ERROR_XPC_BAD_CONVERT_JS;
  266. }
  267. struct MutableObjectHandleWrapper {
  268. explicit MutableObjectHandleWrapper(JS::MutableHandle<JSObject*> aHandle)
  269. : mHandle(aHandle)
  270. {
  271. }
  272. void operator=(JSObject* aObject)
  273. {
  274. MOZ_ASSERT(aObject);
  275. mHandle.set(aObject);
  276. }
  277. operator JSObject*() const
  278. {
  279. return mHandle;
  280. }
  281. private:
  282. JS::MutableHandle<JSObject*> mHandle;
  283. };
  284. struct MutableValueHandleWrapper {
  285. explicit MutableValueHandleWrapper(JS::MutableHandle<JS::Value> aHandle)
  286. : mHandle(aHandle)
  287. {
  288. }
  289. void operator=(JSObject* aObject)
  290. {
  291. MOZ_ASSERT(aObject);
  292. mHandle.setObject(*aObject);
  293. }
  294. operator JSObject*() const
  295. {
  296. return &mHandle.toObject();
  297. }
  298. private:
  299. JS::MutableHandle<JS::Value> mHandle;
  300. };
  301. } // namespace binding_detail
  302. // UnwrapObject overloads that ensure we have a MutableHandle to keep it alive.
  303. template<prototypes::ID PrototypeID, class T, typename U>
  304. MOZ_ALWAYS_INLINE nsresult
  305. UnwrapObject(JS::MutableHandle<JSObject*> obj, U& value)
  306. {
  307. binding_detail::MutableObjectHandleWrapper wrapper(obj);
  308. return binding_detail::UnwrapObjectInternal<T, true>(
  309. wrapper, value, PrototypeID, PrototypeTraits<PrototypeID>::Depth);
  310. }
  311. template<prototypes::ID PrototypeID, class T, typename U>
  312. MOZ_ALWAYS_INLINE nsresult
  313. UnwrapObject(JS::MutableHandle<JS::Value> obj, U& value)
  314. {
  315. MOZ_ASSERT(obj.isObject());
  316. binding_detail::MutableValueHandleWrapper wrapper(obj);
  317. return binding_detail::UnwrapObjectInternal<T, true>(
  318. wrapper, value, PrototypeID, PrototypeTraits<PrototypeID>::Depth);
  319. }
  320. // UnwrapObject overloads that ensure we have a strong ref to keep it alive.
  321. template<prototypes::ID PrototypeID, class T, typename U>
  322. MOZ_ALWAYS_INLINE nsresult
  323. UnwrapObject(JSObject* obj, RefPtr<U>& value)
  324. {
  325. return binding_detail::UnwrapObjectInternal<T, true>(
  326. obj, value, PrototypeID, PrototypeTraits<PrototypeID>::Depth);
  327. }
  328. template<prototypes::ID PrototypeID, class T, typename U>
  329. MOZ_ALWAYS_INLINE nsresult
  330. UnwrapObject(JSObject* obj, nsCOMPtr<U>& value)
  331. {
  332. return binding_detail::UnwrapObjectInternal<T, true>(
  333. obj, value, PrototypeID, PrototypeTraits<PrototypeID>::Depth);
  334. }
  335. template<prototypes::ID PrototypeID, class T, typename U>
  336. MOZ_ALWAYS_INLINE nsresult
  337. UnwrapObject(JSObject* obj, OwningNonNull<U>& value)
  338. {
  339. return binding_detail::UnwrapObjectInternal<T, true>(
  340. obj, value, PrototypeID, PrototypeTraits<PrototypeID>::Depth);
  341. }
  342. // An UnwrapObject overload that just calls one of the JSObject* ones.
  343. template<prototypes::ID PrototypeID, class T, typename U>
  344. MOZ_ALWAYS_INLINE nsresult
  345. UnwrapObject(JS::Handle<JS::Value> obj, U& value)
  346. {
  347. MOZ_ASSERT(obj.isObject());
  348. return UnwrapObject<PrototypeID, T>(&obj.toObject(), value);
  349. }
  350. template<prototypes::ID PrototypeID, class T>
  351. MOZ_ALWAYS_INLINE bool
  352. IsInstanceOf(JSObject* obj)
  353. {
  354. void* ignored;
  355. nsresult unwrapped = binding_detail::UnwrapObjectInternal<T, true>(
  356. obj, ignored, PrototypeID, PrototypeTraits<PrototypeID>::Depth);
  357. return NS_SUCCEEDED(unwrapped);
  358. }
  359. template<prototypes::ID PrototypeID, class T, typename U>
  360. MOZ_ALWAYS_INLINE nsresult
  361. UnwrapNonWrapperObject(JSObject* obj, U& value)
  362. {
  363. MOZ_ASSERT(!js::IsWrapper(obj));
  364. return binding_detail::UnwrapObjectInternal<T, false>(
  365. obj, value, PrototypeID, PrototypeTraits<PrototypeID>::Depth);
  366. }
  367. inline bool
  368. IsNotDateOrRegExp(JSContext* cx, JS::Handle<JSObject*> obj,
  369. bool* notDateOrRegExp)
  370. {
  371. MOZ_ASSERT(obj);
  372. js::ESClass cls;
  373. if (!js::GetBuiltinClass(cx, obj, &cls)) {
  374. return false;
  375. }
  376. *notDateOrRegExp = cls != js::ESClass::Date && cls != js::ESClass::RegExp;
  377. return true;
  378. }
  379. MOZ_ALWAYS_INLINE bool
  380. IsObjectValueConvertibleToDictionary(JSContext* cx,
  381. JS::Handle<JS::Value> objVal,
  382. bool* convertible)
  383. {
  384. JS::Rooted<JSObject*> obj(cx, &objVal.toObject());
  385. return IsNotDateOrRegExp(cx, obj, convertible);
  386. }
  387. MOZ_ALWAYS_INLINE bool
  388. IsConvertibleToDictionary(JSContext* cx, JS::Handle<JS::Value> val,
  389. bool* convertible)
  390. {
  391. if (val.isNullOrUndefined()) {
  392. *convertible = true;
  393. return true;
  394. }
  395. if (!val.isObject()) {
  396. *convertible = false;
  397. return true;
  398. }
  399. return IsObjectValueConvertibleToDictionary(cx, val, convertible);
  400. }
  401. MOZ_ALWAYS_INLINE bool
  402. IsConvertibleToCallbackInterface(JSContext* cx, JS::Handle<JSObject*> obj,
  403. bool* convertible)
  404. {
  405. return IsNotDateOrRegExp(cx, obj, convertible);
  406. }
  407. // The items in the protoAndIfaceCache are indexed by the prototypes::id::ID,
  408. // constructors::id::ID and namedpropertiesobjects::id::ID enums, in that order.
  409. // The end of the prototype objects should be the start of the interface
  410. // objects, and the end of the interface objects should be the start of the
  411. // named properties objects.
  412. static_assert((size_t)constructors::id::_ID_Start ==
  413. (size_t)prototypes::id::_ID_Count &&
  414. (size_t)namedpropertiesobjects::id::_ID_Start ==
  415. (size_t)constructors::id::_ID_Count,
  416. "Overlapping or discontiguous indexes.");
  417. const size_t kProtoAndIfaceCacheCount = namedpropertiesobjects::id::_ID_Count;
  418. class ProtoAndIfaceCache
  419. {
  420. // The caching strategy we use depends on what sort of global we're dealing
  421. // with. For a window-like global, we want everything to be as fast as
  422. // possible, so we use a flat array, indexed by prototype/constructor ID.
  423. // For everything else (e.g. globals for JSMs), space is more important than
  424. // speed, so we use a two-level lookup table.
  425. class ArrayCache : public Array<JS::Heap<JSObject*>, kProtoAndIfaceCacheCount>
  426. {
  427. public:
  428. JSObject* EntrySlotIfExists(size_t i) {
  429. return (*this)[i];
  430. }
  431. JS::Heap<JSObject*>& EntrySlotOrCreate(size_t i) {
  432. return (*this)[i];
  433. }
  434. JS::Heap<JSObject*>& EntrySlotMustExist(size_t i) {
  435. return (*this)[i];
  436. }
  437. void Trace(JSTracer* aTracer) {
  438. for (size_t i = 0; i < ArrayLength(*this); ++i) {
  439. JS::TraceEdge(aTracer, &(*this)[i], "protoAndIfaceCache[i]");
  440. }
  441. }
  442. size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
  443. return aMallocSizeOf(this);
  444. }
  445. };
  446. class PageTableCache
  447. {
  448. public:
  449. PageTableCache() {
  450. memset(mPages.begin(), 0, sizeof(mPages));
  451. }
  452. ~PageTableCache() {
  453. for (size_t i = 0; i < ArrayLength(mPages); ++i) {
  454. delete mPages[i];
  455. }
  456. }
  457. JSObject* EntrySlotIfExists(size_t i) {
  458. MOZ_ASSERT(i < kProtoAndIfaceCacheCount);
  459. size_t pageIndex = i / kPageSize;
  460. size_t leafIndex = i % kPageSize;
  461. Page* p = mPages[pageIndex];
  462. if (!p) {
  463. return nullptr;
  464. }
  465. return (*p)[leafIndex];
  466. }
  467. JS::Heap<JSObject*>& EntrySlotOrCreate(size_t i) {
  468. MOZ_ASSERT(i < kProtoAndIfaceCacheCount);
  469. size_t pageIndex = i / kPageSize;
  470. size_t leafIndex = i % kPageSize;
  471. Page* p = mPages[pageIndex];
  472. if (!p) {
  473. p = new Page;
  474. mPages[pageIndex] = p;
  475. }
  476. return (*p)[leafIndex];
  477. }
  478. JS::Heap<JSObject*>& EntrySlotMustExist(size_t i) {
  479. MOZ_ASSERT(i < kProtoAndIfaceCacheCount);
  480. size_t pageIndex = i / kPageSize;
  481. size_t leafIndex = i % kPageSize;
  482. Page* p = mPages[pageIndex];
  483. MOZ_ASSERT(p);
  484. return (*p)[leafIndex];
  485. }
  486. void Trace(JSTracer* trc) {
  487. for (size_t i = 0; i < ArrayLength(mPages); ++i) {
  488. Page* p = mPages[i];
  489. if (p) {
  490. for (size_t j = 0; j < ArrayLength(*p); ++j) {
  491. JS::TraceEdge(trc, &(*p)[j], "protoAndIfaceCache[i]");
  492. }
  493. }
  494. }
  495. }
  496. size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
  497. size_t n = aMallocSizeOf(this);
  498. for (size_t i = 0; i < ArrayLength(mPages); ++i) {
  499. n += aMallocSizeOf(mPages[i]);
  500. }
  501. return n;
  502. }
  503. private:
  504. static const size_t kPageSize = 16;
  505. typedef Array<JS::Heap<JSObject*>, kPageSize> Page;
  506. static const size_t kNPages = kProtoAndIfaceCacheCount / kPageSize +
  507. size_t(bool(kProtoAndIfaceCacheCount % kPageSize));
  508. Array<Page*, kNPages> mPages;
  509. };
  510. public:
  511. enum Kind {
  512. WindowLike,
  513. NonWindowLike
  514. };
  515. explicit ProtoAndIfaceCache(Kind aKind) : mKind(aKind) {
  516. MOZ_COUNT_CTOR(ProtoAndIfaceCache);
  517. if (aKind == WindowLike) {
  518. mArrayCache = new ArrayCache();
  519. } else {
  520. mPageTableCache = new PageTableCache();
  521. }
  522. }
  523. ~ProtoAndIfaceCache() {
  524. if (mKind == WindowLike) {
  525. delete mArrayCache;
  526. } else {
  527. delete mPageTableCache;
  528. }
  529. MOZ_COUNT_DTOR(ProtoAndIfaceCache);
  530. }
  531. #define FORWARD_OPERATION(opName, args) \
  532. do { \
  533. if (mKind == WindowLike) { \
  534. return mArrayCache->opName args; \
  535. } else { \
  536. return mPageTableCache->opName args; \
  537. } \
  538. } while(0)
  539. // Return the JSObject stored in slot i, if that slot exists. If
  540. // the slot does not exist, return null.
  541. JSObject* EntrySlotIfExists(size_t i) {
  542. FORWARD_OPERATION(EntrySlotIfExists, (i));
  543. }
  544. // Return a reference to slot i, creating it if necessary. There
  545. // may not be an object in the returned slot.
  546. JS::Heap<JSObject*>& EntrySlotOrCreate(size_t i) {
  547. FORWARD_OPERATION(EntrySlotOrCreate, (i));
  548. }
  549. // Return a reference to slot i, which is guaranteed to already
  550. // exist. There may not be an object in the slot, if prototype and
  551. // constructor initialization for one of our bindings failed.
  552. JS::Heap<JSObject*>& EntrySlotMustExist(size_t i) {
  553. FORWARD_OPERATION(EntrySlotMustExist, (i));
  554. }
  555. void Trace(JSTracer *aTracer) {
  556. FORWARD_OPERATION(Trace, (aTracer));
  557. }
  558. size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
  559. size_t n = aMallocSizeOf(this);
  560. n += (mKind == WindowLike
  561. ? mArrayCache->SizeOfIncludingThis(aMallocSizeOf)
  562. : mPageTableCache->SizeOfIncludingThis(aMallocSizeOf));
  563. return n;
  564. }
  565. #undef FORWARD_OPERATION
  566. private:
  567. union {
  568. ArrayCache *mArrayCache;
  569. PageTableCache *mPageTableCache;
  570. };
  571. Kind mKind;
  572. };
  573. inline void
  574. AllocateProtoAndIfaceCache(JSObject* obj, ProtoAndIfaceCache::Kind aKind)
  575. {
  576. MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
  577. MOZ_ASSERT(js::GetReservedSlot(obj, DOM_PROTOTYPE_SLOT).isUndefined());
  578. ProtoAndIfaceCache* protoAndIfaceCache = new ProtoAndIfaceCache(aKind);
  579. js::SetReservedSlot(obj, DOM_PROTOTYPE_SLOT,
  580. JS::PrivateValue(protoAndIfaceCache));
  581. }
  582. #ifdef DEBUG
  583. struct VerifyTraceProtoAndIfaceCacheCalledTracer : public JS::CallbackTracer
  584. {
  585. bool ok;
  586. explicit VerifyTraceProtoAndIfaceCacheCalledTracer(JSContext* cx)
  587. : JS::CallbackTracer(cx), ok(false)
  588. {}
  589. void onChild(const JS::GCCellPtr&) override {
  590. // We don't do anything here, we only want to verify that
  591. // TraceProtoAndIfaceCache was called.
  592. }
  593. TracerKind getTracerKind() const override { return TracerKind::VerifyTraceProtoAndIface; }
  594. };
  595. #endif
  596. inline void
  597. TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
  598. {
  599. MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
  600. #ifdef DEBUG
  601. if (trc->isCallbackTracer() &&
  602. (trc->asCallbackTracer()->getTracerKind() ==
  603. JS::CallbackTracer::TracerKind::VerifyTraceProtoAndIface)) {
  604. // We don't do anything here, we only want to verify that
  605. // TraceProtoAndIfaceCache was called.
  606. static_cast<VerifyTraceProtoAndIfaceCacheCalledTracer*>(trc)->ok = true;
  607. return;
  608. }
  609. #endif
  610. if (!DOMGlobalHasProtoAndIFaceCache(obj))
  611. return;
  612. ProtoAndIfaceCache* protoAndIfaceCache = GetProtoAndIfaceCache(obj);
  613. protoAndIfaceCache->Trace(trc);
  614. }
  615. inline void
  616. DestroyProtoAndIfaceCache(JSObject* obj)
  617. {
  618. MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
  619. if (!DOMGlobalHasProtoAndIFaceCache(obj)) {
  620. return;
  621. }
  622. ProtoAndIfaceCache* protoAndIfaceCache = GetProtoAndIfaceCache(obj);
  623. delete protoAndIfaceCache;
  624. }
  625. /**
  626. * Add constants to an object.
  627. */
  628. bool
  629. DefineConstants(JSContext* cx, JS::Handle<JSObject*> obj,
  630. const ConstantSpec* cs);
  631. struct JSNativeHolder
  632. {
  633. JSNative mNative;
  634. const NativePropertyHooks* mPropertyHooks;
  635. };
  636. struct NamedConstructor
  637. {
  638. const char* mName;
  639. const JSNativeHolder mHolder;
  640. unsigned mNargs;
  641. };
  642. /*
  643. * Create a DOM interface object (if constructorClass is non-null) and/or a
  644. * DOM interface prototype object (if protoClass is non-null).
  645. *
  646. * global is used as the parent of the interface object and the interface
  647. * prototype object
  648. * protoProto is the prototype to use for the interface prototype object.
  649. * interfaceProto is the prototype to use for the interface object. This can be
  650. * null if both constructorClass and constructor are null (as in,
  651. * if we're not creating an interface object at all).
  652. * protoClass is the JSClass to use for the interface prototype object.
  653. * This is null if we should not create an interface prototype
  654. * object.
  655. * protoCache a pointer to a JSObject pointer where we should cache the
  656. * interface prototype object. This must be null if protoClass is and
  657. * vice versa.
  658. * constructorClass is the JSClass to use for the interface object.
  659. * This is null if we should not create an interface object or
  660. * if it should be a function object.
  661. * constructor holds the JSNative to back the interface object which should be a
  662. * Function, unless constructorClass is non-null in which case it is
  663. * ignored. If this is null and constructorClass is also null then
  664. * we should not create an interface object at all.
  665. * ctorNargs is the length of the constructor function; 0 if no constructor
  666. * constructorCache a pointer to a JSObject pointer where we should cache the
  667. * interface object. This must be null if both constructorClass
  668. * and constructor are null, and non-null otherwise.
  669. * properties contains the methods, attributes and constants to be defined on
  670. * objects in any compartment.
  671. * chromeProperties contains the methods, attributes and constants to be defined
  672. * on objects in chrome compartments. This must be null if the
  673. * interface doesn't have any ChromeOnly properties or if the
  674. * object is being created in non-chrome compartment.
  675. * defineOnGlobal controls whether properties should be defined on the given
  676. * global for the interface object (if any) and named
  677. * constructors (if any) for this interface. This can be
  678. * false in situations where we want the properties to only
  679. * appear on privileged Xrays but not on the unprivileged
  680. * underlying global.
  681. * unscopableNames if not null it points to a null-terminated list of const
  682. * char* names of the unscopable properties for this interface.
  683. * isGlobal if true, we're creating interface objects for a [Global] or
  684. * [PrimaryGlobal] interface, and hence shouldn't define properties on
  685. * the prototype object.
  686. *
  687. * At least one of protoClass, constructorClass or constructor should be
  688. * non-null. If constructorClass or constructor are non-null, the resulting
  689. * interface object will be defined on the given global with property name
  690. * |name|, which must also be non-null.
  691. */
  692. void
  693. CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
  694. JS::Handle<JSObject*> protoProto,
  695. const js::Class* protoClass, JS::Heap<JSObject*>* protoCache,
  696. JS::Handle<JSObject*> interfaceProto,
  697. const js::Class* constructorClass,
  698. unsigned ctorNargs, const NamedConstructor* namedConstructors,
  699. JS::Heap<JSObject*>* constructorCache,
  700. const NativeProperties* regularProperties,
  701. const NativeProperties* chromeOnlyProperties,
  702. const char* name, bool defineOnGlobal,
  703. const char* const* unscopableNames,
  704. bool isGlobal);
  705. /**
  706. * Define the properties (regular and chrome-only) on obj.
  707. *
  708. * obj the object to instal the properties on. This should be the interface
  709. * prototype object for regular interfaces and the instance object for
  710. * interfaces marked with Global.
  711. * properties contains the methods, attributes and constants to be defined on
  712. * objects in any compartment.
  713. * chromeProperties contains the methods, attributes and constants to be defined
  714. * on objects in chrome compartments. This must be null if the
  715. * interface doesn't have any ChromeOnly properties or if the
  716. * object is being created in non-chrome compartment.
  717. */
  718. bool
  719. DefineProperties(JSContext* cx, JS::Handle<JSObject*> obj,
  720. const NativeProperties* properties,
  721. const NativeProperties* chromeOnlyProperties);
  722. /*
  723. * Define the unforgeable methods on an object.
  724. */
  725. bool
  726. DefineUnforgeableMethods(JSContext* cx, JS::Handle<JSObject*> obj,
  727. const Prefable<const JSFunctionSpec>* props);
  728. /*
  729. * Define the unforgeable attributes on an object.
  730. */
  731. bool
  732. DefineUnforgeableAttributes(JSContext* cx, JS::Handle<JSObject*> obj,
  733. const Prefable<const JSPropertySpec>* props);
  734. #define HAS_MEMBER_TYPEDEFS \
  735. private: \
  736. typedef char yes[1]; \
  737. typedef char no[2]
  738. #ifdef _MSC_VER
  739. #define HAS_MEMBER_CHECK(_name) \
  740. template<typename V> static yes& Check##_name(char (*)[(&V::_name == 0) + 1])
  741. #else
  742. #define HAS_MEMBER_CHECK(_name) \
  743. template<typename V> static yes& Check##_name(char (*)[sizeof(&V::_name) + 1])
  744. #endif
  745. #define HAS_MEMBER(_memberName, _valueName) \
  746. private: \
  747. HAS_MEMBER_CHECK(_memberName); \
  748. template<typename V> static no& Check##_memberName(...); \
  749. \
  750. public: \
  751. static bool const _valueName = \
  752. sizeof(Check##_memberName<T>(nullptr)) == sizeof(yes)
  753. template<class T>
  754. struct NativeHasMember
  755. {
  756. HAS_MEMBER_TYPEDEFS;
  757. HAS_MEMBER(GetParentObject, GetParentObject);
  758. HAS_MEMBER(WrapObject, WrapObject);
  759. };
  760. template<class T>
  761. struct IsSmartPtr
  762. {
  763. HAS_MEMBER_TYPEDEFS;
  764. HAS_MEMBER(get, value);
  765. };
  766. template<class T>
  767. struct IsRefcounted
  768. {
  769. HAS_MEMBER_TYPEDEFS;
  770. HAS_MEMBER(AddRef, HasAddref);
  771. HAS_MEMBER(Release, HasRelease);
  772. public:
  773. static bool const value = HasAddref && HasRelease;
  774. private:
  775. // This struct only works if T is fully declared (not just forward declared).
  776. // The IsBaseOf check will ensure that, we don't really need it for any other
  777. // reason (the static assert will of course always be true).
  778. static_assert(!IsBaseOf<nsISupports, T>::value || IsRefcounted::value,
  779. "Classes derived from nsISupports are refcounted!");
  780. };
  781. #undef HAS_MEMBER
  782. #undef HAS_MEMBER_CHECK
  783. #undef HAS_MEMBER_TYPEDEFS
  784. #ifdef DEBUG
  785. template <class T, bool isISupports=IsBaseOf<nsISupports, T>::value>
  786. struct
  787. CheckWrapperCacheCast
  788. {
  789. static bool Check()
  790. {
  791. return reinterpret_cast<uintptr_t>(
  792. static_cast<nsWrapperCache*>(
  793. reinterpret_cast<T*>(1))) == 1;
  794. }
  795. };
  796. template <class T>
  797. struct
  798. CheckWrapperCacheCast<T, true>
  799. {
  800. static bool Check()
  801. {
  802. return true;
  803. }
  804. };
  805. #endif
  806. MOZ_ALWAYS_INLINE bool
  807. CouldBeDOMBinding(void*)
  808. {
  809. return true;
  810. }
  811. MOZ_ALWAYS_INLINE bool
  812. CouldBeDOMBinding(nsWrapperCache* aCache)
  813. {
  814. return aCache->IsDOMBinding();
  815. }
  816. inline bool
  817. TryToOuterize(JS::MutableHandle<JS::Value> rval)
  818. {
  819. if (js::IsWindow(&rval.toObject())) {
  820. JSObject* obj = js::ToWindowProxyIfWindow(&rval.toObject());
  821. MOZ_ASSERT(obj);
  822. rval.set(JS::ObjectValue(*obj));
  823. }
  824. return true;
  825. }
  826. // Make sure to wrap the given string value into the right compartment, as
  827. // needed.
  828. MOZ_ALWAYS_INLINE
  829. bool
  830. MaybeWrapStringValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
  831. {
  832. MOZ_ASSERT(rval.isString());
  833. JSString* str = rval.toString();
  834. if (JS::GetStringZone(str) != js::GetContextZone(cx)) {
  835. return JS_WrapValue(cx, rval);
  836. }
  837. return true;
  838. }
  839. // Make sure to wrap the given object value into the right compartment as
  840. // needed. This will work correctly, but possibly slowly, on all objects.
  841. MOZ_ALWAYS_INLINE
  842. bool
  843. MaybeWrapObjectValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
  844. {
  845. MOZ_ASSERT(rval.isObject());
  846. // Cross-compartment always requires wrapping.
  847. JSObject* obj = &rval.toObject();
  848. if (js::GetObjectCompartment(obj) != js::GetContextCompartment(cx)) {
  849. return JS_WrapValue(cx, rval);
  850. }
  851. // We're same-compartment, but even then we might need to wrap
  852. // objects specially. Check for that.
  853. if (IsDOMObject(obj)) {
  854. return TryToOuterize(rval);
  855. }
  856. // It's not a WebIDL object, so it's OK to just leave it as-is: only WebIDL
  857. // objects (specifically only windows) require outerization.
  858. return true;
  859. }
  860. // Like MaybeWrapObjectValue, but also allows null
  861. MOZ_ALWAYS_INLINE
  862. bool
  863. MaybeWrapObjectOrNullValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
  864. {
  865. MOZ_ASSERT(rval.isObjectOrNull());
  866. if (rval.isNull()) {
  867. return true;
  868. }
  869. return MaybeWrapObjectValue(cx, rval);
  870. }
  871. // Wrapping for objects that are known to not be DOM or XPConnect objects
  872. MOZ_ALWAYS_INLINE
  873. bool
  874. MaybeWrapNonDOMObjectValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
  875. {
  876. MOZ_ASSERT(rval.isObject());
  877. MOZ_ASSERT(!GetDOMClass(&rval.toObject()));
  878. MOZ_ASSERT(!(js::GetObjectClass(&rval.toObject())->flags &
  879. JSCLASS_PRIVATE_IS_NSISUPPORTS));
  880. JSObject* obj = &rval.toObject();
  881. if (js::GetObjectCompartment(obj) == js::GetContextCompartment(cx)) {
  882. return true;
  883. }
  884. return JS_WrapValue(cx, rval);
  885. }
  886. // Like MaybeWrapNonDOMObjectValue but allows null
  887. MOZ_ALWAYS_INLINE
  888. bool
  889. MaybeWrapNonDOMObjectOrNullValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
  890. {
  891. MOZ_ASSERT(rval.isObjectOrNull());
  892. if (rval.isNull()) {
  893. return true;
  894. }
  895. return MaybeWrapNonDOMObjectValue(cx, rval);
  896. }
  897. // If rval is a gcthing and is not in the compartment of cx, wrap rval
  898. // into the compartment of cx (typically by replacing it with an Xray or
  899. // cross-compartment wrapper around the original object).
  900. MOZ_ALWAYS_INLINE bool
  901. MaybeWrapValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
  902. {
  903. if (rval.isString()) {
  904. return MaybeWrapStringValue(cx, rval);
  905. }
  906. if (!rval.isObject()) {
  907. return true;
  908. }
  909. return MaybeWrapObjectValue(cx, rval);
  910. }
  911. namespace binding_detail {
  912. enum GetOrCreateReflectorWrapBehavior {
  913. eWrapIntoContextCompartment,
  914. eDontWrapIntoContextCompartment
  915. };
  916. template <class T>
  917. struct TypeNeedsOuterization
  918. {
  919. // We only need to outerize Window objects, so anything inheriting from
  920. // nsGlobalWindow (which inherits from EventTarget itself).
  921. static const bool value =
  922. IsBaseOf<nsGlobalWindow, T>::value || IsSame<EventTarget, T>::value;
  923. };
  924. #ifdef DEBUG
  925. template<typename T, bool isISupports=IsBaseOf<nsISupports, T>::value>
  926. struct CheckWrapperCacheTracing
  927. {
  928. static inline void Check(T* aObject)
  929. {
  930. }
  931. };
  932. template<typename T>
  933. struct CheckWrapperCacheTracing<T, true>
  934. {
  935. static void Check(T* aObject)
  936. {
  937. // Rooting analysis thinks QueryInterface may GC, but we're dealing with
  938. // a subset of QueryInterface, C++ only types here.
  939. JS::AutoSuppressGCAnalysis nogc;
  940. nsWrapperCache* wrapperCacheFromQI = nullptr;
  941. aObject->QueryInterface(NS_GET_IID(nsWrapperCache),
  942. reinterpret_cast<void**>(&wrapperCacheFromQI));
  943. MOZ_ASSERT(wrapperCacheFromQI,
  944. "Missing nsWrapperCache from QueryInterface implementation?");
  945. if (!wrapperCacheFromQI->GetWrapperPreserveColor()) {
  946. // Can't assert that we trace the wrapper, since we don't have any
  947. // wrapper to trace.
  948. return;
  949. }
  950. nsISupports* ccISupports = nullptr;
  951. aObject->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
  952. reinterpret_cast<void**>(&ccISupports));
  953. MOZ_ASSERT(ccISupports,
  954. "nsWrapperCache object which isn't cycle collectable?");
  955. nsXPCOMCycleCollectionParticipant* participant = nullptr;
  956. CallQueryInterface(ccISupports, &participant);
  957. MOZ_ASSERT(participant, "Can't QI to CycleCollectionParticipant?");
  958. bool wasPreservingWrapper = wrapperCacheFromQI->PreservingWrapper();
  959. wrapperCacheFromQI->SetPreservingWrapper(true);
  960. wrapperCacheFromQI->CheckCCWrapperTraversal(ccISupports, participant);
  961. wrapperCacheFromQI->SetPreservingWrapper(wasPreservingWrapper);
  962. }
  963. };
  964. void
  965. AssertReflectorHasGivenProto(JSContext* aCx, JSObject* aReflector,
  966. JS::Handle<JSObject*> aGivenProto);
  967. #endif // DEBUG
  968. template <class T, GetOrCreateReflectorWrapBehavior wrapBehavior>
  969. MOZ_ALWAYS_INLINE bool
  970. DoGetOrCreateDOMReflector(JSContext* cx, T* value,
  971. JS::Handle<JSObject*> givenProto,
  972. JS::MutableHandle<JS::Value> rval)
  973. {
  974. MOZ_ASSERT(value);
  975. // We can get rid of this when we remove support for hasXPConnectImpls.
  976. bool couldBeDOMBinding = CouldBeDOMBinding(value);
  977. JSObject* obj = value->GetWrapper();
  978. if (obj) {
  979. #ifdef DEBUG
  980. AssertReflectorHasGivenProto(cx, obj, givenProto);
  981. // Have to reget obj because AssertReflectorHasGivenProto can
  982. // trigger gc so the pointer may now be invalid.
  983. obj = value->GetWrapper();
  984. #endif
  985. } else {
  986. // Inline this here while we have non-dom objects in wrapper caches.
  987. if (!couldBeDOMBinding) {
  988. return false;
  989. }
  990. obj = value->WrapObject(cx, givenProto);
  991. if (!obj) {
  992. // At this point, obj is null, so just return false.
  993. // Callers seem to be testing JS_IsExceptionPending(cx) to
  994. // figure out whether WrapObject() threw.
  995. return false;
  996. }
  997. #ifdef DEBUG
  998. if (IsBaseOf<nsWrapperCache, T>::value) {
  999. CheckWrapperCacheTracing<T>::Check(value);
  1000. }
  1001. #endif
  1002. }
  1003. #ifdef DEBUG
  1004. const DOMJSClass* clasp = GetDOMClass(obj);
  1005. // clasp can be null if the cache contained a non-DOM object.
  1006. if (clasp) {
  1007. // Some sanity asserts about our object. Specifically:
  1008. // 1) If our class claims we're nsISupports, we better be nsISupports
  1009. // XXXbz ideally, we could assert that reinterpret_cast to nsISupports
  1010. // does the right thing, but I don't see a way to do it. :(
  1011. // 2) If our class doesn't claim we're nsISupports we better be
  1012. // reinterpret_castable to nsWrapperCache.
  1013. MOZ_ASSERT(clasp, "What happened here?");
  1014. MOZ_ASSERT_IF(clasp->mDOMObjectIsISupports, (IsBaseOf<nsISupports, T>::value));
  1015. MOZ_ASSERT(CheckWrapperCacheCast<T>::Check());
  1016. }
  1017. #endif
  1018. rval.set(JS::ObjectValue(*obj));
  1019. bool sameCompartment =
  1020. js::GetObjectCompartment(obj) == js::GetContextCompartment(cx);
  1021. if (sameCompartment && couldBeDOMBinding) {
  1022. return TypeNeedsOuterization<T>::value ? TryToOuterize(rval) : true;
  1023. }
  1024. if (wrapBehavior == eDontWrapIntoContextCompartment) {
  1025. if (TypeNeedsOuterization<T>::value) {
  1026. JSAutoCompartment ac(cx, obj);
  1027. return TryToOuterize(rval);
  1028. }
  1029. return true;
  1030. }
  1031. return JS_WrapValue(cx, rval);
  1032. }
  1033. } // namespace binding_detail
  1034. // Create a JSObject wrapping "value", if there isn't one already, and store it
  1035. // in rval. "value" must be a concrete class that implements a
  1036. // GetWrapperPreserveColor() which can return its existing wrapper, if any, and
  1037. // a WrapObject() which will try to create a wrapper. Typically, this is done by
  1038. // having "value" inherit from nsWrapperCache.
  1039. //
  1040. // The value stored in rval will be ready to be exposed to whatever JS
  1041. // is running on cx right now. In particular, it will be in the
  1042. // compartment of cx, and outerized as needed.
  1043. template <class T>
  1044. MOZ_ALWAYS_INLINE bool
  1045. GetOrCreateDOMReflector(JSContext* cx, T* value,
  1046. JS::MutableHandle<JS::Value> rval,
  1047. JS::Handle<JSObject*> givenProto = nullptr)
  1048. {
  1049. using namespace binding_detail;
  1050. return DoGetOrCreateDOMReflector<T, eWrapIntoContextCompartment>(cx, value,
  1051. givenProto,
  1052. rval);
  1053. }
  1054. // Like GetOrCreateDOMReflector but doesn't wrap into the context compartment,
  1055. // and hence does not actually require cx to be in a compartment.
  1056. template <class T>
  1057. MOZ_ALWAYS_INLINE bool
  1058. GetOrCreateDOMReflectorNoWrap(JSContext* cx, T* value,
  1059. JS::MutableHandle<JS::Value> rval)
  1060. {
  1061. using namespace binding_detail;
  1062. return DoGetOrCreateDOMReflector<T, eDontWrapIntoContextCompartment>(cx,
  1063. value,
  1064. nullptr,
  1065. rval);
  1066. }
  1067. // Create a JSObject wrapping "value", for cases when "value" is a
  1068. // non-wrapper-cached object using WebIDL bindings. "value" must implement a
  1069. // WrapObject() method taking a JSContext and a scope.
  1070. template <class T>
  1071. inline bool
  1072. WrapNewBindingNonWrapperCachedObject(JSContext* cx,
  1073. JS::Handle<JSObject*> scopeArg,
  1074. T* value,
  1075. JS::MutableHandle<JS::Value> rval,
  1076. JS::Handle<JSObject*> givenProto = nullptr)
  1077. {
  1078. static_assert(IsRefcounted<T>::value, "Don't pass owned classes in here.");
  1079. MOZ_ASSERT(value);
  1080. // We try to wrap in the compartment of the underlying object of "scope"
  1081. JS::Rooted<JSObject*> obj(cx);
  1082. {
  1083. // scope for the JSAutoCompartment so that we restore the compartment
  1084. // before we call JS_WrapValue.
  1085. Maybe<JSAutoCompartment> ac;
  1086. // Maybe<Handle> doesn't so much work, and in any case, adding
  1087. // more Maybe (one for a Rooted and one for a Handle) adds more
  1088. // code (and branches!) than just adding a single rooted.
  1089. JS::Rooted<JSObject*> scope(cx, scopeArg);
  1090. JS::Rooted<JSObject*> proto(cx, givenProto);
  1091. if (js::IsWrapper(scope)) {
  1092. scope = js::CheckedUnwrap(scope, /* stopAtWindowProxy = */ false);
  1093. if (!scope)
  1094. return false;
  1095. ac.emplace(cx, scope);
  1096. if (!JS_WrapObject(cx, &proto)) {
  1097. return false;
  1098. }
  1099. }
  1100. MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
  1101. if (!value->WrapObject(cx, proto, &obj)) {
  1102. return false;
  1103. }
  1104. }
  1105. // We can end up here in all sorts of compartments, per above. Make
  1106. // sure to JS_WrapValue!
  1107. rval.set(JS::ObjectValue(*obj));
  1108. return MaybeWrapObjectValue(cx, rval);
  1109. }
  1110. // Create a JSObject wrapping "value", for cases when "value" is a
  1111. // non-wrapper-cached owned object using WebIDL bindings. "value" must implement a
  1112. // WrapObject() method taking a JSContext, a scope, and a boolean outparam that
  1113. // is true if the JSObject took ownership
  1114. template <class T>
  1115. inline bool
  1116. WrapNewBindingNonWrapperCachedObject(JSContext* cx,
  1117. JS::Handle<JSObject*> scopeArg,
  1118. nsAutoPtr<T>& value,
  1119. JS::MutableHandle<JS::Value> rval,
  1120. JS::Handle<JSObject*> givenProto = nullptr)
  1121. {
  1122. static_assert(!IsRefcounted<T>::value, "Only pass owned classes in here.");
  1123. // We do a runtime check on value, because otherwise we might in
  1124. // fact end up wrapping a null and invoking methods on it later.
  1125. if (!value) {
  1126. NS_RUNTIMEABORT("Don't try to wrap null objects");
  1127. }
  1128. // We try to wrap in the compartment of the underlying object of "scope"
  1129. JS::Rooted<JSObject*> obj(cx);
  1130. {
  1131. // scope for the JSAutoCompartment so that we restore the compartment
  1132. // before we call JS_WrapValue.
  1133. Maybe<JSAutoCompartment> ac;
  1134. // Maybe<Handle> doesn't so much work, and in any case, adding
  1135. // more Maybe (one for a Rooted and one for a Handle) adds more
  1136. // code (and branches!) than just adding a single rooted.
  1137. JS::Rooted<JSObject*> scope(cx, scopeArg);
  1138. JS::Rooted<JSObject*> proto(cx, givenProto);
  1139. if (js::IsWrapper(scope)) {
  1140. scope = js::CheckedUnwrap(scope, /* stopAtWindowProxy = */ false);
  1141. if (!scope)
  1142. return false;
  1143. ac.emplace(cx, scope);
  1144. if (!JS_WrapObject(cx, &proto)) {
  1145. return false;
  1146. }
  1147. }
  1148. MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
  1149. if (!value->WrapObject(cx, proto, &obj)) {
  1150. return false;
  1151. }
  1152. value.forget();
  1153. }
  1154. // We can end up here in all sorts of compartments, per above. Make
  1155. // sure to JS_WrapValue!
  1156. rval.set(JS::ObjectValue(*obj));
  1157. return MaybeWrapObjectValue(cx, rval);
  1158. }
  1159. // Helper for smart pointers (nsRefPtr/nsCOMPtr).
  1160. template <template <typename> class SmartPtr, typename T,
  1161. typename U=typename EnableIf<IsRefcounted<T>::value, T>::Type,
  1162. typename V=typename EnableIf<IsSmartPtr<SmartPtr<T>>::value, T>::Type>
  1163. inline bool
  1164. WrapNewBindingNonWrapperCachedObject(JSContext* cx, JS::Handle<JSObject*> scope,
  1165. const SmartPtr<T>& value,
  1166. JS::MutableHandle<JS::Value> rval,
  1167. JS::Handle<JSObject*> givenProto = nullptr)
  1168. {
  1169. return WrapNewBindingNonWrapperCachedObject(cx, scope, value.get(), rval,
  1170. givenProto);
  1171. }
  1172. // Helper for object references (as opposed to pointers).
  1173. template <typename T,
  1174. typename U=typename EnableIf<!IsSmartPtr<T>::value, T>::Type>
  1175. inline bool
  1176. WrapNewBindingNonWrapperCachedObject(JSContext* cx, JS::Handle<JSObject*> scope,
  1177. T& value,
  1178. JS::MutableHandle<JS::Value> rval,
  1179. JS::Handle<JSObject*> givenProto = nullptr)
  1180. {
  1181. return WrapNewBindingNonWrapperCachedObject(cx, scope, &value, rval,
  1182. givenProto);
  1183. }
  1184. // Only set allowNativeWrapper to false if you really know you need it, if in
  1185. // doubt use true. Setting it to false disables security wrappers.
  1186. bool
  1187. NativeInterface2JSObjectAndThrowIfFailed(JSContext* aCx,
  1188. JS::Handle<JSObject*> aScope,
  1189. JS::MutableHandle<JS::Value> aRetval,
  1190. xpcObjectHelper& aHelper,
  1191. const nsIID* aIID,
  1192. bool aAllowNativeWrapper);
  1193. /**
  1194. * A method to handle new-binding wrap failure, by possibly falling back to
  1195. * wrapping as a non-new-binding object.
  1196. */
  1197. template <class T>
  1198. MOZ_ALWAYS_INLINE bool
  1199. HandleNewBindingWrappingFailure(JSContext* cx, JS::Handle<JSObject*> scope,
  1200. T* value, JS::MutableHandle<JS::Value> rval)
  1201. {
  1202. if (JS_IsExceptionPending(cx)) {
  1203. return false;
  1204. }
  1205. qsObjectHelper helper(value, GetWrapperCache(value));
  1206. return NativeInterface2JSObjectAndThrowIfFailed(cx, scope, rval,
  1207. helper, nullptr, true);
  1208. }
  1209. // Helper for calling HandleNewBindingWrappingFailure with smart pointers
  1210. // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
  1211. template <class T, bool isSmartPtr=IsSmartPtr<T>::value>
  1212. struct HandleNewBindingWrappingFailureHelper
  1213. {
  1214. static inline bool Wrap(JSContext* cx, JS::Handle<JSObject*> scope,
  1215. const T& value, JS::MutableHandle<JS::Value> rval)
  1216. {
  1217. return HandleNewBindingWrappingFailure(cx, scope, value.get(), rval);
  1218. }
  1219. };
  1220. template <class T>
  1221. struct HandleNewBindingWrappingFailureHelper<T, false>
  1222. {
  1223. static inline bool Wrap(JSContext* cx, JS::Handle<JSObject*> scope, T& value,
  1224. JS::MutableHandle<JS::Value> rval)
  1225. {
  1226. return HandleNewBindingWrappingFailure(cx, scope, &value, rval);
  1227. }
  1228. };
  1229. template<class T>
  1230. inline bool
  1231. HandleNewBindingWrappingFailure(JSContext* cx, JS::Handle<JSObject*> scope,
  1232. T& value, JS::MutableHandle<JS::Value> rval)
  1233. {
  1234. return HandleNewBindingWrappingFailureHelper<T>::Wrap(cx, scope, value, rval);
  1235. }
  1236. template<bool Fatal>
  1237. inline bool
  1238. EnumValueNotFound(JSContext* cx, JS::HandleString str, const char* type,
  1239. const char* sourceDescription);
  1240. template<>
  1241. inline bool
  1242. EnumValueNotFound<false>(JSContext* cx, JS::HandleString str, const char* type,
  1243. const char* sourceDescription)
  1244. {
  1245. // TODO: Log a warning to the console.
  1246. return true;
  1247. }
  1248. template<>
  1249. inline bool
  1250. EnumValueNotFound<true>(JSContext* cx, JS::HandleString str, const char* type,
  1251. const char* sourceDescription)
  1252. {
  1253. JSAutoByteString deflated;
  1254. if (!deflated.encodeUtf8(cx, str)) {
  1255. return false;
  1256. }
  1257. return ThrowErrorMessage(cx, MSG_INVALID_ENUM_VALUE, sourceDescription,
  1258. deflated.ptr(), type);
  1259. }
  1260. template<typename CharT>
  1261. inline int
  1262. FindEnumStringIndexImpl(const CharT* chars, size_t length, const EnumEntry* values)
  1263. {
  1264. int i = 0;
  1265. for (const EnumEntry* value = values; value->value; ++value, ++i) {
  1266. if (length != value->length) {
  1267. continue;
  1268. }
  1269. bool equal = true;
  1270. const char* val = value->value;
  1271. for (size_t j = 0; j != length; ++j) {
  1272. if (unsigned(val[j]) != unsigned(chars[j])) {
  1273. equal = false;
  1274. break;
  1275. }
  1276. }
  1277. if (equal) {
  1278. return i;
  1279. }
  1280. }
  1281. return -1;
  1282. }
  1283. template<bool InvalidValueFatal>
  1284. inline bool
  1285. FindEnumStringIndex(JSContext* cx, JS::Handle<JS::Value> v, const EnumEntry* values,
  1286. const char* type, const char* sourceDescription, int* index)
  1287. {
  1288. // JS_StringEqualsAscii is slow as molasses, so don't use it here.
  1289. JS::RootedString str(cx, JS::ToString(cx, v));
  1290. if (!str) {
  1291. return false;
  1292. }
  1293. {
  1294. size_t length;
  1295. JS::AutoCheckCannotGC nogc;
  1296. if (js::StringHasLatin1Chars(str)) {
  1297. const JS::Latin1Char* chars = JS_GetLatin1StringCharsAndLength(cx, nogc, str,
  1298. &length);
  1299. if (!chars) {
  1300. return false;
  1301. }
  1302. *index = FindEnumStringIndexImpl(chars, length, values);
  1303. } else {
  1304. const char16_t* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, str,
  1305. &length);
  1306. if (!chars) {
  1307. return false;
  1308. }
  1309. *index = FindEnumStringIndexImpl(chars, length, values);
  1310. }
  1311. if (*index >= 0) {
  1312. return true;
  1313. }
  1314. }
  1315. return EnumValueNotFound<InvalidValueFatal>(cx, str, type, sourceDescription);
  1316. }
  1317. inline nsWrapperCache*
  1318. GetWrapperCache(const ParentObject& aParentObject)
  1319. {
  1320. return aParentObject.mWrapperCache;
  1321. }
  1322. template<class T>
  1323. inline T*
  1324. GetParentPointer(T* aObject)
  1325. {
  1326. return aObject;
  1327. }
  1328. inline nsISupports*
  1329. GetParentPointer(const ParentObject& aObject)
  1330. {
  1331. return aObject.mObject;
  1332. }
  1333. template <typename T>
  1334. inline bool
  1335. GetUseXBLScope(T* aParentObject)
  1336. {
  1337. return false;
  1338. }
  1339. inline bool
  1340. GetUseXBLScope(const ParentObject& aParentObject)
  1341. {
  1342. return aParentObject.mUseXBLScope;
  1343. }
  1344. template<class T>
  1345. inline void
  1346. ClearWrapper(T* p, nsWrapperCache* cache)
  1347. {
  1348. cache->ClearWrapper();
  1349. }
  1350. template<class T>
  1351. inline void
  1352. ClearWrapper(T* p, void*)
  1353. {
  1354. nsWrapperCache* cache;
  1355. CallQueryInterface(p, &cache);
  1356. ClearWrapper(p, cache);
  1357. }
  1358. template<class T>
  1359. inline void
  1360. UpdateWrapper(T* p, nsWrapperCache* cache, JSObject* obj, const JSObject* old)
  1361. {
  1362. JS::AutoAssertGCCallback inCallback(obj);
  1363. cache->UpdateWrapper(obj, old);
  1364. }
  1365. template<class T>
  1366. inline void
  1367. UpdateWrapper(T* p, void*, JSObject* obj, const JSObject* old)
  1368. {
  1369. JS::AutoAssertGCCallback inCallback(obj);
  1370. nsWrapperCache* cache;
  1371. CallQueryInterface(p, &cache);
  1372. UpdateWrapper(p, cache, obj, old);
  1373. }
  1374. // Attempt to preserve the wrapper, if any, for a Paris DOM bindings object.
  1375. // Return true if we successfully preserved the wrapper, or there is no wrapper
  1376. // to preserve. In the latter case we don't need to preserve the wrapper, because
  1377. // the object can only be obtained by JS once, or they cannot be meaningfully
  1378. // owned from the native side.
  1379. //
  1380. // This operation will return false only for non-nsISupports cycle-collected
  1381. // objects, because we cannot determine if they are wrappercached or not.
  1382. bool
  1383. TryPreserveWrapper(JSObject* obj);
  1384. // Can only be called with a DOM JSClass.
  1385. bool
  1386. InstanceClassHasProtoAtDepth(const js::Class* clasp,
  1387. uint32_t protoID, uint32_t depth);
  1388. // Only set allowNativeWrapper to false if you really know you need it, if in
  1389. // doubt use true. Setting it to false disables security wrappers.
  1390. bool
  1391. XPCOMObjectToJsval(JSContext* cx, JS::Handle<JSObject*> scope,
  1392. xpcObjectHelper& helper, const nsIID* iid,
  1393. bool allowNativeWrapper, JS::MutableHandle<JS::Value> rval);
  1394. // Special-cased wrapping for variants
  1395. bool
  1396. VariantToJsval(JSContext* aCx, nsIVariant* aVariant,
  1397. JS::MutableHandle<JS::Value> aRetval);
  1398. // Wrap an object "p" which is not using WebIDL bindings yet. This _will_
  1399. // actually work on WebIDL binding objects that are wrappercached, but will be
  1400. // much slower than GetOrCreateDOMReflector. "cache" must either be null or be
  1401. // the nsWrapperCache for "p".
  1402. template<class T>
  1403. inline bool
  1404. WrapObject(JSContext* cx, T* p, nsWrapperCache* cache, const nsIID* iid,
  1405. JS::MutableHandle<JS::Value> rval)
  1406. {
  1407. if (xpc_FastGetCachedWrapper(cx, cache, rval))
  1408. return true;
  1409. qsObjectHelper helper(p, cache);
  1410. JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
  1411. return XPCOMObjectToJsval(cx, scope, helper, iid, true, rval);
  1412. }
  1413. // A specialization of the above for nsIVariant, because that needs to
  1414. // do something different.
  1415. template<>
  1416. inline bool
  1417. WrapObject<nsIVariant>(JSContext* cx, nsIVariant* p,
  1418. nsWrapperCache* cache, const nsIID* iid,
  1419. JS::MutableHandle<JS::Value> rval)
  1420. {
  1421. MOZ_ASSERT(iid);
  1422. MOZ_ASSERT(iid->Equals(NS_GET_IID(nsIVariant)));
  1423. return VariantToJsval(cx, p, rval);
  1424. }
  1425. // Wrap an object "p" which is not using WebIDL bindings yet. Just like the
  1426. // variant that takes an nsWrapperCache above, but will try to auto-derive the
  1427. // nsWrapperCache* from "p".
  1428. template<class T>
  1429. inline bool
  1430. WrapObject(JSContext* cx, T* p, const nsIID* iid,
  1431. JS::MutableHandle<JS::Value> rval)
  1432. {
  1433. return WrapObject(cx, p, GetWrapperCache(p), iid, rval);
  1434. }
  1435. // Just like the WrapObject above, but without requiring you to pick which
  1436. // interface you're wrapping as. This should only be used for objects that have
  1437. // classinfo, for which it doesn't matter what IID is used to wrap.
  1438. template<class T>
  1439. inline bool
  1440. WrapObject(JSContext* cx, T* p, JS::MutableHandle<JS::Value> rval)
  1441. {
  1442. return WrapObject(cx, p, nullptr, rval);
  1443. }
  1444. // Helper to make it possible to wrap directly out of an nsCOMPtr
  1445. template<class T>
  1446. inline bool
  1447. WrapObject(JSContext* cx, const nsCOMPtr<T>& p,
  1448. const nsIID* iid, JS::MutableHandle<JS::Value> rval)
  1449. {
  1450. return WrapObject(cx, p.get(), iid, rval);
  1451. }
  1452. // Helper to make it possible to wrap directly out of an nsCOMPtr
  1453. template<class T>
  1454. inline bool
  1455. WrapObject(JSContext* cx, const nsCOMPtr<T>& p,
  1456. JS::MutableHandle<JS::Value> rval)
  1457. {
  1458. return WrapObject(cx, p, nullptr, rval);
  1459. }
  1460. // Helper to make it possible to wrap directly out of an nsRefPtr
  1461. template<class T>
  1462. inline bool
  1463. WrapObject(JSContext* cx, const RefPtr<T>& p,
  1464. const nsIID* iid, JS::MutableHandle<JS::Value> rval)
  1465. {
  1466. return WrapObject(cx, p.get(), iid, rval);
  1467. }
  1468. // Helper to make it possible to wrap directly out of an nsRefPtr
  1469. template<class T>
  1470. inline bool
  1471. WrapObject(JSContext* cx, const RefPtr<T>& p,
  1472. JS::MutableHandle<JS::Value> rval)
  1473. {
  1474. return WrapObject(cx, p, nullptr, rval);
  1475. }
  1476. // Specialization to make it easy to use WrapObject in codegen.
  1477. template<>
  1478. inline bool
  1479. WrapObject<JSObject>(JSContext* cx, JSObject* p,
  1480. JS::MutableHandle<JS::Value> rval)
  1481. {
  1482. rval.set(JS::ObjectOrNullValue(p));
  1483. return true;
  1484. }
  1485. inline bool
  1486. WrapObject(JSContext* cx, JSObject& p, JS::MutableHandle<JS::Value> rval)
  1487. {
  1488. rval.set(JS::ObjectValue(p));
  1489. return true;
  1490. }
  1491. // Given an object "p" that inherits from nsISupports, wrap it and return the
  1492. // result. Null is returned on wrapping failure. This is somewhat similar to
  1493. // WrapObject() above, but does NOT allow Xrays around the result, since we
  1494. // don't want those for our parent object.
  1495. template<typename T>
  1496. static inline JSObject*
  1497. WrapNativeISupports(JSContext* cx, T* p, nsWrapperCache* cache)
  1498. {
  1499. qsObjectHelper helper(ToSupports(p), cache);
  1500. JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
  1501. JS::Rooted<JS::Value> v(cx);
  1502. return XPCOMObjectToJsval(cx, scope, helper, nullptr, false, &v) ?
  1503. v.toObjectOrNull() :
  1504. nullptr;
  1505. }
  1506. // Fallback for when our parent is not a WebIDL binding object.
  1507. template<typename T, bool isISupports=IsBaseOf<nsISupports, T>::value>
  1508. struct WrapNativeFallback
  1509. {
  1510. static inline JSObject* Wrap(JSContext* cx, T* parent, nsWrapperCache* cache)
  1511. {
  1512. return nullptr;
  1513. }
  1514. };
  1515. // Fallback for when our parent is not a WebIDL binding object but _is_ an
  1516. // nsISupports object.
  1517. template<typename T >
  1518. struct WrapNativeFallback<T, true >
  1519. {
  1520. static inline JSObject* Wrap(JSContext* cx, T* parent, nsWrapperCache* cache)
  1521. {
  1522. return WrapNativeISupports(cx, parent, cache);
  1523. }
  1524. };
  1525. // Wrapping of our native parent, for cases when it's a WebIDL object (though
  1526. // possibly preffed off).
  1527. template<typename T, bool hasWrapObject=NativeHasMember<T>::WrapObject>
  1528. struct WrapNativeHelper
  1529. {
  1530. static inline JSObject* Wrap(JSContext* cx, T* parent, nsWrapperCache* cache)
  1531. {
  1532. MOZ_ASSERT(cache);
  1533. JSObject* obj;
  1534. if ((obj = cache->GetWrapper())) {
  1535. // GetWrapper always unmarks gray.
  1536. MOZ_ASSERT(!JS::ObjectIsMarkedGray(obj));
  1537. return obj;
  1538. }
  1539. // Inline this here while we have non-dom objects in wrapper caches.
  1540. if (!CouldBeDOMBinding(parent)) {
  1541. // WrapNativeFallback never returns a gray thing.
  1542. obj = WrapNativeFallback<T>::Wrap(cx, parent, cache);
  1543. MOZ_ASSERT_IF(obj, !JS::ObjectIsMarkedGray(obj));
  1544. } else {
  1545. // WrapObject never returns a gray thing.
  1546. obj = parent->WrapObject(cx, nullptr);
  1547. MOZ_ASSERT_IF(obj, !JS::ObjectIsMarkedGray(obj));
  1548. }
  1549. return obj;
  1550. }
  1551. };
  1552. // Wrapping of our native parent, for cases when it's not a WebIDL object. In
  1553. // this case it must be nsISupports.
  1554. template<typename T>
  1555. struct WrapNativeHelper<T, false>
  1556. {
  1557. static inline JSObject* Wrap(JSContext* cx, T* parent, nsWrapperCache* cache)
  1558. {
  1559. JSObject* obj;
  1560. if (cache && (obj = cache->GetWrapper())) {
  1561. #ifdef DEBUG
  1562. JS::Rooted<JSObject*> rootedObj(cx, obj);
  1563. NS_ASSERTION(WrapNativeISupports(cx, parent, cache) == rootedObj,
  1564. "Unexpected object in nsWrapperCache");
  1565. obj = rootedObj;
  1566. #endif
  1567. MOZ_ASSERT(!JS::ObjectIsMarkedGray(obj));
  1568. return obj;
  1569. }
  1570. obj = WrapNativeISupports(cx, parent, cache);
  1571. MOZ_ASSERT_IF(obj, !JS::ObjectIsMarkedGray(obj));
  1572. return obj;
  1573. }
  1574. };
  1575. // Finding the associated global for an object.
  1576. template<typename T>
  1577. static inline JSObject*
  1578. FindAssociatedGlobal(JSContext* cx, T* p, nsWrapperCache* cache,
  1579. bool useXBLScope = false)
  1580. {
  1581. if (!p) {
  1582. return JS::CurrentGlobalOrNull(cx);
  1583. }
  1584. JSObject* obj = WrapNativeHelper<T>::Wrap(cx, p, cache);
  1585. if (!obj) {
  1586. return nullptr;
  1587. }
  1588. MOZ_ASSERT(!JS::ObjectIsMarkedGray(obj));
  1589. obj = js::GetGlobalForObjectCrossCompartment(obj);
  1590. if (!useXBLScope) {
  1591. return obj;
  1592. }
  1593. // If useXBLScope is true, it means that the canonical reflector for this
  1594. // native object should live in the content XBL scope. Note that we never put
  1595. // anonymous content inside an add-on scope.
  1596. if (xpc::IsInContentXBLScope(obj)) {
  1597. return obj;
  1598. }
  1599. JS::Rooted<JSObject*> rootedObj(cx, obj);
  1600. JSObject* xblScope = xpc::GetXBLScope(cx, rootedObj);
  1601. MOZ_ASSERT_IF(xblScope, JS_IsGlobalObject(xblScope));
  1602. MOZ_ASSERT_IF(xblScope, !JS::ObjectIsMarkedGray(xblScope));
  1603. return xblScope;
  1604. }
  1605. // Finding of the associated global for an object, when we don't want to
  1606. // explicitly pass in things like the nsWrapperCache for it.
  1607. template<typename T>
  1608. static inline JSObject*
  1609. FindAssociatedGlobal(JSContext* cx, const T& p)
  1610. {
  1611. return FindAssociatedGlobal(cx, GetParentPointer(p), GetWrapperCache(p), GetUseXBLScope(p));
  1612. }
  1613. // Specialization for the case of nsIGlobalObject, since in that case
  1614. // we can just get the JSObject* directly.
  1615. template<>
  1616. inline JSObject*
  1617. FindAssociatedGlobal(JSContext* cx, nsIGlobalObject* const& p)
  1618. {
  1619. if (!p) {
  1620. return JS::CurrentGlobalOrNull(cx);
  1621. }
  1622. JSObject* global = p->GetGlobalJSObject();
  1623. if (!global) {
  1624. return nullptr;
  1625. }
  1626. MOZ_ASSERT(JS_IsGlobalObject(global));
  1627. // This object could be gray if the nsIGlobalObject is the only thing keeping
  1628. // it alive.
  1629. JS::ExposeObjectToActiveJS(global);
  1630. return global;
  1631. }
  1632. template<typename T,
  1633. bool hasAssociatedGlobal=NativeHasMember<T>::GetParentObject>
  1634. struct FindAssociatedGlobalForNative
  1635. {
  1636. static JSObject* Get(JSContext* cx, JS::Handle<JSObject*> obj)
  1637. {
  1638. MOZ_ASSERT(js::IsObjectInContextCompartment(obj, cx));
  1639. T* native = UnwrapDOMObject<T>(obj);
  1640. return FindAssociatedGlobal(cx, native->GetParentObject());
  1641. }
  1642. };
  1643. template<typename T>
  1644. struct FindAssociatedGlobalForNative<T, false>
  1645. {
  1646. static JSObject* Get(JSContext* cx, JS::Handle<JSObject*> obj)
  1647. {
  1648. MOZ_CRASH();
  1649. return nullptr;
  1650. }
  1651. };
  1652. // Helper for calling GetOrCreateDOMReflector with smart pointers
  1653. // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
  1654. template <class T, bool isSmartPtr=IsSmartPtr<T>::value>
  1655. struct GetOrCreateDOMReflectorHelper
  1656. {
  1657. static inline bool GetOrCreate(JSContext* cx, const T& value,
  1658. JS::Handle<JSObject*> givenProto,
  1659. JS::MutableHandle<JS::Value> rval)
  1660. {
  1661. return GetOrCreateDOMReflector(cx, value.get(), rval, givenProto);
  1662. }
  1663. };
  1664. template <class T>
  1665. struct GetOrCreateDOMReflectorHelper<T, false>
  1666. {
  1667. static inline bool GetOrCreate(JSContext* cx, T& value,
  1668. JS::Handle<JSObject*> givenProto,
  1669. JS::MutableHandle<JS::Value> rval)
  1670. {
  1671. static_assert(IsRefcounted<T>::value, "Don't pass owned classes in here.");
  1672. return GetOrCreateDOMReflector(cx, &value, rval, givenProto);
  1673. }
  1674. };
  1675. template<class T>
  1676. inline bool
  1677. GetOrCreateDOMReflector(JSContext* cx, T& value,
  1678. JS::MutableHandle<JS::Value> rval,
  1679. JS::Handle<JSObject*> givenProto = nullptr)
  1680. {
  1681. return GetOrCreateDOMReflectorHelper<T>::GetOrCreate(cx, value, givenProto,
  1682. rval);
  1683. }
  1684. // Helper for calling GetOrCreateDOMReflectorNoWrap with smart pointers
  1685. // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
  1686. template <class T, bool isSmartPtr=IsSmartPtr<T>::value>
  1687. struct GetOrCreateDOMReflectorNoWrapHelper
  1688. {
  1689. static inline bool GetOrCreate(JSContext* cx, const T& value,
  1690. JS::MutableHandle<JS::Value> rval)
  1691. {
  1692. return GetOrCreateDOMReflectorNoWrap(cx, value.get(), rval);
  1693. }
  1694. };
  1695. template <class T>
  1696. struct GetOrCreateDOMReflectorNoWrapHelper<T, false>
  1697. {
  1698. static inline bool GetOrCreate(JSContext* cx, T& value,
  1699. JS::MutableHandle<JS::Value> rval)
  1700. {
  1701. return GetOrCreateDOMReflectorNoWrap(cx, &value, rval);
  1702. }
  1703. };
  1704. template<class T>
  1705. inline bool
  1706. GetOrCreateDOMReflectorNoWrap(JSContext* cx, T& value,
  1707. JS::MutableHandle<JS::Value> rval)
  1708. {
  1709. return
  1710. GetOrCreateDOMReflectorNoWrapHelper<T>::GetOrCreate(cx, value, rval);
  1711. }
  1712. template <class T>
  1713. inline JSObject*
  1714. GetCallbackFromCallbackObject(T* aObj)
  1715. {
  1716. return aObj->Callback();
  1717. }
  1718. // Helper for getting the callback JSObject* of a smart ptr around a
  1719. // CallbackObject or a reference to a CallbackObject or something like
  1720. // that.
  1721. template <class T, bool isSmartPtr=IsSmartPtr<T>::value>
  1722. struct GetCallbackFromCallbackObjectHelper
  1723. {
  1724. static inline JSObject* Get(const T& aObj)
  1725. {
  1726. return GetCallbackFromCallbackObject(aObj.get());
  1727. }
  1728. };
  1729. template <class T>
  1730. struct GetCallbackFromCallbackObjectHelper<T, false>
  1731. {
  1732. static inline JSObject* Get(T& aObj)
  1733. {
  1734. return GetCallbackFromCallbackObject(&aObj);
  1735. }
  1736. };
  1737. template<class T>
  1738. inline JSObject*
  1739. GetCallbackFromCallbackObject(T& aObj)
  1740. {
  1741. return GetCallbackFromCallbackObjectHelper<T>::Get(aObj);
  1742. }
  1743. static inline bool
  1744. AtomizeAndPinJSString(JSContext* cx, jsid& id, const char* chars)
  1745. {
  1746. if (JSString *str = ::JS_AtomizeAndPinString(cx, chars)) {
  1747. id = INTERNED_STRING_TO_JSID(cx, str);
  1748. return true;
  1749. }
  1750. return false;
  1751. }
  1752. // Spec needs a name property
  1753. template <typename Spec>
  1754. static bool
  1755. InitIds(JSContext* cx, const Prefable<Spec>* prefableSpecs, jsid* ids)
  1756. {
  1757. MOZ_ASSERT(prefableSpecs);
  1758. MOZ_ASSERT(prefableSpecs->specs);
  1759. do {
  1760. // We ignore whether the set of ids is enabled and just intern all the IDs,
  1761. // because this is only done once per application runtime.
  1762. Spec* spec = prefableSpecs->specs;
  1763. do {
  1764. if (!JS::PropertySpecNameToPermanentId(cx, spec->name, ids)) {
  1765. return false;
  1766. }
  1767. } while (++ids, (++spec)->name);
  1768. // We ran out of ids for that pref. Put a JSID_VOID in on the id
  1769. // corresponding to the list terminator for the pref.
  1770. *ids = JSID_VOID;
  1771. ++ids;
  1772. } while ((++prefableSpecs)->specs);
  1773. return true;
  1774. }
  1775. bool
  1776. QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp);
  1777. template <class T>
  1778. struct
  1779. WantsQueryInterface
  1780. {
  1781. static_assert(IsBaseOf<nsISupports, T>::value,
  1782. "QueryInterface can't work without an nsISupports.");
  1783. static bool Enabled(JSContext* aCx, JSObject* aGlobal)
  1784. {
  1785. return NS_IsMainThread() && IsChromeOrXBL(aCx, aGlobal);
  1786. }
  1787. };
  1788. void
  1789. GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
  1790. nsWrapperCache* aCache, nsIJSID* aIID,
  1791. JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError);
  1792. template<class T>
  1793. void
  1794. GetInterface(JSContext* aCx, T* aThis, nsIJSID* aIID,
  1795. JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError)
  1796. {
  1797. GetInterfaceImpl(aCx, aThis, aThis, aIID, aRetval, aError);
  1798. }
  1799. bool
  1800. ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
  1801. bool
  1802. ThrowConstructorWithoutNew(JSContext* cx, const char* name);
  1803. bool
  1804. GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
  1805. JS::Handle<JS::Value> receiver, JS::Handle<jsid> id,
  1806. bool* found, JS::MutableHandle<JS::Value> vp);
  1807. //
  1808. bool
  1809. HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
  1810. JS::Handle<jsid> id, bool* has);
  1811. // Append the property names in "names" to "props". If
  1812. // shadowPrototypeProperties is false then skip properties that are also
  1813. // present on the proto chain of proxy. If shadowPrototypeProperties is true,
  1814. // then the "proxy" argument is ignored.
  1815. bool
  1816. AppendNamedPropertyIds(JSContext* cx, JS::Handle<JSObject*> proxy,
  1817. nsTArray<nsString>& names,
  1818. bool shadowPrototypeProperties, JS::AutoIdVector& props);
  1819. namespace binding_detail {
  1820. class FastErrorResult :
  1821. public mozilla::binding_danger::TErrorResult<
  1822. mozilla::binding_danger::JustAssertCleanupPolicy>
  1823. {
  1824. };
  1825. } // namespace binding_detail
  1826. enum StringificationBehavior {
  1827. eStringify,
  1828. eEmpty,
  1829. eNull
  1830. };
  1831. template<typename T>
  1832. static inline bool
  1833. ConvertJSValueToString(JSContext* cx, JS::Handle<JS::Value> v,
  1834. StringificationBehavior nullBehavior,
  1835. StringificationBehavior undefinedBehavior,
  1836. T& result)
  1837. {
  1838. JSString *s;
  1839. if (v.isString()) {
  1840. s = v.toString();
  1841. } else {
  1842. StringificationBehavior behavior;
  1843. if (v.isNull()) {
  1844. behavior = nullBehavior;
  1845. } else if (v.isUndefined()) {
  1846. behavior = undefinedBehavior;
  1847. } else {
  1848. behavior = eStringify;
  1849. }
  1850. if (behavior != eStringify) {
  1851. if (behavior == eEmpty) {
  1852. result.Truncate();
  1853. } else {
  1854. result.SetIsVoid(true);
  1855. }
  1856. return true;
  1857. }
  1858. s = JS::ToString(cx, v);
  1859. if (!s) {
  1860. return false;
  1861. }
  1862. }
  1863. return AssignJSString(cx, result, s);
  1864. }
  1865. template<typename T>
  1866. static inline bool
  1867. ConvertJSValueToString(JSContext* cx, JS::Handle<JS::Value> v, T& result)
  1868. {
  1869. return ConvertJSValueToString(cx, v, eStringify, eStringify, result);
  1870. }
  1871. void
  1872. NormalizeUSVString(nsAString& aString);
  1873. void
  1874. NormalizeUSVString(binding_detail::FakeString& aString);
  1875. template<typename T>
  1876. static inline bool
  1877. ConvertJSValueToUSVString(JSContext* cx, JS::Handle<JS::Value> v, T& result)
  1878. {
  1879. if (!ConvertJSValueToString(cx, v, eStringify, eStringify, result)) {
  1880. return false;
  1881. }
  1882. NormalizeUSVString(result);
  1883. return true;
  1884. }
  1885. template<typename T>
  1886. inline bool
  1887. ConvertIdToString(JSContext* cx, JS::HandleId id, T& result, bool& isSymbol)
  1888. {
  1889. if (MOZ_LIKELY(JSID_IS_STRING(id))) {
  1890. if (!AssignJSString(cx, result, JSID_TO_STRING(id))) {
  1891. return false;
  1892. }
  1893. } else if (JSID_IS_SYMBOL(id)) {
  1894. isSymbol = true;
  1895. return true;
  1896. } else {
  1897. JS::RootedValue nameVal(cx, js::IdToValue(id));
  1898. if (!ConvertJSValueToString(cx, nameVal, eStringify, eStringify, result)) {
  1899. return false;
  1900. }
  1901. }
  1902. isSymbol = false;
  1903. return true;
  1904. }
  1905. bool
  1906. ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
  1907. bool nullable, nsACString& result);
  1908. inline bool
  1909. ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
  1910. nsACString& result)
  1911. {
  1912. return ConvertJSValueToByteString(cx, v, false, result);
  1913. }
  1914. template<typename T>
  1915. void DoTraceSequence(JSTracer* trc, FallibleTArray<T>& seq);
  1916. template<typename T>
  1917. void DoTraceSequence(JSTracer* trc, InfallibleTArray<T>& seq);
  1918. // Class used to trace sequences, with specializations for various
  1919. // sequence types.
  1920. template<typename T,
  1921. bool isDictionary=IsBaseOf<DictionaryBase, T>::value,
  1922. bool isTypedArray=IsBaseOf<AllTypedArraysBase, T>::value,
  1923. bool isOwningUnion=IsBaseOf<AllOwningUnionBase, T>::value>
  1924. class SequenceTracer
  1925. {
  1926. explicit SequenceTracer() = delete; // Should never be instantiated
  1927. };
  1928. // sequence<object> or sequence<object?>
  1929. template<>
  1930. class SequenceTracer<JSObject*, false, false, false>
  1931. {
  1932. explicit SequenceTracer() = delete; // Should never be instantiated
  1933. public:
  1934. static void TraceSequence(JSTracer* trc, JSObject** objp, JSObject** end) {
  1935. for (; objp != end; ++objp) {
  1936. JS::UnsafeTraceRoot(trc, objp, "sequence<object>");
  1937. }
  1938. }
  1939. };
  1940. // sequence<any>
  1941. template<>
  1942. class SequenceTracer<JS::Value, false, false, false>
  1943. {
  1944. explicit SequenceTracer() = delete; // Should never be instantiated
  1945. public:
  1946. static void TraceSequence(JSTracer* trc, JS::Value* valp, JS::Value* end) {
  1947. for (; valp != end; ++valp) {
  1948. JS::UnsafeTraceRoot(trc, valp, "sequence<any>");
  1949. }
  1950. }
  1951. };
  1952. // sequence<sequence<T>>
  1953. template<typename T>
  1954. class SequenceTracer<Sequence<T>, false, false, false>
  1955. {
  1956. explicit SequenceTracer() = delete; // Should never be instantiated
  1957. public:
  1958. static void TraceSequence(JSTracer* trc, Sequence<T>* seqp, Sequence<T>* end) {
  1959. for (; seqp != end; ++seqp) {
  1960. DoTraceSequence(trc, *seqp);
  1961. }
  1962. }
  1963. };
  1964. // sequence<sequence<T>> as return value
  1965. template<typename T>
  1966. class SequenceTracer<nsTArray<T>, false, false, false>
  1967. {
  1968. explicit SequenceTracer() = delete; // Should never be instantiated
  1969. public:
  1970. static void TraceSequence(JSTracer* trc, nsTArray<T>* seqp, nsTArray<T>* end) {
  1971. for (; seqp != end; ++seqp) {
  1972. DoTraceSequence(trc, *seqp);
  1973. }
  1974. }
  1975. };
  1976. // sequence<someDictionary>
  1977. template<typename T>
  1978. class SequenceTracer<T, true, false, false>
  1979. {
  1980. explicit SequenceTracer() = delete; // Should never be instantiated
  1981. public:
  1982. static void TraceSequence(JSTracer* trc, T* dictp, T* end) {
  1983. for (; dictp != end; ++dictp) {
  1984. dictp->TraceDictionary(trc);
  1985. }
  1986. }
  1987. };
  1988. // sequence<SomeTypedArray>
  1989. template<typename T>
  1990. class SequenceTracer<T, false, true, false>
  1991. {
  1992. explicit SequenceTracer() = delete; // Should never be instantiated
  1993. public:
  1994. static void TraceSequence(JSTracer* trc, T* arrayp, T* end) {
  1995. for (; arrayp != end; ++arrayp) {
  1996. arrayp->TraceSelf(trc);
  1997. }
  1998. }
  1999. };
  2000. // sequence<SomeOwningUnion>
  2001. template<typename T>
  2002. class SequenceTracer<T, false, false, true>
  2003. {
  2004. explicit SequenceTracer() = delete; // Should never be instantiated
  2005. public:
  2006. static void TraceSequence(JSTracer* trc, T* arrayp, T* end) {
  2007. for (; arrayp != end; ++arrayp) {
  2008. arrayp->TraceUnion(trc);
  2009. }
  2010. }
  2011. };
  2012. // sequence<T?> with T? being a Nullable<T>
  2013. template<typename T>
  2014. class SequenceTracer<Nullable<T>, false, false, false>
  2015. {
  2016. explicit SequenceTracer() = delete; // Should never be instantiated
  2017. public:
  2018. static void TraceSequence(JSTracer* trc, Nullable<T>* seqp,
  2019. Nullable<T>* end) {
  2020. for (; seqp != end; ++seqp) {
  2021. if (!seqp->IsNull()) {
  2022. // Pretend like we actually have a length-one sequence here so
  2023. // we can do template instantiation correctly for T.
  2024. T& val = seqp->Value();
  2025. T* ptr = &val;
  2026. SequenceTracer<T>::TraceSequence(trc, ptr, ptr+1);
  2027. }
  2028. }
  2029. }
  2030. };
  2031. template<typename K, typename V>
  2032. void TraceRecord(JSTracer* trc, Record<K, V>& record)
  2033. {
  2034. for (auto& entry : record.Entries()) {
  2035. // Act like it's a one-element sequence to leverage all that infrastructure.
  2036. SequenceTracer<V>::TraceSequence(trc, &entry.mValue, &entry.mValue + 1);
  2037. }
  2038. }
  2039. // sequence<record>
  2040. template<typename K, typename V>
  2041. class SequenceTracer<Record<K, V>, false, false, false>
  2042. {
  2043. explicit SequenceTracer() = delete; // Should never be instantiated
  2044. public:
  2045. static void TraceSequence(JSTracer* trc, Record<K, V>* seqp,
  2046. Record<K, V>* end) {
  2047. for (; seqp != end; ++seqp) {
  2048. TraceRecord(trc, *seqp);
  2049. }
  2050. }
  2051. };
  2052. template<typename T>
  2053. void DoTraceSequence(JSTracer* trc, FallibleTArray<T>& seq)
  2054. {
  2055. SequenceTracer<T>::TraceSequence(trc, seq.Elements(),
  2056. seq.Elements() + seq.Length());
  2057. }
  2058. template<typename T>
  2059. void DoTraceSequence(JSTracer* trc, InfallibleTArray<T>& seq)
  2060. {
  2061. SequenceTracer<T>::TraceSequence(trc, seq.Elements(),
  2062. seq.Elements() + seq.Length());
  2063. }
  2064. // Rooter class for sequences; this is what we mostly use in the codegen
  2065. template<typename T>
  2066. class MOZ_RAII SequenceRooter final : private JS::CustomAutoRooter
  2067. {
  2068. public:
  2069. SequenceRooter(JSContext *aCx, FallibleTArray<T>* aSequence
  2070. MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  2071. : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
  2072. mFallibleArray(aSequence),
  2073. mSequenceType(eFallibleArray)
  2074. {
  2075. }
  2076. SequenceRooter(JSContext *aCx, InfallibleTArray<T>* aSequence
  2077. MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  2078. : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
  2079. mInfallibleArray(aSequence),
  2080. mSequenceType(eInfallibleArray)
  2081. {
  2082. }
  2083. SequenceRooter(JSContext *aCx, Nullable<nsTArray<T> >* aSequence
  2084. MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  2085. : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
  2086. mNullableArray(aSequence),
  2087. mSequenceType(eNullableArray)
  2088. {
  2089. }
  2090. private:
  2091. enum SequenceType {
  2092. eInfallibleArray,
  2093. eFallibleArray,
  2094. eNullableArray
  2095. };
  2096. virtual void trace(JSTracer *trc) override
  2097. {
  2098. if (mSequenceType == eFallibleArray) {
  2099. DoTraceSequence(trc, *mFallibleArray);
  2100. } else if (mSequenceType == eInfallibleArray) {
  2101. DoTraceSequence(trc, *mInfallibleArray);
  2102. } else {
  2103. MOZ_ASSERT(mSequenceType == eNullableArray);
  2104. if (!mNullableArray->IsNull()) {
  2105. DoTraceSequence(trc, mNullableArray->Value());
  2106. }
  2107. }
  2108. }
  2109. union {
  2110. InfallibleTArray<T>* mInfallibleArray;
  2111. FallibleTArray<T>* mFallibleArray;
  2112. Nullable<nsTArray<T> >* mNullableArray;
  2113. };
  2114. SequenceType mSequenceType;
  2115. };
  2116. // Rooter class for Record; this is what we mostly use in the codegen.
  2117. template<typename K, typename V>
  2118. class MOZ_RAII RecordRooter final : private JS::CustomAutoRooter
  2119. {
  2120. public:
  2121. RecordRooter(JSContext *aCx, Record<K, V>* aRecord
  2122. MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  2123. : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
  2124. mRecord(aRecord),
  2125. mRecordType(eRecord)
  2126. {
  2127. }
  2128. RecordRooter(JSContext *aCx, Nullable<Record<K, V>>* aRecord
  2129. MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  2130. : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
  2131. mNullableRecord(aRecord),
  2132. mRecordType(eNullableRecord)
  2133. {
  2134. }
  2135. private:
  2136. enum RecordType {
  2137. eRecord,
  2138. eNullableRecord
  2139. };
  2140. virtual void trace(JSTracer *trc) override
  2141. {
  2142. if (mRecordType == eRecord) {
  2143. TraceRecord(trc, *mRecord);
  2144. } else {
  2145. MOZ_ASSERT(mRecordType == eNullableRecord);
  2146. if (!mNullableRecord->IsNull()) {
  2147. TraceRecord(trc, mNullableRecord->Value());
  2148. }
  2149. }
  2150. }
  2151. union {
  2152. Record<K, V>* mRecord;
  2153. Nullable<Record<K, V>>* mNullableRecord;
  2154. };
  2155. RecordType mRecordType;
  2156. };
  2157. template<typename T>
  2158. class MOZ_RAII RootedUnion : public T,
  2159. private JS::CustomAutoRooter
  2160. {
  2161. public:
  2162. explicit RootedUnion(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
  2163. T(),
  2164. JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
  2165. {
  2166. }
  2167. virtual void trace(JSTracer *trc) override
  2168. {
  2169. this->TraceUnion(trc);
  2170. }
  2171. };
  2172. template<typename T>
  2173. class MOZ_STACK_CLASS NullableRootedUnion : public Nullable<T>,
  2174. private JS::CustomAutoRooter
  2175. {
  2176. public:
  2177. explicit NullableRootedUnion(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
  2178. Nullable<T>(),
  2179. JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
  2180. {
  2181. }
  2182. virtual void trace(JSTracer *trc) override
  2183. {
  2184. if (!this->IsNull()) {
  2185. this->Value().TraceUnion(trc);
  2186. }
  2187. }
  2188. };
  2189. inline bool
  2190. IdEquals(jsid id, const char* string)
  2191. {
  2192. return JSID_IS_STRING(id) &&
  2193. JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), string);
  2194. }
  2195. inline bool
  2196. AddStringToIDVector(JSContext* cx, JS::AutoIdVector& vector, const char* name)
  2197. {
  2198. return vector.growBy(1) &&
  2199. AtomizeAndPinJSString(cx, *(vector[vector.length() - 1]).address(), name);
  2200. }
  2201. // We use one constructor JSNative to represent all DOM interface objects (so
  2202. // we can easily detect when we need to wrap them in an Xray wrapper). We store
  2203. // the real JSNative in the mNative member of a JSNativeHolder in the
  2204. // CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a
  2205. // specific interface object. We also store the NativeProperties in the
  2206. // JSNativeHolder.
  2207. // Note that some interface objects are not yet a JSFunction but a normal
  2208. // JSObject with a DOMJSClass, those do not use these slots.
  2209. enum {
  2210. CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT = 0
  2211. };
  2212. bool
  2213. Constructor(JSContext* cx, unsigned argc, JS::Value* vp);
  2214. // Implementation of the bits that XrayWrapper needs
  2215. /**
  2216. * This resolves operations, attributes and constants of the interfaces for obj.
  2217. *
  2218. * wrapper is the Xray JS object.
  2219. * obj is the target object of the Xray, a binding's instance object or a
  2220. * interface or interface prototype object.
  2221. */
  2222. bool
  2223. XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
  2224. JS::Handle<JSObject*> obj,
  2225. JS::Handle<jsid> id,
  2226. JS::MutableHandle<JS::PropertyDescriptor> desc,
  2227. bool& cacheOnHolder);
  2228. /**
  2229. * Define a property on obj through an Xray wrapper.
  2230. *
  2231. * wrapper is the Xray JS object.
  2232. * obj is the target object of the Xray, a binding's instance object or a
  2233. * interface or interface prototype object.
  2234. * id and desc are the parameters for the property to be defined.
  2235. * result is the out-parameter indicating success (read it only if
  2236. * this returns true and also sets *defined to true).
  2237. * defined will be set to true if a property was set as a result of this call.
  2238. */
  2239. bool
  2240. XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
  2241. JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
  2242. JS::Handle<JS::PropertyDescriptor> desc,
  2243. JS::ObjectOpResult &result,
  2244. bool *defined);
  2245. /**
  2246. * Add to props the property keys of all indexed or named properties of obj and
  2247. * operations, attributes and constants of the interfaces for obj.
  2248. *
  2249. * wrapper is the Xray JS object.
  2250. * obj is the target object of the Xray, a binding's instance object or a
  2251. * interface or interface prototype object.
  2252. * flags are JSITER_* flags.
  2253. */
  2254. bool
  2255. XrayOwnPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
  2256. JS::Handle<JSObject*> obj,
  2257. unsigned flags, JS::AutoIdVector& props);
  2258. /**
  2259. * Returns the prototype to use for an Xray for a DOM object, wrapped in cx's
  2260. * compartment. This always returns the prototype that would be used for a DOM
  2261. * object if we ignore any changes that might have been done to the prototype
  2262. * chain by JS, the XBL code or plugins.
  2263. *
  2264. * cx should be in the Xray's compartment.
  2265. * obj is the target object of the Xray, a binding's instance object or an
  2266. * interface or interface prototype object.
  2267. */
  2268. inline bool
  2269. XrayGetNativeProto(JSContext* cx, JS::Handle<JSObject*> obj,
  2270. JS::MutableHandle<JSObject*> protop)
  2271. {
  2272. JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj));
  2273. {
  2274. JSAutoCompartment ac(cx, global);
  2275. const DOMJSClass* domClass = GetDOMClass(obj);
  2276. if (domClass) {
  2277. ProtoHandleGetter protoGetter = domClass->mGetProto;
  2278. if (protoGetter) {
  2279. protop.set(protoGetter(cx));
  2280. } else {
  2281. protop.set(JS::GetRealmObjectPrototype(cx));
  2282. }
  2283. } else if (JS_ObjectIsFunction(cx, obj)) {
  2284. MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
  2285. protop.set(JS::GetRealmFunctionPrototype(cx));
  2286. } else {
  2287. const js::Class* clasp = js::GetObjectClass(obj);
  2288. MOZ_ASSERT(IsDOMIfaceAndProtoClass(clasp));
  2289. ProtoGetter protoGetter =
  2290. DOMIfaceAndProtoJSClass::FromJSClass(clasp)->mGetParentProto;
  2291. protop.set(protoGetter(cx));
  2292. }
  2293. }
  2294. return JS_WrapObject(cx, protop);
  2295. }
  2296. /**
  2297. * Get the Xray expando class to use for the given DOM object.
  2298. */
  2299. const JSClass*
  2300. XrayGetExpandoClass(JSContext* cx, JS::Handle<JSObject*> obj);
  2301. /**
  2302. * Delete a named property, if any. Return value is false if exception thrown,
  2303. * true otherwise. The caller should not do any more work after calling this
  2304. * function, because it has no way whether a deletion was performed and hence
  2305. * opresult already has state set on it. If callers ever need to change that,
  2306. * add a "bool* found" argument and change the generated DeleteNamedProperty to
  2307. * use it instead of a local variable.
  2308. */
  2309. bool
  2310. XrayDeleteNamedProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
  2311. JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
  2312. JS::ObjectOpResult& opresult);
  2313. /**
  2314. * Get the object which should be used to cache the return value of a property
  2315. * getter in the case of a [Cached] or [StoreInSlot] property. `obj` is the
  2316. * `this` value for our property getter that we're working with.
  2317. *
  2318. * This function can return null on failure to allocate the object, throwing on
  2319. * the JSContext in the process.
  2320. *
  2321. * The isXray outparam will be set to true if obj is an Xray and false
  2322. * otherwise.
  2323. *
  2324. * Note that the Slow version should only be called from
  2325. * GetCachedSlotStorageObject.
  2326. */
  2327. JSObject*
  2328. GetCachedSlotStorageObjectSlow(JSContext* cx, JS::Handle<JSObject*> obj,
  2329. bool* isXray);
  2330. inline JSObject*
  2331. GetCachedSlotStorageObject(JSContext* cx, JS::Handle<JSObject*> obj,
  2332. bool* isXray) {
  2333. if (IsDOMObject(obj)) {
  2334. *isXray = false;
  2335. return obj;
  2336. }
  2337. return GetCachedSlotStorageObjectSlow(cx, obj, isXray);
  2338. }
  2339. extern NativePropertyHooks sEmptyNativePropertyHooks;
  2340. extern const js::ClassOps sBoringInterfaceObjectClassClassOps;
  2341. extern const js::ObjectOps sInterfaceObjectClassObjectOps;
  2342. inline bool
  2343. UseDOMXray(JSObject* obj)
  2344. {
  2345. const js::Class* clasp = js::GetObjectClass(obj);
  2346. return IsDOMClass(clasp) ||
  2347. JS_IsNativeFunction(obj, Constructor) ||
  2348. IsDOMIfaceAndProtoClass(clasp);
  2349. }
  2350. #ifdef DEBUG
  2351. inline bool
  2352. HasConstructor(JSObject* obj)
  2353. {
  2354. return JS_IsNativeFunction(obj, Constructor) ||
  2355. js::GetObjectClass(obj)->getConstruct();
  2356. }
  2357. #endif
  2358. // Helpers for creating a const version of a type.
  2359. template<typename T>
  2360. const T& Constify(T& arg)
  2361. {
  2362. return arg;
  2363. }
  2364. // Helper for turning (Owning)NonNull<T> into T&
  2365. template<typename T>
  2366. T& NonNullHelper(T& aArg)
  2367. {
  2368. return aArg;
  2369. }
  2370. template<typename T>
  2371. T& NonNullHelper(NonNull<T>& aArg)
  2372. {
  2373. return aArg;
  2374. }
  2375. template<typename T>
  2376. const T& NonNullHelper(const NonNull<T>& aArg)
  2377. {
  2378. return aArg;
  2379. }
  2380. template<typename T>
  2381. T& NonNullHelper(OwningNonNull<T>& aArg)
  2382. {
  2383. return aArg;
  2384. }
  2385. template<typename T>
  2386. const T& NonNullHelper(const OwningNonNull<T>& aArg)
  2387. {
  2388. return aArg;
  2389. }
  2390. inline
  2391. void NonNullHelper(NonNull<binding_detail::FakeString>& aArg)
  2392. {
  2393. // This overload is here to make sure that we never end up applying
  2394. // NonNullHelper to a NonNull<binding_detail::FakeString>. If we
  2395. // try to, it should fail to compile, since presumably the caller will try to
  2396. // use our nonexistent return value.
  2397. }
  2398. inline
  2399. void NonNullHelper(const NonNull<binding_detail::FakeString>& aArg)
  2400. {
  2401. // This overload is here to make sure that we never end up applying
  2402. // NonNullHelper to a NonNull<binding_detail::FakeString>. If we
  2403. // try to, it should fail to compile, since presumably the caller will try to
  2404. // use our nonexistent return value.
  2405. }
  2406. inline
  2407. void NonNullHelper(binding_detail::FakeString& aArg)
  2408. {
  2409. // This overload is here to make sure that we never end up applying
  2410. // NonNullHelper to a FakeString before we've constified it. If we
  2411. // try to, it should fail to compile, since presumably the caller will try to
  2412. // use our nonexistent return value.
  2413. }
  2414. MOZ_ALWAYS_INLINE
  2415. const nsAString& NonNullHelper(const binding_detail::FakeString& aArg)
  2416. {
  2417. return aArg;
  2418. }
  2419. // Reparent the wrapper of aObj to whatever its native now thinks its
  2420. // parent should be.
  2421. nsresult
  2422. ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObj);
  2423. /**
  2424. * Used to implement the Symbol.hasInstance property of an interface object.
  2425. */
  2426. bool
  2427. InterfaceHasInstance(JSContext* cx, unsigned argc, JS::Value* vp);
  2428. bool
  2429. InterfaceHasInstance(JSContext* cx, int prototypeID, int depth,
  2430. JS::Handle<JSObject*> instance,
  2431. bool* bp);
  2432. // Helper for lenient getters/setters to report to console. If this
  2433. // returns false, we couldn't even get a global.
  2434. bool
  2435. ReportLenientThisUnwrappingFailure(JSContext* cx, JSObject* obj);
  2436. // Given a JSObject* that represents the chrome side of a JS-implemented WebIDL
  2437. // interface, get the nsIGlobalObject corresponding to the content side, if any.
  2438. // A false return means an exception was thrown.
  2439. bool
  2440. GetContentGlobalForJSImplementedObject(JSContext* cx, JS::Handle<JSObject*> obj,
  2441. nsIGlobalObject** global);
  2442. void
  2443. ConstructJSImplementation(const char* aContractId,
  2444. nsIGlobalObject* aGlobal,
  2445. JS::MutableHandle<JSObject*> aObject,
  2446. ErrorResult& aRv);
  2447. already_AddRefed<nsIGlobalObject>
  2448. ConstructJSImplementation(const char* aContractId,
  2449. const GlobalObject& aGlobal,
  2450. JS::MutableHandle<JSObject*> aObject,
  2451. ErrorResult& aRv);
  2452. /**
  2453. * Convert an nsCString to jsval, returning true on success.
  2454. * These functions are intended for ByteString implementations.
  2455. * As such, the string is not UTF-8 encoded. Any UTF8 strings passed to these
  2456. * methods will be mangled.
  2457. */
  2458. bool NonVoidByteStringToJsval(JSContext *cx, const nsACString &str,
  2459. JS::MutableHandle<JS::Value> rval);
  2460. inline bool ByteStringToJsval(JSContext *cx, const nsACString &str,
  2461. JS::MutableHandle<JS::Value> rval)
  2462. {
  2463. if (str.IsVoid()) {
  2464. rval.setNull();
  2465. return true;
  2466. }
  2467. return NonVoidByteStringToJsval(cx, str, rval);
  2468. }
  2469. template<class T, bool isISupports=IsBaseOf<nsISupports, T>::value>
  2470. struct PreserveWrapperHelper
  2471. {
  2472. static void PreserveWrapper(T* aObject)
  2473. {
  2474. aObject->PreserveWrapper(aObject, NS_CYCLE_COLLECTION_PARTICIPANT(T));
  2475. }
  2476. };
  2477. template<class T>
  2478. struct PreserveWrapperHelper<T, true>
  2479. {
  2480. static void PreserveWrapper(T* aObject)
  2481. {
  2482. aObject->PreserveWrapper(reinterpret_cast<nsISupports*>(aObject));
  2483. }
  2484. };
  2485. template<class T>
  2486. void PreserveWrapper(T* aObject)
  2487. {
  2488. PreserveWrapperHelper<T>::PreserveWrapper(aObject);
  2489. }
  2490. template<class T, bool isISupports=IsBaseOf<nsISupports, T>::value>
  2491. struct CastingAssertions
  2492. {
  2493. static bool ToSupportsIsCorrect(T*)
  2494. {
  2495. return true;
  2496. }
  2497. static bool ToSupportsIsOnPrimaryInheritanceChain(T*, nsWrapperCache*)
  2498. {
  2499. return true;
  2500. }
  2501. };
  2502. template<class T>
  2503. struct CastingAssertions<T, true>
  2504. {
  2505. static bool ToSupportsIsCorrect(T* aObject)
  2506. {
  2507. return ToSupports(aObject) == reinterpret_cast<nsISupports*>(aObject);
  2508. }
  2509. static bool ToSupportsIsOnPrimaryInheritanceChain(T* aObject,
  2510. nsWrapperCache* aCache)
  2511. {
  2512. return reinterpret_cast<void*>(aObject) != aCache;
  2513. }
  2514. };
  2515. template<class T>
  2516. bool
  2517. ToSupportsIsCorrect(T* aObject)
  2518. {
  2519. return CastingAssertions<T>::ToSupportsIsCorrect(aObject);
  2520. }
  2521. template<class T>
  2522. bool
  2523. ToSupportsIsOnPrimaryInheritanceChain(T* aObject, nsWrapperCache* aCache)
  2524. {
  2525. return CastingAssertions<T>::ToSupportsIsOnPrimaryInheritanceChain(aObject,
  2526. aCache);
  2527. }
  2528. // The BindingJSObjectCreator class is supposed to be used by a caller that
  2529. // wants to create and initialise a binding JSObject. After initialisation has
  2530. // been successfully completed it should call ForgetObject().
  2531. // The BindingJSObjectCreator object will root the JSObject until ForgetObject()
  2532. // is called on it. If the native object for the binding is refcounted it will
  2533. // also hold a strong reference to it, that reference is transferred to the
  2534. // JSObject (which holds the native in a slot) when ForgetObject() is called. If
  2535. // the BindingJSObjectCreator object is destroyed and ForgetObject() was never
  2536. // called on it then the JSObject's slot holding the native will be set to
  2537. // undefined, and for a refcounted native the strong reference will be released.
  2538. template<class T>
  2539. class MOZ_STACK_CLASS BindingJSObjectCreator
  2540. {
  2541. public:
  2542. explicit BindingJSObjectCreator(JSContext* aCx)
  2543. : mReflector(aCx)
  2544. {
  2545. }
  2546. ~BindingJSObjectCreator()
  2547. {
  2548. if (mReflector) {
  2549. js::SetReservedOrProxyPrivateSlot(mReflector, DOM_OBJECT_SLOT,
  2550. JS::UndefinedValue());
  2551. }
  2552. }
  2553. void
  2554. CreateProxyObject(JSContext* aCx, const js::Class* aClass,
  2555. const DOMProxyHandler* aHandler,
  2556. JS::Handle<JSObject*> aProto, T* aNative,
  2557. JS::MutableHandle<JSObject*> aReflector)
  2558. {
  2559. js::ProxyOptions options;
  2560. options.setClass(aClass);
  2561. JS::Rooted<JS::Value> proxyPrivateVal(aCx, JS::PrivateValue(aNative));
  2562. aReflector.set(js::NewProxyObject(aCx, aHandler, proxyPrivateVal, aProto,
  2563. options));
  2564. if (aReflector) {
  2565. mNative = aNative;
  2566. mReflector = aReflector;
  2567. }
  2568. }
  2569. void
  2570. CreateObject(JSContext* aCx, const JSClass* aClass,
  2571. JS::Handle<JSObject*> aProto,
  2572. T* aNative, JS::MutableHandle<JSObject*> aReflector)
  2573. {
  2574. aReflector.set(JS_NewObjectWithGivenProto(aCx, aClass, aProto));
  2575. if (aReflector) {
  2576. js::SetReservedSlot(aReflector, DOM_OBJECT_SLOT, JS::PrivateValue(aNative));
  2577. mNative = aNative;
  2578. mReflector = aReflector;
  2579. }
  2580. }
  2581. void
  2582. InitializationSucceeded()
  2583. {
  2584. void* dummy;
  2585. mNative.forget(&dummy);
  2586. mReflector = nullptr;
  2587. }
  2588. private:
  2589. struct OwnedNative
  2590. {
  2591. // Make sure the native objects inherit from NonRefcountedDOMObject so
  2592. // that we log their ctor and dtor.
  2593. static_assert(IsBaseOf<NonRefcountedDOMObject, T>::value,
  2594. "Non-refcounted objects with DOM bindings should inherit "
  2595. "from NonRefcountedDOMObject.");
  2596. OwnedNative&
  2597. operator=(T* aNative)
  2598. {
  2599. return *this;
  2600. }
  2601. // This signature sucks, but it's the only one that will make a nsRefPtr
  2602. // just forget about its pointer without warning.
  2603. void
  2604. forget(void**)
  2605. {
  2606. }
  2607. };
  2608. JS::Rooted<JSObject*> mReflector;
  2609. typename Conditional<IsRefcounted<T>::value, RefPtr<T>, OwnedNative>::Type mNative;
  2610. };
  2611. template<class T>
  2612. struct DeferredFinalizerImpl
  2613. {
  2614. typedef typename Conditional<IsSame<T, nsISupports>::value,
  2615. nsCOMPtr<T>,
  2616. typename Conditional<IsRefcounted<T>::value,
  2617. RefPtr<T>,
  2618. nsAutoPtr<T>>::Type>::Type SmartPtr;
  2619. typedef SegmentedVector<SmartPtr> SmartPtrArray;
  2620. static_assert(IsSame<T, nsISupports>::value || !IsBaseOf<nsISupports, T>::value,
  2621. "nsISupports classes should all use the nsISupports instantiation");
  2622. static inline void
  2623. AppendAndTake(SegmentedVector<nsCOMPtr<nsISupports>>& smartPtrArray, nsISupports* ptr)
  2624. {
  2625. smartPtrArray.InfallibleAppend(dont_AddRef(ptr));
  2626. }
  2627. template<class U>
  2628. static inline void
  2629. AppendAndTake(SegmentedVector<RefPtr<U>>& smartPtrArray, U* ptr)
  2630. {
  2631. smartPtrArray.InfallibleAppend(dont_AddRef(ptr));
  2632. }
  2633. template<class U>
  2634. static inline void
  2635. AppendAndTake(SegmentedVector<nsAutoPtr<U>>& smartPtrArray, U* ptr)
  2636. {
  2637. smartPtrArray.InfallibleAppend(ptr);
  2638. }
  2639. static void*
  2640. AppendDeferredFinalizePointer(void* aData, void* aObject)
  2641. {
  2642. SmartPtrArray* pointers = static_cast<SmartPtrArray*>(aData);
  2643. if (!pointers) {
  2644. pointers = new SmartPtrArray();
  2645. }
  2646. AppendAndTake(*pointers, static_cast<T*>(aObject));
  2647. return pointers;
  2648. }
  2649. static bool
  2650. DeferredFinalize(uint32_t aSlice, void* aData)
  2651. {
  2652. MOZ_ASSERT(aSlice > 0, "nonsensical/useless call with aSlice == 0");
  2653. SmartPtrArray* pointers = static_cast<SmartPtrArray*>(aData);
  2654. uint32_t oldLen = pointers->Length();
  2655. if (oldLen < aSlice) {
  2656. aSlice = oldLen;
  2657. }
  2658. uint32_t newLen = oldLen - aSlice;
  2659. pointers->PopLastN(aSlice);
  2660. if (newLen == 0) {
  2661. delete pointers;
  2662. return true;
  2663. }
  2664. return false;
  2665. }
  2666. };
  2667. template<class T,
  2668. bool isISupports=IsBaseOf<nsISupports, T>::value>
  2669. struct DeferredFinalizer
  2670. {
  2671. static void
  2672. AddForDeferredFinalization(T* aObject)
  2673. {
  2674. typedef DeferredFinalizerImpl<T> Impl;
  2675. DeferredFinalize(Impl::AppendDeferredFinalizePointer,
  2676. Impl::DeferredFinalize, aObject);
  2677. }
  2678. };
  2679. template<class T>
  2680. struct DeferredFinalizer<T, true>
  2681. {
  2682. static void
  2683. AddForDeferredFinalization(T* aObject)
  2684. {
  2685. DeferredFinalize(reinterpret_cast<nsISupports*>(aObject));
  2686. }
  2687. };
  2688. template<class T>
  2689. static void
  2690. AddForDeferredFinalization(T* aObject)
  2691. {
  2692. DeferredFinalizer<T>::AddForDeferredFinalization(aObject);
  2693. }
  2694. // This returns T's CC participant if it participates in CC or null if it
  2695. // doesn't. This also returns null for classes that don't inherit from
  2696. // nsISupports (QI should be used to get the participant for those).
  2697. template<class T, bool isISupports=IsBaseOf<nsISupports, T>::value>
  2698. class GetCCParticipant
  2699. {
  2700. // Helper for GetCCParticipant for classes that participate in CC.
  2701. template<class U>
  2702. static nsCycleCollectionParticipant*
  2703. GetHelper(int, typename U::NS_CYCLE_COLLECTION_INNERCLASS* dummy=nullptr)
  2704. {
  2705. return T::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant();
  2706. }
  2707. // Helper for GetCCParticipant for classes that don't participate in CC.
  2708. template<class U>
  2709. static nsCycleCollectionParticipant*
  2710. GetHelper(double)
  2711. {
  2712. return nullptr;
  2713. }
  2714. public:
  2715. static nsCycleCollectionParticipant*
  2716. Get()
  2717. {
  2718. // Passing int() here will try to call the GetHelper that takes an int as
  2719. // its firt argument. If T doesn't participate in CC then substitution for
  2720. // the second argument (with a default value) will fail and because of
  2721. // SFINAE the next best match (the variant taking a double) will be called.
  2722. return GetHelper<T>(int());
  2723. }
  2724. };
  2725. template<class T>
  2726. class GetCCParticipant<T, true>
  2727. {
  2728. public:
  2729. static nsCycleCollectionParticipant*
  2730. Get()
  2731. {
  2732. return nullptr;
  2733. }
  2734. };
  2735. void
  2736. FinalizeGlobal(JSFreeOp* aFop, JSObject* aObj);
  2737. bool
  2738. ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
  2739. JS::Handle<jsid> aId, bool* aResolvedp);
  2740. bool
  2741. MayResolveGlobal(const JSAtomState& aNames, jsid aId, JSObject* aMaybeObj);
  2742. bool
  2743. EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);
  2744. template <class T>
  2745. struct CreateGlobalOptions
  2746. {
  2747. static const ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
  2748. ProtoAndIfaceCache::NonWindowLike;
  2749. static void TraceGlobal(JSTracer* aTrc, JSObject* aObj)
  2750. {
  2751. mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
  2752. }
  2753. static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
  2754. {
  2755. MOZ_ALWAYS_TRUE(TryPreserveWrapper(aGlobal));
  2756. return true;
  2757. }
  2758. };
  2759. template <>
  2760. struct CreateGlobalOptions<nsGlobalWindow>
  2761. {
  2762. static const ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
  2763. ProtoAndIfaceCache::WindowLike;
  2764. static void TraceGlobal(JSTracer* aTrc, JSObject* aObj);
  2765. static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
  2766. };
  2767. nsresult
  2768. RegisterDOMNames();
  2769. // The return value is true if we created and successfully performed our part of
  2770. // the setup for the global, false otherwise.
  2771. //
  2772. // Typically this method's caller will want to ensure that
  2773. // xpc::InitGlobalObjectOptions is called before, and xpc::InitGlobalObject is
  2774. // called after, this method, to ensure that this global object and its
  2775. // compartment are consistent with other global objects.
  2776. template <class T, ProtoHandleGetter GetProto>
  2777. bool
  2778. CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache,
  2779. const JSClass* aClass, JS::CompartmentOptions& aOptions,
  2780. JSPrincipals* aPrincipal, bool aInitStandardClasses,
  2781. JS::MutableHandle<JSObject*> aGlobal)
  2782. {
  2783. aOptions.creationOptions().setTrace(CreateGlobalOptions<T>::TraceGlobal);
  2784. if (xpc::SharedMemoryEnabled()) {
  2785. aOptions.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
  2786. }
  2787. aGlobal.set(JS_NewGlobalObject(aCx, aClass, aPrincipal,
  2788. JS::DontFireOnNewGlobalHook, aOptions));
  2789. if (!aGlobal) {
  2790. NS_WARNING("Failed to create global");
  2791. return false;
  2792. }
  2793. JSAutoCompartment ac(aCx, aGlobal);
  2794. {
  2795. js::SetReservedSlot(aGlobal, DOM_OBJECT_SLOT, JS::PrivateValue(aNative));
  2796. NS_ADDREF(aNative);
  2797. aCache->SetWrapper(aGlobal);
  2798. dom::AllocateProtoAndIfaceCache(aGlobal,
  2799. CreateGlobalOptions<T>::ProtoAndIfaceCacheKind);
  2800. if (!CreateGlobalOptions<T>::PostCreateGlobal(aCx, aGlobal)) {
  2801. return false;
  2802. }
  2803. }
  2804. if (aInitStandardClasses &&
  2805. !JS_InitStandardClasses(aCx, aGlobal)) {
  2806. NS_WARNING("Failed to init standard classes");
  2807. return false;
  2808. }
  2809. JS::Handle<JSObject*> proto = GetProto(aCx);
  2810. if (!proto || !JS_SplicePrototype(aCx, aGlobal, proto)) {
  2811. NS_WARNING("Failed to set proto");
  2812. return false;
  2813. }
  2814. bool succeeded;
  2815. if (!JS_SetImmutablePrototype(aCx, aGlobal, &succeeded)) {
  2816. return false;
  2817. }
  2818. MOZ_ASSERT(succeeded,
  2819. "making a fresh global object's [[Prototype]] immutable can "
  2820. "internally fail, but it should never be unsuccessful");
  2821. return true;
  2822. }
  2823. /*
  2824. * Holds a jsid that is initialized to a pinned string, with automatic
  2825. * conversion to Handle<jsid>, as it is held live forever by pinning.
  2826. */
  2827. class PinnedStringId
  2828. {
  2829. jsid id;
  2830. public:
  2831. PinnedStringId() : id(JSID_VOID) {}
  2832. bool init(JSContext *cx, const char *string) {
  2833. JSString* str = JS_AtomizeAndPinString(cx, string);
  2834. if (!str)
  2835. return false;
  2836. id = INTERNED_STRING_TO_JSID(cx, str);
  2837. return true;
  2838. }
  2839. operator const jsid& () {
  2840. return id;
  2841. }
  2842. operator JS::Handle<jsid> () {
  2843. /* This is safe because we have pinned the string. */
  2844. return JS::Handle<jsid>::fromMarkedLocation(&id);
  2845. }
  2846. };
  2847. bool
  2848. GenericBindingGetter(JSContext* cx, unsigned argc, JS::Value* vp);
  2849. bool
  2850. GenericBindingSetter(JSContext* cx, unsigned argc, JS::Value* vp);
  2851. bool
  2852. GenericBindingMethod(JSContext* cx, unsigned argc, JS::Value* vp);
  2853. bool
  2854. GenericPromiseReturningBindingMethod(JSContext* cx, unsigned argc, JS::Value* vp);
  2855. bool
  2856. StaticMethodPromiseWrapper(JSContext* cx, unsigned argc, JS::Value* vp);
  2857. // ConvertExceptionToPromise should only be called when we have an error
  2858. // condition (e.g. returned false from a JSAPI method). Note that there may be
  2859. // no exception on cx, in which case this is an uncatchable failure that will
  2860. // simply be propagated. Otherwise this method will attempt to convert the
  2861. // exception to a Promise rejected with the exception that it will store in
  2862. // rval.
  2863. //
  2864. // promiseScope should be the scope in which the Promise should be created.
  2865. bool
  2866. ConvertExceptionToPromise(JSContext* cx,
  2867. JSObject* promiseScope,
  2868. JS::MutableHandle<JS::Value> rval);
  2869. #ifdef DEBUG
  2870. void
  2871. AssertReturnTypeMatchesJitinfo(const JSJitInfo* aJitinfo,
  2872. JS::Handle<JS::Value> aValue);
  2873. #endif
  2874. // This function is called by the bindings layer for methods/getters/setters
  2875. // that are not safe to be called in prerendering mode. It checks to make sure
  2876. // that the |this| object is not running in a global that is in prerendering
  2877. // mode. Otherwise, it aborts execution of timers and event handlers, and
  2878. // returns false which gets converted to an uncatchable exception by the
  2879. // bindings layer.
  2880. bool
  2881. EnforceNotInPrerendering(JSContext* aCx, JSObject* aObj);
  2882. // Handles the violation of a blacklisted action in prerendering mode by
  2883. // aborting the scripts, and preventing timers and event handlers from running
  2884. // in the window in the future.
  2885. void
  2886. HandlePrerenderingViolation(nsPIDOMWindowInner* aWindow);
  2887. bool
  2888. CallerSubsumes(JSObject* aObject);
  2889. MOZ_ALWAYS_INLINE bool
  2890. CallerSubsumes(JS::Handle<JS::Value> aValue)
  2891. {
  2892. if (!aValue.isObject()) {
  2893. return true;
  2894. }
  2895. return CallerSubsumes(&aValue.toObject());
  2896. }
  2897. template<class T>
  2898. inline bool
  2899. WrappedJSToDictionary(JSContext* aCx, nsISupports* aObject, T& aDictionary)
  2900. {
  2901. nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(aObject);
  2902. if (!wrappedObj) {
  2903. return false;
  2904. }
  2905. JS::Rooted<JSObject*> obj(aCx, wrappedObj->GetJSObject());
  2906. if (!obj) {
  2907. return false;
  2908. }
  2909. JSAutoCompartment ac(aCx, obj);
  2910. JS::Rooted<JS::Value> v(aCx, JS::ObjectValue(*obj));
  2911. return aDictionary.Init(aCx, v);
  2912. }
  2913. template<class T>
  2914. inline bool
  2915. WrappedJSToDictionary(nsISupports* aObject, T& aDictionary)
  2916. {
  2917. nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(aObject);
  2918. NS_ENSURE_TRUE(wrappedObj, false);
  2919. JS::Rooted<JSObject*> obj(RootingCx(), wrappedObj->GetJSObject());
  2920. NS_ENSURE_TRUE(obj, false);
  2921. nsIGlobalObject* global = xpc::NativeGlobal(obj);
  2922. NS_ENSURE_TRUE(global, false);
  2923. // we need this AutoEntryScript here because the spec requires us to execute
  2924. // getters when parsing a dictionary
  2925. AutoEntryScript aes(global, "WebIDL dictionary creation");
  2926. JS::Rooted<JS::Value> v(aes.cx(), JS::ObjectValue(*obj));
  2927. return aDictionary.Init(aes.cx(), v);
  2928. }
  2929. template<class T, class S>
  2930. inline RefPtr<T>
  2931. StrongOrRawPtr(already_AddRefed<S>&& aPtr)
  2932. {
  2933. return aPtr.template downcast<T>();
  2934. }
  2935. template<class T,
  2936. class ReturnType=typename Conditional<IsRefcounted<T>::value, T*,
  2937. nsAutoPtr<T>>::Type>
  2938. inline ReturnType
  2939. StrongOrRawPtr(T* aPtr)
  2940. {
  2941. return ReturnType(aPtr);
  2942. }
  2943. template<class T, template<typename> class SmartPtr, class S>
  2944. inline void
  2945. StrongOrRawPtr(SmartPtr<S>&& aPtr) = delete;
  2946. template<class T>
  2947. struct StrongPtrForMember
  2948. {
  2949. typedef typename Conditional<IsRefcounted<T>::value,
  2950. RefPtr<T>, nsAutoPtr<T>>::Type Type;
  2951. };
  2952. namespace binding_detail {
  2953. inline
  2954. JSObject*
  2955. GetHackedNamespaceProtoObject(JSContext* aCx)
  2956. {
  2957. return JS_NewPlainObject(aCx);
  2958. }
  2959. } // namespace binding_detail
  2960. // Resolve an id on the given global object that wants to be included in
  2961. // Exposed=System webidl annotations. False return value means exception
  2962. // thrown.
  2963. bool SystemGlobalResolve(JSContext* cx, JS::Handle<JSObject*> obj,
  2964. JS::Handle<jsid> id, bool* resolvedp);
  2965. // Enumerate all ids on the given global object that wants to be included in
  2966. // Exposed=System webidl annotations. False return value means exception
  2967. // thrown.
  2968. bool SystemGlobalEnumerate(JSContext* cx, JS::Handle<JSObject*> obj);
  2969. // Slot indexes for maplike/setlike forEach functions
  2970. #define FOREACH_CALLBACK_SLOT 0
  2971. #define FOREACH_MAPLIKEORSETLIKEOBJ_SLOT 1
  2972. // Backing function for running .forEach() on maplike/setlike interfaces.
  2973. // Unpacks callback and maplike/setlike object from reserved slots, then runs
  2974. // callback for each key (and value, for maplikes)
  2975. bool ForEachHandler(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
  2976. // Unpacks backing object (ES6 map/set) from the reserved slot of a reflector
  2977. // for a maplike/setlike interface. If backing object does not exist, creates
  2978. // backing object in the compartment of the reflector involved, making this safe
  2979. // to use across compartments/via xrays. Return values of these methods will
  2980. // always be in the context compartment.
  2981. bool GetMaplikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
  2982. size_t aSlotIndex,
  2983. JS::MutableHandle<JSObject*> aBackingObj,
  2984. bool* aBackingObjCreated);
  2985. bool GetSetlikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
  2986. size_t aSlotIndex,
  2987. JS::MutableHandle<JSObject*> aBackingObj,
  2988. bool* aBackingObjCreated);
  2989. // Get the desired prototype object for an object construction from the given
  2990. // CallArgs. Null is returned if the default prototype should be used.
  2991. bool
  2992. GetDesiredProto(JSContext* aCx, const JS::CallArgs& aCallArgs,
  2993. JS::MutableHandle<JSObject*> aDesiredProto);
  2994. // This function is expected to be called from the constructor function for an
  2995. // HTML element interface; the global/callargs need to be whatever was passed to
  2996. // that constructor function.
  2997. already_AddRefed<nsGenericHTMLElement>
  2998. CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
  2999. JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv);
  3000. void
  3001. SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
  3002. UseCounter aUseCounter);
  3003. // Warnings
  3004. void
  3005. DeprecationWarning(JSContext* aCx, JSObject* aObject,
  3006. nsIDocument::DeprecatedOperations aOperation);
  3007. // A callback to perform funToString on an interface object
  3008. JSString*
  3009. InterfaceObjectToString(JSContext* aCx, JS::Handle<JSObject*> aObject,
  3010. unsigned /* indent */);
  3011. namespace binding_detail {
  3012. // Get a JS global object that can be used for some temporary allocations. The
  3013. // idea is that this should be used for situations when you need to operate in
  3014. // _some_ compartment but don't care which one. A typical example is when you
  3015. // have non-JS input, non-JS output, but have to go through some sort of JS
  3016. // representation in the middle, so need a compartment to allocate things in.
  3017. //
  3018. // It's VERY important that any consumers of this function only do things that
  3019. // are guaranteed to be side-effect-free, even in the face of a script
  3020. // environment controlled by a hostile adversary. This is because in the worker
  3021. // case the global is in fact the worker global, so it and its standard objects
  3022. // are controlled by the worker script. This is why this function is in the
  3023. // binding_detail namespace. Any use of this function MUST be very carefully
  3024. // reviewed by someone who is sufficiently devious and has a very good
  3025. // understanding of all the code that will run while we're using the return
  3026. // value, including the SpiderMonkey parts.
  3027. JSObject* UnprivilegedJunkScopeOrWorkerGlobal();
  3028. } // namespace binding_detail
  3029. } // namespace dom
  3030. } // namespace mozilla
  3031. #endif /* mozilla_dom_BindingUtils_h__ */