dom/base/nsDOMClassInfo.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 sw=2 et tw=78: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "mozilla/ArrayUtils.h"
     8 // On top because they include basictypes.h:
     9 #include "mozilla/dom/SmsFilter.h"
    11 #ifdef XP_WIN
    12 #undef GetClassName
    13 #endif
    15 // JavaScript includes
    16 #include "jsapi.h"
    17 #include "jsfriendapi.h"
    18 #include "WrapperFactory.h"
    19 #include "AccessCheck.h"
    20 #include "XrayWrapper.h"
    22 #include "xpcpublic.h"
    23 #include "xpcprivate.h"
    24 #include "XPCWrapper.h"
    26 #include "mozilla/DOMEventTargetHelper.h"
    27 #include "mozilla/dom/RegisterBindings.h"
    29 #include "nscore.h"
    30 #include "nsDOMClassInfo.h"
    31 #include "nsCRT.h"
    32 #include "nsCRTGlue.h"
    33 #include "nsICategoryManager.h"
    34 #include "nsIComponentRegistrar.h"
    35 #include "nsXPCOM.h"
    36 #include "nsISupportsPrimitives.h"
    37 #include "nsIXPConnect.h"
    38 #include "nsIXPCSecurityManager.h"
    39 #include "xptcall.h"
    40 #include "nsTArray.h"
    41 #include "nsDocument.h" // nsDOMStyleSheetList
    42 #include "nsDOMBlobBuilder.h"
    44 // General helper includes
    45 #include "nsGlobalWindow.h"
    46 #include "nsIContent.h"
    47 #include "nsIDocument.h"
    48 #include "nsIDOMDocument.h"
    49 #include "nsIDOMEvent.h"
    50 #include "nsIDOMEventListener.h"
    51 #include "nsContentUtils.h"
    52 #include "nsCxPusher.h"
    53 #include "nsIDOMWindowUtils.h"
    54 #include "nsIDOMGlobalPropertyInitializer.h"
    55 #include "nsLocation.h"
    56 #include "mozilla/Attributes.h"
    57 #include "mozilla/Telemetry.h"
    59 // Window scriptable helper includes
    60 #include "nsIDocShell.h"
    61 #include "nsIScriptExternalNameSet.h"
    62 #include "nsJSUtils.h"
    63 #include "nsScriptNameSpaceManager.h"
    64 #include "nsIJSNativeInitializer.h"
    65 #include "nsJSEnvironment.h"
    67 // DOM base includes
    68 #include "nsIDOMLocation.h"
    69 #include "nsIDOMWindow.h"
    70 #include "nsPIDOMWindow.h"
    71 #include "nsIDOMJSWindow.h"
    72 #include "nsIDOMChromeWindow.h"
    73 #include "nsIDOMConstructor.h"
    75 // DOM core includes
    76 #include "nsError.h"
    77 #include "nsIDOMUserDataHandler.h"
    78 #include "nsIDOMXULButtonElement.h"
    79 #include "nsIDOMXULCheckboxElement.h"
    80 #include "nsIDOMXULPopupElement.h"
    82 // Event related includes
    83 #include "nsIDOMEventTarget.h"
    85 // CSS related includes
    86 #include "nsCSSRules.h"
    87 #include "nsIDOMCSSRule.h"
    88 #include "nsICSSRuleList.h"
    89 #include "nsAutoPtr.h"
    90 #include "nsMemory.h"
    92 // Tranformiix
    93 #include "nsIXSLTProcessor.h"
    94 #include "nsIXSLTProcessorPrivate.h"
    96 // includes needed for the prototype chain interfaces
    97 #include "nsIDOMCSSCharsetRule.h"
    98 #include "nsIDOMCSSImportRule.h"
    99 #include "nsIDOMCSSMediaRule.h"
   100 #include "nsIDOMCSSFontFaceRule.h"
   101 #include "nsIDOMCSSMozDocumentRule.h"
   102 #include "nsIDOMCSSSupportsRule.h"
   103 #include "nsIDOMMozCSSKeyframeRule.h"
   104 #include "nsIDOMMozCSSKeyframesRule.h"
   105 #include "nsIDOMCSSPageRule.h"
   106 #include "nsIDOMCSSStyleRule.h"
   107 #include "nsIDOMCSSStyleSheet.h"
   108 #include "nsIDOMXULCommandDispatcher.h"
   109 #include "nsIControllers.h"
   110 #include "nsIBoxObject.h"
   111 #ifdef MOZ_XUL
   112 #include "nsITreeSelection.h"
   113 #include "nsITreeContentView.h"
   114 #include "nsITreeView.h"
   115 #include "nsIXULTemplateBuilder.h"
   116 #include "nsITreeColumns.h"
   117 #endif
   118 #include "nsIDOMXPathExpression.h"
   119 #include "nsIDOMNSXPathExpression.h"
   120 #include "nsIDOMXPathNSResolver.h"
   121 #include "nsIDOMXPathResult.h"
   123 #include "nsIDOMSVGNumber.h"
   125 // Storage includes
   126 #include "nsIDOMStorage.h"
   127 #include "nsPIDOMStorage.h"
   129 // Drag and drop
   130 #include "nsIDOMFile.h"
   131 #include "nsDOMBlobBuilder.h" // nsDOMMultipartFile
   133 #include "nsIEventListenerService.h"
   134 #include "nsIMessageManager.h"
   136 #include "mozilla/dom/TouchEvent.h"
   138 #include "nsWrapperCacheInlines.h"
   139 #include "mozilla/dom/HTMLCollectionBinding.h"
   141 #include "nsIDOMMobileMessageManager.h"
   142 #include "nsIDOMMozSmsMessage.h"
   143 #include "nsIDOMMozMmsMessage.h"
   144 #include "nsIDOMSmsFilter.h"
   145 #include "nsIDOMSmsSegmentInfo.h"
   146 #include "nsIDOMMozMobileMessageThread.h"
   148 #ifdef MOZ_B2G_RIL
   149 #include "nsIDOMMobileConnection.h"
   150 #endif // MOZ_B2G_RIL
   152 #ifdef MOZ_B2G_FM
   153 #include "FMRadio.h"
   154 #endif
   156 #include "nsIDOMGlobalObjectConstructor.h"
   157 #include "nsDebug.h"
   159 #include "mozilla/dom/BindingUtils.h"
   160 #include "mozilla/Likely.h"
   161 #include "WindowNamedPropertiesHandler.h"
   162 #include "nsIInterfaceInfoManager.h"
   163 #include "mozilla/dom/EventTargetBinding.h"
   164 #include "mozilla/dom/WindowBinding.h"
   166 #ifdef MOZ_TIME_MANAGER
   167 #include "TimeManager.h"
   168 #endif
   170 using namespace mozilla;
   171 using namespace mozilla::dom;
   173 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
   175 // NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
   176 //       are defined in nsIDOMClassInfo.h.
   178 #define WINDOW_SCRIPTABLE_FLAGS                                               \
   179  (nsIXPCScriptable::WANT_PRECREATE |                                          \
   180   nsIXPCScriptable::WANT_POSTCREATE |                                         \
   181   nsIXPCScriptable::WANT_ENUMERATE |                                          \
   182   nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |                               \
   183   nsIXPCScriptable::IS_GLOBAL_OBJECT |                                        \
   184   nsIXPCScriptable::WANT_OUTER_OBJECT)
   186 #define ARRAY_SCRIPTABLE_FLAGS                                                \
   187   (DOM_DEFAULT_SCRIPTABLE_FLAGS       |                                       \
   188    nsIXPCScriptable::WANT_GETPROPERTY |                                       \
   189    nsIXPCScriptable::WANT_ENUMERATE)
   191 #define EVENTTARGET_SCRIPTABLE_FLAGS                                          \
   192   (DOM_DEFAULT_SCRIPTABLE_FLAGS       |                                       \
   193    nsIXPCScriptable::WANT_ADDPROPERTY)
   195 #define DOMCLASSINFO_STANDARD_FLAGS                                           \
   196   (nsIClassInfo::MAIN_THREAD_ONLY |                                           \
   197    nsIClassInfo::DOM_OBJECT       |                                           \
   198    nsIClassInfo::SINGLETON_CLASSINFO)
   201 #ifdef DEBUG
   202 #define NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                \
   203     eDOMClassInfo_##_class##_id,
   204 #else
   205 #define NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                \
   206   // nothing
   207 #endif
   209 /**
   210  * To generate the bitmap for a class that we're sure doesn't implement any of
   211  * the interfaces in DOMCI_CASTABLE_INTERFACES.
   212  */
   213 #define DOMCI_DATA_NO_CLASS(_dom_class)                                       \
   214 const uint32_t kDOMClassInfo_##_dom_class##_interfaces =                      \
   215   0;
   217 DOMCI_DATA_NO_CLASS(ContentFrameMessageManager)
   218 DOMCI_DATA_NO_CLASS(ChromeMessageBroadcaster)
   219 DOMCI_DATA_NO_CLASS(ChromeMessageSender)
   221 DOMCI_DATA_NO_CLASS(DOMPrototype)
   222 DOMCI_DATA_NO_CLASS(DOMConstructor)
   224 DOMCI_DATA_NO_CLASS(UserDataHandler)
   225 DOMCI_DATA_NO_CLASS(XULControlElement)
   226 DOMCI_DATA_NO_CLASS(XULLabeledControlElement)
   227 DOMCI_DATA_NO_CLASS(XULButtonElement)
   228 DOMCI_DATA_NO_CLASS(XULCheckboxElement)
   229 DOMCI_DATA_NO_CLASS(XULPopupElement)
   231 #define NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags,              \
   232                                         _chromeOnly, _allowXBL)               \
   233   { #_class,                                                                  \
   234     nullptr,                                                                  \
   235     { _helper::doCreate },                                                    \
   236     nullptr,                                                                  \
   237     nullptr,                                                                  \
   238     nullptr,                                                                  \
   239     _flags,                                                                   \
   240     true,                                                                     \
   241     0,                                                                        \
   242     _chromeOnly,                                                              \
   243     _allowXBL,                                                                \
   244     false,                                                                    \
   245     NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                    \
   246   },
   248 #define NS_DEFINE_CLASSINFO_DATA(_class, _helper, _flags)                     \
   249   NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, false, false)
   251 #define NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(_class, _helper, _flags)         \
   252   NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, true, false)
   254 #define NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(_class, _helper, _flags)          \
   255   NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, true, true)
   258 // This list of NS_DEFINE_CLASSINFO_DATA macros is what gives the DOM
   259 // classes their correct behavior when used through XPConnect. The
   260 // arguments that are passed to NS_DEFINE_CLASSINFO_DATA are
   261 //
   262 // 1. Class name as it should appear in JavaScript, this name is also
   263 //    used to find the id of the class in nsDOMClassInfo
   264 //    (i.e. e<classname>_id)
   265 // 2. Scriptable helper class
   266 // 3. nsIClassInfo/nsIXPCScriptable flags (i.e. for GetScriptableFlags)
   268 static nsDOMClassInfoData sClassInfoData[] = {
   269   // Base classes
   271   // The Window class lets you QI into interfaces that are not in the
   272   // flattened set (i.e. nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY
   273   // is not set), because of this make sure all scriptable interfaces
   274   // that are implemented by nsGlobalWindow can securely be exposed
   275   // to JS.
   278   NS_DEFINE_CLASSINFO_DATA(Window, nsWindowSH,
   279                            DEFAULT_SCRIPTABLE_FLAGS |
   280                            WINDOW_SCRIPTABLE_FLAGS)
   282   NS_DEFINE_CLASSINFO_DATA(Location, nsLocationSH,
   283                            ((DOM_DEFAULT_SCRIPTABLE_FLAGS |
   284                              nsIXPCScriptable::WANT_ADDPROPERTY) &
   285                             ~nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE))
   287   NS_DEFINE_CLASSINFO_DATA(DOMPrototype, nsDOMConstructorSH,
   288                            DOM_BASE_SCRIPTABLE_FLAGS |
   289                            nsIXPCScriptable::WANT_PRECREATE |
   290                            nsIXPCScriptable::WANT_NEWRESOLVE |
   291                            nsIXPCScriptable::WANT_HASINSTANCE |
   292                            nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
   293   NS_DEFINE_CLASSINFO_DATA(DOMConstructor, nsDOMConstructorSH,
   294                            DOM_BASE_SCRIPTABLE_FLAGS |
   295                            nsIXPCScriptable::WANT_PRECREATE |
   296                            nsIXPCScriptable::WANT_NEWRESOLVE |
   297                            nsIXPCScriptable::WANT_HASINSTANCE |
   298                            nsIXPCScriptable::WANT_CALL |
   299                            nsIXPCScriptable::WANT_CONSTRUCT |
   300                            nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
   302   // Misc Core related classes
   304   // CSS classes
   305   NS_DEFINE_CLASSINFO_DATA(CSSStyleRule, nsDOMGenericSH,
   306                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   307   NS_DEFINE_CLASSINFO_DATA(CSSCharsetRule, nsDOMGenericSH,
   308                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   309   NS_DEFINE_CLASSINFO_DATA(CSSImportRule, nsDOMGenericSH,
   310                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   311   NS_DEFINE_CLASSINFO_DATA(CSSMediaRule, nsDOMGenericSH,
   312                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   313   NS_DEFINE_CLASSINFO_DATA(CSSNameSpaceRule, nsDOMGenericSH,
   314                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   315   NS_DEFINE_CLASSINFO_DATA(CSSRuleList, nsCSSRuleListSH,
   316                            ARRAY_SCRIPTABLE_FLAGS)
   317   NS_DEFINE_CLASSINFO_DATA(CSSStyleSheet, nsDOMGenericSH,
   318                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   320   // XUL classes
   321 #ifdef MOZ_XUL
   322   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCommandDispatcher, nsDOMGenericSH,
   323                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   324 #endif
   325   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULControllers, nsNonDOMObjectSH,
   326                                       DEFAULT_SCRIPTABLE_FLAGS)
   327   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(BoxObject, nsDOMGenericSH,
   328                                       DEFAULT_SCRIPTABLE_FLAGS)
   329 #ifdef MOZ_XUL
   330   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeSelection, nsDOMGenericSH,
   331                                       DEFAULT_SCRIPTABLE_FLAGS)
   332   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeContentView, nsDOMGenericSH,
   333                                       DEFAULT_SCRIPTABLE_FLAGS)
   334 #endif
   336   // DOM Chrome Window class.
   337   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(ChromeWindow, nsWindowSH,
   338                                       DEFAULT_SCRIPTABLE_FLAGS |
   339                                       WINDOW_SCRIPTABLE_FLAGS)
   341 #ifdef MOZ_XUL
   342   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTemplateBuilder, nsDOMGenericSH,
   343                                       DEFAULT_SCRIPTABLE_FLAGS)
   345   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTreeBuilder, nsDOMGenericSH,
   346                                       DEFAULT_SCRIPTABLE_FLAGS)
   347 #endif
   349 #ifdef MOZ_XUL
   350   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeColumn, nsDOMGenericSH,
   351                                       DEFAULT_SCRIPTABLE_FLAGS)
   352 #endif
   354   NS_DEFINE_CLASSINFO_DATA(CSSMozDocumentRule, nsDOMGenericSH,
   355                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   357   NS_DEFINE_CLASSINFO_DATA(CSSSupportsRule, nsDOMGenericSH,
   358                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   360   // other SVG classes
   361   NS_DEFINE_CLASSINFO_DATA(SVGNumber, nsDOMGenericSH,
   362                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   364   NS_DEFINE_CLASSINFO_DATA(WindowUtils, nsDOMGenericSH,
   365                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   367   NS_DEFINE_CLASSINFO_DATA(XSLTProcessor, nsDOMGenericSH,
   368                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   370   NS_DEFINE_CLASSINFO_DATA(XPathExpression, nsDOMGenericSH,
   371                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   372   NS_DEFINE_CLASSINFO_DATA(XPathNSResolver, nsDOMGenericSH,
   373                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   374   NS_DEFINE_CLASSINFO_DATA(XPathResult, nsDOMGenericSH,
   375                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   377   // WhatWG Storage
   379   // mrbkap says we don't need WANT_ADDPROPERTY on Storage objects
   380   // since a call to addProperty() is always followed by a call to
   381   // setProperty(), except in the case when a getter or setter is set
   382   // for a property. But we don't care about getters or setters here.
   383   NS_DEFINE_CLASSINFO_DATA(Storage, nsStorage2SH,
   384                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
   385                            nsIXPCScriptable::WANT_NEWRESOLVE |
   386                            nsIXPCScriptable::WANT_GETPROPERTY |
   387                            nsIXPCScriptable::WANT_SETPROPERTY |
   388                            nsIXPCScriptable::WANT_DELPROPERTY |
   389                            nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |
   390                            nsIXPCScriptable::WANT_NEWENUMERATE)
   392   NS_DEFINE_CLASSINFO_DATA(Blob, nsDOMGenericSH,
   393                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   394   NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH,
   395                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   397   NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH,
   398                            DEFAULT_SCRIPTABLE_FLAGS |
   399                            WINDOW_SCRIPTABLE_FLAGS)
   401   NS_DEFINE_CLASSINFO_DATA(MozMobileMessageManager, nsDOMGenericSH,
   402                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   404   NS_DEFINE_CLASSINFO_DATA(MozSmsMessage, nsDOMGenericSH,
   405                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   407   NS_DEFINE_CLASSINFO_DATA(MozMmsMessage, nsDOMGenericSH,
   408                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   410   NS_DEFINE_CLASSINFO_DATA(MozSmsFilter, nsDOMGenericSH,
   411                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   413   NS_DEFINE_CLASSINFO_DATA(MozSmsSegmentInfo, nsDOMGenericSH,
   414                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   416   NS_DEFINE_CLASSINFO_DATA(MozMobileMessageThread, nsDOMGenericSH,
   417                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   419 #ifdef MOZ_B2G_RIL
   420   NS_DEFINE_CLASSINFO_DATA(MozMobileConnection, nsDOMGenericSH,
   421                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   422 #endif
   424   NS_DEFINE_CLASSINFO_DATA(CSSFontFaceRule, nsDOMGenericSH,
   425                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   427   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH,
   428                                        DOM_DEFAULT_SCRIPTABLE_FLAGS |
   429                                        nsIXPCScriptable::IS_GLOBAL_OBJECT)
   430   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageBroadcaster, nsDOMGenericSH,
   431                                        DOM_DEFAULT_SCRIPTABLE_FLAGS)
   432   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageSender, nsDOMGenericSH,
   433                                        DOM_DEFAULT_SCRIPTABLE_FLAGS)
   436   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH,
   437                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   438   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframesRule, nsDOMGenericSH,
   439                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   441   NS_DEFINE_CLASSINFO_DATA(CSSPageRule, nsDOMGenericSH,
   442                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   444   NS_DEFINE_CLASSINFO_DATA(CSSFontFeatureValuesRule, nsDOMGenericSH,
   445                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   447   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(UserDataHandler, nsDOMGenericSH,
   448                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   449   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULControlElement, nsDOMGenericSH,
   450                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   451   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULLabeledControlElement, nsDOMGenericSH,
   452                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   453   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULButtonElement, nsDOMGenericSH,
   454                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   455   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCheckboxElement, nsDOMGenericSH,
   456                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   457   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULPopupElement, nsDOMGenericSH,
   458                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   459 };
   461 #define NS_DEFINE_CONTRACT_CTOR(_class, _contract_id)                           \
   462   static nsresult                                                               \
   463   _class##Ctor(nsISupports** aInstancePtrResult)                                \
   464   {                                                                             \
   465     nsresult rv = NS_OK;                                                        \
   466     nsCOMPtr<nsISupports> native = do_CreateInstance(_contract_id, &rv);        \
   467     native.forget(aInstancePtrResult);                                          \
   468     return rv;                                                                  \
   469   }
   471 NS_DEFINE_CONTRACT_CTOR(XSLTProcessor,
   472                         "@mozilla.org/document-transformer;1?type=xslt")
   474 #undef NS_DEFINE_CONTRACT_CTOR
   476 struct nsConstructorFuncMapData
   477 {
   478   int32_t mDOMClassInfoID;
   479   nsDOMConstructorFunc mConstructorFunc;
   480 };
   482 #define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func)                        \
   483   { eDOMClassInfo_##_class##_id, _func },
   485 static const nsConstructorFuncMapData kConstructorFuncMap[] =
   486 {
   487   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Blob, nsDOMMultipartFile::NewBlob)
   488   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMMultipartFile::NewFile)
   489   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozSmsFilter, SmsFilter::NewSmsFilter)
   490   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XSLTProcessor, XSLTProcessorCtor)
   491 };
   492 #undef NS_DEFINE_CONSTRUCTOR_FUNC_DATA
   494 nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr;
   495 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nullptr;
   496 bool nsDOMClassInfo::sIsInitialized = false;
   499 jsid nsDOMClassInfo::sLocation_id        = JSID_VOID;
   500 jsid nsDOMClassInfo::sConstructor_id     = JSID_VOID;
   501 jsid nsDOMClassInfo::sLength_id          = JSID_VOID;
   502 jsid nsDOMClassInfo::sItem_id            = JSID_VOID;
   503 jsid nsDOMClassInfo::sNamedItem_id       = JSID_VOID;
   504 jsid nsDOMClassInfo::sEnumerate_id       = JSID_VOID;
   505 jsid nsDOMClassInfo::sTop_id             = JSID_VOID;
   506 jsid nsDOMClassInfo::sDocument_id        = JSID_VOID;
   507 jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
   509 static const JSClass *sObjectClass = nullptr;
   511 /**
   512  * Set our JSClass pointer for the Object class
   513  */
   514 static void
   515 FindObjectClass(JSContext* cx, JSObject* aGlobalObject)
   516 {
   517   NS_ASSERTION(!sObjectClass,
   518                "Double set of sObjectClass");
   519   JS::Rooted<JSObject*> obj(cx), proto(cx, aGlobalObject);
   520   do {
   521     obj = proto;
   522     js::GetObjectProto(cx, obj, &proto);
   523   } while (proto);
   525   sObjectClass = js::GetObjectJSClass(obj);
   526 }
   528 static inline JSString *
   529 IdToString(JSContext *cx, jsid id)
   530 {
   531   if (JSID_IS_STRING(id))
   532     return JSID_TO_STRING(id);
   533   JS::Rooted<JS::Value> idval(cx);
   534   if (!::JS_IdToValue(cx, id, &idval))
   535     return nullptr;
   536   return JS::ToString(cx, idval);
   537 }
   539 static inline nsresult
   540 WrapNative(JSContext *cx, nsISupports *native,
   541            nsWrapperCache *cache, const nsIID* aIID, JS::MutableHandle<JS::Value> vp,
   542            bool aAllowWrapping)
   543 {
   544   if (!native) {
   545     vp.setNull();
   547     return NS_OK;
   548   }
   550   JSObject *wrapper = xpc_FastGetCachedWrapper(cx, cache, vp);
   551   if (wrapper) {
   552     return NS_OK;
   553   }
   555   JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
   556   return nsDOMClassInfo::XPConnect()->WrapNativeToJSVal(cx, scope, native,
   557                                                         cache, aIID,
   558                                                         aAllowWrapping, vp);
   559 }
   561 static inline nsresult
   562 WrapNative(JSContext *cx, nsISupports *native, const nsIID* aIID,
   563            bool aAllowWrapping, JS::MutableHandle<JS::Value> vp)
   564 {
   565   return WrapNative(cx, native, nullptr, aIID, vp, aAllowWrapping);
   566 }
   568 // Same as the WrapNative above, but use these if aIID is nsISupports' IID.
   569 static inline nsresult
   570 WrapNative(JSContext *cx, nsISupports *native,
   571            bool aAllowWrapping, JS::MutableHandle<JS::Value> vp)
   572 {
   573   return WrapNative(cx, native, nullptr, nullptr, vp, aAllowWrapping);
   574 }
   576 static inline nsresult
   577 WrapNative(JSContext *cx, nsISupports *native,
   578            nsWrapperCache *cache, bool aAllowWrapping,
   579            JS::MutableHandle<JS::Value> vp)
   580 {
   581   return WrapNative(cx, native, cache, nullptr, vp, aAllowWrapping);
   582 }
   584 // Helper to handle torn-down inner windows.
   585 static inline nsresult
   586 SetParentToWindow(nsGlobalWindow *win, JSObject **parent)
   587 {
   588   MOZ_ASSERT(win);
   589   MOZ_ASSERT(win->IsInnerWindow());
   590   *parent = win->FastGetGlobalJSObject();
   592   if (MOZ_UNLIKELY(!*parent)) {
   593     // The inner window has been torn down. The scope is dying, so don't create
   594     // any new wrappers.
   595     return NS_ERROR_FAILURE;
   596   }
   597   return NS_OK;
   598 }
   600 // static
   602 nsISupports *
   603 nsDOMClassInfo::GetNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj)
   604 {
   605   return wrapper ? wrapper->Native() : static_cast<nsISupports*>(js::GetObjectPrivate(obj));
   606 }
   608 nsresult
   609 nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
   610 {
   611 #define SET_JSID_TO_STRING(_id, _cx, _str)                                    \
   612   if (JSString *str = ::JS_InternString(_cx, _str))                           \
   613       _id = INTERNED_STRING_TO_JSID(_cx, str);                                \
   614   else                                                                        \
   615       return NS_ERROR_OUT_OF_MEMORY;
   617   SET_JSID_TO_STRING(sLocation_id,        cx, "location");
   618   SET_JSID_TO_STRING(sConstructor_id,     cx, "constructor");
   619   SET_JSID_TO_STRING(sLength_id,          cx, "length");
   620   SET_JSID_TO_STRING(sItem_id,            cx, "item");
   621   SET_JSID_TO_STRING(sNamedItem_id,       cx, "namedItem");
   622   SET_JSID_TO_STRING(sEnumerate_id,       cx, "enumerateProperties");
   623   SET_JSID_TO_STRING(sTop_id,             cx, "top");
   624   SET_JSID_TO_STRING(sDocument_id,        cx, "document");
   625   SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
   627   return NS_OK;
   628 }
   630 // static
   631 bool
   632 nsDOMClassInfo::ObjectIsNativeWrapper(JSContext* cx, JSObject* obj)
   633 {
   634   return xpc::WrapperFactory::IsXrayWrapper(obj) &&
   635          xpc::AccessCheck::wrapperSubsumes(obj);
   636 }
   638 nsDOMClassInfo::nsDOMClassInfo(nsDOMClassInfoData* aData) : mData(aData)
   639 {
   640 }
   642 nsDOMClassInfo::~nsDOMClassInfo()
   643 {
   644   if (IS_EXTERNAL(mData->mCachedClassInfo)) {
   645     // Some compilers don't like delete'ing a const nsDOMClassInfo*
   646     nsDOMClassInfoData* data = const_cast<nsDOMClassInfoData*>(mData);
   647     delete static_cast<nsExternalDOMClassInfoData*>(data);
   648   }
   649 }
   651 NS_IMPL_ADDREF(nsDOMClassInfo)
   652 NS_IMPL_RELEASE(nsDOMClassInfo)
   654 NS_INTERFACE_MAP_BEGIN(nsDOMClassInfo)
   655   if (aIID.Equals(NS_GET_IID(nsXPCClassInfo)))
   656     foundInterface = static_cast<nsIClassInfo*>(
   657                                     static_cast<nsXPCClassInfo*>(this));
   658   else
   659   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   660   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   661   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIClassInfo)
   662 NS_INTERFACE_MAP_END
   665 static const JSClass sDOMConstructorProtoClass = {
   666   "DOM Constructor.prototype", 0,
   667   JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   668   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nullptr
   669 };
   672 static const char *
   673 CutPrefix(const char *aName) {
   674   static const char prefix_nsIDOM[] = "nsIDOM";
   675   static const char prefix_nsI[]    = "nsI";
   677   if (strncmp(aName, prefix_nsIDOM, sizeof(prefix_nsIDOM) - 1) == 0) {
   678     return aName + sizeof(prefix_nsIDOM) - 1;
   679   }
   681   if (strncmp(aName, prefix_nsI, sizeof(prefix_nsI) - 1) == 0) {
   682     return aName + sizeof(prefix_nsI) - 1;
   683   }
   685   return aName;
   686 }
   688 // static
   689 nsresult
   690 nsDOMClassInfo::RegisterClassProtos(int32_t aClassInfoID)
   691 {
   692   nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
   693   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
   694   bool found_old;
   696   const nsIID *primary_iid = sClassInfoData[aClassInfoID].mProtoChainInterface;
   698   if (!primary_iid || primary_iid == &NS_GET_IID(nsISupports)) {
   699     return NS_OK;
   700   }
   702   nsCOMPtr<nsIInterfaceInfoManager>
   703     iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
   704   NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
   706   nsCOMPtr<nsIInterfaceInfo> if_info;
   707   bool first = true;
   709   iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info));
   711   while (if_info) {
   712     const nsIID *iid = nullptr;
   714     if_info->GetIIDShared(&iid);
   715     NS_ENSURE_TRUE(iid, NS_ERROR_UNEXPECTED);
   717     if (iid->Equals(NS_GET_IID(nsISupports))) {
   718       break;
   719     }
   721     const char *name = nullptr;
   722     if_info->GetNameShared(&name);
   723     NS_ENSURE_TRUE(name, NS_ERROR_UNEXPECTED);
   725     nameSpaceManager->RegisterClassProto(CutPrefix(name), iid, &found_old);
   727     if (first) {
   728       first = false;
   729     } else if (found_old) {
   730       break;
   731     }
   733     nsCOMPtr<nsIInterfaceInfo> tmp(if_info);
   734     tmp->GetParent(getter_AddRefs(if_info));
   735   }
   737   return NS_OK;
   738 }
   740 // static
   741 nsresult
   742 nsDOMClassInfo::RegisterExternalClasses()
   743 {
   744   nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
   745   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
   747   nsCOMPtr<nsIComponentRegistrar> registrar;
   748   nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
   749   NS_ENSURE_SUCCESS(rv, rv);
   751   nsCOMPtr<nsICategoryManager> cm =
   752     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
   753   NS_ENSURE_SUCCESS(rv, rv);
   755   nsCOMPtr<nsISimpleEnumerator> e;
   756   rv = cm->EnumerateCategory(JAVASCRIPT_DOM_CLASS, getter_AddRefs(e));
   757   NS_ENSURE_SUCCESS(rv, rv);
   759   nsXPIDLCString contractId;
   760   nsAutoCString categoryEntry;
   761   nsCOMPtr<nsISupports> entry;
   763   while (NS_SUCCEEDED(e->GetNext(getter_AddRefs(entry)))) {
   764     nsCOMPtr<nsISupportsCString> category(do_QueryInterface(entry));
   766     if (!category) {
   767       NS_WARNING("Category entry not an nsISupportsCString!");
   768       continue;
   769     }
   771     rv = category->GetData(categoryEntry);
   773     cm->GetCategoryEntry(JAVASCRIPT_DOM_CLASS, categoryEntry.get(),
   774                          getter_Copies(contractId));
   775     NS_ENSURE_SUCCESS(rv, rv);
   777     nsCID *cid;
   778     rv = registrar->ContractIDToCID(contractId, &cid);
   779     if (NS_FAILED(rv)) {
   780       NS_WARNING("Bad contract id registered with the script namespace manager");
   781       continue;
   782     }
   784     rv = nameSpaceManager->RegisterExternalClassName(categoryEntry.get(), *cid);
   785     nsMemory::Free(cid);
   786     NS_ENSURE_SUCCESS(rv, rv);
   787   }
   789   return nameSpaceManager->RegisterExternalInterfaces(true);
   790 }
   792 #define _DOM_CLASSINFO_MAP_BEGIN(_class, _ifptr, _has_class_if)               \
   793   {                                                                           \
   794     nsDOMClassInfoData &d = sClassInfoData[eDOMClassInfo_##_class##_id];      \
   795     d.mProtoChainInterface = _ifptr;                                          \
   796     d.mHasClassInterface = _has_class_if;                                     \
   797     d.mInterfacesBitmap = kDOMClassInfo_##_class##_interfaces;                \
   798     static const nsIID *interface_list[] = {
   800 #define DOM_CLASSINFO_MAP_BEGIN(_class, _interface)                           \
   801   _DOM_CLASSINFO_MAP_BEGIN(_class, &NS_GET_IID(_interface), true)
   803 #define DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(_class, _interface)               \
   804   _DOM_CLASSINFO_MAP_BEGIN(_class, &NS_GET_IID(_interface), false)
   806 #define DOM_CLASSINFO_MAP_ENTRY(_if)                                          \
   807       &NS_GET_IID(_if),
   809 #define DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(_if, _cond)                       \
   810       (_cond) ? &NS_GET_IID(_if) : nullptr,
   812 #define DOM_CLASSINFO_MAP_END                                                 \
   813       nullptr                                                                  \
   814     };                                                                        \
   815                                                                               \
   816     /* Compact the interface list */                                          \
   817     size_t count = ArrayLength(interface_list);                               \
   818     /* count is the number of array entries, which is one greater than the */ \
   819     /* number of interfaces due to the terminating null */                    \
   820     for (size_t i = 0; i < count - 1; ++i) {                                  \
   821       if (!interface_list[i]) {                                               \
   822         /* We are moving the element at index i+1 and successors, */          \
   823         /* so we must move only count - (i+1) elements total. */              \
   824         memmove(&interface_list[i], &interface_list[i+1],                     \
   825                 sizeof(nsIID*) * (count - (i+1)));                            \
   826         /* Make sure to examine the new pointer we ended up with at this */   \
   827         /* slot, since it may be null too */                                  \
   828         --i;                                                                  \
   829         --count;                                                              \
   830       }                                                                       \
   831     }                                                                         \
   832                                                                               \
   833     d.mInterfaces = interface_list;                                           \
   834   }
   836 #ifdef MOZ_B2G
   837 #define DOM_CLASSINFO_WINDOW_MAP_ENTRIES                                       \
   838   DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)                                        \
   839   DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowB2G)                                     \
   840   DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)                                      \
   841   DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)                                   \
   842   DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)                              \
   843   DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowPerformance)                             \
   844   DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor)                               \
   845   DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver,                   \
   846                                       TouchEvent::PrefEnabled())
   847 #else // !MOZ_B2G
   848 #define DOM_CLASSINFO_WINDOW_MAP_ENTRIES                                       \
   849   DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)                                        \
   850   DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)                                      \
   851   DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)                                   \
   852   DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)                              \
   853   DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowPerformance)                             \
   854   DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor)                               \
   855   DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver,                   \
   856                                       TouchEvent::PrefEnabled())
   857 #endif // MOZ_B2G
   859 nsresult
   860 nsDOMClassInfo::Init()
   861 {
   862   /* Errors that can trigger early returns are done first,
   863      otherwise nsDOMClassInfo is left in a half inited state. */
   864   static_assert(sizeof(uintptr_t) == sizeof(void*),
   865                 "BAD! You'll need to adjust the size of uintptr_t to the "
   866                 "size of a pointer on your platform.");
   868   NS_ENSURE_TRUE(!sIsInitialized, NS_ERROR_ALREADY_INITIALIZED);
   870   nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
   871   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
   873   nsresult rv = CallGetService(nsIXPConnect::GetCID(), &sXPConnect);
   874   NS_ENSURE_SUCCESS(rv, rv);
   876   nsCOMPtr<nsIXPCFunctionThisTranslator> elt = new nsEventListenerThisTranslator();
   877   sXPConnect->SetFunctionThisTranslator(NS_GET_IID(nsIDOMEventListener), elt);
   879   nsCOMPtr<nsIScriptSecurityManager> sm =
   880     do_GetService("@mozilla.org/scriptsecuritymanager;1", &rv);
   881   NS_ENSURE_SUCCESS(rv, rv);
   883   sSecMan = sm;
   884   NS_ADDREF(sSecMan);
   886   AutoSafeJSContext cx;
   888   DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
   889     DOM_CLASSINFO_WINDOW_MAP_ENTRIES
   890 #ifdef MOZ_WEBSPEECH
   891     DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter)
   892 #endif
   893   DOM_CLASSINFO_MAP_END
   895   DOM_CLASSINFO_MAP_BEGIN(WindowUtils, nsIDOMWindowUtils)
   896     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowUtils)
   897   DOM_CLASSINFO_MAP_END
   899   DOM_CLASSINFO_MAP_BEGIN(Location, nsIDOMLocation)
   900     DOM_CLASSINFO_MAP_ENTRY(nsIDOMLocation)
   901   DOM_CLASSINFO_MAP_END
   903   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor)
   904     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   905   DOM_CLASSINFO_MAP_END
   907   DOM_CLASSINFO_MAP_BEGIN(DOMConstructor, nsIDOMDOMConstructor)
   908     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   909   DOM_CLASSINFO_MAP_END
   911   DOM_CLASSINFO_MAP_BEGIN(CSSStyleRule, nsIDOMCSSStyleRule)
   912     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleRule)
   913   DOM_CLASSINFO_MAP_END
   915   DOM_CLASSINFO_MAP_BEGIN(CSSCharsetRule, nsIDOMCSSCharsetRule)
   916     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSCharsetRule)
   917   DOM_CLASSINFO_MAP_END
   919   DOM_CLASSINFO_MAP_BEGIN(CSSImportRule, nsIDOMCSSImportRule)
   920     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSImportRule)
   921   DOM_CLASSINFO_MAP_END
   923   DOM_CLASSINFO_MAP_BEGIN(CSSMediaRule, nsIDOMCSSMediaRule)
   924     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMediaRule)
   925   DOM_CLASSINFO_MAP_END
   927   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(CSSNameSpaceRule, nsIDOMCSSRule)
   928     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule)
   929   DOM_CLASSINFO_MAP_END
   931   DOM_CLASSINFO_MAP_BEGIN(CSSRuleList, nsIDOMCSSRuleList)
   932     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRuleList)
   933   DOM_CLASSINFO_MAP_END
   935   DOM_CLASSINFO_MAP_BEGIN(CSSStyleSheet, nsIDOMCSSStyleSheet)
   936     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleSheet)
   937   DOM_CLASSINFO_MAP_END
   939 #ifdef MOZ_XUL
   940   DOM_CLASSINFO_MAP_BEGIN(XULCommandDispatcher, nsIDOMXULCommandDispatcher)
   941     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCommandDispatcher)
   942   DOM_CLASSINFO_MAP_END
   943 #endif
   945   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULControllers, nsIControllers)
   946     DOM_CLASSINFO_MAP_ENTRY(nsIControllers)
   947   DOM_CLASSINFO_MAP_END
   949   DOM_CLASSINFO_MAP_BEGIN(BoxObject, nsIBoxObject)
   950     DOM_CLASSINFO_MAP_ENTRY(nsIBoxObject)
   951   DOM_CLASSINFO_MAP_END
   953 #ifdef MOZ_XUL
   954   DOM_CLASSINFO_MAP_BEGIN(TreeSelection, nsITreeSelection)
   955     DOM_CLASSINFO_MAP_ENTRY(nsITreeSelection)
   956   DOM_CLASSINFO_MAP_END
   958   DOM_CLASSINFO_MAP_BEGIN(TreeContentView, nsITreeContentView)
   959     DOM_CLASSINFO_MAP_ENTRY(nsITreeContentView)
   960     DOM_CLASSINFO_MAP_ENTRY(nsITreeView)
   961   DOM_CLASSINFO_MAP_END
   962 #endif
   964   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeWindow, nsIDOMWindow)
   965     DOM_CLASSINFO_WINDOW_MAP_ENTRIES
   966     DOM_CLASSINFO_MAP_ENTRY(nsIDOMChromeWindow)
   967 #ifdef MOZ_WEBSPEECH
   968     DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter)
   969 #endif
   970   DOM_CLASSINFO_MAP_END
   972 #ifdef MOZ_XUL
   973   DOM_CLASSINFO_MAP_BEGIN(XULTemplateBuilder, nsIXULTemplateBuilder)
   974     DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder)
   975   DOM_CLASSINFO_MAP_END
   977   DOM_CLASSINFO_MAP_BEGIN(XULTreeBuilder, nsIXULTreeBuilder)
   978     DOM_CLASSINFO_MAP_ENTRY(nsIXULTreeBuilder)
   979     DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder)
   980     DOM_CLASSINFO_MAP_ENTRY(nsITreeView)
   981   DOM_CLASSINFO_MAP_END
   982 #endif
   984 #ifdef MOZ_XUL
   985   DOM_CLASSINFO_MAP_BEGIN(TreeColumn, nsITreeColumn)
   986     DOM_CLASSINFO_MAP_ENTRY(nsITreeColumn)
   987   DOM_CLASSINFO_MAP_END
   988 #endif
   990   DOM_CLASSINFO_MAP_BEGIN(CSSMozDocumentRule, nsIDOMCSSMozDocumentRule)
   991     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
   992   DOM_CLASSINFO_MAP_END
   994   DOM_CLASSINFO_MAP_BEGIN(CSSSupportsRule, nsIDOMCSSSupportsRule)
   995     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSSupportsRule)
   996   DOM_CLASSINFO_MAP_END
   998   // The SVG document
  1000   // other SVG classes
  1001   DOM_CLASSINFO_MAP_BEGIN(SVGNumber, nsIDOMSVGNumber)
  1002     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGNumber)
  1003   DOM_CLASSINFO_MAP_END
  1005   DOM_CLASSINFO_MAP_BEGIN(XSLTProcessor, nsIXSLTProcessor)
  1006     DOM_CLASSINFO_MAP_ENTRY(nsIXSLTProcessor)
  1007     DOM_CLASSINFO_MAP_ENTRY(nsIXSLTProcessorPrivate)
  1008   DOM_CLASSINFO_MAP_END
  1010   DOM_CLASSINFO_MAP_BEGIN(XPathExpression, nsIDOMXPathExpression)
  1011     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathExpression)
  1012     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSXPathExpression)
  1013   DOM_CLASSINFO_MAP_END
  1015   DOM_CLASSINFO_MAP_BEGIN(XPathNSResolver, nsIDOMXPathNSResolver)
  1016     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathNSResolver)
  1017   DOM_CLASSINFO_MAP_END
  1019   DOM_CLASSINFO_MAP_BEGIN(XPathResult, nsIDOMXPathResult)
  1020     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathResult)
  1021   DOM_CLASSINFO_MAP_END
  1023   DOM_CLASSINFO_MAP_BEGIN(Storage, nsIDOMStorage)
  1024     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorage)
  1025   DOM_CLASSINFO_MAP_END
  1027   DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob)
  1028     DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
  1029   DOM_CLASSINFO_MAP_END
  1031   DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
  1032     DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
  1033     DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
  1034   DOM_CLASSINFO_MAP_END
  1036   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
  1037     DOM_CLASSINFO_WINDOW_MAP_ENTRIES
  1038     DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
  1039 #ifdef MOZ_WEBSPEECH
  1040     DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter)
  1041 #endif
  1042   DOM_CLASSINFO_MAP_END
  1044   DOM_CLASSINFO_MAP_BEGIN(MozMobileMessageManager, nsIDOMMozMobileMessageManager)
  1045      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileMessageManager)
  1046   DOM_CLASSINFO_MAP_END
  1048   DOM_CLASSINFO_MAP_BEGIN(MozSmsMessage, nsIDOMMozSmsMessage)
  1049      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsMessage)
  1050   DOM_CLASSINFO_MAP_END
  1052   DOM_CLASSINFO_MAP_BEGIN(MozMmsMessage, nsIDOMMozMmsMessage)
  1053      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMmsMessage)
  1054   DOM_CLASSINFO_MAP_END
  1056   DOM_CLASSINFO_MAP_BEGIN(MozSmsFilter, nsIDOMMozSmsFilter)
  1057      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsFilter)
  1058   DOM_CLASSINFO_MAP_END
  1060   DOM_CLASSINFO_MAP_BEGIN(MozSmsSegmentInfo, nsIDOMMozSmsSegmentInfo)
  1061      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsSegmentInfo)
  1062   DOM_CLASSINFO_MAP_END
  1064   DOM_CLASSINFO_MAP_BEGIN(MozMobileMessageThread, nsIDOMMozMobileMessageThread)
  1065      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileMessageThread)
  1066   DOM_CLASSINFO_MAP_END
  1068 #ifdef MOZ_B2G_RIL
  1069   DOM_CLASSINFO_MAP_BEGIN(MozMobileConnection, nsIDOMMozMobileConnection)
  1070      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileConnection)
  1071      DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
  1072   DOM_CLASSINFO_MAP_END
  1073 #endif // MOZ_B2G_RIL
  1075   DOM_CLASSINFO_MAP_BEGIN(CSSFontFaceRule, nsIDOMCSSFontFaceRule)
  1076     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFaceRule)
  1077   DOM_CLASSINFO_MAP_END
  1079   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsISupports)
  1080     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
  1081     DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
  1082     DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
  1083     DOM_CLASSINFO_MAP_ENTRY(nsISyncMessageSender)
  1084     DOM_CLASSINFO_MAP_ENTRY(nsIContentFrameMessageManager)
  1085   DOM_CLASSINFO_MAP_END
  1087   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageBroadcaster, nsISupports)
  1088     DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader)
  1089     DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
  1090     DOM_CLASSINFO_MAP_ENTRY(nsIMessageBroadcaster)
  1091   DOM_CLASSINFO_MAP_END
  1093   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageSender, nsISupports)
  1094     DOM_CLASSINFO_MAP_ENTRY(nsIProcessChecker)
  1095     DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader)
  1096     DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
  1097     DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
  1098   DOM_CLASSINFO_MAP_END
  1100   DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframeRule, nsIDOMMozCSSKeyframeRule)
  1101     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
  1102   DOM_CLASSINFO_MAP_END
  1104   DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframesRule, nsIDOMMozCSSKeyframesRule)
  1105     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframesRule)
  1106   DOM_CLASSINFO_MAP_END
  1108   DOM_CLASSINFO_MAP_BEGIN(CSSPageRule, nsIDOMCSSPageRule)
  1109     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSPageRule)
  1110   DOM_CLASSINFO_MAP_END
  1112   DOM_CLASSINFO_MAP_BEGIN(CSSFontFeatureValuesRule, nsIDOMCSSFontFeatureValuesRule)
  1113     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule)
  1114   DOM_CLASSINFO_MAP_END
  1116   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(UserDataHandler, nsIDOMUserDataHandler)
  1117     DOM_CLASSINFO_MAP_ENTRY(nsIDOMUserDataHandler)
  1118   DOM_CLASSINFO_MAP_END
  1120   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULControlElement, nsIDOMXULControlElement)
  1121     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULControlElement)
  1122   DOM_CLASSINFO_MAP_END
  1124   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULLabeledControlElement, nsIDOMXULLabeledControlElement)
  1125     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULLabeledControlElement)
  1126   DOM_CLASSINFO_MAP_END
  1128   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULButtonElement, nsIDOMXULButtonElement)
  1129     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULButtonElement)
  1130   DOM_CLASSINFO_MAP_END
  1132   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULCheckboxElement, nsIDOMXULCheckboxElement)
  1133     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCheckboxElement)
  1134   DOM_CLASSINFO_MAP_END
  1136   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULPopupElement, nsIDOMXULPopupElement)
  1137     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULPopupElement)
  1138   DOM_CLASSINFO_MAP_END
  1140   static_assert(MOZ_ARRAY_LENGTH(sClassInfoData) == eDOMClassInfoIDCount,
  1141                 "The number of items in sClassInfoData doesn't match the "
  1142                 "number of nsIDOMClassInfo ID's, this is bad! Fix it!");
  1144 #ifdef DEBUG
  1145   for (size_t i = 0; i < eDOMClassInfoIDCount; i++) {
  1146     if (!sClassInfoData[i].u.mConstructorFptr ||
  1147         sClassInfoData[i].mDebugID != i) {
  1148       MOZ_CRASH("Class info data out of sync, you forgot to update "
  1149                 "nsDOMClassInfo.h and nsDOMClassInfo.cpp! Fix this, "
  1150                 "mozilla will not work without this fixed!");
  1154   for (size_t i = 0; i < eDOMClassInfoIDCount; i++) {
  1155     if (!sClassInfoData[i].mInterfaces) {
  1156       MOZ_CRASH("Class info data without an interface list! Fix this, "
  1157                 "mozilla will not work without this fixed!");
  1160 #endif
  1162   // Initialize static JSString's
  1163   DefineStaticJSVals(cx);
  1165   int32_t i;
  1167   for (i = 0; i < eDOMClassInfoIDCount; ++i) {
  1168     if (i == eDOMClassInfo_DOMPrototype_id) {
  1169       continue;
  1172     nsDOMClassInfoData& data = sClassInfoData[i];
  1173     nameSpaceManager->RegisterClassName(data.mName, i, data.mChromeOnly,
  1174                                         data.mAllowXBL, &data.mNameUTF16);
  1177   for (i = 0; i < eDOMClassInfoIDCount; ++i) {
  1178     RegisterClassProtos(i);
  1181   RegisterExternalClasses();
  1183   // Register new DOM bindings
  1184   mozilla::dom::Register(nameSpaceManager);
  1186   sIsInitialized = true;
  1188   return NS_OK;
  1191 // static
  1192 int32_t
  1193 nsDOMClassInfo::GetArrayIndexFromId(JSContext *cx, JS::Handle<jsid> id, bool *aIsNumber)
  1195   if (aIsNumber) {
  1196     *aIsNumber = false;
  1199   int i;
  1200   if (JSID_IS_INT(id)) {
  1201       i = JSID_TO_INT(id);
  1202   } else {
  1203       JS::Rooted<JS::Value> idval(cx);
  1204       double array_index;
  1205       if (!::JS_IdToValue(cx, id, &idval) ||
  1206           !JS::ToNumber(cx, idval, &array_index) ||
  1207           !::JS_DoubleIsInt32(array_index, &i)) {
  1208         return -1;
  1212   if (aIsNumber) {
  1213     *aIsNumber = true;
  1216   return i;
  1219 NS_IMETHODIMP
  1220 nsDOMClassInfo::GetInterfaces(uint32_t *aCount, nsIID ***aArray)
  1222   uint32_t count = 0;
  1224   while (mData->mInterfaces[count]) {
  1225     count++;
  1228   *aCount = count;
  1230   if (!count) {
  1231     *aArray = nullptr;
  1233     return NS_OK;
  1236   *aArray = static_cast<nsIID **>(nsMemory::Alloc(count * sizeof(nsIID *)));
  1237   NS_ENSURE_TRUE(*aArray, NS_ERROR_OUT_OF_MEMORY);
  1239   uint32_t i;
  1240   for (i = 0; i < count; i++) {
  1241     nsIID *iid = static_cast<nsIID *>(nsMemory::Clone(mData->mInterfaces[i],
  1242                                                          sizeof(nsIID)));
  1244     if (!iid) {
  1245       NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, *aArray);
  1247       return NS_ERROR_OUT_OF_MEMORY;
  1250     *((*aArray) + i) = iid;
  1253   return NS_OK;
  1256 NS_IMETHODIMP
  1257 nsDOMClassInfo::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
  1259   if (language == nsIProgrammingLanguage::JAVASCRIPT) {
  1260     *_retval = static_cast<nsIXPCScriptable *>(this);
  1262     NS_ADDREF(*_retval);
  1263   } else {
  1264     *_retval = nullptr;
  1267   return NS_OK;
  1270 NS_IMETHODIMP
  1271 nsDOMClassInfo::GetContractID(char **aContractID)
  1273   *aContractID = nullptr;
  1275   return NS_OK;
  1278 NS_IMETHODIMP
  1279 nsDOMClassInfo::GetClassDescription(char **aClassDescription)
  1281   return GetClassName(aClassDescription);
  1284 NS_IMETHODIMP
  1285 nsDOMClassInfo::GetClassID(nsCID **aClassID)
  1287   *aClassID = nullptr;
  1288   return NS_OK;
  1291 NS_IMETHODIMP
  1292 nsDOMClassInfo::GetClassIDNoAlloc(nsCID *aClassID)
  1294   return NS_ERROR_NOT_AVAILABLE;
  1297 NS_IMETHODIMP
  1298 nsDOMClassInfo::GetImplementationLanguage(uint32_t *aImplLanguage)
  1300   *aImplLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  1302   return NS_OK;
  1305 NS_IMETHODIMP
  1306 nsDOMClassInfo::GetFlags(uint32_t *aFlags)
  1308   *aFlags = DOMCLASSINFO_STANDARD_FLAGS;
  1310   return NS_OK;
  1313 // nsIXPCScriptable
  1315 NS_IMETHODIMP
  1316 nsDOMClassInfo::GetClassName(char **aClassName)
  1318   *aClassName = NS_strdup(mData->mName);
  1320   return NS_OK;
  1323 // virtual
  1324 uint32_t
  1325 nsDOMClassInfo::GetScriptableFlags()
  1327   return mData->mScriptableFlags;
  1330 NS_IMETHODIMP
  1331 nsDOMClassInfo::PreCreate(nsISupports *nativeObj, JSContext *cx,
  1332                           JSObject *globalObj, JSObject **parentObj)
  1334   *parentObj = globalObj;
  1335   return NS_OK;
  1338 NS_IMETHODIMP
  1339 nsDOMClassInfo::Create(nsIXPConnectWrappedNative *wrapper,
  1340                        JSContext *cx, JSObject *obj)
  1342   NS_WARNING("nsDOMClassInfo::Create Don't call me!");
  1344   return NS_ERROR_UNEXPECTED;
  1347 NS_IMETHODIMP
  1348 nsDOMClassInfo::PostCreate(nsIXPConnectWrappedNative *wrapper,
  1349                            JSContext *cx, JSObject *obj)
  1351   NS_WARNING("nsDOMClassInfo::PostCreate Don't call me!");
  1353   return NS_ERROR_UNEXPECTED;
  1356 NS_IMETHODIMP
  1357 nsDOMClassInfo::PostTransplant(nsIXPConnectWrappedNative *wrapper,
  1358                                JSContext *cx, JSObject *obj)
  1360   MOZ_CRASH("nsDOMClassInfo::PostTransplant Don't call me!");
  1363 NS_IMETHODIMP
  1364 nsDOMClassInfo::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1365                             JSObject *obj, jsid id, jsval *vp,
  1366                             bool *_retval)
  1368   NS_WARNING("nsDOMClassInfo::AddProperty Don't call me!");
  1370   return NS_ERROR_UNEXPECTED;
  1373 NS_IMETHODIMP
  1374 nsDOMClassInfo::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1375                             JSObject *obj, jsid id, bool *_retval)
  1377   NS_WARNING("nsDOMClassInfo::DelProperty Don't call me!");
  1379   return NS_ERROR_UNEXPECTED;
  1382 NS_IMETHODIMP
  1383 nsDOMClassInfo::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1384                             JSObject *obj, jsid id, jsval *vp,
  1385                             bool *_retval)
  1387   NS_WARNING("nsDOMClassInfo::GetProperty Don't call me!");
  1389   return NS_OK;
  1392 NS_IMETHODIMP
  1393 nsDOMClassInfo::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1394                             JSObject *obj, jsid id, jsval *vp,
  1395                             bool *_retval)
  1397   NS_WARNING("nsDOMClassInfo::SetProperty Don't call me!");
  1399   return NS_ERROR_UNEXPECTED;
  1402 NS_IMETHODIMP
  1403 nsDOMClassInfo::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1404                           JSObject *obj, bool *_retval)
  1406   return NS_OK;
  1409 NS_IMETHODIMP
  1410 nsDOMClassInfo::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
  1411                              JSContext *cx, JSObject *obj, uint32_t enum_op,
  1412                              jsval *statep, jsid *idp, bool *_retval)
  1414   NS_WARNING("nsDOMClassInfo::NewEnumerate Don't call me!");
  1416   return NS_ERROR_UNEXPECTED;
  1419 nsresult
  1420 nsDOMClassInfo::ResolveConstructor(JSContext *cx, JSObject *aObj,
  1421                                    JSObject **objp)
  1423   JS::Rooted<JSObject*> obj(cx, aObj);
  1424   JS::Rooted<JSObject*> global(cx, ::JS_GetGlobalForObject(cx, obj));
  1426   JS::Rooted<JS::Value> val(cx);
  1427   if (!::JS_LookupProperty(cx, global, mData->mName, &val)) {
  1428     return NS_ERROR_UNEXPECTED;
  1431   if (!JSVAL_IS_PRIMITIVE(val)) {
  1432     // If val is not an (non-null) object there either is no
  1433     // constructor for this class, or someone messed with
  1434     // window.classname, just fall through and let the JS engine
  1435     // return the Object constructor.
  1437     if (!::JS_DefinePropertyById(cx, obj, sConstructor_id, val, JS_PropertyStub,
  1438                                  JS_StrictPropertyStub, JSPROP_ENUMERATE)) {
  1439       return NS_ERROR_UNEXPECTED;
  1442     *objp = obj;
  1445   return NS_OK;
  1448 NS_IMETHODIMP
  1449 nsDOMClassInfo::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1450                            JSObject *obj, jsid id, JSObject **objp,
  1451                            bool *_retval)
  1453   if (id == sConstructor_id) {
  1454     return ResolveConstructor(cx, obj, objp);
  1457   return NS_OK;
  1460 NS_IMETHODIMP
  1461 nsDOMClassInfo::Convert(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1462                         JSObject *obj, uint32_t type, jsval *vp,
  1463                         bool *_retval)
  1465   NS_WARNING("nsDOMClassInfo::Convert Don't call me!");
  1467   return NS_ERROR_UNEXPECTED;
  1470 NS_IMETHODIMP
  1471 nsDOMClassInfo::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
  1472                          JSObject *obj)
  1474   NS_WARNING("nsDOMClassInfo::Finalize Don't call me!");
  1476   return NS_ERROR_UNEXPECTED;
  1479 NS_IMETHODIMP
  1480 nsDOMClassInfo::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1481                      JSObject *obj, const JS::CallArgs &args, bool *_retval)
  1483   NS_WARNING("nsDOMClassInfo::Call Don't call me!");
  1485   return NS_ERROR_UNEXPECTED;
  1488 NS_IMETHODIMP
  1489 nsDOMClassInfo::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1490                           JSObject *obj, const JS::CallArgs &args,
  1491                           bool *_retval)
  1493   NS_WARNING("nsDOMClassInfo::Construct Don't call me!");
  1495   return NS_ERROR_UNEXPECTED;
  1498 NS_IMETHODIMP
  1499 nsDOMClassInfo::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1500                             JSObject *obj, JS::Handle<JS::Value> val, bool *bp,
  1501                             bool *_retval)
  1503   NS_WARNING("nsDOMClassInfo::HasInstance Don't call me!");
  1505   return NS_ERROR_UNEXPECTED;
  1508 NS_IMETHODIMP
  1509 nsDOMClassInfo::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
  1510                             JSObject * obj, JSObject * *_retval)
  1512   NS_WARNING("nsDOMClassInfo::OuterObject Don't call me!");
  1514   return NS_ERROR_UNEXPECTED;
  1517 static nsresult
  1518 GetExternalClassInfo(nsScriptNameSpaceManager *aNameSpaceManager,
  1519                      const nsAString &aName,
  1520                      const nsGlobalNameStruct *aStruct,
  1521                      const nsGlobalNameStruct **aResult)
  1523   NS_ASSERTION(aStruct->mType ==
  1524                  nsGlobalNameStruct::eTypeExternalClassInfoCreator,
  1525                "Wrong type!");
  1527   nsresult rv;
  1528   nsCOMPtr<nsIDOMCIExtension> creator(do_CreateInstance(aStruct->mCID, &rv));
  1529   NS_ENSURE_SUCCESS(rv, rv);
  1531   nsCOMPtr<nsIDOMScriptObjectFactory> sof(do_GetService(kDOMSOF_CID));
  1532   NS_ENSURE_TRUE(sof, NS_ERROR_FAILURE);
  1534   rv = creator->RegisterDOMCI(NS_ConvertUTF16toUTF8(aName).get(), sof);
  1535   NS_ENSURE_SUCCESS(rv, rv);
  1537   const nsGlobalNameStruct *name_struct = aNameSpaceManager->LookupName(aName);
  1538   if (name_struct &&
  1539       name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
  1540     *aResult = name_struct;
  1542   else {
  1543     NS_ERROR("Couldn't get the DOM ClassInfo data.");
  1545     *aResult = nullptr;
  1548   return NS_OK;
  1552 static nsresult
  1553 ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
  1554                  JS::Handle<JSObject*> obj, const char16_t *name,
  1555                  const nsDOMClassInfoData *ci_data,
  1556                  const nsGlobalNameStruct *name_struct,
  1557                  nsScriptNameSpaceManager *nameSpaceManager,
  1558                  JSObject *dot_prototype,
  1559                  JS::MutableHandle<JSPropertyDescriptor> ctorDesc);
  1561 NS_IMETHODIMP
  1562 nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
  1564   uint32_t flags = (mData->mScriptableFlags & DONT_ENUM_STATIC_PROPS)
  1565                    ? 0
  1566                    : JSPROP_ENUMERATE;
  1568   uint32_t count = 0;
  1569   while (mData->mInterfaces[count]) {
  1570     count++;
  1573   JS::Rooted<JSObject*> proto(cx, aProto);
  1574   if (!xpc::DOM_DefineQuickStubs(cx, proto, flags, count, mData->mInterfaces)) {
  1575     JS_ClearPendingException(cx);
  1578   // This is called before any other location that requires
  1579   // sObjectClass, so compute it here. We assume that nobody has had a
  1580   // chance to monkey around with proto's prototype chain before this.
  1581   if (!sObjectClass) {
  1582     FindObjectClass(cx, proto);
  1583     NS_ASSERTION(sObjectClass && !strcmp(sObjectClass->name, "Object"),
  1584                  "Incorrect object class!");
  1587 #ifdef DEBUG
  1588     JS::Rooted<JSObject*> proto2(cx);
  1589     JS_GetPrototype(cx, proto, &proto2);
  1590     NS_ASSERTION(proto2 && JS_GetClass(proto2) == sObjectClass,
  1591                  "Hmm, somebody did something evil?");
  1592 #endif
  1594 #ifdef DEBUG
  1595   if (mData->mHasClassInterface && mData->mProtoChainInterface &&
  1596       mData->mProtoChainInterface != &NS_GET_IID(nsISupports)) {
  1597     nsCOMPtr<nsIInterfaceInfoManager>
  1598       iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
  1600     if (iim) {
  1601       nsCOMPtr<nsIInterfaceInfo> if_info;
  1602       iim->GetInfoForIID(mData->mProtoChainInterface,
  1603                          getter_AddRefs(if_info));
  1605       if (if_info) {
  1606         nsXPIDLCString name;
  1607         if_info->GetName(getter_Copies(name));
  1608         NS_ASSERTION(nsCRT::strcmp(CutPrefix(name), mData->mName) == 0,
  1609                      "Class name and proto chain interface name mismatch!");
  1613 #endif
  1615   // Make prototype delegation work correctly. Consider if a site sets
  1616   // HTMLElement.prototype.foopy = function () { ... } Now, calling
  1617   // document.body.foopy() needs to ensure that looking up foopy on
  1618   // document.body's prototype will find the right function.
  1619   JS::Rooted<JSObject*> global(cx, ::JS_GetGlobalForObject(cx, proto));
  1621   // Only do this if the global object is a window.
  1622   // XXX Is there a better way to check this?
  1623   nsISupports *globalNative = XPConnect()->GetNativeOfWrapper(cx, global);
  1624   nsCOMPtr<nsPIDOMWindow> piwin = do_QueryInterface(globalNative);
  1625   if (!piwin) {
  1626     return NS_OK;
  1629   nsGlobalWindow *win = nsGlobalWindow::FromSupports(globalNative);
  1630   if (win->IsClosedOrClosing()) {
  1631     return NS_OK;
  1634   // If the window is in a different compartment than the global object, then
  1635   // it's likely that global is a sandbox object whose prototype is a window.
  1636   // Don't do anything in this case.
  1637   if (win->FastGetGlobalJSObject() &&
  1638       js::GetObjectCompartment(global) != js::GetObjectCompartment(win->FastGetGlobalJSObject())) {
  1639     return NS_OK;
  1642   if (win->IsOuterWindow()) {
  1643     // XXXjst: Do security checks here when we remove the security
  1644     // checks on the inner window.
  1646     win = win->GetCurrentInnerWindowInternal();
  1648     if (!win || !(global = win->GetGlobalJSObject()) ||
  1649         win->IsClosedOrClosing()) {
  1650       return NS_OK;
  1654   // Don't overwrite a property set by content.
  1655   bool contentDefinedProperty;
  1656   if (!::JS_AlreadyHasOwnUCProperty(cx, global, reinterpret_cast<const jschar*>(mData->mNameUTF16),
  1657                                     NS_strlen(mData->mNameUTF16),
  1658                                     &contentDefinedProperty)) {
  1659     return NS_ERROR_FAILURE;
  1662   nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
  1663   NS_ENSURE_TRUE(nameSpaceManager, NS_OK);
  1665   JS::Rooted<JSPropertyDescriptor> desc(cx);
  1666   nsresult rv = ResolvePrototype(sXPConnect, win, cx, global, mData->mNameUTF16,
  1667                                  mData, nullptr, nameSpaceManager, proto,
  1668                                  &desc);
  1669   NS_ENSURE_SUCCESS(rv, rv);
  1670   if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined() &&
  1671       !JS_DefineUCProperty(cx, global, mData->mNameUTF16,
  1672                            NS_strlen(mData->mNameUTF16),
  1673                            desc.value(), desc.getter(), desc.setter(),
  1674                            desc.attributes())) {
  1675     return NS_ERROR_UNEXPECTED;
  1678   return NS_OK;
  1681 // static
  1682 nsIClassInfo *
  1683 NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID)
  1685   if (aID >= eDOMClassInfoIDCount) {
  1686     NS_ERROR("Bad ID!");
  1688     return nullptr;
  1691   if (!nsDOMClassInfo::sIsInitialized) {
  1692     nsresult rv = nsDOMClassInfo::Init();
  1694     NS_ENSURE_SUCCESS(rv, nullptr);
  1697   if (!sClassInfoData[aID].mCachedClassInfo) {
  1698     nsDOMClassInfoData& data = sClassInfoData[aID];
  1700     data.mCachedClassInfo = data.u.mConstructorFptr(&data);
  1701     NS_ENSURE_TRUE(data.mCachedClassInfo, nullptr);
  1703     NS_ADDREF(data.mCachedClassInfo);
  1706   NS_ASSERTION(!IS_EXTERNAL(sClassInfoData[aID].mCachedClassInfo),
  1707                "This is bad, internal class marked as external!");
  1709   return sClassInfoData[aID].mCachedClassInfo;
  1712 // static
  1713 nsIClassInfo *
  1714 nsDOMClassInfo::GetClassInfoInstance(nsDOMClassInfoData* aData)
  1716   NS_ASSERTION(IS_EXTERNAL(aData->mCachedClassInfo)
  1717                || !aData->mCachedClassInfo,
  1718                "This is bad, external class marked as internal!");
  1720   if (!aData->mCachedClassInfo) {
  1721     if (aData->u.mExternalConstructorFptr) {
  1722       aData->mCachedClassInfo =
  1723         aData->u.mExternalConstructorFptr(aData->mName);
  1724     } else {
  1725       aData->mCachedClassInfo = nsDOMGenericSH::doCreate(aData);
  1727     NS_ENSURE_TRUE(aData->mCachedClassInfo, nullptr);
  1729     NS_ADDREF(aData->mCachedClassInfo);
  1730     aData->mCachedClassInfo = MARK_EXTERNAL(aData->mCachedClassInfo);
  1733   return GET_CLEAN_CI_PTR(aData->mCachedClassInfo);
  1737 // static
  1738 void
  1739 nsDOMClassInfo::ShutDown()
  1741   if (sClassInfoData[0].u.mConstructorFptr) {
  1742     uint32_t i;
  1744     for (i = 0; i < eDOMClassInfoIDCount; i++) {
  1745       NS_IF_RELEASE(sClassInfoData[i].mCachedClassInfo);
  1749   sLocation_id        = JSID_VOID;
  1750   sConstructor_id     = JSID_VOID;
  1751   sLength_id          = JSID_VOID;
  1752   sItem_id            = JSID_VOID;
  1753   sEnumerate_id       = JSID_VOID;
  1754   sTop_id             = JSID_VOID;
  1755   sDocument_id        = JSID_VOID;
  1756   sWrappedJSObject_id = JSID_VOID;
  1758   NS_IF_RELEASE(sXPConnect);
  1759   NS_IF_RELEASE(sSecMan);
  1760   sIsInitialized = false;
  1763 // Window helper
  1765 NS_IMETHODIMP
  1766 nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
  1767                       JSObject *globalObj, JSObject **parentObj)
  1769   // Normally ::PreCreate() is used to give XPConnect the parent
  1770   // object for the object that's being wrapped, this parent object is
  1771   // set as the parent of the wrapper and it's also used to find the
  1772   // right scope for the object being wrapped. Now, in the case of the
  1773   // global object the wrapper shouldn't have a parent but we supply
  1774   // one here anyway (the global object itself) and this will be used
  1775   // by XPConnect only to find the right scope, once the scope is
  1776   // found XPConnect will find the existing wrapper (which always
  1777   // exists since it's created on window construction), since an
  1778   // existing wrapper is found the parent we supply here is ignored
  1779   // after the wrapper is found.
  1781   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeObj));
  1782   NS_ASSERTION(sgo, "nativeObj not a global object!");
  1784   nsGlobalWindow *win = nsGlobalWindow::FromSupports(nativeObj);
  1785   NS_ASSERTION(win->IsInnerWindow(), "Should be inner window.");
  1787   // We sometimes get a disconnected window during file api test. :-(
  1788   if (!win->GetOuterWindowInternal())
  1789     return NS_ERROR_FAILURE;
  1791   // If we're bootstrapping, we don't have a JS object yet.
  1792   if (win->GetOuterWindowInternal()->IsCreatingInnerWindow())
  1793     return NS_OK;
  1795   return SetParentToWindow(win, parentObj);
  1798 NS_IMETHODIMP
  1799 nsWindowSH::PostCreatePrototype(JSContext* aCx, JSObject* aProto)
  1801   JS::Rooted<JSObject*> proto(aCx, aProto);
  1803   nsresult rv = nsDOMClassInfo::PostCreatePrototype(aCx, proto);
  1804   NS_ENSURE_SUCCESS(rv, rv);
  1806   // We should probably move this into the CreateInterfaceObjects for Window
  1807   // once it is on WebIDL bindings.
  1808   WindowNamedPropertiesHandler::Install(aCx, proto);
  1809   return NS_OK;
  1812 NS_IMETHODIMP
  1813 nsWindowSH::PostCreate(nsIXPConnectWrappedNative *wrapper,
  1814                        JSContext *cx, JSObject *obj)
  1816   JS::Rooted<JSObject*> window(cx, obj);
  1818 #ifdef DEBUG
  1819   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
  1821   NS_ASSERTION(sgo && sgo->GetGlobalJSObject() == obj,
  1822                "Multiple wrappers created for global object!");
  1823 #endif
  1825   const NativeProperties* windowProperties =
  1826     WindowBinding::sNativePropertyHooks->mNativeProperties.regular;
  1827   const NativeProperties* eventTargetProperties =
  1828     EventTargetBinding::sNativePropertyHooks->mNativeProperties.regular;
  1830   return DefineWebIDLBindingPropertiesOnXPCObject(cx, window, windowProperties, true) &&
  1831          DefineWebIDLBindingPropertiesOnXPCObject(cx, window, eventTargetProperties, true) ?
  1832          NS_OK : NS_ERROR_FAILURE;
  1835 struct ResolveGlobalNameClosure
  1837   JSContext* cx;
  1838   JS::Handle<JSObject*> obj;
  1839   bool* retval;
  1840 };
  1842 static PLDHashOperator
  1843 ResolveGlobalName(const nsAString& aName,
  1844                   const nsGlobalNameStruct& aNameStruct,
  1845                   void* aClosure)
  1847   ResolveGlobalNameClosure* closure =
  1848     static_cast<ResolveGlobalNameClosure*>(aClosure);
  1849   JS::Rooted<JS::Value> dummy(closure->cx);
  1850   bool ok = JS_LookupUCProperty(closure->cx, closure->obj,
  1851                                 aName.BeginReading(), aName.Length(),
  1852                                 &dummy);
  1853   if (!ok) {
  1854     *closure->retval = false;
  1855     return PL_DHASH_STOP;
  1857   return PL_DHASH_NEXT;
  1860 NS_IMETHODIMP
  1861 nsWindowSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1862                       JSObject *aObj, bool *_retval)
  1864   JS::Rooted<JSObject*> obj(cx, aObj);
  1865   if (!xpc::WrapperFactory::IsXrayWrapper(obj)) {
  1866     *_retval = JS_EnumerateStandardClasses(cx, obj);
  1867     if (!*_retval) {
  1868       return NS_OK;
  1871     // Now resolve everything from the namespace manager
  1872     nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
  1873     if (!nameSpaceManager) {
  1874       NS_ERROR("Can't get namespace manager.");
  1875       return NS_ERROR_UNEXPECTED;
  1877     ResolveGlobalNameClosure closure = { cx, obj, _retval };
  1878     nameSpaceManager->EnumerateGlobalNames(ResolveGlobalName, &closure);
  1881   return NS_OK;
  1884 static nsDOMConstructorFunc
  1885 FindConstructorFunc(const nsDOMClassInfoData *aDOMClassInfoData)
  1887   for (uint32_t i = 0; i < ArrayLength(kConstructorFuncMap); ++i) {
  1888     if (&sClassInfoData[kConstructorFuncMap[i].mDOMClassInfoID] ==
  1889         aDOMClassInfoData) {
  1890       return kConstructorFuncMap[i].mConstructorFunc;
  1893   return nullptr;
  1896 static nsresult
  1897 BaseStubConstructor(nsIWeakReference* aWeakOwner,
  1898                     const nsGlobalNameStruct *name_struct, JSContext *cx,
  1899                     JS::Handle<JSObject*> obj, const JS::CallArgs &args)
  1901   MOZ_ASSERT(obj);
  1903   nsresult rv;
  1904   nsCOMPtr<nsISupports> native;
  1905   if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
  1906     const nsDOMClassInfoData* ci_data =
  1907       &sClassInfoData[name_struct->mDOMClassInfoID];
  1908     nsDOMConstructorFunc func = FindConstructorFunc(ci_data);
  1909     if (func) {
  1910       rv = func(getter_AddRefs(native));
  1911     } else {
  1912       rv = NS_ERROR_NOT_AVAILABLE;
  1914   } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
  1915     native = do_CreateInstance(name_struct->mCID, &rv);
  1916   } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
  1917     native = do_CreateInstance(name_struct->mAlias->mCID, &rv);
  1918   } else {
  1919     native = do_CreateInstance(*name_struct->mData->mConstructorCID, &rv);
  1921   if (NS_FAILED(rv)) {
  1922     NS_ERROR("Failed to create the object");
  1923     return rv;
  1926   nsCOMPtr<nsIJSNativeInitializer> initializer(do_QueryInterface(native));
  1927   nsCOMPtr<nsIDOMGlobalObjectConstructor> constructor(do_QueryInterface(native));
  1928   if (initializer || constructor) {
  1929     // Initialize object using the current inner window, but only if
  1930     // the caller can access it.
  1931     nsCOMPtr<nsPIDOMWindow> owner = do_QueryReferent(aWeakOwner);
  1932     nsPIDOMWindow* outerWindow = owner ? owner->GetOuterWindow() : nullptr;
  1933     nsPIDOMWindow* currentInner =
  1934       outerWindow ? outerWindow->GetCurrentInnerWindow() : nullptr;
  1935     if (!currentInner ||
  1936         (owner != currentInner &&
  1937          !nsContentUtils::CanCallerAccess(currentInner))) {
  1938       return NS_ERROR_DOM_SECURITY_ERR;
  1941     if (initializer) {
  1942       rv = initializer->Initialize(currentInner, cx, obj, args);
  1943       if (NS_FAILED(rv)) {
  1944         return rv;
  1946     } else {
  1947       nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(native);
  1949       JS::Rooted<JSObject*> thisObject(cx, wrappedJS->GetJSObject());
  1950       if (!thisObject) {
  1951         return NS_ERROR_UNEXPECTED;
  1954       nsCxPusher pusher;
  1955       pusher.Push(cx);
  1957       JSAutoCompartment ac(cx, thisObject);
  1959       JS::Rooted<JS::Value> funval(cx);
  1960       if (!JS_GetProperty(cx, thisObject, "constructor", &funval) ||
  1961           !funval.isObject()) {
  1962         return NS_ERROR_UNEXPECTED;
  1965       // Check if the object is even callable.
  1966       NS_ENSURE_STATE(JS_ObjectIsCallable(cx, &funval.toObject()));
  1968         // wrap parameters in the target compartment
  1969         // we also pass in the calling window as the first argument
  1970         unsigned argc = args.length() + 1;
  1971         JS::AutoValueVector argv(cx);
  1972         if (!argv.resize(argc)) {
  1973           return NS_ERROR_OUT_OF_MEMORY;
  1976         nsCOMPtr<nsIDOMWindow> currentWin(do_GetInterface(currentInner));
  1977         rv = WrapNative(cx, currentWin, &NS_GET_IID(nsIDOMWindow),
  1978                         true, argv.handleAt(0));
  1980         for (size_t i = 1; i < argc; ++i) {
  1981           argv[i] = args[i - 1];
  1982           if (!JS_WrapValue(cx, argv.handleAt(i)))
  1983             return NS_ERROR_FAILURE;
  1986         JS::Rooted<JS::Value> frval(cx);
  1987         bool ret = JS_CallFunctionValue(cx, thisObject, funval, argv, &frval);
  1989         if (!ret) {
  1990           return NS_ERROR_FAILURE;
  1996   js::AssertSameCompartment(cx, obj);
  1997   return WrapNative(cx, native, true, args.rval());
  2000 static nsresult
  2001 DefineInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj, const nsIID *aIID)
  2003   nsCOMPtr<nsIInterfaceInfoManager>
  2004     iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
  2005   NS_ENSURE_TRUE(iim, NS_ERROR_UNEXPECTED);
  2007   nsCOMPtr<nsIInterfaceInfo> if_info;
  2009   nsresult rv = iim->GetInfoForIID(aIID, getter_AddRefs(if_info));
  2010   NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && if_info, rv);
  2012   uint16_t constant_count;
  2014   if_info->GetConstantCount(&constant_count);
  2016   if (!constant_count) {
  2017     return NS_OK;
  2020   nsCOMPtr<nsIInterfaceInfo> parent_if_info;
  2022   rv = if_info->GetParent(getter_AddRefs(parent_if_info));
  2023   NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && parent_if_info, rv);
  2025   uint16_t parent_constant_count, i;
  2026   parent_if_info->GetConstantCount(&parent_constant_count);
  2028   JS::Rooted<JS::Value> v(cx);
  2029   for (i = parent_constant_count; i < constant_count; i++) {
  2030     const nsXPTConstant *c = nullptr;
  2032     rv = if_info->GetConstant(i, &c);
  2033     NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && c, rv);
  2035     uint16_t type = c->GetType().TagPart();
  2037     v.setUndefined();
  2038     switch (type) {
  2039       case nsXPTType::T_I8:
  2040       case nsXPTType::T_U8:
  2042         v.setInt32(c->GetValue()->val.u8);
  2043         break;
  2045       case nsXPTType::T_I16:
  2046       case nsXPTType::T_U16:
  2048         v.setInt32(c->GetValue()->val.u16);
  2049         break;
  2051       case nsXPTType::T_I32:
  2053         v = JS_NumberValue(c->GetValue()->val.i32);
  2054         break;
  2056       case nsXPTType::T_U32:
  2058         v = JS_NumberValue(c->GetValue()->val.u32);
  2059         break;
  2061       default:
  2063 #ifdef DEBUG
  2064         NS_ERROR("Non-numeric constant found in interface.");
  2065 #endif
  2066         continue;
  2070     if (!::JS_DefineProperty(cx, obj, c->GetName(), v,
  2071                              JSPROP_ENUMERATE | JSPROP_READONLY |
  2072                              JSPROP_PERMANENT,
  2073                              JS_PropertyStub, JS_StrictPropertyStub)) {
  2074       return NS_ERROR_UNEXPECTED;
  2078   return NS_OK;
  2081 class nsDOMConstructor MOZ_FINAL : public nsIDOMDOMConstructor
  2083 protected:
  2084   nsDOMConstructor(const char16_t* aName,
  2085                    bool aIsConstructable,
  2086                    nsPIDOMWindow* aOwner)
  2087     : mClassName(aName),
  2088       mConstructable(aIsConstructable),
  2089       mWeakOwner(do_GetWeakReference(aOwner))
  2093 public:
  2095   static nsresult Create(const char16_t* aName,
  2096                          const nsDOMClassInfoData* aData,
  2097                          const nsGlobalNameStruct* aNameStruct,
  2098                          nsPIDOMWindow* aOwner,
  2099                          nsDOMConstructor** aResult);
  2101   NS_DECL_ISUPPORTS
  2102   NS_DECL_NSIDOMDOMCONSTRUCTOR
  2104   nsresult PreCreate(JSContext *cx, JSObject *globalObj, JSObject **parentObj);
  2106   nsresult Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  2107                      JS::Handle<JSObject*> obj, const JS::CallArgs &args,
  2108                      bool *_retval);
  2110   nsresult HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  2111                        JS::Handle<JSObject*> obj, const jsval &val, bool *bp,
  2112                        bool *_retval);
  2114   nsresult ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj);
  2116 private:
  2117   const nsGlobalNameStruct *GetNameStruct()
  2119     if (!mClassName) {
  2120       NS_ERROR("Can't get name");
  2121       return nullptr;
  2124     const nsGlobalNameStruct *nameStruct;
  2125 #ifdef DEBUG
  2126     nsresult rv =
  2127 #endif
  2128       GetNameStruct(nsDependentString(mClassName), &nameStruct);
  2130     NS_ASSERTION(NS_FAILED(rv) || nameStruct, "Name isn't in hash.");
  2132     return nameStruct;
  2135   static nsresult GetNameStruct(const nsAString& aName,
  2136                                 const nsGlobalNameStruct **aNameStruct)
  2138     *aNameStruct = nullptr;
  2140     nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
  2141     if (!nameSpaceManager) {
  2142       NS_ERROR("Can't get namespace manager.");
  2143       return NS_ERROR_UNEXPECTED;
  2146     *aNameStruct = nameSpaceManager->LookupName(aName);
  2148     // Return NS_OK here, aName just isn't a DOM class but nothing failed.
  2149     return NS_OK;
  2152   static bool IsConstructable(const nsDOMClassInfoData *aData)
  2154     if (IS_EXTERNAL(aData->mCachedClassInfo)) {
  2155       const nsExternalDOMClassInfoData* data =
  2156         static_cast<const nsExternalDOMClassInfoData*>(aData);
  2157       return data->mConstructorCID != nullptr;
  2160     return FindConstructorFunc(aData);
  2162   static bool IsConstructable(const nsGlobalNameStruct *aNameStruct)
  2164     return
  2165       (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
  2166        IsConstructable(&sClassInfoData[aNameStruct->mDOMClassInfoID])) ||
  2167       (aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo &&
  2168        IsConstructable(aNameStruct->mData)) ||
  2169       aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructor ||
  2170       aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias;
  2173   const char16_t*   mClassName;
  2174   const bool mConstructable;
  2175   nsWeakPtr          mWeakOwner;
  2176 };
  2178 //static
  2179 nsresult
  2180 nsDOMConstructor::Create(const char16_t* aName,
  2181                          const nsDOMClassInfoData* aData,
  2182                          const nsGlobalNameStruct* aNameStruct,
  2183                          nsPIDOMWindow* aOwner,
  2184                          nsDOMConstructor** aResult)
  2186   *aResult = nullptr;
  2187   // Prevent creating a constructor if aOwner is inner window which doesn't have
  2188   // an outer window. If the outer window doesn't have an inner window or the
  2189   // caller can't access the outer window's current inner window then try to use
  2190   // the owner (so long as it is, in fact, an inner window). If that doesn't
  2191   // work then prevent creation also.
  2192   nsPIDOMWindow* outerWindow = aOwner->GetOuterWindow();
  2193   nsPIDOMWindow* currentInner =
  2194     outerWindow ? outerWindow->GetCurrentInnerWindow() : aOwner;
  2195   if (!currentInner ||
  2196       (aOwner != currentInner &&
  2197        !nsContentUtils::CanCallerAccess(currentInner) &&
  2198        !(currentInner = aOwner)->IsInnerWindow())) {
  2199     return NS_ERROR_DOM_SECURITY_ERR;
  2202   bool constructable = aNameStruct ?
  2203                          IsConstructable(aNameStruct) :
  2204                          IsConstructable(aData);
  2206   *aResult = new nsDOMConstructor(aName, constructable, currentInner);
  2207   NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
  2208   NS_ADDREF(*aResult);
  2209   return NS_OK;
  2212 NS_IMPL_ADDREF(nsDOMConstructor)
  2213 NS_IMPL_RELEASE(nsDOMConstructor)
  2214 NS_INTERFACE_MAP_BEGIN(nsDOMConstructor)
  2215   NS_INTERFACE_MAP_ENTRY(nsIDOMDOMConstructor)
  2216   NS_INTERFACE_MAP_ENTRY(nsISupports)
  2217   if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
  2218 #ifdef DEBUG
  2220       const nsGlobalNameStruct *name_struct = GetNameStruct();
  2221       NS_ASSERTION(!name_struct ||
  2222                    mConstructable == IsConstructable(name_struct),
  2223                    "Can't change constructability dynamically!");
  2225 #endif
  2226     foundInterface =
  2227       NS_GetDOMClassInfoInstance(mConstructable ?
  2228                                  eDOMClassInfo_DOMConstructor_id :
  2229                                  eDOMClassInfo_DOMPrototype_id);
  2230     if (!foundInterface) {
  2231       *aInstancePtr = nullptr;
  2232       return NS_ERROR_OUT_OF_MEMORY;
  2234   } else
  2235 NS_INTERFACE_MAP_END
  2237 nsresult
  2238 nsDOMConstructor::PreCreate(JSContext *cx, JSObject *globalObj, JSObject **parentObj)
  2240   nsCOMPtr<nsPIDOMWindow> owner(do_QueryReferent(mWeakOwner));
  2241   if (!owner) {
  2242     // Can't do anything.
  2243     return NS_OK;
  2246   nsGlobalWindow *win = static_cast<nsGlobalWindow *>(owner.get());
  2247   return SetParentToWindow(win, parentObj);
  2250 nsresult
  2251 nsDOMConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
  2252                             JS::Handle<JSObject*> obj, const JS::CallArgs &args,
  2253                             bool *_retval)
  2255   MOZ_ASSERT(obj);
  2257   const nsGlobalNameStruct *name_struct = GetNameStruct();
  2258   NS_ENSURE_TRUE(name_struct, NS_ERROR_FAILURE);
  2260   if (!IsConstructable(name_struct)) {
  2261     // ignore return value, we return false anyway
  2262     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
  2265   return BaseStubConstructor(mWeakOwner, name_struct, cx, obj, args);
  2268 nsresult
  2269 nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
  2270                               JSContext * cx, JS::Handle<JSObject*> obj,
  2271                               const jsval &v, bool *bp, bool *_retval)
  2274   // No need to look these up in the hash.
  2275   *bp = false;
  2276   if (JSVAL_IS_PRIMITIVE(v)) {
  2277     return NS_OK;
  2280   JS::Rooted<JSObject*> dom_obj(cx, v.toObjectOrNull());
  2281   NS_ASSERTION(dom_obj, "nsDOMConstructor::HasInstance couldn't get object");
  2283   // This might not be the right object, if there are wrappers. Unwrap if we can.
  2284   JSObject *wrapped_obj = js::CheckedUnwrap(dom_obj, /* stopAtOuter = */ false);
  2285   if (wrapped_obj)
  2286       dom_obj = wrapped_obj;
  2288   const JSClass *dom_class = JS_GetClass(dom_obj);
  2289   if (!dom_class) {
  2290     NS_ERROR("nsDOMConstructor::HasInstance can't get class.");
  2291     return NS_ERROR_UNEXPECTED;
  2294   const nsGlobalNameStruct *name_struct;
  2295   nsresult rv = GetNameStruct(NS_ConvertASCIItoUTF16(dom_class->name), &name_struct);
  2296   if (NS_FAILED(rv)) {
  2297     return rv;
  2300   if (!name_struct) {
  2301     // This isn't a normal DOM object, see if this constructor lives on its
  2302     // prototype chain.
  2303     JS::Rooted<JS::Value> val(cx);
  2304     if (!JS_GetProperty(cx, obj, "prototype", &val)) {
  2305       return NS_ERROR_UNEXPECTED;
  2308     if (JSVAL_IS_PRIMITIVE(val)) {
  2309       return NS_OK;
  2312     JS::Rooted<JSObject*> dot_prototype(cx, val.toObjectOrNull());
  2314     JS::Rooted<JSObject*> proto(cx, dom_obj);
  2315     for (;;) {
  2316       if (!JS_GetPrototype(cx, proto, &proto)) {
  2317         return NS_ERROR_UNEXPECTED;
  2319       if (!proto) {
  2320         break;
  2322       if (proto == dot_prototype) {
  2323         *bp = true;
  2324         break;
  2328     return NS_OK;
  2331   if (name_struct->mType != nsGlobalNameStruct::eTypeClassConstructor &&
  2332       name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo &&
  2333       name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructorAlias) {
  2334     // Doesn't have DOM interfaces.
  2335     return NS_OK;
  2338   const nsGlobalNameStruct *class_name_struct = GetNameStruct();
  2339   NS_ENSURE_TRUE(class_name_struct, NS_ERROR_FAILURE);
  2341   if (name_struct == class_name_struct) {
  2342     *bp = true;
  2344     return NS_OK;
  2347   nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
  2348   NS_ASSERTION(nameSpaceManager, "Can't get namespace manager?");
  2350   const nsIID *class_iid;
  2351   if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
  2352       class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
  2353     class_iid = &class_name_struct->mIID;
  2354   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
  2355     class_iid =
  2356       sClassInfoData[class_name_struct->mDOMClassInfoID].mProtoChainInterface;
  2357   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
  2358     class_iid = class_name_struct->mData->mProtoChainInterface;
  2359   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
  2360     const nsGlobalNameStruct* alias_struct =
  2361       nameSpaceManager->GetConstructorProto(class_name_struct);
  2362     if (!alias_struct) {
  2363       NS_ERROR("Couldn't get constructor prototype.");
  2364       return NS_ERROR_UNEXPECTED;
  2367     if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
  2368       class_iid =
  2369         sClassInfoData[alias_struct->mDOMClassInfoID].mProtoChainInterface;
  2370     } else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
  2371       class_iid = alias_struct->mData->mProtoChainInterface;
  2372     } else {
  2373       NS_ERROR("Expected eTypeClassConstructor or eTypeExternalClassInfo.");
  2374       return NS_ERROR_UNEXPECTED;
  2376   } else {
  2377     *bp = false;
  2379     return NS_OK;
  2382   if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
  2383     name_struct = nameSpaceManager->GetConstructorProto(name_struct);
  2384     if (!name_struct) {
  2385       NS_ERROR("Couldn't get constructor prototype.");
  2386       return NS_ERROR_UNEXPECTED;
  2390   NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
  2391                name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
  2392                "The constructor was set up with a struct of the wrong type.");
  2394   const nsDOMClassInfoData *ci_data = nullptr;
  2395   if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
  2396       name_struct->mDOMClassInfoID >= 0) {
  2397     ci_data = &sClassInfoData[name_struct->mDOMClassInfoID];
  2398   } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
  2399     ci_data = name_struct->mData;
  2402   nsCOMPtr<nsIInterfaceInfoManager>
  2403     iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
  2404   if (!iim) {
  2405     NS_ERROR("nsDOMConstructor::HasInstance can't get interface info mgr.");
  2406     return NS_ERROR_UNEXPECTED;
  2409   nsCOMPtr<nsIInterfaceInfo> if_info;
  2410   uint32_t count = 0;
  2411   const nsIID* class_interface;
  2412   while ((class_interface = ci_data->mInterfaces[count++])) {
  2413     if (class_iid->Equals(*class_interface)) {
  2414       *bp = true;
  2416       return NS_OK;
  2419     iim->GetInfoForIID(class_interface, getter_AddRefs(if_info));
  2420     if (!if_info) {
  2421       NS_ERROR("nsDOMConstructor::HasInstance can't get interface info.");
  2422       return NS_ERROR_UNEXPECTED;
  2425     if_info->HasAncestor(class_iid, bp);
  2427     if (*bp) {
  2428       return NS_OK;
  2432   return NS_OK;
  2435 nsresult
  2436 nsDOMConstructor::ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj)
  2438   const nsGlobalNameStruct *class_name_struct = GetNameStruct();
  2439   if (!class_name_struct)
  2440     return NS_ERROR_UNEXPECTED;
  2442   const nsIID *class_iid;
  2443   if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
  2444       class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
  2445     class_iid = &class_name_struct->mIID;
  2446   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
  2447     class_iid =
  2448       sClassInfoData[class_name_struct->mDOMClassInfoID].mProtoChainInterface;
  2449   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
  2450     class_iid = class_name_struct->mData->mProtoChainInterface;
  2451   } else {
  2452     return NS_OK;
  2455   nsresult rv = DefineInterfaceConstants(cx, obj, class_iid);
  2456   NS_ENSURE_SUCCESS(rv, rv);
  2458   return NS_OK;
  2461 NS_IMETHODIMP
  2462 nsDOMConstructor::ToString(nsAString &aResult)
  2464   aResult.AssignLiteral("[object ");
  2465   aResult.Append(mClassName);
  2466   aResult.Append(char16_t(']'));
  2468   return NS_OK;
  2472 static nsresult
  2473 GetXPCProto(nsIXPConnect *aXPConnect, JSContext *cx, nsGlobalWindow *aWin,
  2474             const nsGlobalNameStruct *aNameStruct,
  2475             nsIXPConnectJSObjectHolder **aProto)
  2477   NS_ASSERTION(aNameStruct->mType ==
  2478                  nsGlobalNameStruct::eTypeClassConstructor ||
  2479                aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
  2480                "Wrong type!");
  2482   nsCOMPtr<nsIClassInfo> ci;
  2483   if (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
  2484     int32_t id = aNameStruct->mDOMClassInfoID;
  2485     NS_ABORT_IF_FALSE(id >= 0, "Negative DOM classinfo?!?");
  2487     nsDOMClassInfoID ci_id = (nsDOMClassInfoID)id;
  2489     ci = NS_GetDOMClassInfoInstance(ci_id);
  2491     // In most cases we want to find the wrapped native prototype in
  2492     // aWin's scope and use that prototype for
  2493     // ClassName.prototype. But in the case where we're setting up
  2494     // "Window.prototype" or "ChromeWindow.prototype" we want to do
  2495     // the look up in aWin's outer window's scope since the inner
  2496     // window's wrapped native prototype comes from the outer
  2497     // window's scope.
  2498     if (ci_id == eDOMClassInfo_Window_id ||
  2499         ci_id == eDOMClassInfo_ModalContentWindow_id ||
  2500         ci_id == eDOMClassInfo_ChromeWindow_id) {
  2501       nsGlobalWindow *scopeWindow = aWin->GetOuterWindowInternal();
  2503       if (scopeWindow) {
  2504         aWin = scopeWindow;
  2508   else {
  2509     ci = nsDOMClassInfo::GetClassInfoInstance(aNameStruct->mData);
  2511   NS_ENSURE_TRUE(ci, NS_ERROR_UNEXPECTED);
  2513   nsresult rv =
  2514     aXPConnect->GetWrappedNativePrototype(cx, aWin->GetGlobalJSObject(), ci,
  2515                                           aProto);
  2516   NS_ENSURE_SUCCESS(rv, rv);
  2518   JS::Rooted<JSObject*> proto_obj(cx, (*aProto)->GetJSObject());
  2519   if (!JS_WrapObject(cx, &proto_obj)) {
  2520     return NS_ERROR_FAILURE;
  2523   NS_IF_RELEASE(*aProto);
  2524   return aXPConnect->HoldObject(cx, proto_obj, aProto);
  2527 // Either ci_data must be non-null or name_struct must be non-null and of type
  2528 // eTypeClassProto.
  2529 static nsresult
  2530 ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
  2531                  JS::Handle<JSObject*> obj, const char16_t *name,
  2532                  const nsDOMClassInfoData *ci_data,
  2533                  const nsGlobalNameStruct *name_struct,
  2534                  nsScriptNameSpaceManager *nameSpaceManager,
  2535                  JSObject* aDot_prototype,
  2536                  JS::MutableHandle<JSPropertyDescriptor> ctorDesc)
  2538   JS::Rooted<JSObject*> dot_prototype(cx, aDot_prototype);
  2539   NS_ASSERTION(ci_data ||
  2540                (name_struct &&
  2541                 name_struct->mType == nsGlobalNameStruct::eTypeClassProto),
  2542                "Wrong type or missing ci_data!");
  2544   nsRefPtr<nsDOMConstructor> constructor;
  2545   nsresult rv = nsDOMConstructor::Create(name, ci_data, name_struct, aWin,
  2546                                          getter_AddRefs(constructor));
  2547   NS_ENSURE_SUCCESS(rv, rv);
  2549   JS::Rooted<JS::Value> v(cx);
  2551   js::AssertSameCompartment(cx, obj);
  2552   rv = WrapNative(cx, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
  2553                   false, &v);
  2554   NS_ENSURE_SUCCESS(rv, rv);
  2556   FillPropertyDescriptor(ctorDesc, obj, 0, v);
  2557   // And make sure we wrap the value into the right compartment.  Note that we
  2558   // do this with ctorDesc.value(), not with v, because we need v to be in the
  2559   // right compartment (that of the reflector of |constructor|) below.
  2560   if (!JS_WrapValue(cx, ctorDesc.value())) {
  2561     return NS_ERROR_UNEXPECTED;
  2564   JS::Rooted<JSObject*> class_obj(cx, &v.toObject());
  2566   const nsIID *primary_iid = &NS_GET_IID(nsISupports);
  2568   if (!ci_data) {
  2569     primary_iid = &name_struct->mIID;
  2571   else if (ci_data->mProtoChainInterface) {
  2572     primary_iid = ci_data->mProtoChainInterface;
  2575   nsCOMPtr<nsIInterfaceInfo> if_info;
  2576   nsCOMPtr<nsIInterfaceInfo> parent;
  2577   const char *class_parent_name = nullptr;
  2579   if (!primary_iid->Equals(NS_GET_IID(nsISupports))) {
  2580     JSAutoCompartment ac(cx, class_obj);
  2582     rv = DefineInterfaceConstants(cx, class_obj, primary_iid);
  2583     NS_ENSURE_SUCCESS(rv, rv);
  2585     nsCOMPtr<nsIInterfaceInfoManager>
  2586       iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
  2587     NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
  2589     iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info));
  2590     NS_ENSURE_TRUE(if_info, NS_ERROR_UNEXPECTED);
  2592     const nsIID *iid = nullptr;
  2594     if (ci_data && !ci_data->mHasClassInterface) {
  2595       if_info->GetIIDShared(&iid);
  2596     } else {
  2597       if_info->GetParent(getter_AddRefs(parent));
  2598       NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
  2600       parent->GetIIDShared(&iid);
  2603     if (iid) {
  2604       if (!iid->Equals(NS_GET_IID(nsISupports))) {
  2605         if (ci_data && !ci_data->mHasClassInterface) {
  2606           // If the class doesn't have a class interface the primary
  2607           // interface is the interface that should be
  2608           // constructor.prototype.__proto__.
  2610           if_info->GetNameShared(&class_parent_name);
  2611         } else {
  2612           // If the class does have a class interface (or there's no
  2613           // real class for this name) then the parent of the
  2614           // primary interface is what we want on
  2615           // constructor.prototype.__proto__.
  2617           NS_ASSERTION(parent, "Whoa, this is bad, null parent here!");
  2619           parent->GetNameShared(&class_parent_name);
  2626     JS::Rooted<JSObject*> winobj(cx, aWin->FastGetGlobalJSObject());
  2628     JS::Rooted<JSObject*> proto(cx);
  2630     if (class_parent_name) {
  2631       JSAutoCompartment ac(cx, winobj);
  2633       JS::Rooted<JS::Value> val(cx);
  2634       if (!JS_LookupProperty(cx, winobj, CutPrefix(class_parent_name), &val)) {
  2635         return NS_ERROR_UNEXPECTED;
  2638       if (val.isObject()) {
  2639         JS::Rooted<JSObject*> obj(cx, &val.toObject());
  2640         if (!JS_LookupProperty(cx, obj, "prototype", &val)) {
  2641           return NS_ERROR_UNEXPECTED;
  2644         if (val.isObject()) {
  2645           proto = &val.toObject();
  2650     if (dot_prototype) {
  2651       JSAutoCompartment ac(cx, dot_prototype);
  2652       JS::Rooted<JSObject*> xpc_proto_proto(cx);
  2653       if (!::JS_GetPrototype(cx, dot_prototype, &xpc_proto_proto)) {
  2654         return NS_ERROR_UNEXPECTED;
  2657       if (proto &&
  2658           (!xpc_proto_proto ||
  2659            JS_GetClass(xpc_proto_proto) == sObjectClass)) {
  2660         if (!JS_WrapObject(cx, &proto) ||
  2661             !JS_SetPrototype(cx, dot_prototype, proto)) {
  2662           return NS_ERROR_UNEXPECTED;
  2665     } else {
  2666       JSAutoCompartment ac(cx, winobj);
  2667       if (!proto) {
  2668         proto = JS_GetObjectPrototype(cx, winobj);
  2670       dot_prototype = ::JS_NewObjectWithUniqueType(cx,
  2671                                                    &sDOMConstructorProtoClass,
  2672                                                    proto,
  2673                                                    winobj);
  2674       NS_ENSURE_TRUE(dot_prototype, NS_ERROR_OUT_OF_MEMORY);
  2678   v = OBJECT_TO_JSVAL(dot_prototype);
  2680   JSAutoCompartment ac(cx, class_obj);
  2682   // Per ECMA, the prototype property is {DontEnum, DontDelete, ReadOnly}
  2683   if (!JS_WrapValue(cx, &v) ||
  2684       !JS_DefineProperty(cx, class_obj, "prototype", v,
  2685                          JSPROP_PERMANENT | JSPROP_READONLY,
  2686                          JS_PropertyStub, JS_StrictPropertyStub)) {
  2687     return NS_ERROR_UNEXPECTED;
  2690   return NS_OK;
  2693 static bool
  2694 OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct,
  2695                              nsGlobalWindow *aWin, JSContext *cx)
  2697   MOZ_ASSERT(aStruct->mType == nsGlobalNameStruct::eTypeProperty ||
  2698              aStruct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
  2699              aStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo);
  2701   // Don't expose chrome only constructors to content windows.
  2702   if (aStruct->mChromeOnly) {
  2703     bool expose;
  2704     if (aStruct->mAllowXBL) {
  2705       expose = IsChromeOrXBL(cx, nullptr);
  2706     } else {
  2707       expose = nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal());
  2710     if (!expose) {
  2711       return false;
  2715   // Don't expose CSSSupportsRule unless @supports processing is enabled.
  2716   if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSSupportsRule_id) {
  2717     if (!CSSSupportsRule::PrefEnabled()) {
  2718       return false;
  2722   // Don't expose CSSFontFeatureValuesRule unless the pref is enabled
  2723   if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSFontFeatureValuesRule_id) {
  2724     return nsCSSFontFeatureValuesRule::PrefEnabled();
  2727   return true;
  2730 bool
  2731 nsWindowSH::NameStructEnabled(JSContext* aCx, nsGlobalWindow *aWin,
  2732                               const nsAString& aName,
  2733                               const nsGlobalNameStruct& aNameStruct)
  2735   const nsGlobalNameStruct* nameStruct = &aNameStruct;
  2736   if (nameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) {
  2737     nsresult rv = GetExternalClassInfo(GetNameSpaceManager(), aName, nameStruct,
  2738                                        &nameStruct);
  2739     if (NS_FAILED(rv) || !nameStruct) {
  2740       return false;
  2744   return (nameStruct->mType != nsGlobalNameStruct::eTypeProperty &&
  2745           nameStruct->mType != nsGlobalNameStruct::eTypeClassConstructor &&
  2746           nameStruct->mType != nsGlobalNameStruct::eTypeExternalClassInfo) ||
  2747          OldBindingConstructorEnabled(nameStruct, aWin, aCx);
  2750 #ifdef RELEASE_BUILD
  2751 #define USE_CONTROLLERS_SHIM
  2752 #endif
  2754 #ifdef USE_CONTROLLERS_SHIM
  2755 static const JSClass ControllersShimClass = {
  2756     "XULControllers", 0,
  2757     JS_PropertyStub,   JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
  2758     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nullptr
  2759 };
  2760 #endif
  2762 // static
  2763 nsresult
  2764 nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
  2765                           JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
  2766                           JS::MutableHandle<JSPropertyDescriptor> desc)
  2768 #ifdef USE_CONTROLLERS_SHIM
  2769   if (id == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_CONTROLLERS) &&
  2770       !xpc::IsXrayWrapper(obj) &&
  2771       !nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal()))
  2773     if (aWin->GetDoc()) {
  2774       aWin->GetDoc()->WarnOnceAbout(nsIDocument::eWindow_Controllers);
  2776     JS::Rooted<JSObject*> shim(cx, JS_NewObject(cx, &ControllersShimClass, JS::NullPtr(), obj));
  2777     if (NS_WARN_IF(!shim)) {
  2778       return NS_ERROR_OUT_OF_MEMORY;
  2780     FillPropertyDescriptor(desc, obj, JS::ObjectValue(*shim), /* readOnly = */ false);
  2781     return NS_OK;
  2783 #endif
  2785   nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
  2786   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
  2788   nsDependentJSString name(id);
  2790   const char16_t *class_name = nullptr;
  2791   const nsGlobalNameStruct *name_struct =
  2792     nameSpaceManager->LookupName(name, &class_name);
  2794   if (!name_struct) {
  2795     return NS_OK;
  2798   // The class_name had better match our name
  2799   MOZ_ASSERT(name.Equals(class_name));
  2801   NS_ENSURE_TRUE(class_name, NS_ERROR_UNEXPECTED);
  2803   nsresult rv = NS_OK;
  2805   if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) {
  2806     rv = GetExternalClassInfo(nameSpaceManager, name, name_struct,
  2807                               &name_struct);
  2808     if (NS_FAILED(rv) || !name_struct) {
  2809       return rv;
  2813   if (name_struct->mType == nsGlobalNameStruct::eTypeNewDOMBinding ||
  2814       name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
  2815       name_struct->mType == nsGlobalNameStruct::eTypeClassProto ||
  2816       name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
  2817     // Lookup new DOM bindings.
  2818     DefineInterface getOrCreateInterfaceObject =
  2819       name_struct->mDefineDOMInterface;
  2820     if (getOrCreateInterfaceObject) {
  2821       if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
  2822           !OldBindingConstructorEnabled(name_struct, aWin, cx)) {
  2823         return NS_OK;
  2826       ConstructorEnabled* checkEnabledForScope = name_struct->mConstructorEnabled;
  2827       // We do the enabled check on the current compartment of cx, but for the
  2828       // actual object we pass in the underlying object in the Xray case.  That
  2829       // way the callee can decide whether to allow access based on the caller
  2830       // or the window being touched.
  2831       JS::Rooted<JSObject*> global(cx,
  2832         js::CheckedUnwrap(obj, /* stopAtOuter = */ false));
  2833       if (!global) {
  2834         return NS_ERROR_DOM_SECURITY_ERR;
  2836       if (checkEnabledForScope && !checkEnabledForScope(cx, global)) {
  2837         return NS_OK;
  2840       // The DOM constructor resolve machinery interacts with Xrays in tricky
  2841       // ways, and there are some asymmetries that are important to understand.
  2842       //
  2843       // In the regular (non-Xray) case, we only want to resolve constructors
  2844       // once (so that if they're deleted, they don't reappear). We do this by
  2845       // stashing the constructor in a slot on the global, such that we can see
  2846       // during resolve whether we've created it already. This is rather
  2847       // memory-intensive, so we don't try to maintain these semantics when
  2848       // manipulating a global over Xray (so the properties just re-resolve if
  2849       // they've been deleted).
  2850       //
  2851       // Unfortunately, there's a bit of an impedance-mismatch between the Xray
  2852       // and non-Xray machinery. The Xray machinery wants an API that returns a
  2853       // JSPropertyDescriptor, so that the resolve hook doesn't have to get
  2854       // snared up with trying to define a property on the Xray holder. At the
  2855       // same time, the DefineInterface callbacks are set up to define things
  2856       // directly on the global.  And re-jiggering them to return property
  2857       // descriptors is tricky, because some DefineInterface callbacks define
  2858       // multiple things (like the Image() alias for HTMLImageElement).
  2859       //
  2860       // So the setup is as-follows:
  2861       //
  2862       // * The resolve function takes a JSPropertyDescriptor, but in the
  2863       //   non-Xray case, callees may define things directly on the global, and
  2864       //   set the value on the property descriptor to |undefined| to indicate
  2865       //   that there's nothing more for the caller to do. We assert against
  2866       //   this behavior in the Xray case.
  2867       //
  2868       // * We make sure that we do a non-Xray resolve first, so that all the
  2869       //   slots are set up. In the Xray case, this means unwrapping and doing
  2870       //   a non-Xray resolve before doing the Xray resolve.
  2871       //
  2872       // This all could use some grand refactoring, but for now we just limp
  2873       // along.
  2874       if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
  2875         JS::Rooted<JSObject*> interfaceObject(cx);
  2877           JSAutoCompartment ac(cx, global);
  2878           interfaceObject = getOrCreateInterfaceObject(cx, global, id, false);
  2880         if (NS_WARN_IF(!interfaceObject)) {
  2881           return NS_ERROR_FAILURE;
  2883         if (!JS_WrapObject(cx, &interfaceObject)) {
  2884           return NS_ERROR_FAILURE;
  2887         FillPropertyDescriptor(desc, obj, 0, JS::ObjectValue(*interfaceObject));
  2888       } else {
  2889         JS::Rooted<JSObject*> interfaceObject(cx,
  2890           getOrCreateInterfaceObject(cx, obj, id, true));
  2891         if (NS_WARN_IF(!interfaceObject)) {
  2892           return NS_ERROR_FAILURE;
  2894         // We've already defined the property.  We indicate this to the caller
  2895         // by filling a property descriptor with JS::UndefinedValue() as the
  2896         // value.  We still have to fill in a property descriptor, though, so
  2897         // that the caller knows the property is in fact on this object.  It
  2898         // doesn't matter what we pass for the "readonly" argument here.
  2899         FillPropertyDescriptor(desc, obj, JS::UndefinedValue(), false);
  2902       return NS_OK;
  2906   if (name_struct->mType == nsGlobalNameStruct::eTypeInterface) {
  2907     // We're resolving a name of a DOM interface for which there is no
  2908     // direct DOM class, create a constructor object...
  2909     nsRefPtr<nsDOMConstructor> constructor;
  2910     rv = nsDOMConstructor::Create(class_name,
  2911                                   nullptr,
  2912                                   name_struct,
  2913                                   static_cast<nsPIDOMWindow*>(aWin),
  2914                                   getter_AddRefs(constructor));
  2915     NS_ENSURE_SUCCESS(rv, rv);
  2917     JS::Rooted<JS::Value> v(cx);
  2918     js::AssertSameCompartment(cx, obj);
  2919     rv = WrapNative(cx, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
  2920                     false, &v);
  2921     NS_ENSURE_SUCCESS(rv, rv);
  2923     JS::Rooted<JSObject*> class_obj(cx, &v.toObject());
  2925     // ... and define the constants from the DOM interface on that
  2926     // constructor object.
  2929       JSAutoCompartment ac(cx, class_obj);
  2930       rv = DefineInterfaceConstants(cx, class_obj, &name_struct->mIID);
  2931       NS_ENSURE_SUCCESS(rv, rv);
  2934     if (!JS_WrapValue(cx, &v)) {
  2935       return NS_ERROR_UNEXPECTED;
  2938     FillPropertyDescriptor(desc, obj, 0, v);
  2939     return NS_OK;
  2942   if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
  2943       name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
  2944     if (!OldBindingConstructorEnabled(name_struct, aWin, cx)) {
  2945       return NS_OK;
  2948     // Create the XPConnect prototype for our classinfo, PostCreateProto will
  2949     // set up the prototype chain.  This will go ahead and define things on the
  2950     // actual window's global.
  2951     nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
  2952     rv = GetXPCProto(sXPConnect, cx, aWin, name_struct,
  2953                      getter_AddRefs(proto_holder));
  2954     NS_ENSURE_SUCCESS(rv, rv);
  2955     bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj);
  2956     MOZ_ASSERT_IF(obj != aWin->GetGlobalJSObject(), isXray);
  2957     if (!isXray) {
  2958       // GetXPCProto already defined the property for us
  2959       FillPropertyDescriptor(desc, obj, JS::UndefinedValue(), false);
  2960       return NS_OK;
  2963     // This is the Xray case.  Look up the constructor object for this
  2964     // prototype.
  2965     JS::Rooted<JSObject*> dot_prototype(cx, proto_holder->GetJSObject());
  2966     NS_ENSURE_STATE(dot_prototype);
  2968     const nsDOMClassInfoData *ci_data;
  2969     if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
  2970       ci_data = &sClassInfoData[name_struct->mDOMClassInfoID];
  2971     } else {
  2972       ci_data = name_struct->mData;
  2975     return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data,
  2976                             name_struct, nameSpaceManager, dot_prototype,
  2977                             desc);
  2980   if (name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
  2981     // We don't have a XPConnect prototype object, let ResolvePrototype create
  2982     // one.
  2983     return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, nullptr,
  2984                             name_struct, nameSpaceManager, nullptr, desc);
  2987   if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
  2988     const nsGlobalNameStruct *alias_struct =
  2989       nameSpaceManager->GetConstructorProto(name_struct);
  2990     NS_ENSURE_TRUE(alias_struct, NS_ERROR_UNEXPECTED);
  2992     // We need to use the XPConnect prototype for the DOM class that this
  2993     // constructor is an alias for (for example for Image we need the prototype
  2994     // for HTMLImageElement).
  2995     nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
  2996     rv = GetXPCProto(sXPConnect, cx, aWin, alias_struct,
  2997                      getter_AddRefs(proto_holder));
  2998     NS_ENSURE_SUCCESS(rv, rv);
  3000     JSObject* dot_prototype = proto_holder->GetJSObject();
  3001     NS_ENSURE_STATE(dot_prototype);
  3003     const nsDOMClassInfoData *ci_data;
  3004     if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
  3005       ci_data = &sClassInfoData[alias_struct->mDOMClassInfoID];
  3006     } else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
  3007       ci_data = alias_struct->mData;
  3008     } else {
  3009       return NS_ERROR_UNEXPECTED;
  3012     return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data,
  3013                             name_struct, nameSpaceManager, nullptr, desc);
  3016   if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
  3017     nsRefPtr<nsDOMConstructor> constructor;
  3018     rv = nsDOMConstructor::Create(class_name, nullptr, name_struct,
  3019                                   static_cast<nsPIDOMWindow*>(aWin),
  3020                                   getter_AddRefs(constructor));
  3021     NS_ENSURE_SUCCESS(rv, rv);
  3023     JS::Rooted<JS::Value> val(cx);
  3024     js::AssertSameCompartment(cx, obj);
  3025     rv = WrapNative(cx, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
  3026                     true, &val);
  3027     NS_ENSURE_SUCCESS(rv, rv);
  3029     NS_ASSERTION(val.isObject(), "Why didn't we get a JSObject?");
  3031     FillPropertyDescriptor(desc, obj, 0, val);
  3033     return NS_OK;
  3036   if (name_struct->mType == nsGlobalNameStruct::eTypeProperty) {
  3037     if (!OldBindingConstructorEnabled(name_struct, aWin, cx))
  3038       return NS_OK;
  3040     // Before defining a global property, check for a named subframe of the
  3041     // same name. If it exists, we don't want to shadow it.
  3042     nsCOMPtr<nsIDOMWindow> childWin = aWin->GetChildWindow(name);
  3043     if (childWin)
  3044       return NS_OK;
  3046     nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv));
  3047     NS_ENSURE_SUCCESS(rv, rv);
  3049     JS::Rooted<JS::Value> prop_val(cx, JS::UndefinedValue()); // Property value.
  3051     nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
  3052     if (gpi) {
  3053       rv = gpi->Init(aWin, &prop_val);
  3054       NS_ENSURE_SUCCESS(rv, rv);
  3057     if (JSVAL_IS_PRIMITIVE(prop_val) && !JSVAL_IS_NULL(prop_val)) {
  3058       if (aWin->IsOuterWindow()) {
  3059         nsGlobalWindow *inner = aWin->GetCurrentInnerWindowInternal();
  3060         NS_ENSURE_TRUE(inner, NS_ERROR_UNEXPECTED);
  3063       rv = WrapNative(cx, native, true, &prop_val);
  3066     NS_ENSURE_SUCCESS(rv, rv);
  3068     if (!JS_WrapValue(cx, &prop_val)) {
  3069       return NS_ERROR_UNEXPECTED;
  3072     FillPropertyDescriptor(desc, obj, prop_val, false);
  3074     return NS_OK;
  3077   return rv;
  3080 template<class Interface>
  3081 static nsresult
  3082 LocationSetterGuts(JSContext *cx, JSObject *obj, JS::MutableHandle<JS::Value> vp)
  3084   // This function duplicates some of the logic in XPC_WN_HelperSetProperty
  3085   obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
  3086   if (!IS_WN_REFLECTOR(obj))
  3087       return NS_ERROR_XPC_BAD_CONVERT_JS;
  3088   XPCWrappedNative *wrapper = XPCWrappedNative::Get(obj);
  3090   // The error checks duplicate code in THROW_AND_RETURN_IF_BAD_WRAPPER
  3091   NS_ENSURE_TRUE(!wrapper || wrapper->IsValid(), NS_ERROR_XPC_HAS_BEEN_SHUTDOWN);
  3093   nsCOMPtr<Interface> xpcomObj = do_QueryWrappedNative(wrapper, obj);
  3094   NS_ENSURE_TRUE(xpcomObj, NS_ERROR_UNEXPECTED);
  3096   nsCOMPtr<nsIDOMLocation> location;
  3097   nsresult rv = xpcomObj->GetLocation(getter_AddRefs(location));
  3098   NS_ENSURE_SUCCESS(rv, rv);
  3100   // Grab the value we're being set to before we stomp on |vp|
  3101   JS::Rooted<JSString*> val(cx, JS::ToString(cx, vp));
  3102   NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
  3104   // Make sure |val| stays alive below
  3105   JS::Anchor<JSString *> anchor(val);
  3107   // We have to wrap location into vp before null-checking location, to
  3108   // avoid assigning the wrong thing into the slot.
  3109   rv = WrapNative(cx, location, &NS_GET_IID(nsIDOMLocation), true, vp);
  3110   NS_ENSURE_SUCCESS(rv, rv);
  3112   if (!location) {
  3113     // Make this a no-op
  3114     return NS_OK;
  3117   nsDependentJSString depStr;
  3118   NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED);
  3120   return location->SetHref(depStr);
  3123 template<class Interface>
  3124 static bool
  3125 LocationSetter(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool strict,
  3126                JS::MutableHandle<JS::Value> vp)
  3128   nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp);
  3129   if (NS_FAILED(rv)) {
  3130     xpc::Throw(cx, rv);
  3131     return false;
  3134   return true;
  3137 static bool
  3138 LocationSetterUnwrapper(JSContext *cx, JS::Handle<JSObject*> obj_, JS::Handle<jsid> id,
  3139                         bool strict, JS::MutableHandle<JS::Value> vp)
  3141   JS::Rooted<JSObject*> obj(cx, obj_);
  3143   JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj);
  3144   if (wrapped) {
  3145     obj = wrapped;
  3148   return LocationSetter<nsIDOMWindow>(cx, obj, id, strict, vp);
  3151 NS_IMETHODIMP
  3152 nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3153                        JSObject *obj_, jsid id_, JSObject **objp,
  3154                        bool *_retval)
  3156   JS::Rooted<JSObject*> obj(cx, obj_);
  3157   JS::Rooted<jsid> id(cx, id_);
  3159   if (!JSID_IS_STRING(id)) {
  3160     return NS_OK;
  3163   MOZ_ASSERT(*_retval == true); // guaranteed by XPC_WN_Helper_NewResolve
  3165   nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
  3166   MOZ_ASSERT(win->IsInnerWindow());
  3168   // Don't resolve standard classes on XrayWrappers, only resolve them if we're
  3169   // resolving on the real global object.
  3170   bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj);
  3171   if (!isXray) {
  3172     bool did_resolve = false;
  3173     if (!JS_ResolveStandardClass(cx, obj, id, &did_resolve)) {
  3174       // Return NS_OK to avoid stomping over the exception that was passed
  3175       // down from the ResolveStandardClass call.
  3176       *_retval = false;
  3177       return NS_OK;
  3180     if (did_resolve) {
  3181       *objp = obj;
  3182       return NS_OK;
  3186   // WebIDL quickstubs handle location for us, but Xrays don't see those.  So if
  3187   // we're an Xray, we have to resolve stuff here to make "window.location =
  3188   // someString" work.
  3189   if (sLocation_id == id && isXray) {
  3190     nsCOMPtr<nsIDOMLocation> location;
  3191     nsresult rv = win->GetLocation(getter_AddRefs(location));
  3192     NS_ENSURE_SUCCESS(rv, rv);
  3194     JS::Rooted<JS::Value> v(cx);
  3195     rv = WrapNative(cx, location, &NS_GET_IID(nsIDOMLocation), true, &v);
  3196     NS_ENSURE_SUCCESS(rv, rv);
  3198     bool ok = JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub,
  3199                                     LocationSetterUnwrapper,
  3200                                     JSPROP_PERMANENT | JSPROP_ENUMERATE);
  3202     if (!ok) {
  3203       return NS_ERROR_FAILURE;
  3206     *objp = obj;
  3208     return NS_OK;
  3211   // WebIDL quickstubs handle "top" for us, but Xrays don't see those.  So if
  3212   // we're an Xray and we want "top" to be JSPROP_PERMANENT, we need to resolve
  3213   // it here.
  3214   if (sTop_id == id && isXray) {
  3215     nsCOMPtr<nsIDOMWindow> top;
  3216     nsresult rv = win->GetScriptableTop(getter_AddRefs(top));
  3217     NS_ENSURE_SUCCESS(rv, rv);
  3219     JS::Rooted<JS::Value> v(cx);
  3220     js::AssertSameCompartment(cx, obj);
  3221     rv = WrapNative(cx, top, &NS_GET_IID(nsIDOMWindow), true, &v);
  3222     NS_ENSURE_SUCCESS(rv, rv);
  3224     // Hold on to the top window object as a global property so we
  3225     // don't need to worry about losing expando properties etc.
  3226     if (!JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub, JS_StrictPropertyStub,
  3227                                JSPROP_READONLY | JSPROP_PERMANENT |
  3228                                JSPROP_ENUMERATE)) {
  3229       return NS_ERROR_FAILURE;
  3231     *objp = obj;
  3233     return NS_OK;
  3236   if (isXray) {
  3237     // We promise to resolve on the underlying object first.  That will create
  3238     // the actual interface object if needed and store it in a data structure
  3239     // hanging off the global.  Then our second call will wrap up in an Xray as
  3240     // needed.  We do things this way because we use the existence of the
  3241     // object in that data structure as a flag that indicates that its name
  3242     // (and any relevant named constructor names) has been resolved before;
  3243     // this allows us to avoid re-resolving in the Xray case if the property is
  3244     // deleted by page script.
  3245     JS::Rooted<JSObject*> global(cx,
  3246       js::UncheckedUnwrap(obj, /* stopAtOuter = */ false));
  3247     JSAutoCompartment ac(cx, global);
  3248     JS::Rooted<JSPropertyDescriptor> desc(cx);
  3249     if (!win->DoNewResolve(cx, global, id, &desc)) {
  3250       return NS_ERROR_FAILURE;
  3252     // If we have an object here, that means we resolved the property.
  3253     // But if the value is undefined, that means that GlobalResolve
  3254     // also already defined it, so we don't have to.
  3255     if (desc.object() && !desc.value().isUndefined() &&
  3256         !JS_DefinePropertyById(cx, global, id, desc.value(),
  3257                                desc.getter(), desc.setter(),
  3258                                desc.attributes())) {
  3259       return NS_ERROR_FAILURE;
  3263   JS::Rooted<JSPropertyDescriptor> desc(cx);
  3264   if (!win->DoNewResolve(cx, obj, id, &desc)) {
  3265     return NS_ERROR_FAILURE;
  3267   if (desc.object()) {
  3268     // If we have an object here, that means we resolved the property.
  3269     // But if the value is undefined, that means that GlobalResolve
  3270     // also already defined it, so we don't have to.  Note that in the
  3271     // Xray case we should never see undefined.
  3272     MOZ_ASSERT_IF(isXray, !desc.value().isUndefined());
  3273     if (!desc.value().isUndefined() &&
  3274         !JS_DefinePropertyById(cx, obj, id, desc.value(),
  3275                                desc.getter(), desc.setter(),
  3276                                desc.attributes())) {
  3277       return NS_ERROR_FAILURE;
  3280     *objp = obj;
  3281     return NS_OK;
  3284   if (sDocument_id == id) {
  3285     nsCOMPtr<nsIDocument> document = win->GetDoc();
  3286     JS::Rooted<JS::Value> v(cx);
  3287     nsresult rv = WrapNative(cx, document, document,
  3288                              &NS_GET_IID(nsIDOMDocument), &v, false);
  3289     NS_ENSURE_SUCCESS(rv, rv);
  3291     // nsIDocument::WrapObject will handle defining the property.
  3292     *objp = obj;
  3294     // NB: We need to do this for any Xray wrapper.
  3295     if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
  3296       *_retval = JS_WrapValue(cx, &v) &&
  3297                  JS_DefineProperty(cx, obj, "document", v,
  3298                                    JSPROP_READONLY | JSPROP_ENUMERATE,
  3299                                    JS_PropertyStub, JS_StrictPropertyStub);
  3300       if (!*_retval) {
  3301         return NS_ERROR_UNEXPECTED;
  3305     return NS_OK;
  3308   return nsDOMGenericSH::NewResolve(wrapper, cx, obj, id, objp, _retval);
  3311 NS_IMETHODIMP
  3312 nsWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
  3313                         JSObject * obj, JSObject * *_retval)
  3315   nsGlobalWindow *origWin = nsGlobalWindow::FromWrapper(wrapper);
  3316   nsGlobalWindow *win = origWin->GetOuterWindowInternal();
  3318   if (!win) {
  3319     // If we no longer have an outer window. No code should ever be
  3320     // running on a window w/o an outer, which means this hook should
  3321     // never be called when we have no outer. But just in case, return
  3322     // null to prevent leaking an inner window to code in a different
  3323     // window.
  3324     *_retval = nullptr;
  3325     return NS_ERROR_UNEXPECTED;
  3328   JS::Rooted<JSObject*> winObj(cx, win->FastGetGlobalJSObject());
  3329   MOZ_ASSERT(winObj);
  3331   // Note that while |wrapper| is same-compartment with cx, the outer window
  3332   // might not be. If we're running script in an inactive scope and evalute
  3333   // |this|, the outer window is actually a cross-compartment wrapper. So we
  3334   // need to wrap here.
  3335   if (!JS_WrapObject(cx, &winObj)) {
  3336     *_retval = nullptr;
  3337     return NS_ERROR_UNEXPECTED;
  3340   *_retval = winObj;
  3341   return NS_OK;
  3344 NS_IMETHODIMP
  3345 nsLocationSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
  3346                         JSObject *globalObj, JSObject **parentObj)
  3348   // window.location can be held onto by both evil pages that want to track the
  3349   // user's progress on the web and bookmarklets that want to use the location
  3350   // object. Parent it to the outer window so that access checks do the Right
  3351   // Thing.
  3352   *parentObj = globalObj;
  3354   nsCOMPtr<nsIDOMLocation> safeLoc(do_QueryInterface(nativeObj));
  3355   if (!safeLoc) {
  3356     // Oops, this wasn't really a location object. This can happen if someone
  3357     // tries to use our scriptable helper as a real object and tries to wrap
  3358     // it, see bug 319296
  3359     return NS_OK;
  3362   nsLocation *loc = (nsLocation *)safeLoc.get();
  3363   nsIDocShell *ds = loc->GetDocShell();
  3364   if (!ds) {
  3365     NS_WARNING("Refusing to create a location in the wrong scope");
  3366     return NS_ERROR_UNEXPECTED;
  3369   nsCOMPtr<nsIScriptGlobalObject> sgo = do_GetInterface(ds);
  3370   if (!sgo) {
  3371     NS_WARNING("Refusing to create a location in the wrong scope because the "
  3372                "docshell is being destroyed");
  3373     return NS_ERROR_UNEXPECTED;
  3376   *parentObj = sgo->GetGlobalJSObject();
  3377   return *parentObj ? NS_OK : NS_ERROR_FAILURE;
  3380 NS_IMETHODIMP
  3381 nsLocationSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3382                           JSObject *obj, jsid aId, jsval *vp, bool *_retval)
  3384   JS::Rooted<JSObject*> rootedObj(cx, obj);
  3386   // Shadowing protection. This will go away when nsLocation moves to the new
  3387   // bindings.
  3388   JS::Rooted<jsid> id(cx, aId);
  3389   if (wrapper->HasNativeMember(id)) {
  3390     JS_ReportError(cx, "Permission denied to shadow native property");
  3391     return NS_ERROR_FAILURE;
  3394   nsLocation* location = static_cast<nsLocation*>(GetNative(wrapper, rootedObj));
  3395   location->PreserveWrapper(location);
  3397   return NS_OK;
  3400 // EventTarget helper
  3402 NS_IMETHODIMP
  3403 nsEventTargetSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
  3404                            JSObject *aGlobalObj, JSObject **parentObj)
  3406   JS::Rooted<JSObject*> globalObj(cx, aGlobalObj);
  3407   DOMEventTargetHelper* target = DOMEventTargetHelper::FromSupports(nativeObj);
  3409   nsCOMPtr<nsIScriptGlobalObject> native_parent;
  3410   target->GetParentObject(getter_AddRefs(native_parent));
  3412   *parentObj = native_parent ? native_parent->GetGlobalJSObject() : globalObj;
  3414   return *parentObj ? NS_OK : NS_ERROR_FAILURE;
  3417 NS_IMETHODIMP
  3418 nsEventTargetSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3419                              JSObject *obj, jsid id, jsval *vp, bool *_retval)
  3421   nsEventTargetSH::PreserveWrapper(GetNative(wrapper, obj));
  3423   return NS_OK;
  3426 void
  3427 nsEventTargetSH::PreserveWrapper(nsISupports *aNative)
  3429   DOMEventTargetHelper* target = DOMEventTargetHelper::FromSupports(aNative);
  3430   target->PreserveWrapper(aNative);
  3433 // Generic array scriptable helper.
  3435 NS_IMETHODIMP
  3436 nsGenericArraySH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3437                              JSObject *aObj, jsid aId, JSObject **objp,
  3438                              bool *_retval)
  3440   JS::Rooted<JSObject*> obj(cx, aObj);
  3441   JS::Rooted<jsid> id(cx, aId);
  3442   if (id == sLength_id) {
  3443     // Bail early; this isn't something we're interested in
  3444     return NS_OK;
  3447   bool is_number = false;
  3448   int32_t n = GetArrayIndexFromId(cx, id, &is_number);
  3450   if (is_number && n >= 0) {
  3451     // XXX The following is a cheap optimization to avoid hitting xpconnect to
  3452     // get the length. We may want to consider asking our concrete
  3453     // implementation for the length, and falling back onto the GetProperty if
  3454     // it doesn't provide one.
  3456     uint32_t length;
  3457     nsresult rv = GetLength(wrapper, cx, obj, &length);
  3458     NS_ENSURE_SUCCESS(rv, rv);
  3460     uint32_t index = uint32_t(n);
  3461     if (index < length) {
  3462       *_retval = ::JS_DefineElement(cx, obj, index, JSVAL_VOID, nullptr, nullptr,
  3463                                     JSPROP_ENUMERATE | JSPROP_SHARED);
  3464       *objp = obj;
  3468   return NS_OK;
  3471 nsresult
  3472 nsGenericArraySH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3473                             JS::Handle<JSObject*> obj, uint32_t *length)
  3475   *length = 0;
  3477   JS::Rooted<JS::Value> lenval(cx);
  3478   if (!JS_GetProperty(cx, obj, "length", &lenval)) {
  3479     return NS_ERROR_UNEXPECTED;
  3482   if (!JSVAL_IS_INT(lenval)) {
  3483     // This can apparently happen with some sparse array impls falling back
  3484     // onto this code.
  3485     return NS_OK;
  3488   int32_t slen = JSVAL_TO_INT(lenval);
  3489   if (slen < 0) {
  3490     return NS_OK;
  3493   *length = (uint32_t)slen;
  3495   return NS_OK;
  3498 NS_IMETHODIMP
  3499 nsGenericArraySH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3500                             JSObject *aObj, bool *_retval)
  3502   // Recursion protection in case someone tries to be smart and call
  3503   // the enumerate hook from a user defined .length getter, or
  3504   // somesuch.
  3506   JS::Rooted<JSObject*> obj(cx, aObj);
  3507   static bool sCurrentlyEnumerating;
  3509   if (sCurrentlyEnumerating) {
  3510     // Don't recurse to death.
  3511     return NS_OK;
  3514   sCurrentlyEnumerating = true;
  3516   JS::Rooted<JS::Value> len_val(cx);
  3517   bool ok = ::JS_GetProperty(cx, obj, "length", &len_val);
  3519   if (ok && JSVAL_IS_INT(len_val)) {
  3520     int32_t length = JSVAL_TO_INT(len_val);
  3522     for (int32_t i = 0; ok && i < length; ++i) {
  3523       ok = ::JS_DefineElement(cx, obj, i, JSVAL_VOID, nullptr, nullptr,
  3524                               JSPROP_ENUMERATE | JSPROP_SHARED);
  3528   sCurrentlyEnumerating = false;
  3530   return ok ? NS_OK : NS_ERROR_UNEXPECTED;
  3533 // Array scriptable helper
  3535 NS_IMETHODIMP
  3536 nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3537                        JSObject *aObj, jsid aId, jsval *vp, bool *_retval)
  3539   JS::Rooted<JSObject*> obj(cx, aObj);
  3540   JS::Rooted<jsid> id(cx, aId);
  3541   bool is_number = false;
  3542   int32_t n = GetArrayIndexFromId(cx, id, &is_number);
  3544   nsresult rv = NS_OK;
  3546   if (is_number) {
  3547     if (n < 0) {
  3548       return NS_ERROR_DOM_INDEX_SIZE_ERR;
  3551     // Make sure rv == NS_OK here, so GetItemAt implementations that never fail
  3552     // don't have to set rv.
  3553     rv = NS_OK;
  3554     nsWrapperCache *cache = nullptr;
  3555     nsISupports* array_item =
  3556       GetItemAt(GetNative(wrapper, obj), n, &cache, &rv);
  3557     NS_ENSURE_SUCCESS(rv, rv);
  3559     if (array_item) {
  3560       JS::Rooted<JS::Value> rval(cx);
  3561       rv = WrapNative(cx, array_item, cache, true, &rval);
  3562       NS_ENSURE_SUCCESS(rv, rv);
  3563       *vp = rval;
  3565       rv = NS_SUCCESS_I_DID_SOMETHING;
  3569   return rv;
  3573 // CSSRuleList scriptable helper
  3575 nsISupports*
  3576 nsCSSRuleListSH::GetItemAt(nsISupports *aNative, uint32_t aIndex,
  3577                            nsWrapperCache **aCache, nsresult *aResult)
  3579   nsICSSRuleList* list = static_cast<nsICSSRuleList*>(aNative);
  3580 #ifdef DEBUG
  3582     nsCOMPtr<nsICSSRuleList> list_qi = do_QueryInterface(aNative);
  3584     // If this assertion fires the QI implementation for the object in
  3585     // question doesn't use the nsICSSRuleList pointer as the nsISupports
  3586     // pointer. That must be fixed, or we'll crash...
  3587     NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!");
  3589 #endif
  3591   return list->Item(aIndex);
  3595 // Storage2SH
  3597 // One reason we need a newResolve hook is that in order for
  3598 // enumeration of storage object keys to work the keys we're
  3599 // enumerating need to exist on the storage object for the JS engine
  3600 // to find them.
  3602 NS_IMETHODIMP
  3603 nsStorage2SH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3604                          JSObject *obj, jsid aId, JSObject **objp,
  3605                          bool *_retval)
  3607   JS::Rooted<jsid> id(cx, aId);
  3608   if (ObjectIsNativeWrapper(cx, obj)) {
  3609     return NS_OK;
  3612   JS::Rooted<JSObject*> realObj(cx, wrapper->GetJSObject());
  3614   JSAutoCompartment ac(cx, realObj);
  3616   // First check to see if the property is defined on our prototype,
  3617   // after converting id to a string if it's an integer.
  3619   JS::Rooted<JSString*> jsstr(cx, IdToString(cx, id));
  3620   if (!jsstr) {
  3621     return NS_OK;
  3624   JS::Rooted<JSObject*> proto(cx);
  3625   if (!::JS_GetPrototype(cx, realObj, &proto)) {
  3626     return NS_ERROR_FAILURE;
  3628   bool hasProp;
  3630   if (proto &&
  3631       (::JS_HasPropertyById(cx, proto, id, &hasProp) &&
  3632        hasProp)) {
  3633     // We found the property we're resolving on the prototype,
  3634     // nothing left to do here then.
  3636     return NS_OK;
  3639   // We're resolving property that doesn't exist on the prototype,
  3640   // check if the key exists in the storage object.
  3642   nsCOMPtr<nsIDOMStorage> storage(do_QueryWrappedNative(wrapper));
  3644   nsDependentJSString depStr;
  3645   NS_ENSURE_TRUE(depStr.init(cx, jsstr), NS_ERROR_UNEXPECTED);
  3647   // GetItem() will return null if the caller can't access the session
  3648   // storage item.
  3649   nsAutoString data;
  3650   nsresult rv = storage->GetItem(depStr, data);
  3651   NS_ENSURE_SUCCESS(rv, rv);
  3653   if (!DOMStringIsNull(data)) {
  3654     if (!::JS_DefinePropertyById(cx, realObj, id, JSVAL_VOID, nullptr,
  3655                                  nullptr, JSPROP_ENUMERATE)) {
  3656       return NS_ERROR_FAILURE;
  3659     *objp = realObj;
  3662   return NS_OK;
  3665 NS_IMETHODIMP
  3666 nsStorage2SH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3667                           JSObject *aObj, jsid aId, jsval *vp, bool *_retval)
  3669   JS::Rooted<JSObject*> obj(cx, aObj);
  3670   JS::Rooted<jsid> id(cx, aId);
  3671   nsCOMPtr<nsIDOMStorage> storage(do_QueryWrappedNative(wrapper));
  3672   NS_ENSURE_TRUE(storage, NS_ERROR_UNEXPECTED);
  3674   JSString* key = IdToString(cx, id);
  3675   NS_ENSURE_TRUE(key, NS_ERROR_UNEXPECTED);
  3677   nsDependentJSString keyStr;
  3678   NS_ENSURE_TRUE(keyStr.init(cx, key), NS_ERROR_UNEXPECTED);
  3680   // For native wrappers, do not get random names on storage objects.
  3681   if (ObjectIsNativeWrapper(cx, obj)) {
  3682     return NS_ERROR_NOT_AVAILABLE;
  3685   nsAutoString val;
  3686   nsresult rv = storage->GetItem(keyStr, val);
  3687   NS_ENSURE_SUCCESS(rv, rv);
  3689   if (DOMStringIsNull(val)) {
  3690     // No such key.
  3691     *vp = JSVAL_VOID;
  3692   } else {
  3693     JSString* str =
  3694       JS_NewUCStringCopyN(cx, static_cast<const jschar *>(val.get()),
  3695                           val.Length());
  3696     NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
  3698     *vp = STRING_TO_JSVAL(str);
  3701   return NS_SUCCESS_I_DID_SOMETHING;
  3704 NS_IMETHODIMP
  3705 nsStorage2SH::SetProperty(nsIXPConnectWrappedNative *wrapper,
  3706                           JSContext *cx, JSObject *obj, jsid aId,
  3707                           jsval *vp, bool *_retval)
  3709   JS::Rooted<jsid> id(cx, aId);
  3710   nsCOMPtr<nsIDOMStorage> storage(do_QueryWrappedNative(wrapper));
  3711   NS_ENSURE_TRUE(storage, NS_ERROR_UNEXPECTED);
  3713   JSString *key = IdToString(cx, id);
  3714   NS_ENSURE_TRUE(key, NS_ERROR_UNEXPECTED);
  3716   nsDependentJSString keyStr;
  3717   NS_ENSURE_TRUE(keyStr.init(cx, key), NS_ERROR_UNEXPECTED);
  3719   JS::Rooted<JS::Value> val(cx, *vp);
  3720   JSString *value = JS::ToString(cx, val);
  3721   NS_ENSURE_TRUE(value, NS_ERROR_UNEXPECTED);
  3723   nsDependentJSString valueStr;
  3724   NS_ENSURE_TRUE(valueStr.init(cx, value), NS_ERROR_UNEXPECTED);
  3726   nsresult rv = storage->SetItem(keyStr, valueStr);
  3727   if (NS_SUCCEEDED(rv)) {
  3728     rv = NS_SUCCESS_I_DID_SOMETHING;
  3731   return rv;
  3734 NS_IMETHODIMP
  3735 nsStorage2SH::DelProperty(nsIXPConnectWrappedNative *wrapper,
  3736                           JSContext *cx, JSObject *obj, jsid aId,
  3737                           bool *_retval)
  3739   JS::Rooted<jsid> id(cx, aId);
  3740   nsCOMPtr<nsIDOMStorage> storage(do_QueryWrappedNative(wrapper));
  3741   NS_ENSURE_TRUE(storage, NS_ERROR_UNEXPECTED);
  3743   JSString *key = IdToString(cx, id);
  3744   NS_ENSURE_TRUE(key, NS_ERROR_UNEXPECTED);
  3746   nsDependentJSString keyStr;
  3747   NS_ENSURE_TRUE(keyStr.init(cx, key), NS_ERROR_UNEXPECTED);
  3749   nsresult rv = storage->RemoveItem(keyStr);
  3750   if (NS_FAILED(rv)) {
  3751     return rv;
  3754   *_retval = true;
  3755   return NS_SUCCESS_I_DID_SOMETHING;
  3759 NS_IMETHODIMP
  3760 nsStorage2SH::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3761                            JSObject *obj, uint32_t enum_op, jsval *statep,
  3762                            jsid *idp, bool *_retval)
  3764   if (enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) {
  3765     nsCOMPtr<nsPIDOMStorage> storage(do_QueryWrappedNative(wrapper));
  3767     // XXXndeakin need to free the keys afterwards
  3768     nsTArray<nsString> *keys = storage->GetKeys();
  3769     NS_ENSURE_TRUE(keys, NS_ERROR_OUT_OF_MEMORY);
  3771     *statep = PRIVATE_TO_JSVAL(keys);
  3773     if (idp) {
  3774       *idp = INT_TO_JSID(keys->Length());
  3776     return NS_OK;
  3779   nsTArray<nsString> *keys =
  3780     (nsTArray<nsString> *)JSVAL_TO_PRIVATE(*statep);
  3782   if (enum_op == JSENUMERATE_NEXT && keys->Length() != 0) {
  3783     nsString& key = keys->ElementAt(0);
  3784     JS::Rooted<JSString*> str(cx, JS_NewUCStringCopyN(cx, key.get(), key.Length()));
  3785     NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
  3787     JS::Rooted<jsid> id(cx);
  3788     JS_StringToId(cx, str, &id);
  3789     *idp = id;
  3791     keys->RemoveElementAt(0);
  3793     return NS_OK;
  3796   // destroy the keys array if we have no keys or if we're done
  3797   NS_ABORT_IF_FALSE(enum_op == JSENUMERATE_DESTROY ||
  3798                     (enum_op == JSENUMERATE_NEXT && keys->Length() == 0),
  3799                     "Bad call from the JS engine");
  3800   delete keys;
  3802   *statep = JSVAL_NULL;
  3804   return NS_OK;
  3807 // nsIDOMEventListener::HandleEvent() 'this' converter helper
  3809 NS_INTERFACE_MAP_BEGIN(nsEventListenerThisTranslator)
  3810   NS_INTERFACE_MAP_ENTRY(nsIXPCFunctionThisTranslator)
  3811   NS_INTERFACE_MAP_ENTRY(nsISupports)
  3812 NS_INTERFACE_MAP_END
  3815 NS_IMPL_ADDREF(nsEventListenerThisTranslator)
  3816 NS_IMPL_RELEASE(nsEventListenerThisTranslator)
  3819 NS_IMETHODIMP
  3820 nsEventListenerThisTranslator::TranslateThis(nsISupports *aInitialThis,
  3821                                              nsISupports **_retval)
  3823   nsCOMPtr<nsIDOMEvent> event(do_QueryInterface(aInitialThis));
  3824   NS_ENSURE_TRUE(event, NS_ERROR_UNEXPECTED);
  3826   nsCOMPtr<EventTarget> target = event->InternalDOMEvent()->GetCurrentTarget();
  3827   target.forget(_retval);
  3828   return NS_OK;
  3831 NS_IMETHODIMP
  3832 nsDOMConstructorSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
  3833                               JSObject *aGlobalObj, JSObject **parentObj)
  3835   JS::Rooted<JSObject*> globalObj(cx, aGlobalObj);
  3836   nsDOMConstructor *wrapped = static_cast<nsDOMConstructor *>(nativeObj);
  3838 #ifdef DEBUG
  3840     nsCOMPtr<nsIDOMDOMConstructor> is_constructor =
  3841       do_QueryInterface(nativeObj);
  3842     NS_ASSERTION(is_constructor, "How did we not get a constructor?");
  3844 #endif
  3846   return wrapped->PreCreate(cx, globalObj, parentObj);
  3849 NS_IMETHODIMP
  3850 nsDOMConstructorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3851                                JSObject *aObj, jsid aId, JSObject **objp,
  3852                                bool *_retval)
  3854   JS::Rooted<JSObject*> obj(cx, aObj);
  3855   JS::Rooted<jsid> id(cx, aId);
  3856   // For regular DOM constructors, we have our interface constants defined on
  3857   // us by nsWindowSH::GlobalResolve. However, XrayWrappers can't see these
  3858   // interface constants (as they look like expando properties) so we have to
  3859   // specially resolve those constants here, but only for Xray wrappers.
  3860   if (!ObjectIsNativeWrapper(cx, obj)) {
  3861     return NS_OK;
  3864   JS::Rooted<JSObject*> nativePropsObj(cx, xpc::XrayUtils::GetNativePropertiesObject(cx, obj));
  3865   nsDOMConstructor *wrapped =
  3866     static_cast<nsDOMConstructor *>(wrapper->Native());
  3867   nsresult rv = wrapped->ResolveInterfaceConstants(cx, nativePropsObj);
  3868   NS_ENSURE_SUCCESS(rv, rv);
  3870   // Now re-lookup the ID to see if we should report back that we resolved the
  3871   // looked-for constant. Note that we don't have to worry about infinitely
  3872   // recurring back here because the Xray wrapper's holder object doesn't call
  3873   // NewResolve hooks.
  3874   bool found;
  3875   if (!JS_HasPropertyById(cx, nativePropsObj, id, &found)) {
  3876     *_retval = false;
  3877     return NS_OK;
  3880   if (found) {
  3881     *objp = obj;
  3883   return NS_OK;
  3886 NS_IMETHODIMP
  3887 nsDOMConstructorSH::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3888                          JSObject *aObj, const JS::CallArgs &args, bool *_retval)
  3890   JS::Rooted<JSObject*> obj(cx, aObj);
  3891   MOZ_ASSERT(obj);
  3893   nsDOMConstructor *wrapped =
  3894     static_cast<nsDOMConstructor *>(wrapper->Native());
  3896 #ifdef DEBUG
  3898     nsCOMPtr<nsIDOMDOMConstructor> is_constructor =
  3899       do_QueryWrappedNative(wrapper);
  3900     NS_ASSERTION(is_constructor, "How did we not get a constructor?");
  3902 #endif
  3904   return wrapped->Construct(wrapper, cx, obj, args, _retval);
  3907 NS_IMETHODIMP
  3908 nsDOMConstructorSH::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  3909                               JSObject *aObj, const JS::CallArgs &args, bool *_retval)
  3911   JS::Rooted<JSObject*> obj(cx, aObj);
  3912   MOZ_ASSERT(obj);
  3914   nsDOMConstructor *wrapped =
  3915     static_cast<nsDOMConstructor *>(wrapper->Native());
  3917 #ifdef DEBUG
  3919     nsCOMPtr<nsIDOMDOMConstructor> is_constructor =
  3920       do_QueryWrappedNative(wrapper);
  3921     NS_ASSERTION(is_constructor, "How did we not get a constructor?");
  3923 #endif
  3925   return wrapped->Construct(wrapper, cx, obj, args, _retval);
  3928 NS_IMETHODIMP
  3929 nsDOMConstructorSH::HasInstance(nsIXPConnectWrappedNative *wrapper,
  3930                                 JSContext *cx, JSObject *aObj, JS::Handle<JS::Value> val,
  3931                                 bool *bp, bool *_retval)
  3933   JS::Rooted<JSObject*> obj(cx, aObj);
  3934   nsDOMConstructor *wrapped =
  3935     static_cast<nsDOMConstructor *>(wrapper->Native());
  3937 #ifdef DEBUG
  3939     nsCOMPtr<nsIDOMDOMConstructor> is_constructor =
  3940       do_QueryWrappedNative(wrapper);
  3941     NS_ASSERTION(is_constructor, "How did we not get a constructor?");
  3943 #endif
  3945   return wrapped->HasInstance(wrapper, cx, obj, val, bp, _retval);
  3948 NS_IMETHODIMP
  3949 nsNonDOMObjectSH::GetFlags(uint32_t *aFlags)
  3951   // This is NOT a DOM Object.  Use this helper class for cases when you need
  3952   // to do something like implement nsISecurityCheckedComponent in a meaningful
  3953   // way.
  3954   *aFlags = nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::SINGLETON_CLASSINFO;
  3955   return NS_OK;

mercurial