tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

xpcprivate.h (97713B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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/. */
      6 
      7 /*
      8 * XPConnect allows JS code to manipulate C++ object and C++ code to manipulate
      9 * JS objects. JS manipulation of C++ objects tends to be significantly more
     10 * complex. This comment explains how it is orchestrated by XPConnect.
     11 *
     12 * For each C++ object to be manipulated in JS, there is a corresponding JS
     13 * object. This is called the "flattened JS object". By default, there is an
     14 * additional C++ object involved of type XPCWrappedNative. The XPCWrappedNative
     15 * holds pointers to the C++ object and the flat JS object.
     16 *
     17 * All XPCWrappedNative objects belong to an XPCWrappedNativeScope. These scopes
     18 * are essentially in 1:1 correspondence with JS compartments. The
     19 * XPCWrappedNativeScope has a pointer to the JS compartment. The global of a
     20 * flattened JS object is one of the globals in this compartment (the exception
     21 * to this rule is when a PreCreate hook asks for a different global; see
     22 * nsIXPCScriptable below).
     23 *
     24 * Some C++ objects (notably DOM objects) have information associated with them
     25 * that lists the interfaces implemented by these objects. A C++ object exposes
     26 * this information by implementing nsIClassInfo. If a C++ object implements
     27 * nsIClassInfo, then JS code can call its methods without needing to use
     28 * QueryInterface first. Typically, all instances of a C++ class share the same
     29 * nsIClassInfo instance. (That is, obj->QueryInterface(nsIClassInfo) returns
     30 * the same result for every obj of a given class.)
     31 *
     32 * XPConnect tracks nsIClassInfo information in an XPCWrappedNativeProto object.
     33 * A given XPCWrappedNativeScope will have one XPCWrappedNativeProto for each
     34 * nsIClassInfo instance being used. The XPCWrappedNativeProto has an associated
     35 * JS object, which is used as the prototype of all flattened JS objects created
     36 * for C++ objects with the given nsIClassInfo.
     37 *
     38 * Each XPCWrappedNativeProto has a pointer to its XPCWrappedNativeScope. If an
     39 * XPCWrappedNative wraps a C++ object with class info, then it points to its
     40 * XPCWrappedNativeProto. Otherwise it points to its XPCWrappedNativeScope. (The
     41 * pointers are smooshed together in a tagged union.) Either way it can reach
     42 * its scope.
     43 *
     44 * An XPCWrappedNativeProto keeps track of the set of interfaces implemented by
     45 * the C++ object in an XPCNativeSet. (The list of interfaces is obtained by
     46 * calling a method on the nsIClassInfo.) An XPCNativeSet is a collection of
     47 * XPCNativeInterfaces. Each interface stores the list of members, which can be
     48 * methods, constants, getters, or setters.
     49 *
     50 * An XPCWrappedNative also points to an XPCNativeSet. Initially this starts out
     51 * the same as the XPCWrappedNativeProto's set. If there is no proto, it starts
     52 * out as a singleton set containing nsISupports. If JS code QI's new interfaces
     53 * outside of the existing set, the set will grow. All QueryInterface results
     54 * are cached in XPCWrappedNativeTearOff objects, which are linked off of the
     55 * XPCWrappedNative.
     56 *
     57 * Besides having class info, a C++ object may be "scriptable" (i.e., implement
     58 * nsIXPCScriptable). This allows it to implement a more DOM-like interface,
     59 * besides just exposing XPCOM methods and constants. An nsIXPCScriptable
     60 * instance has hooks that correspond to all the normal JSClass hooks. Each
     61 * nsIXPCScriptable instance can have pointers from XPCWrappedNativeProto and
     62 * XPCWrappedNative (since C++ objects can have scriptable info without having
     63 * class info).
     64 */
     65 
     66 /* All the XPConnect private declarations - only include locally. */
     67 
     68 #ifndef xpcprivate_h___
     69 #define xpcprivate_h___
     70 
     71 #include "mozilla/Assertions.h"
     72 #include "mozilla/Attributes.h"
     73 #include "mozilla/BasePrincipal.h"
     74 #include "mozilla/CycleCollectedJSContext.h"
     75 #include "mozilla/CycleCollectedJSRuntime.h"
     76 #include "mozilla/DebugOnly.h"
     77 #include "mozilla/DefineEnum.h"
     78 #include "mozilla/HashFunctions.h"
     79 #include "mozilla/LinkedList.h"
     80 #include "mozilla/Maybe.h"
     81 #include "mozilla/MemoryReporting.h"
     82 #include "mozilla/PodOperations.h"
     83 #include "mozilla/mozalloc.h"
     84 #include "mozilla/Preferences.h"
     85 #include "mozilla/TimeStamp.h"
     86 #include "mozilla/UniquePtr.h"
     87 #include "mozilla/Vector.h"
     88 
     89 #include "mozilla/dom/ScriptSettings.h"
     90 
     91 #include <math.h>
     92 #include <stdint.h>
     93 #include <stdlib.h>
     94 #include <string.h>
     95 
     96 #include "xpcpublic.h"
     97 #include "js/HashTable.h"
     98 #include "js/GCHashTable.h"
     99 #include "js/Object.h"              // JS::GetClass, JS::GetCompartment
    100 #include "js/PropertyAndElement.h"  // JS_DefineProperty
    101 #include "js/TracingAPI.h"
    102 #include "js/WeakMapPtr.h"
    103 #include "nscore.h"
    104 #include "nsXPCOM.h"
    105 #include "nsCycleCollectionParticipant.h"
    106 #include "nsDebug.h"
    107 #include "nsISupports.h"
    108 #include "nsIServiceManager.h"
    109 #include "nsIClassInfoImpl.h"
    110 #include "nsIComponentManager.h"
    111 #include "nsIComponentRegistrar.h"
    112 #include "nsISupportsPrimitives.h"
    113 #include "nsISimpleEnumerator.h"
    114 #include "nsIXPConnect.h"
    115 #include "nsIXPCScriptable.h"
    116 #include "nsIObserver.h"
    117 #include "nsWeakReference.h"
    118 #include "nsCOMPtr.h"
    119 #include "nsXPTCUtils.h"
    120 #include "xptinfo.h"
    121 #include "XPCForwards.h"
    122 #include "XPCLog.h"
    123 #include "xpccomponents.h"
    124 #include "prenv.h"
    125 #include "prcvar.h"
    126 #include "nsString.h"
    127 #include "nsReadableUtils.h"
    128 
    129 #include "MainThreadUtils.h"
    130 
    131 #include "nsIConsoleService.h"
    132 
    133 #include "nsVariant.h"
    134 #include "nsCOMArray.h"
    135 #include "nsTArray.h"
    136 #include "nsBaseHashtable.h"
    137 #include "nsHashKeys.h"
    138 #include "nsWrapperCache.h"
    139 #include "nsDeque.h"
    140 
    141 #include "nsIScriptSecurityManager.h"
    142 
    143 #include "nsIPrincipal.h"
    144 #include "nsJSPrincipals.h"
    145 #include "nsIScriptObjectPrincipal.h"
    146 #include "xpcObjectHelper.h"
    147 
    148 #include "SandboxPrivate.h"
    149 #include "SystemGlobal.h"
    150 
    151 #ifdef XP_WIN
    152 // Nasty MS defines
    153 #  ifdef GetClassInfo
    154 #    undef GetClassInfo
    155 #  endif
    156 #  ifdef GetClassName
    157 #    undef GetClassName
    158 #  endif
    159 #endif /* XP_WIN */
    160 
    161 namespace mozilla {
    162 namespace dom {
    163 class AutoEntryScript;
    164 class Exception;
    165 }  // namespace dom
    166 }  // namespace mozilla
    167 
    168 /***************************************************************************/
    169 // data declarations...
    170 extern const char XPC_EXCEPTION_CONTRACTID[];
    171 extern const char XPC_CONSOLE_CONTRACTID[];
    172 extern const char XPC_SCRIPT_ERROR_CONTRACTID[];
    173 extern const char XPC_XPCONNECT_CONTRACTID[];
    174 
    175 /***************************************************************************/
    176 // Helper function.
    177 
    178 namespace xpc {
    179 
    180 inline bool IsWrappedNativeReflector(JSObject* obj) {
    181  return JS::GetClass(obj)->isWrappedNative();
    182 }
    183 
    184 }  // namespace xpc
    185 
    186 /***************************************************************************
    187 ****************************************************************************
    188 *
    189 * Core runtime and context classes...
    190 *
    191 ****************************************************************************
    192 ***************************************************************************/
    193 
    194 // We have a general rule internally that getters that return addref'd interface
    195 // pointer generally do so using an 'out' parm. When interface pointers are
    196 // returned as function call result values they are not addref'd. Exceptions
    197 // to this rule are noted explicitly.
    198 
    199 class nsXPConnect final : public nsIXPConnect {
    200 public:
    201  // all the interface method declarations...
    202  NS_DECL_ISUPPORTS
    203 
    204  // non-interface implementation
    205 public:
    206  static XPCJSRuntime* GetRuntimeInstance();
    207  XPCJSContext* GetContext() { return mContext; }
    208 
    209  static nsIScriptSecurityManager* SecurityManager() {
    210    MOZ_ASSERT(NS_IsMainThread());
    211    MOZ_ASSERT(gScriptSecurityManager);
    212    return gScriptSecurityManager;
    213  }
    214 
    215  static nsIPrincipal* SystemPrincipal() {
    216    MOZ_ASSERT(NS_IsMainThread());
    217    MOZ_ASSERT(gSystemPrincipal);
    218    return gSystemPrincipal;
    219  }
    220 
    221  // Called by module code in dll startup
    222  static void InitStatics();
    223  // Called by module code on dll shutdown.
    224  static void ReleaseXPConnectSingleton();
    225 
    226  static void InitJSContext();
    227 
    228  void RecordTraversal(void* p, nsISupports* s);
    229 
    230 protected:
    231  virtual ~nsXPConnect();
    232 
    233  nsXPConnect();
    234 
    235 private:
    236  // Singleton instance
    237  static nsXPConnect* gSelf;
    238  static bool gOnceAliveNowDead;
    239 
    240  XPCJSContext* mContext = nullptr;
    241  XPCJSRuntime* mRuntime = nullptr;
    242 
    243  friend class nsIXPConnect;
    244 
    245 public:
    246  static nsIScriptSecurityManager* gScriptSecurityManager;
    247  static nsIPrincipal* gSystemPrincipal;
    248 };
    249 
    250 /***************************************************************************/
    251 
    252 // In the current xpconnect system there can only be one XPCJSContext.
    253 // So, xpconnect can only be used on one JSContext within the process.
    254 
    255 class WatchdogManager;
    256 
    257 // clang-format off
    258 MOZ_DEFINE_ENUM(WatchdogTimestampCategory, (
    259    TimestampWatchdogWakeup,
    260    TimestampWatchdogHibernateStart,
    261    TimestampWatchdogHibernateStop,
    262    TimestampContextStateChange
    263 ));
    264 // clang-format on
    265 
    266 class AsyncFreeSnowWhite;
    267 class XPCWrappedNativeScope;
    268 
    269 using XPCWrappedNativeScopeList = mozilla::LinkedList<XPCWrappedNativeScope>;
    270 
    271 class XPCJSContext final : public mozilla::CycleCollectedJSContext,
    272                           public mozilla::LinkedListElement<XPCJSContext> {
    273 public:
    274  static XPCJSContext* NewXPCJSContext();
    275  static XPCJSContext* Get();
    276 
    277  XPCJSRuntime* Runtime() const;
    278 
    279  virtual mozilla::CycleCollectedJSRuntime* CreateRuntime(
    280      JSContext* aCx) override;
    281 
    282  XPCCallContext* GetCallContext() const { return mCallContext; }
    283  XPCCallContext* SetCallContext(XPCCallContext* ccx) {
    284    XPCCallContext* old = mCallContext;
    285    mCallContext = ccx;
    286    return old;
    287  }
    288 
    289  jsid GetResolveName() const { return mResolveName; }
    290  jsid SetResolveName(jsid name) {
    291    jsid old = mResolveName;
    292    mResolveName = name;
    293    return old;
    294  }
    295 
    296  XPCWrappedNative* GetResolvingWrapper() const { return mResolvingWrapper; }
    297  XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w) {
    298    XPCWrappedNative* old = mResolvingWrapper;
    299    mResolvingWrapper = w;
    300    return old;
    301  }
    302 
    303  bool JSContextInitialized(JSContext* cx);
    304 
    305  virtual void BeforeProcessTask(bool aMightBlock) override;
    306  virtual void AfterProcessTask(uint32_t aNewRecursionDepth) override;
    307 
    308  // Relay to the CCGCScheduler instead of queuing up an idle runnable
    309  // (as is done for workers in CycleCollectedJSContext).
    310  virtual void MaybePokeGC() override;
    311 
    312  ~XPCJSContext();
    313 
    314  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
    315 
    316  bool IsSystemCaller() const override;
    317 
    318  AutoMarkingPtr** GetAutoRootsAdr() { return &mAutoRoots; }
    319 
    320  nsresult GetPendingResult() { return mPendingResult; }
    321  void SetPendingResult(nsresult rv) { mPendingResult = rv; }
    322 
    323  PRTime GetWatchdogTimestamp(WatchdogTimestampCategory aCategory);
    324 
    325  static bool RecordScriptActivity(bool aActive);
    326 
    327  bool SetHasScriptActivity(bool aActive) {
    328    bool oldValue = mHasScriptActivity;
    329    mHasScriptActivity = aActive;
    330    return oldValue;
    331  }
    332 
    333  static bool InterruptCallback(JSContext* cx);
    334 
    335  // Mapping of often used strings to jsid atoms that live 'forever'.
    336  //
    337  // To add a new string: add to this list and to XPCJSRuntime::mStrings
    338  // at the top of XPCJSRuntime.cpp
    339  enum {
    340    IDX_CONSTRUCTOR = 0,
    341    IDX_TO_STRING,
    342    IDX_TO_SOURCE,
    343    IDX_VALUE,
    344    IDX_QUERY_INTERFACE,
    345    IDX_COMPONENTS,
    346    IDX_CC,
    347    IDX_CI,
    348    IDX_CR,
    349    IDX_CU,
    350    IDX_SERVICES,
    351    IDX_WRAPPED_JSOBJECT,
    352    IDX_PROTOTYPE,
    353    IDX_EVAL,
    354    IDX_CONTROLLERS,
    355    IDX_CONTROLLERS_CLASS,
    356    IDX_LENGTH,
    357    IDX_NAME,
    358    IDX_UNDEFINED,
    359    IDX_EMPTYSTRING,
    360    IDX_FILENAME,
    361    IDX_LINENUMBER,
    362    IDX_COLUMNNUMBER,
    363    IDX_STACK,
    364    IDX_MESSAGE,
    365    IDX_CAUSE,
    366    IDX_ERRORS,
    367    IDX_LASTINDEX,
    368    IDX_THEN,
    369    IDX_ISINSTANCE,
    370    IDX_INFINITY,
    371    IDX_NAN,
    372    IDX_CLASS_ID,
    373    IDX_INTERFACE_ID,
    374    IDX_INITIALIZER,
    375    IDX_PRINT,
    376    IDX_FETCH,
    377    IDX_CRYPTO,
    378    IDX_INDEXEDDB,
    379    IDX_STRUCTUREDCLONE,
    380    IDX_LOCKS,
    381 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    382    IDX_SUPPRESSED,
    383    IDX_ERROR,
    384 #endif
    385    IDX_TOTAL_COUNT  // just a count of the above
    386  };
    387 
    388  inline JS::HandleId GetStringID(unsigned index) const;
    389  inline const char* GetStringName(unsigned index) const;
    390 
    391 private:
    392  XPCJSContext();
    393 
    394  MOZ_IS_CLASS_INIT
    395  nsresult Initialize();
    396 
    397  XPCCallContext* mCallContext;
    398  AutoMarkingPtr* mAutoRoots;
    399  jsid mResolveName;
    400  XPCWrappedNative* mResolvingWrapper;
    401  WatchdogManager* mWatchdogManager;
    402 
    403  // Number of XPCJSContexts currently alive.
    404  static uint32_t sInstanceCount;
    405  static mozilla::StaticAutoPtr<WatchdogManager> sWatchdogInstance;
    406  static WatchdogManager* GetWatchdogManager();
    407 
    408  // If we spend too much time running JS code in an event handler, then we
    409  // want to show the slow script UI. The timeout T is controlled by prefs. We
    410  // invoke the interrupt callback once after T/2 seconds and set
    411  // mSlowScriptSecondHalf to true. After another T/2 seconds, we invoke the
    412  // interrupt callback again. Since mSlowScriptSecondHalf is now true, it
    413  // shows the slow script UI. The reason we invoke the callback twice is to
    414  // ensure that putting the computer to sleep while running a script doesn't
    415  // cause the UI to be shown. If the laptop goes to sleep during one of the
    416  // timeout periods, the script still has the other T/2 seconds to complete
    417  // before the slow script UI is shown.
    418  bool mSlowScriptSecondHalf;
    419 
    420  // mSlowScriptCheckpoint is set to the time when:
    421  // 1. We started processing the current event, or
    422  // 2. mSlowScriptSecondHalf was set to true
    423  // (whichever comes later). We use it to determine whether the interrupt
    424  // callback needs to do anything.
    425  mozilla::TimeStamp mSlowScriptCheckpoint;
    426  // Accumulates total time we actually waited for telemetry
    427  mozilla::TimeDuration mSlowScriptActualWait;
    428  bool mTimeoutAccumulated;
    429  bool mExecutedChromeScript;
    430 
    431  bool mHasScriptActivity;
    432 
    433  // mPendingResult is used to implement Components.returnCode.  Only really
    434  // meaningful while calling through XPCWrappedJS.
    435  nsresult mPendingResult;
    436 
    437  // These members must be accessed via WatchdogManager.
    438  enum { CONTEXT_ACTIVE, CONTEXT_INACTIVE } mActive;
    439  PRTime mLastStateChange;
    440 
    441  friend class XPCJSRuntime;
    442  friend class Watchdog;
    443  friend class WatchdogManager;
    444  friend class AutoLockWatchdog;
    445 };
    446 
    447 class XPCJSRuntime final : public mozilla::CycleCollectedJSRuntime {
    448 public:
    449  static XPCJSRuntime* Get();
    450 
    451  void RemoveWrappedJS(nsXPCWrappedJS* wrapper);
    452  void AssertInvalidWrappedJSNotInTable(nsXPCWrappedJS* wrapper) const;
    453 
    454  JSObject2WrappedJSMap* GetMultiCompartmentWrappedJSMap() const {
    455    return mWrappedJSMap.get();
    456  }
    457 
    458  IID2NativeInterfaceMap* GetIID2NativeInterfaceMap() const {
    459    return mIID2NativeInterfaceMap.get();
    460  }
    461 
    462  ClassInfo2NativeSetMap* GetClassInfo2NativeSetMap() const {
    463    return mClassInfo2NativeSetMap.get();
    464  }
    465 
    466  NativeSetMap* GetNativeSetMap() const { return mNativeSetMap.get(); }
    467 
    468  using WrappedNativeProtoVector =
    469      mozilla::Vector<mozilla::UniquePtr<XPCWrappedNativeProto>, 0,
    470                      InfallibleAllocPolicy>;
    471  WrappedNativeProtoVector& GetDyingWrappedNativeProtos() {
    472    return mDyingWrappedNativeProtos;
    473  }
    474 
    475  XPCWrappedNativeScopeList& GetWrappedNativeScopes() {
    476    return mWrappedNativeScopes;
    477  }
    478 
    479  bool InitializeStrings(JSContext* cx);
    480 
    481  virtual bool DescribeCustomObjects(JSObject* aObject, const JSClass* aClasp,
    482                                     char (&aName)[72]) const override;
    483  virtual bool NoteCustomGCThingXPCOMChildren(
    484      const JSClass* aClasp, JSObject* aObj,
    485      nsCycleCollectionTraversalCallback& aCb) const override;
    486 
    487  /**
    488   * Infrastructure for classes that need to defer part of the finalization
    489   * until after the GC has run, for example for objects that we don't want to
    490   * destroy during the GC.
    491   */
    492 
    493 public:
    494  bool GetDoingFinalization() const { return mDoingFinalization; }
    495 
    496  JS::HandleId GetStringID(unsigned index) const {
    497    MOZ_ASSERT(index < XPCJSContext::IDX_TOTAL_COUNT, "index out of range");
    498    // fromMarkedLocation() is safe because the string is interned.
    499    return JS::HandleId::fromMarkedLocation(&mStrIDs[index]);
    500  }
    501  const char* GetStringName(unsigned index) const {
    502    MOZ_ASSERT(index < XPCJSContext::IDX_TOTAL_COUNT, "index out of range");
    503    return mStrings[index];
    504  }
    505 
    506  virtual bool UsefulToMergeZones() const override;
    507  void TraceAdditionalNativeBlackRoots(JSTracer* trc) override;
    508  void TraceAdditionalNativeGrayRoots(JSTracer* aTracer) override;
    509  void TraverseAdditionalNativeRoots(
    510      nsCycleCollectionNoteRootCallback& cb) override;
    511  void UnmarkSkippableJSHolders();
    512  void PrepareForForgetSkippable() override;
    513  void BeginCycleCollectionCallback(mozilla::CCReason aReason) override;
    514  void EndCycleCollectionCallback(
    515      mozilla::CycleCollectorResults& aResults) override;
    516  void DispatchDeferredDeletion(bool aContinuation,
    517                                bool aPurge = false) override;
    518 
    519  void CustomGCCallback(JSGCStatus status) override;
    520  void CustomOutOfMemoryCallback() override;
    521  void OnLargeAllocationFailure();
    522  static void GCSliceCallback(JSContext* cx, JS::GCProgress progress,
    523                              const JS::GCDescription& desc);
    524  static void DoCycleCollectionCallback(JSContext* cx);
    525  static void FinalizeCallback(JS::GCContext* gcx, JSFinalizeStatus status,
    526                               void* data);
    527  static void WeakPointerZonesCallback(JSTracer* trc, void* data);
    528  static void WeakPointerCompartmentCallback(JSTracer* trc,
    529                                             JS::Compartment* comp, void* data);
    530 
    531  inline void AddSubjectToFinalizationWJS(nsXPCWrappedJS* wrappedJS);
    532 
    533  void DebugDump(int16_t depth);
    534 
    535  bool GCIsRunning() const { return mGCIsRunning; }
    536 
    537  ~XPCJSRuntime();
    538 
    539  void AddGCCallback(xpcGCCallback cb);
    540  void RemoveGCCallback(xpcGCCallback cb);
    541 
    542  JSObject* GetUAWidgetScope(JSContext* cx, nsIPrincipal* principal);
    543 
    544  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
    545 
    546  /**
    547   * The unprivileged junk scope is an unprivileged sandbox global used for
    548   * convenience by certain operations which need an unprivileged global but
    549   * don't have one immediately handy. It should generally be avoided when
    550   * possible.
    551   *
    552   * The scope is created lazily when it is needed, and held weakly so that it
    553   * is destroyed when there are no longer any remaining external references to
    554   * it. This means that under low memory conditions, when the scope does not
    555   * already exist, we may not be able to create one. In these circumstances,
    556   * the infallible version of this API will abort, and the fallible version
    557   * will return null. Callers should therefore prefer the fallible version when
    558   * on a codepath which can already return failure, but may use the infallible
    559   * one otherwise.
    560   */
    561  JSObject* UnprivilegedJunkScope();
    562  JSObject* UnprivilegedJunkScope(const mozilla::fallible_t&);
    563 
    564  bool IsUnprivilegedJunkScope(JSObject*);
    565 
    566  void DeleteSingletonScopes();
    567 
    568 private:
    569  explicit XPCJSRuntime(JSContext* aCx);
    570 
    571  MOZ_IS_CLASS_INIT
    572  void Initialize(JSContext* cx);
    573  void Shutdown(JSContext* cx) override;
    574 
    575  static const char* const mStrings[XPCJSContext::IDX_TOTAL_COUNT];
    576  jsid mStrIDs[XPCJSContext::IDX_TOTAL_COUNT];
    577 
    578  struct Hasher {
    579    using Key = RefPtr<mozilla::BasePrincipal>;
    580    using Lookup = Key;
    581    static uint32_t hash(const Lookup& l) { return l->GetOriginNoSuffixHash(); }
    582    static bool match(const Key& k, const Lookup& l) {
    583      return k->FastEquals(l);
    584    }
    585  };
    586 
    587  struct MapEntryGCPolicy {
    588    static bool traceWeak(JSTracer* trc,
    589                          RefPtr<mozilla::BasePrincipal>* /* unused */,
    590                          JS::Heap<JSObject*>* value) {
    591      return JS::GCPolicy<JS::Heap<JSObject*>>::traceWeak(trc, value);
    592    }
    593  };
    594 
    595  typedef JS::GCHashMap<RefPtr<mozilla::BasePrincipal>, JS::Heap<JSObject*>,
    596                        Hasher, js::SystemAllocPolicy, MapEntryGCPolicy>
    597      Principal2JSObjectMap;
    598 
    599  mozilla::UniquePtr<JSObject2WrappedJSMap> mWrappedJSMap;
    600  mozilla::UniquePtr<IID2NativeInterfaceMap> mIID2NativeInterfaceMap;
    601  mozilla::UniquePtr<ClassInfo2NativeSetMap> mClassInfo2NativeSetMap;
    602  mozilla::UniquePtr<NativeSetMap> mNativeSetMap;
    603  Principal2JSObjectMap mUAWidgetScopeMap;
    604  XPCWrappedNativeScopeList mWrappedNativeScopes;
    605  WrappedNativeProtoVector mDyingWrappedNativeProtos;
    606  bool mGCIsRunning;
    607  nsTArray<nsISupports*> mNativesToReleaseArray;
    608  bool mDoingFinalization;
    609  mozilla::LinkedList<nsXPCWrappedJS> mSubjectToFinalizationWJS;
    610  nsTArray<xpcGCCallback> extraGCCallbacks;
    611  JS::GCSliceCallback mPrevGCSliceCallback;
    612  JS::DoCycleCollectionCallback mPrevDoCycleCollectionCallback;
    613  mozilla::WeakPtr<SandboxPrivate> mUnprivilegedJunkScope;
    614  RefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer;
    615 
    616  friend class XPCJSContext;
    617  friend class XPCIncrementalReleaseRunnable;
    618 };
    619 
    620 inline JS::HandleId XPCJSContext::GetStringID(unsigned index) const {
    621  return Runtime()->GetStringID(index);
    622 }
    623 
    624 inline const char* XPCJSContext::GetStringName(unsigned index) const {
    625  return Runtime()->GetStringName(index);
    626 }
    627 
    628 /***************************************************************************/
    629 
    630 // No virtuals
    631 // XPCCallContext is ALWAYS declared as a local variable in some function;
    632 // i.e. instance lifetime is always controled by some C++ function returning.
    633 //
    634 // These things are created frequently in many places. We *intentionally* do
    635 // not inialialize all members in order to save on construction overhead.
    636 // Some constructor pass more valid params than others. We init what must be
    637 // init'd and leave other members undefined. In debug builds the accessors
    638 // use a CHECK_STATE macro to track whether or not the object is in a valid
    639 // state to answer the question a caller might be asking. As long as this
    640 // class is maintained correctly it can do its job without a bunch of added
    641 // overhead from useless initializations and non-DEBUG error checking.
    642 //
    643 // Note that most accessors are inlined.
    644 
    645 class MOZ_STACK_CLASS XPCCallContext final {
    646 public:
    647  enum : unsigned { NO_ARGS = (unsigned)-1 };
    648 
    649  explicit XPCCallContext(JSContext* cx, JS::HandleObject obj = nullptr,
    650                          JS::HandleObject funobj = nullptr,
    651                          JS::HandleId id = JS::VoidHandlePropertyKey,
    652                          unsigned argc = NO_ARGS, JS::Value* argv = nullptr,
    653                          JS::Value* rval = nullptr);
    654 
    655  virtual ~XPCCallContext();
    656 
    657  inline bool IsValid() const;
    658 
    659  inline XPCJSContext* GetContext() const;
    660  inline JSContext* GetJSContext() const;
    661  inline bool GetContextPopRequired() const;
    662  inline XPCCallContext* GetPrevCallContext() const;
    663 
    664  inline JSObject* GetFlattenedJSObject() const;
    665  inline XPCWrappedNative* GetWrapper() const;
    666 
    667  inline bool CanGetTearOff() const;
    668  inline XPCWrappedNativeTearOff* GetTearOff() const;
    669 
    670  inline nsIXPCScriptable* GetScriptable() const;
    671  inline XPCNativeSet* GetSet() const;
    672  inline bool CanGetInterface() const;
    673  inline XPCNativeInterface* GetInterface() const;
    674  inline XPCNativeMember* GetMember() const;
    675  inline bool HasInterfaceAndMember() const;
    676  inline bool GetStaticMemberIsLocal() const;
    677  inline unsigned GetArgc() const;
    678  inline JS::Value* GetArgv() const;
    679 
    680  inline uint16_t GetMethodIndex() const;
    681 
    682  inline jsid GetResolveName() const;
    683  inline jsid SetResolveName(JS::HandleId name);
    684 
    685  inline XPCWrappedNative* GetResolvingWrapper() const;
    686  inline XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w);
    687 
    688  inline void SetRetVal(const JS::Value& val);
    689 
    690  void SetName(jsid name);
    691  void SetArgsAndResultPtr(unsigned argc, JS::Value* argv, JS::Value* rval);
    692  void SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member,
    693                   bool isSetter);
    694 
    695  nsresult CanCallNow();
    696 
    697  void SystemIsBeingShutDown();
    698 
    699  operator JSContext*() const { return GetJSContext(); }
    700 
    701 private:
    702  // no copy ctor or assignment allowed
    703  XPCCallContext(const XPCCallContext& r) = delete;
    704  XPCCallContext& operator=(const XPCCallContext& r) = delete;
    705 
    706 private:
    707  // posible values for mState
    708  enum State {
    709    INIT_FAILED,
    710    SYSTEM_SHUTDOWN,
    711    HAVE_CONTEXT,
    712    HAVE_OBJECT,
    713    HAVE_NAME,
    714    HAVE_ARGS,
    715    READY_TO_CALL,
    716    CALL_DONE
    717  };
    718 
    719 #ifdef DEBUG
    720  inline void CHECK_STATE(int s) const { MOZ_ASSERT(mState >= s, "bad state"); }
    721 #else
    722 #  define CHECK_STATE(s) ((void)0)
    723 #endif
    724 
    725 private:
    726  State mState;
    727 
    728  nsCOMPtr<nsIXPConnect> mXPC;
    729 
    730  XPCJSContext* mXPCJSContext;
    731  JSContext* mJSContext;
    732 
    733  // ctor does not necessarily init the following. BEWARE!
    734 
    735  XPCCallContext* mPrevCallContext;
    736 
    737  XPCWrappedNative* mWrapper;
    738  XPCWrappedNativeTearOff* mTearOff;
    739 
    740  nsCOMPtr<nsIXPCScriptable> mScriptable;
    741 
    742  RefPtr<XPCNativeSet> mSet;
    743  RefPtr<XPCNativeInterface> mInterface;
    744  XPCNativeMember* mMember;
    745 
    746  JS::RootedId mName;
    747  bool mStaticMemberIsLocal;
    748 
    749  unsigned mArgc;
    750  JS::Value* mArgv;
    751  JS::Value* mRetVal;
    752 
    753  uint16_t mMethodIndex;
    754 };
    755 
    756 /***************************************************************************
    757 ****************************************************************************
    758 *
    759 * Core classes for wrapped native objects for use from JavaScript...
    760 *
    761 ****************************************************************************
    762 ***************************************************************************/
    763 
    764 // These are the various JSClasses and callbacks whose use that required
    765 // visibility from more than one .cpp file.
    766 
    767 extern const JSClass XPC_WN_NoHelper_JSClass;
    768 extern const JSClass XPC_WN_Proto_JSClass;
    769 extern const JSClass XPC_WN_Tearoff_JSClass;
    770 extern const JSClass XPC_WN_NoHelper_Proto_JSClass;
    771 
    772 extern bool XPC_WN_CallMethod(JSContext* cx, unsigned argc, JS::Value* vp);
    773 
    774 extern bool XPC_WN_GetterSetter(JSContext* cx, unsigned argc, JS::Value* vp);
    775 
    776 /***************************************************************************/
    777 // XPCWrappedNativeScope is one-to-one with a JS compartment.
    778 
    779 class XPCWrappedNativeScope final
    780    : public mozilla::LinkedListElement<XPCWrappedNativeScope> {
    781 public:
    782  XPCJSRuntime* GetRuntime() const { return XPCJSRuntime::Get(); }
    783 
    784  Native2WrappedNativeMap* GetWrappedNativeMap() const {
    785    return mWrappedNativeMap.get();
    786  }
    787 
    788  ClassInfo2WrappedNativeProtoMap* GetWrappedNativeProtoMap() const {
    789    return mWrappedNativeProtoMap.get();
    790  }
    791 
    792  nsXPCComponents* GetComponents() const { return mComponents; }
    793 
    794  bool AttachComponentsObject(JSContext* aCx);
    795 
    796  bool AttachJSServices(JSContext* aCx);
    797 
    798  // Returns the JS object reflection of the Components object.
    799  bool GetComponentsJSObject(JSContext* cx, JS::MutableHandleObject obj);
    800 
    801  JSObject* GetExpandoChain(JS::HandleObject target);
    802 
    803  JSObject* DetachExpandoChain(JS::HandleObject target);
    804 
    805  bool SetExpandoChain(JSContext* cx, JS::HandleObject target,
    806                       JS::HandleObject chain);
    807 
    808  static void SystemIsBeingShutDown();
    809 
    810  static void TraceWrappedNativesInAllScopes(XPCJSRuntime* xpcrt,
    811                                             JSTracer* trc);
    812 
    813  void TraceInside(JSTracer* trc) {
    814    if (mXrayExpandos.initialized()) {
    815      mXrayExpandos.trace(trc);
    816    }
    817    JS::TraceEdge(trc, &mIDProto, "XPCWrappedNativeScope::mIDProto");
    818    JS::TraceEdge(trc, &mIIDProto, "XPCWrappedNativeScope::mIIDProto");
    819    JS::TraceEdge(trc, &mCIDProto, "XPCWrappedNativeScope::mCIDProto");
    820  }
    821 
    822  static void SuspectAllWrappers(nsCycleCollectionNoteRootCallback& cb);
    823 
    824  static void SweepAllWrappedNativeTearOffs();
    825 
    826  void UpdateWeakPointersAfterGC(JSTracer* trc);
    827 
    828  static void DebugDumpAllScopes(int16_t depth);
    829 
    830  void DebugDump(int16_t depth);
    831 
    832  struct ScopeSizeInfo {
    833    explicit ScopeSizeInfo(mozilla::MallocSizeOf mallocSizeOf)
    834        : mMallocSizeOf(mallocSizeOf),
    835          mScopeAndMapSize(0),
    836          mProtoAndIfaceCacheSize(0) {}
    837 
    838    mozilla::MallocSizeOf mMallocSizeOf;
    839    size_t mScopeAndMapSize;
    840    size_t mProtoAndIfaceCacheSize;
    841  };
    842 
    843  static void AddSizeOfAllScopesIncludingThis(JSContext* cx,
    844                                              ScopeSizeInfo* scopeSizeInfo);
    845 
    846  void AddSizeOfIncludingThis(JSContext* cx, ScopeSizeInfo* scopeSizeInfo);
    847 
    848  // Check whether our mAllowContentXBLScope state matches the given
    849  // principal.  This is used to avoid sharing compartments on
    850  // mismatch.
    851  bool XBLScopeStateMatches(nsIPrincipal* aPrincipal);
    852 
    853  XPCWrappedNativeScope(JS::Compartment* aCompartment,
    854                        JS::HandleObject aFirstGlobal);
    855  virtual ~XPCWrappedNativeScope();
    856 
    857  mozilla::UniquePtr<JSObject2JSObjectMap> mWaiverWrapperMap;
    858 
    859  JS::Compartment* Compartment() const { return mCompartment; }
    860 
    861  // Returns the global to use for new WrappedNative objects allocated in this
    862  // compartment. This is better than using arbitrary globals we happen to be in
    863  // because it prevents leaks (objects keep their globals alive).
    864  JSObject* GetGlobalForWrappedNatives() {
    865    return js::GetFirstGlobalInCompartment(Compartment());
    866  }
    867 
    868  bool AllowContentXBLScope(JS::Realm* aRealm);
    869 
    870  // ID Object prototype caches.
    871  JS::Heap<JSObject*> mIDProto;
    872  JS::Heap<JSObject*> mIIDProto;
    873  JS::Heap<JSObject*> mCIDProto;
    874 
    875 protected:
    876  XPCWrappedNativeScope() = delete;
    877 
    878 private:
    879  mozilla::UniquePtr<Native2WrappedNativeMap> mWrappedNativeMap;
    880  mozilla::UniquePtr<ClassInfo2WrappedNativeProtoMap> mWrappedNativeProtoMap;
    881  RefPtr<nsXPCComponents> mComponents;
    882  JS::Compartment* mCompartment;
    883 
    884  JS::WeakMapPtr<JSObject*, JSObject*> mXrayExpandos;
    885 
    886  // For remote XUL domains, we run all XBL in the content scope for compat
    887  // reasons (though we sometimes pref this off for automation). We
    888  // track the result of this decision (mAllowContentXBLScope) for now.
    889  bool mAllowContentXBLScope;
    890 };
    891 
    892 /***************************************************************************/
    893 // Slots we use for our functions
    894 #define XPC_FUNCTION_NATIVE_MEMBER_SLOT 0
    895 #define XPC_FUNCTION_PARENT_OBJECT_SLOT 1
    896 
    897 /***************************************************************************/
    898 // XPCNativeMember represents a single idl declared method, attribute or
    899 // constant.
    900 
    901 // Tight. No virtual methods. Can be bitwise copied (until any resolution done).
    902 
    903 class XPCNativeMember final {
    904 public:
    905  static bool GetCallInfo(JSObject* funobj,
    906                          RefPtr<XPCNativeInterface>* pInterface,
    907                          XPCNativeMember** pMember);
    908 
    909  jsid GetName() const { return mName; }
    910 
    911  uint16_t GetIndex() const { return mIndex; }
    912 
    913  bool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface,
    914                        JS::Value* pval) {
    915    MOZ_ASSERT(IsConstant(),
    916               "Only call this if you're sure this is a constant!");
    917    return Resolve(ccx, iface, nullptr, pval);
    918  }
    919 
    920  bool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface,
    921                         JS::HandleObject parent, JS::Value* pval);
    922 
    923  bool IsMethod() const { return 0 != (mFlags & METHOD); }
    924 
    925  bool IsConstant() const { return 0 != (mFlags & CONSTANT); }
    926 
    927  bool IsAttribute() const { return 0 != (mFlags & GETTER); }
    928 
    929  bool IsWritableAttribute() const { return 0 != (mFlags & SETTER_TOO); }
    930 
    931  bool IsReadOnlyAttribute() const {
    932    return IsAttribute() && !IsWritableAttribute();
    933  }
    934 
    935  void SetName(jsid a) { mName = a; }
    936 
    937  void SetMethod(uint16_t index) {
    938    mFlags = METHOD;
    939    mIndex = index;
    940  }
    941 
    942  void SetConstant(uint16_t index) {
    943    mFlags = CONSTANT;
    944    mIndex = index;
    945  }
    946 
    947  void SetReadOnlyAttribute(uint16_t index) {
    948    mFlags = GETTER;
    949    mIndex = index;
    950  }
    951 
    952  void SetWritableAttribute() {
    953    MOZ_ASSERT(mFlags == GETTER, "bad");
    954    mFlags = GETTER | SETTER_TOO;
    955  }
    956 
    957  static uint16_t GetMaxIndexInInterface() { return (1 << 12) - 1; }
    958 
    959  inline XPCNativeInterface* GetInterface() const;
    960 
    961  void SetIndexInInterface(uint16_t index) { mIndexInInterface = index; }
    962 
    963  /* default ctor - leave random contents */
    964  MOZ_COUNTED_DEFAULT_CTOR(XPCNativeMember)
    965  MOZ_COUNTED_DTOR(XPCNativeMember)
    966 
    967  XPCNativeMember(const XPCNativeMember& other)
    968      : mName(other.mName),
    969        mIndex(other.mIndex),
    970        mFlags(other.mFlags),
    971        mIndexInInterface(other.mIndexInInterface) {
    972    MOZ_COUNT_CTOR(XPCNativeMember);
    973  }
    974 
    975 private:
    976  bool Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
    977               JS::HandleObject parent, JS::Value* vp);
    978 
    979  enum {
    980    METHOD = 0x01,
    981    CONSTANT = 0x02,
    982    GETTER = 0x04,
    983    SETTER_TOO = 0x08
    984    // If you add a flag here, you may need to make mFlags wider and either
    985    // make mIndexInInterface narrower (and adjust
    986    // XPCNativeInterface::NewInstance accordingly) or make this object
    987    // bigger.
    988  };
    989 
    990 private:
    991  // our only data...
    992  jsid mName;
    993  uint16_t mIndex;
    994  // mFlags needs to be wide enough to hold the flags in the above enum.
    995  uint16_t mFlags : 4;
    996  // mIndexInInterface is the index of this in our XPCNativeInterface's
    997  // mMembers.  In theory our XPCNativeInterface could have as many as 2^15-1
    998  // members (since mMemberCount is 15-bit) but in practice we prevent
    999  // creation of XPCNativeInterfaces which have more than 2^12 members.
   1000  // If the width of this field changes, update GetMaxIndexInInterface.
   1001  uint16_t mIndexInInterface : 12;
   1002 };
   1003 
   1004 /***************************************************************************/
   1005 // XPCNativeInterface represents a single idl declared interface. This is
   1006 // primarily the set of XPCNativeMembers.
   1007 
   1008 // Tight. No virtual methods.
   1009 
   1010 class XPCNativeInterface final {
   1011 public:
   1012  NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(XPCNativeInterface,
   1013                                          DestroyInstance(this))
   1014 
   1015  static already_AddRefed<XPCNativeInterface> GetNewOrUsed(JSContext* cx,
   1016                                                           const nsIID* iid);
   1017  static already_AddRefed<XPCNativeInterface> GetNewOrUsed(
   1018      JSContext* cx, const nsXPTInterfaceInfo* info);
   1019  static already_AddRefed<XPCNativeInterface> GetNewOrUsed(JSContext* cx,
   1020                                                           const char* name);
   1021  static already_AddRefed<XPCNativeInterface> GetISupports(JSContext* cx);
   1022 
   1023  inline const nsXPTInterfaceInfo* GetInterfaceInfo() const { return mInfo; }
   1024  inline jsid GetName() const { return mName; }
   1025 
   1026  inline const nsIID* GetIID() const;
   1027  inline const char* GetNameString() const;
   1028  inline XPCNativeMember* FindMember(jsid name) const;
   1029 
   1030  static inline size_t OffsetOfMembers();
   1031 
   1032  uint16_t GetMemberCount() const { return mMemberCount; }
   1033  XPCNativeMember* GetMemberAt(uint16_t i) {
   1034    MOZ_ASSERT(i < mMemberCount, "bad index");
   1035    return &mMembers[i];
   1036  }
   1037 
   1038  void DebugDump(int16_t depth);
   1039 
   1040  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
   1041 
   1042  void Trace(JSTracer* trc);
   1043 
   1044 protected:
   1045  static already_AddRefed<XPCNativeInterface> NewInstance(
   1046      JSContext* cx, IID2NativeInterfaceMap* aMap,
   1047      const nsXPTInterfaceInfo* aInfo);
   1048 
   1049  XPCNativeInterface() = delete;
   1050  XPCNativeInterface(const nsXPTInterfaceInfo* aInfo, jsid aName)
   1051      : mInfo(aInfo), mName(aName), mMemberCount(0) {}
   1052  ~XPCNativeInterface();
   1053 
   1054  void* operator new(size_t, void* p) noexcept(true) { return p; }
   1055 
   1056  XPCNativeInterface(const XPCNativeInterface& r) = delete;
   1057  XPCNativeInterface& operator=(const XPCNativeInterface& r) = delete;
   1058 
   1059  static void DestroyInstance(XPCNativeInterface* inst);
   1060 
   1061 private:
   1062  const nsXPTInterfaceInfo* mInfo;
   1063  jsid mName;
   1064  uint16_t mMemberCount;
   1065  XPCNativeMember mMembers[1];  // always last - object sized for array
   1066 };
   1067 
   1068 /***************************************************************************/
   1069 // XPCNativeSetKey is used to key a XPCNativeSet in a NativeSetMap.
   1070 // It represents a new XPCNativeSet we are considering constructing, without
   1071 // requiring that the set actually be built.
   1072 
   1073 class MOZ_STACK_CLASS XPCNativeSetKey final {
   1074 public:
   1075  // This represents an existing set |baseSet|.
   1076  explicit XPCNativeSetKey(XPCNativeSet* baseSet)
   1077      : mCx(nullptr), mBaseSet(baseSet), mAddition(nullptr) {
   1078    MOZ_ASSERT(baseSet);
   1079  }
   1080 
   1081  // This represents a new set containing only nsISupports and
   1082  // |addition|.  This needs a JSContext because it may need to
   1083  // construct some data structures that need one to construct them.
   1084  explicit XPCNativeSetKey(JSContext* cx, XPCNativeInterface* addition)
   1085      : mCx(cx), mBaseSet(nullptr), mAddition(addition) {
   1086    MOZ_ASSERT(cx);
   1087    MOZ_ASSERT(addition);
   1088  }
   1089 
   1090  // This represents the existing set |baseSet| with the interface
   1091  // |addition| inserted after existing interfaces. |addition| must
   1092  // not already be present in |baseSet|.
   1093  explicit XPCNativeSetKey(XPCNativeSet* baseSet, XPCNativeInterface* addition);
   1094  ~XPCNativeSetKey() = default;
   1095 
   1096  XPCNativeSet* GetBaseSet() const { return mBaseSet; }
   1097  XPCNativeInterface* GetAddition() const { return mAddition; }
   1098 
   1099  mozilla::HashNumber Hash() const;
   1100 
   1101  // Allow shallow copy
   1102 
   1103 private:
   1104  JSContext* mCx;
   1105  RefPtr<XPCNativeSet> mBaseSet;
   1106  RefPtr<XPCNativeInterface> mAddition;
   1107 };
   1108 
   1109 /***************************************************************************/
   1110 // XPCNativeSet represents an ordered collection of XPCNativeInterface pointers.
   1111 
   1112 class XPCNativeSet final {
   1113 public:
   1114  NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(XPCNativeSet, DestroyInstance(this))
   1115 
   1116  static already_AddRefed<XPCNativeSet> GetNewOrUsed(JSContext* cx,
   1117                                                     const nsIID* iid);
   1118  static already_AddRefed<XPCNativeSet> GetNewOrUsed(JSContext* cx,
   1119                                                     nsIClassInfo* classInfo);
   1120  static already_AddRefed<XPCNativeSet> GetNewOrUsed(JSContext* cx,
   1121                                                     XPCNativeSetKey* key);
   1122 
   1123  // This generates a union set.
   1124  //
   1125  // If preserveFirstSetOrder is true, the elements from |firstSet| come first,
   1126  // followed by any non-duplicate items from |secondSet|. If false, the same
   1127  // algorithm is applied; but if we detect that |secondSet| is a superset of
   1128  // |firstSet|, we return |secondSet| without worrying about whether the
   1129  // ordering might differ from |firstSet|.
   1130  static already_AddRefed<XPCNativeSet> GetNewOrUsed(
   1131      JSContext* cx, XPCNativeSet* firstSet, XPCNativeSet* secondSet,
   1132      bool preserveFirstSetOrder);
   1133 
   1134  static void ClearCacheEntryForClassInfo(nsIClassInfo* classInfo);
   1135 
   1136  inline bool FindMember(jsid name, XPCNativeMember** pMember,
   1137                         uint16_t* pInterfaceIndex) const;
   1138 
   1139  inline bool FindMember(jsid name, XPCNativeMember** pMember,
   1140                         RefPtr<XPCNativeInterface>* pInterface) const;
   1141 
   1142  inline bool FindMember(JS::HandleId name, XPCNativeMember** pMember,
   1143                         RefPtr<XPCNativeInterface>* pInterface,
   1144                         XPCNativeSet* protoSet, bool* pIsLocal) const;
   1145 
   1146  inline bool HasInterface(XPCNativeInterface* aInterface) const;
   1147 
   1148  uint16_t GetInterfaceCount() const { return mInterfaceCount; }
   1149  XPCNativeInterface** GetInterfaceArray() { return mInterfaces; }
   1150 
   1151  XPCNativeInterface* GetInterfaceAt(uint16_t i) {
   1152    MOZ_ASSERT(i < mInterfaceCount, "bad index");
   1153    return mInterfaces[i];
   1154  }
   1155 
   1156  inline bool MatchesSetUpToInterface(const XPCNativeSet* other,
   1157                                      XPCNativeInterface* iface) const;
   1158 
   1159  void DebugDump(int16_t depth);
   1160 
   1161  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
   1162 
   1163 protected:
   1164  static already_AddRefed<XPCNativeSet> NewInstance(
   1165      JSContext* cx, nsTArray<RefPtr<XPCNativeInterface>>&& array);
   1166  static already_AddRefed<XPCNativeSet> NewInstanceMutate(XPCNativeSetKey* key);
   1167 
   1168  XPCNativeSet() : mInterfaceCount(0) {}
   1169  ~XPCNativeSet();
   1170  void* operator new(size_t, void* p) noexcept(true) { return p; }
   1171 
   1172  static void DestroyInstance(XPCNativeSet* inst);
   1173 
   1174 private:
   1175  uint16_t mInterfaceCount;
   1176  // Always last - object sized for array.
   1177  // These are strong references.
   1178  XPCNativeInterface* mInterfaces[1];
   1179 };
   1180 
   1181 /***********************************************/
   1182 // XPCWrappedNativeProtos hold the additional shared wrapper data for
   1183 // XPCWrappedNative whose native objects expose nsIClassInfo.
   1184 //
   1185 // The XPCWrappedNativeProto is owned by its mJSProtoObject, until that object
   1186 // is finalized. After that, it is owned by XPCJSRuntime's
   1187 // mDyingWrappedNativeProtos. See XPCWrappedNativeProto::JSProtoObjectFinalized
   1188 // and XPCJSRuntime::FinalizeCallback.
   1189 
   1190 class XPCWrappedNativeProto final {
   1191 public:
   1192  enum Slots { ProtoSlot, SlotCount };
   1193 
   1194  static XPCWrappedNativeProto* GetNewOrUsed(JSContext* cx,
   1195                                             XPCWrappedNativeScope* scope,
   1196                                             nsIClassInfo* classInfo,
   1197                                             nsIXPCScriptable* scriptable);
   1198 
   1199  XPCWrappedNativeScope* GetScope() const { return mScope; }
   1200 
   1201  XPCJSRuntime* GetRuntime() const { return mScope->GetRuntime(); }
   1202 
   1203  JSObject* GetJSProtoObject() const { return mJSProtoObject; }
   1204 
   1205  JSObject* GetJSProtoObjectPreserveColor() const {
   1206    return mJSProtoObject.unbarrieredGet();
   1207  }
   1208 
   1209  nsIClassInfo* GetClassInfo() const { return mClassInfo; }
   1210 
   1211  XPCNativeSet* GetSet() const { return mSet; }
   1212 
   1213  nsIXPCScriptable* GetScriptable() const { return mScriptable; }
   1214 
   1215  void JSProtoObjectFinalized(JS::GCContext* gcx, JSObject* obj);
   1216  void JSProtoObjectMoved(JSObject* obj, const JSObject* old);
   1217 
   1218  static XPCWrappedNativeProto* Get(JSObject* obj);
   1219 
   1220  void SystemIsBeingShutDown();
   1221 
   1222  void DebugDump(int16_t depth);
   1223 
   1224  void TraceSelf(JSTracer* trc) {
   1225    if (mJSProtoObject) {
   1226      TraceEdge(trc, &mJSProtoObject, "XPCWrappedNativeProto::mJSProtoObject");
   1227    }
   1228  }
   1229 
   1230  void TraceJS(JSTracer* trc) { TraceSelf(trc); }
   1231 
   1232  // NOP. This is just here to make the AutoMarkingPtr code compile.
   1233  void Mark() const {}
   1234  inline void AutoTrace(JSTracer* trc) {}
   1235 
   1236  ~XPCWrappedNativeProto();
   1237 
   1238 protected:
   1239  // disable copy ctor and assignment
   1240  XPCWrappedNativeProto(const XPCWrappedNativeProto& r) = delete;
   1241  XPCWrappedNativeProto& operator=(const XPCWrappedNativeProto& r) = delete;
   1242 
   1243  // hide ctor
   1244  XPCWrappedNativeProto(XPCWrappedNativeScope* Scope, nsIClassInfo* ClassInfo,
   1245                        RefPtr<XPCNativeSet>&& Set);
   1246 
   1247  bool Init(JSContext* cx, nsIXPCScriptable* scriptable);
   1248 
   1249 private:
   1250 #ifdef DEBUG
   1251  static int32_t gDEBUG_LiveProtoCount;
   1252 #endif
   1253 
   1254 private:
   1255  XPCWrappedNativeScope* mScope;
   1256  JS::Heap<JSObject*> mJSProtoObject;
   1257  nsCOMPtr<nsIClassInfo> mClassInfo;
   1258  RefPtr<XPCNativeSet> mSet;
   1259  nsCOMPtr<nsIXPCScriptable> mScriptable;
   1260 };
   1261 
   1262 /***********************************************/
   1263 // XPCWrappedNativeTearOff represents the info needed to make calls to one
   1264 // interface on the underlying native object of a XPCWrappedNative.
   1265 
   1266 class XPCWrappedNativeTearOff final {
   1267 public:
   1268  enum Slots { FlatObjectSlot, TearOffSlot, SlotCount };
   1269 
   1270  bool IsAvailable() const { return mInterface == nullptr; }
   1271  bool IsReserved() const { return mInterface == (XPCNativeInterface*)1; }
   1272  bool IsValid() const { return !IsAvailable() && !IsReserved(); }
   1273  void SetReserved() { mInterface = (XPCNativeInterface*)1; }
   1274 
   1275  XPCNativeInterface* GetInterface() const { return mInterface; }
   1276  nsISupports* GetNative() const { return mNative; }
   1277  JSObject* GetJSObject();
   1278  JSObject* GetJSObjectPreserveColor() const;
   1279  void SetInterface(XPCNativeInterface* Interface) { mInterface = Interface; }
   1280  void SetNative(nsISupports* Native) { mNative = Native; }
   1281  already_AddRefed<nsISupports> TakeNative() { return mNative.forget(); }
   1282  void SetJSObject(JSObject* JSObj);
   1283 
   1284  void JSObjectFinalized() { SetJSObject(nullptr); }
   1285  void JSObjectMoved(JSObject* obj, const JSObject* old);
   1286 
   1287  static XPCWrappedNativeTearOff* Get(JSObject* obj);
   1288 
   1289  XPCWrappedNativeTearOff() : mInterface(nullptr), mJSObject(nullptr) {
   1290    MOZ_COUNT_CTOR(XPCWrappedNativeTearOff);
   1291  }
   1292  ~XPCWrappedNativeTearOff();
   1293 
   1294  // NOP. This is just here to make the AutoMarkingPtr code compile.
   1295  inline void TraceJS(JSTracer* trc) {}
   1296  inline void AutoTrace(JSTracer* trc) {}
   1297 
   1298  void Mark() { mJSObject.setFlags(1); }
   1299  void Unmark() { mJSObject.unsetFlags(1); }
   1300  bool IsMarked() const { return mJSObject.hasFlag(1); }
   1301 
   1302  XPCWrappedNativeTearOff* AddTearOff() {
   1303    MOZ_ASSERT(!mNextTearOff);
   1304    mNextTearOff = mozilla::MakeUnique<XPCWrappedNativeTearOff>();
   1305    return mNextTearOff.get();
   1306  }
   1307 
   1308  XPCWrappedNativeTearOff* GetNextTearOff() { return mNextTearOff.get(); }
   1309 
   1310 private:
   1311  XPCWrappedNativeTearOff(const XPCWrappedNativeTearOff& r) = delete;
   1312  XPCWrappedNativeTearOff& operator=(const XPCWrappedNativeTearOff& r) = delete;
   1313 
   1314 private:
   1315  XPCNativeInterface* mInterface;
   1316  // mNative is an nsRefPtr not an nsCOMPtr because it may not be the canonical
   1317  // nsISupports pointer.
   1318  RefPtr<nsISupports> mNative;
   1319  JS::TenuredHeap<JSObject*> mJSObject;
   1320  mozilla::UniquePtr<XPCWrappedNativeTearOff> mNextTearOff;
   1321 };
   1322 
   1323 /***************************************************************************/
   1324 // XPCWrappedNative the wrapper around one instance of a native xpcom object
   1325 // to be used from JavaScript.
   1326 
   1327 class XPCWrappedNative final : public nsIXPConnectWrappedNative {
   1328 public:
   1329  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   1330 
   1331  NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
   1332 
   1333  JSObject* GetJSObject() override;
   1334 
   1335  bool IsValid() const { return mFlatJSObject.hasFlag(FLAT_JS_OBJECT_VALID); }
   1336 
   1337  nsresult DebugDump(int16_t depth);
   1338 
   1339 #define XPC_SCOPE_WORD(s) (intptr_t(s))
   1340 #define XPC_SCOPE_MASK (intptr_t(0x3))
   1341 #define XPC_SCOPE_TAG (intptr_t(0x1))
   1342 #define XPC_WRAPPER_EXPIRED (intptr_t(0x2))
   1343 
   1344  static inline bool IsTaggedScope(XPCWrappedNativeScope* s) {
   1345    return XPC_SCOPE_WORD(s) & XPC_SCOPE_TAG;
   1346  }
   1347 
   1348  static inline XPCWrappedNativeScope* TagScope(XPCWrappedNativeScope* s) {
   1349    MOZ_ASSERT(!IsTaggedScope(s), "bad pointer!");
   1350    return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) | XPC_SCOPE_TAG);
   1351  }
   1352 
   1353  static inline XPCWrappedNativeScope* UnTagScope(XPCWrappedNativeScope* s) {
   1354    return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) & ~XPC_SCOPE_TAG);
   1355  }
   1356 
   1357  inline bool IsWrapperExpired() const {
   1358    return XPC_SCOPE_WORD(mMaybeScope) & XPC_WRAPPER_EXPIRED;
   1359  }
   1360 
   1361  bool HasProto() const { return !IsTaggedScope(mMaybeScope); }
   1362 
   1363  XPCWrappedNativeProto* GetProto() const {
   1364    return HasProto() ? (XPCWrappedNativeProto*)(XPC_SCOPE_WORD(mMaybeProto) &
   1365                                                 ~XPC_SCOPE_MASK)
   1366                      : nullptr;
   1367  }
   1368 
   1369  XPCWrappedNativeScope* GetScope() const {
   1370    return GetProto() ? GetProto()->GetScope()
   1371                      : (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(mMaybeScope) &
   1372                                                 ~XPC_SCOPE_MASK);
   1373  }
   1374 
   1375  nsISupports* GetIdentityObject() const { return mIdentity; }
   1376 
   1377  /**
   1378   * This getter clears the gray bit before handing out the JSObject which
   1379   * means that the object is guaranteed to be kept alive past the next CC.
   1380   */
   1381  JSObject* GetFlatJSObject() const { return mFlatJSObject; }
   1382 
   1383  /**
   1384   * This getter does not change the color of the JSObject meaning that the
   1385   * object returned is not guaranteed to be kept alive past the next CC.
   1386   *
   1387   * This should only be called if you are certain that the return value won't
   1388   * be passed into a JS API function and that it won't be stored without
   1389   * being rooted (or otherwise signaling the stored value to the CC).
   1390   */
   1391  JSObject* GetFlatJSObjectPreserveColor() const {
   1392    return mFlatJSObject.unbarrieredGetPtr();
   1393  }
   1394 
   1395  XPCNativeSet* GetSet() const { return mSet; }
   1396 
   1397  void SetSet(already_AddRefed<XPCNativeSet> set) { mSet = set; }
   1398 
   1399  static XPCWrappedNative* Get(JSObject* obj) {
   1400    MOZ_ASSERT(xpc::IsWrappedNativeReflector(obj));
   1401    return JS::GetObjectISupports<XPCWrappedNative>(obj);
   1402  }
   1403 
   1404 private:
   1405  void SetFlatJSObject(JSObject* object);
   1406  void UnsetFlatJSObject();
   1407 
   1408  inline void ExpireWrapper() {
   1409    mMaybeScope = (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(mMaybeScope) |
   1410                                           XPC_WRAPPER_EXPIRED);
   1411  }
   1412 
   1413 public:
   1414  nsIXPCScriptable* GetScriptable() const { return mScriptable; }
   1415 
   1416  nsIClassInfo* GetClassInfo() const {
   1417    return IsValid() && HasProto() ? GetProto()->GetClassInfo() : nullptr;
   1418  }
   1419 
   1420  bool HasMutatedSet() const {
   1421    return IsValid() && (!HasProto() || GetSet() != GetProto()->GetSet());
   1422  }
   1423 
   1424  XPCJSRuntime* GetRuntime() const {
   1425    XPCWrappedNativeScope* scope = GetScope();
   1426    return scope ? scope->GetRuntime() : nullptr;
   1427  }
   1428 
   1429  static nsresult WrapNewGlobal(JSContext* cx, xpcObjectHelper& nativeHelper,
   1430                                nsIPrincipal* principal,
   1431                                JS::RealmOptions& aOptions,
   1432                                XPCWrappedNative** wrappedGlobal);
   1433 
   1434  static nsresult GetNewOrUsed(JSContext* cx, xpcObjectHelper& helper,
   1435                               XPCWrappedNativeScope* Scope,
   1436                               XPCNativeInterface* Interface,
   1437                               XPCWrappedNative** wrapper);
   1438 
   1439  void FlatJSObjectFinalized();
   1440  void FlatJSObjectMoved(JSObject* obj, const JSObject* old);
   1441 
   1442  void SystemIsBeingShutDown();
   1443 
   1444  enum CallMode { CALL_METHOD, CALL_GETTER, CALL_SETTER };
   1445 
   1446  static bool CallMethod(XPCCallContext& ccx, CallMode mode = CALL_METHOD);
   1447 
   1448  static bool GetAttribute(XPCCallContext& ccx) {
   1449    return CallMethod(ccx, CALL_GETTER);
   1450  }
   1451 
   1452  static bool SetAttribute(XPCCallContext& ccx) {
   1453    return CallMethod(ccx, CALL_SETTER);
   1454  }
   1455 
   1456  XPCWrappedNativeTearOff* FindTearOff(JSContext* cx,
   1457                                       XPCNativeInterface* aInterface,
   1458                                       bool needJSObject = false,
   1459                                       nsresult* pError = nullptr);
   1460  XPCWrappedNativeTearOff* FindTearOff(JSContext* cx, const nsIID& iid);
   1461 
   1462  void Mark() const {}
   1463 
   1464  inline void TraceInside(JSTracer* trc) {
   1465    if (HasProto()) {
   1466      GetProto()->TraceSelf(trc);
   1467    }
   1468 
   1469    JSObject* obj = mFlatJSObject.unbarrieredGetPtr();
   1470    if (obj && JS_IsGlobalObject(obj)) {
   1471      xpc::TraceXPCGlobal(trc, obj);
   1472    }
   1473  }
   1474 
   1475  void TraceJS(JSTracer* trc) { TraceInside(trc); }
   1476 
   1477  void TraceSelf(JSTracer* trc) {
   1478    // If this got called, we're being kept alive by someone who really
   1479    // needs us alive and whole.  Do not let our mFlatJSObject go away.
   1480    // This is the only time we should be tracing our mFlatJSObject,
   1481    // normally somebody else is doing that.
   1482    JS::TraceEdge(trc, &mFlatJSObject, "XPCWrappedNative::mFlatJSObject");
   1483  }
   1484 
   1485  static void Trace(JSTracer* trc, JSObject* obj);
   1486 
   1487  void AutoTrace(JSTracer* trc) { TraceSelf(trc); }
   1488 
   1489  inline void SweepTearOffs();
   1490 
   1491  // Returns a string that should be freed with js_free, or nullptr on
   1492  // failure.
   1493  char* ToString(XPCWrappedNativeTearOff* to = nullptr) const;
   1494 
   1495  static nsIXPCScriptable* GatherProtoScriptable(nsIClassInfo* classInfo);
   1496 
   1497  bool HasExternalReference() const { return mRefCnt > 1; }
   1498 
   1499  void Suspect(nsCycleCollectionNoteRootCallback& cb);
   1500  void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
   1501 
   1502  // Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
   1503 protected:
   1504  XPCWrappedNative() = delete;
   1505 
   1506  // This ctor is used if this object will have a proto.
   1507  XPCWrappedNative(nsCOMPtr<nsISupports>&& aIdentity,
   1508                   XPCWrappedNativeProto* aProto);
   1509 
   1510  // This ctor is used if this object will NOT have a proto.
   1511  XPCWrappedNative(nsCOMPtr<nsISupports>&& aIdentity,
   1512                   XPCWrappedNativeScope* aScope, RefPtr<XPCNativeSet>&& aSet);
   1513 
   1514  virtual ~XPCWrappedNative();
   1515  void Destroy();
   1516 
   1517 private:
   1518  enum {
   1519    // Flags bits for mFlatJSObject:
   1520    FLAT_JS_OBJECT_VALID = js::Bit(0)
   1521  };
   1522 
   1523  bool Init(JSContext* cx, nsIXPCScriptable* scriptable);
   1524  bool FinishInit(JSContext* cx);
   1525 
   1526  bool ExtendSet(JSContext* aCx, XPCNativeInterface* aInterface);
   1527 
   1528  nsresult InitTearOff(JSContext* cx, XPCWrappedNativeTearOff* aTearOff,
   1529                       XPCNativeInterface* aInterface, bool needJSObject);
   1530 
   1531  bool InitTearOffJSObject(JSContext* cx, XPCWrappedNativeTearOff* to);
   1532 
   1533 public:
   1534  static void GatherScriptable(nsISupports* obj, nsIClassInfo* classInfo,
   1535                               nsIXPCScriptable** scrProto,
   1536                               nsIXPCScriptable** scrWrapper);
   1537 
   1538 private:
   1539  union {
   1540    XPCWrappedNativeScope* mMaybeScope;
   1541    XPCWrappedNativeProto* mMaybeProto;
   1542  };
   1543  RefPtr<XPCNativeSet> mSet;
   1544  JS::TenuredHeap<JSObject*> mFlatJSObject;
   1545  nsCOMPtr<nsIXPCScriptable> mScriptable;
   1546  XPCWrappedNativeTearOff mFirstTearOff;
   1547 };
   1548 
   1549 /***************************************************************************
   1550 ****************************************************************************
   1551 *
   1552 * Core classes for wrapped JSObject for use from native code...
   1553 *
   1554 ****************************************************************************
   1555 ***************************************************************************/
   1556 
   1557 /*************************/
   1558 // nsXPCWrappedJS is a wrapper for a single JSObject for use from native code.
   1559 // nsXPCWrappedJS objects are chained together to represent the various
   1560 // interface on the single underlying (possibly aggregate) JSObject.
   1561 
   1562 class nsXPCWrappedJS final : protected nsAutoXPTCStub,
   1563                             public nsIXPConnectWrappedJSUnmarkGray,
   1564                             public nsSupportsWeakReference,
   1565                             public mozilla::LinkedListElement<nsXPCWrappedJS> {
   1566 public:
   1567  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   1568  NS_DECL_NSISUPPORTSWEAKREFERENCE
   1569 
   1570  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(
   1571      nsXPCWrappedJS, nsIXPConnectWrappedJS)
   1572 
   1573  JSObject* GetJSObject() override;
   1574 
   1575  // This method is defined in XPCWrappedJSClass.cpp to preserve VCS blame.
   1576  NS_IMETHOD CallMethod(uint16_t methodIndex, const nsXPTMethodInfo* info,
   1577                        nsXPTCMiniVariant* nativeParams) override;
   1578 
   1579  /*
   1580   * This is rarely called directly. Instead one usually calls
   1581   * XPCConvert::JSObject2NativeInterface which will handles cases where the
   1582   * JS object is already a wrapped native or a DOM object.
   1583   */
   1584 
   1585  static nsresult GetNewOrUsed(JSContext* cx, JS::HandleObject aJSObj,
   1586                               REFNSIID aIID, nsXPCWrappedJS** wrapper);
   1587 
   1588  nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
   1589 
   1590  nsresult DebugDump(int16_t depth);
   1591 
   1592  /**
   1593   * This getter does not change the color of the JSObject meaning that the
   1594   * object returned is not guaranteed to be kept alive past the next CC.
   1595   *
   1596   * This should only be called if you are certain that the return value won't
   1597   * be passed into a JS API function and that it won't be stored without
   1598   * being rooted (or otherwise signaling the stored value to the CC).
   1599   */
   1600  JSObject* GetJSObjectPreserveColor() const { return mJSObj.unbarrieredGet(); }
   1601 
   1602  // Returns true if the wrapper chain contains references to multiple
   1603  // compartments. If the wrapper chain contains references to multiple
   1604  // compartments, then it must be registered on the XPCJSContext. Otherwise,
   1605  // it should be registered in the CompartmentPrivate for the compartment of
   1606  // the root's JS object. This will only return correct results when called
   1607  // on the root wrapper and will assert if not called on a root wrapper.
   1608  bool IsMultiCompartment() const;
   1609 
   1610  const nsXPTInterfaceInfo* GetInfo() const { return mInfo; }
   1611  REFNSIID GetIID() const { return mInfo->IID(); }
   1612  nsXPCWrappedJS* GetRootWrapper() const { return mRoot; }
   1613  nsXPCWrappedJS* GetNextWrapper() const { return mNext; }
   1614 
   1615  nsXPCWrappedJS* Find(REFNSIID aIID);
   1616  nsXPCWrappedJS* FindInherited(REFNSIID aIID);
   1617  nsXPCWrappedJS* FindOrFindInherited(REFNSIID aIID) {
   1618    nsXPCWrappedJS* wrapper = Find(aIID);
   1619    if (wrapper) {
   1620      return wrapper;
   1621    }
   1622    return FindInherited(aIID);
   1623  }
   1624 
   1625  bool IsRootWrapper() const { return mRoot == this; }
   1626  bool IsValid() const { return bool(mJSObj); }
   1627  void SystemIsBeingShutDown();
   1628 
   1629  // These two methods are used by JSObject2WrappedJSMap::FindDyingJSObjects
   1630  // to find non-rooting wrappers for dying JS objects. See the top of
   1631  // XPCWrappedJS.cpp for more details.
   1632  bool IsSubjectToFinalization() const { return IsValid() && mRefCnt == 1; }
   1633 
   1634  void UpdateObjectPointerAfterGC(JSTracer* trc) {
   1635    MOZ_ASSERT(IsRootWrapper());
   1636    JS_UpdateWeakPointerAfterGC(trc, &mJSObj);
   1637  }
   1638 
   1639  bool IsAggregatedToNative() const { return mRoot->mOuter != nullptr; }
   1640  nsISupports* GetAggregatedNativeObject() const { return mRoot->mOuter; }
   1641  void SetAggregatedNativeObject(nsISupports* aNative) {
   1642    MOZ_ASSERT(aNative);
   1643    if (mRoot->mOuter) {
   1644      MOZ_ASSERT(mRoot->mOuter == aNative,
   1645                 "Only one aggregated native can be set");
   1646      return;
   1647    }
   1648    mRoot->mOuter = aNative;
   1649  }
   1650 
   1651  // This method is defined in XPCWrappedJSClass.cpp to preserve VCS blame.
   1652  static void DebugDumpInterfaceInfo(const nsXPTInterfaceInfo* aInfo,
   1653                                     int16_t depth);
   1654 
   1655  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
   1656 
   1657  virtual ~nsXPCWrappedJS();
   1658 
   1659 protected:
   1660  nsXPCWrappedJS() = delete;
   1661  nsXPCWrappedJS(JSContext* cx, JSObject* aJSObj,
   1662                 const nsXPTInterfaceInfo* aInfo, nsXPCWrappedJS* root,
   1663                 nsresult* rv);
   1664 
   1665  bool CanSkip();
   1666  void Destroy();
   1667  void Unlink();
   1668 
   1669 private:
   1670  friend class nsIXPConnectWrappedJS;
   1671 
   1672  JS::Compartment* Compartment() const {
   1673    return JS::GetCompartment(mJSObj.unbarrieredGet());
   1674  }
   1675 
   1676  // These methods are defined in XPCWrappedJSClass.cpp to preserve VCS blame.
   1677  static const nsXPTInterfaceInfo* GetInterfaceInfo(REFNSIID aIID);
   1678 
   1679  nsresult DelegatedQueryInterface(REFNSIID aIID, void** aInstancePtr);
   1680 
   1681  static JSObject* GetRootJSObject(JSContext* cx, JSObject* aJSObj);
   1682 
   1683  static JSObject* CallQueryInterfaceOnJSObject(JSContext* cx, JSObject* jsobj,
   1684                                                JS::HandleObject scope,
   1685                                                REFNSIID aIID);
   1686 
   1687  // aObj is the nsXPCWrappedJS's object. We used this as the callee (or |this|
   1688  // if getter or setter).
   1689  // aSyntheticException, if not null, is the exception we should be using.
   1690  // If null, look for an exception on the JSContext hanging off the
   1691  // XPCCallContext.
   1692  static nsresult CheckForException(
   1693      XPCCallContext& ccx, mozilla::dom::AutoEntryScript& aes,
   1694      JS::HandleObject aObj, const char* aPropertyName,
   1695      const char* anInterfaceName,
   1696      mozilla::dom::Exception* aSyntheticException = nullptr);
   1697 
   1698  static bool GetArraySizeFromParam(const nsXPTMethodInfo* method,
   1699                                    const nsXPTType& type,
   1700                                    nsXPTCMiniVariant* params,
   1701                                    uint32_t* result);
   1702 
   1703  static bool GetInterfaceTypeFromParam(const nsXPTMethodInfo* method,
   1704                                        const nsXPTType& type,
   1705                                        nsXPTCMiniVariant* params,
   1706                                        nsID* result);
   1707 
   1708  static void CleanupOutparams(const nsXPTMethodInfo* info,
   1709                               nsXPTCMiniVariant* nativeParams, bool inOutOnly,
   1710                               uint8_t count);
   1711 
   1712  JS::Heap<JSObject*> mJSObj;
   1713  const nsXPTInterfaceInfo* const mInfo;
   1714  nsXPCWrappedJS* mRoot;  // If mRoot != this, it is an owning pointer.
   1715  nsXPCWrappedJS* mNext;
   1716  nsCOMPtr<nsISupports> mOuter;  // only set in root
   1717 };
   1718 
   1719 /***************************************************************************
   1720 ****************************************************************************
   1721 *
   1722 * All manner of utility classes follow...
   1723 *
   1724 ****************************************************************************
   1725 ***************************************************************************/
   1726 
   1727 namespace xpc {
   1728 
   1729 // A wrapper around JS iterators which presents an equivalent
   1730 // nsISimpleEnumerator interface for their contents.
   1731 class XPCWrappedJSIterator final : public nsISimpleEnumerator {
   1732 public:
   1733  NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedJSIterator)
   1734  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   1735  NS_DECL_NSISIMPLEENUMERATOR
   1736  NS_DECL_NSISIMPLEENUMERATORBASE
   1737 
   1738  explicit XPCWrappedJSIterator(nsIJSEnumerator* aEnum);
   1739 
   1740 private:
   1741  ~XPCWrappedJSIterator() = default;
   1742 
   1743  nsCOMPtr<nsIJSEnumerator> mEnum;
   1744  nsCOMPtr<nsIGlobalObject> mGlobal;
   1745  nsCOMPtr<nsISupports> mNext;
   1746  mozilla::Maybe<bool> mHasNext;
   1747 };
   1748 
   1749 }  // namespace xpc
   1750 
   1751 /***************************************************************************/
   1752 // class here just for static methods
   1753 class XPCConvert {
   1754 public:
   1755  /**
   1756   * Convert a native object into a JS::Value.
   1757   *
   1758   * @param cx the JSContext representing the global we want the value in
   1759   * @param d [out] the resulting JS::Value
   1760   * @param s the native object we're working with
   1761   * @param type the type of object that s is
   1762   * @param iid the interface of s that we want
   1763   * @param scope the default scope to put on the new JSObject's parent
   1764   *        chain
   1765   * @param pErr [out] relevant error code, if any.
   1766   */
   1767 
   1768  static bool NativeData2JS(JSContext* cx, JS::MutableHandleValue d,
   1769                            const void* s, const nsXPTType& type,
   1770                            const nsID* iid, uint32_t arrlen, nsresult* pErr);
   1771 
   1772  static bool JSData2Native(JSContext* cx, void* d, JS::HandleValue s,
   1773                            const nsXPTType& type, const nsID* iid,
   1774                            uint32_t arrlen, nsresult* pErr);
   1775 
   1776  /**
   1777   * Convert a native nsISupports into a JSObject.
   1778   *
   1779   * @param cx the JSContext representing the global we want the object in.
   1780   * @param dest [out] the resulting JSObject
   1781   * @param src the native object we're working with
   1782   * @param iid the interface of src that we want (may be null)
   1783   * @param cache the wrapper cache for src (may be null, in which case src
   1784   *              will be QI'ed to get the cache)
   1785   * @param allowNativeWrapper if true, this method may wrap the resulting
   1786   *        JSObject in an XPCNativeWrapper and return that, as needed.
   1787   * @param pErr [out] relevant error code, if any.
   1788   * @param src_is_identity optional performance hint. Set to true only
   1789   *                        if src is the identity pointer.
   1790   */
   1791  static bool NativeInterface2JSObject(JSContext* cx,
   1792                                       JS::MutableHandleValue dest,
   1793                                       xpcObjectHelper& aHelper,
   1794                                       const nsID* iid, bool allowNativeWrapper,
   1795                                       nsresult* pErr);
   1796 
   1797  static bool GetNativeInterfaceFromJSObject(void** dest, JSObject* src,
   1798                                             const nsID* iid, nsresult* pErr);
   1799  static bool JSObject2NativeInterface(JSContext* cx, void** dest,
   1800                                       JS::HandleObject src, const nsID* iid,
   1801                                       nsISupports* aOuter, nsresult* pErr);
   1802 
   1803  // Note - This return the XPCWrappedNative, rather than the native itself,
   1804  // for the WN case. You probably want UnwrapReflectorToISupports.
   1805  static bool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
   1806 
   1807  static nsresult JSValToXPCException(JSContext* cx, JS::MutableHandleValue s,
   1808                                      const char* ifaceName,
   1809                                      const char* methodName,
   1810                                      mozilla::dom::Exception** exception);
   1811 
   1812  static nsresult ConstructException(nsresult rv, const char* message,
   1813                                     const char* ifaceName,
   1814                                     const char* methodName, nsISupports* data,
   1815                                     mozilla::dom::Exception** exception,
   1816                                     JSContext* cx, JS::Value* jsExceptionPtr);
   1817 
   1818 private:
   1819  /**
   1820   * Convert a native array into a JS::Value.
   1821   *
   1822   * @param cx the JSContext we're working with and in whose global the array
   1823   *           should be created.
   1824   * @param d [out] the resulting JS::Value
   1825   * @param buf the native buffer containing input values
   1826   * @param type the type of objects in the array
   1827   * @param iid the interface of each object in the array that we want
   1828   * @param count the number of items in the array
   1829   * @param scope the default scope to put on the new JSObjects' parent chain
   1830   * @param pErr [out] relevant error code, if any.
   1831   */
   1832  static bool NativeArray2JS(JSContext* cx, JS::MutableHandleValue d,
   1833                             const void* buf, const nsXPTType& type,
   1834                             const nsID* iid, uint32_t count, nsresult* pErr);
   1835 
   1836  using ArrayAllocFixupLen = std::function<void*(uint32_t*)>;
   1837 
   1838  /**
   1839   * Convert a JS::Value into a native array.
   1840   *
   1841   * @param cx the JSContext we're working with
   1842   * @param aJSVal the JS::Value to convert
   1843   * @param aEltType the type of objects in the array
   1844   * @param aIID the interface of each object in the array
   1845   * @param pErr [out] relevant error code, if any
   1846   * @param aAllocFixupLen function called with the JS Array's length to
   1847   *                       allocate the backing buffer. This function may
   1848   *                       modify the length of array to be converted.
   1849   */
   1850  static bool JSArray2Native(JSContext* cx, JS::HandleValue aJSVal,
   1851                             const nsXPTType& aEltType, const nsIID* aIID,
   1852                             nsresult* pErr,
   1853                             const ArrayAllocFixupLen& aAllocFixupLen);
   1854 
   1855  XPCConvert() = delete;
   1856 };
   1857 
   1858 /***************************************************************************/
   1859 // code for throwing exceptions into JS
   1860 
   1861 class nsXPCException;
   1862 
   1863 class XPCThrower {
   1864 public:
   1865  static void Throw(nsresult rv, JSContext* cx);
   1866  static void Throw(nsresult rv, XPCCallContext& ccx);
   1867  static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
   1868  static void ThrowBadParam(nsresult rv, unsigned paramNum,
   1869                            XPCCallContext& ccx);
   1870  static bool SetVerbosity(bool state) {
   1871    bool old = sVerbose;
   1872    sVerbose = state;
   1873    return old;
   1874  }
   1875 
   1876  static bool CheckForPendingException(nsresult result, JSContext* cx);
   1877 
   1878 private:
   1879  static void Verbosify(XPCCallContext& ccx, char** psz, bool own);
   1880 
   1881 private:
   1882  static bool sVerbose;
   1883 };
   1884 
   1885 /***************************************************************************/
   1886 
   1887 class nsXPCException {
   1888 public:
   1889  static bool NameAndFormatForNSResult(nsresult rv, const char** name,
   1890                                       const char** format);
   1891 
   1892  static const void* IterateNSResults(nsresult* rv, const char** name,
   1893                                      const char** format, const void** iterp);
   1894 
   1895  static uint32_t GetNSResultCount();
   1896 };
   1897 
   1898 /***************************************************************************/
   1899 // 'Components' object implementation.
   1900 
   1901 class nsXPCComponents final : public nsIXPCComponents {
   1902 public:
   1903  NS_DECL_ISUPPORTS
   1904  NS_DECL_NSIXPCCOMPONENTS
   1905 
   1906 public:
   1907  void SystemIsBeingShutDown() { ClearMembers(); }
   1908 
   1909  XPCWrappedNativeScope* GetScope() { return mScope; }
   1910 
   1911 protected:
   1912  ~nsXPCComponents();
   1913 
   1914  explicit nsXPCComponents(XPCWrappedNativeScope* aScope);
   1915  void ClearMembers();
   1916 
   1917  XPCWrappedNativeScope* mScope;
   1918 
   1919  RefPtr<nsXPCComponents_Interfaces> mInterfaces;
   1920  RefPtr<nsXPCComponents_Results> mResults;
   1921  RefPtr<nsXPCComponents_Classes> mClasses;
   1922  RefPtr<nsXPCComponents_ID> mID;
   1923  RefPtr<nsXPCComponents_Exception> mException;
   1924  RefPtr<nsXPCComponents_Constructor> mConstructor;
   1925  RefPtr<nsXPCComponents_Utils> mUtils;
   1926 
   1927  friend class XPCWrappedNativeScope;
   1928 };
   1929 
   1930 /******************************************************************************
   1931 * Handles pre/post script processing.
   1932 */
   1933 class MOZ_RAII AutoScriptEvaluate {
   1934 public:
   1935  /**
   1936   * Saves the JSContext as well as initializing our state
   1937   * @param cx The JSContext, this can be null, we don't do anything then
   1938   */
   1939  explicit AutoScriptEvaluate(JSContext* cx)
   1940      : mJSContext(cx), mEvaluated(false) {}
   1941 
   1942  /**
   1943   * Does the pre script evaluation.
   1944   * This function should only be called once, and will assert if called
   1945   * more than once
   1946   */
   1947 
   1948  bool StartEvaluating(JS::HandleObject scope);
   1949 
   1950  /**
   1951   * Does the post script evaluation.
   1952   */
   1953  ~AutoScriptEvaluate();
   1954 
   1955 private:
   1956  JSContext* mJSContext;
   1957  mozilla::Maybe<JS::AutoSaveExceptionState> mState;
   1958  bool mEvaluated;
   1959  mozilla::Maybe<JSAutoRealm> mAutoRealm;
   1960 
   1961  // No copying or assignment allowed
   1962  AutoScriptEvaluate(const AutoScriptEvaluate&) = delete;
   1963  AutoScriptEvaluate& operator=(const AutoScriptEvaluate&) = delete;
   1964 };
   1965 
   1966 /***************************************************************************/
   1967 class MOZ_RAII AutoResolveName {
   1968 public:
   1969  AutoResolveName(XPCCallContext& ccx, JS::HandleId name)
   1970      : mContext(ccx.GetContext()),
   1971        mOld(ccx, mContext->SetResolveName(name))
   1972 #ifdef DEBUG
   1973        ,
   1974        mCheck(ccx, name)
   1975 #endif
   1976  {
   1977  }
   1978 
   1979  ~AutoResolveName() {
   1980    mozilla::DebugOnly<jsid> old = mContext->SetResolveName(mOld);
   1981    MOZ_ASSERT(old == mCheck, "Bad Nesting!");
   1982  }
   1983 
   1984 private:
   1985  XPCJSContext* mContext;
   1986  JS::RootedId mOld;
   1987 #ifdef DEBUG
   1988  JS::RootedId mCheck;
   1989 #endif
   1990 };
   1991 
   1992 /***************************************************************************/
   1993 // AutoMarkingPtr is the base class for the various AutoMarking pointer types
   1994 // below. This system allows us to temporarily protect instances of our garbage
   1995 // collected types after they are constructed but before they are safely
   1996 // attached to other rooted objects.
   1997 // This base class has pure virtual support for marking.
   1998 
   1999 class AutoMarkingPtr {
   2000 public:
   2001  explicit AutoMarkingPtr(JSContext* cx) {
   2002    mRoot = XPCJSContext::Get()->GetAutoRootsAdr();
   2003    mNext = *mRoot;
   2004    *mRoot = this;
   2005  }
   2006 
   2007  virtual ~AutoMarkingPtr() {
   2008    if (mRoot) {
   2009      MOZ_ASSERT(*mRoot == this);
   2010      *mRoot = mNext;
   2011    }
   2012  }
   2013 
   2014  void TraceJSAll(JSTracer* trc) {
   2015    for (AutoMarkingPtr* cur = this; cur; cur = cur->mNext) {
   2016      cur->TraceJS(trc);
   2017    }
   2018  }
   2019 
   2020  void MarkAfterJSFinalizeAll() {
   2021    for (AutoMarkingPtr* cur = this; cur; cur = cur->mNext) {
   2022      cur->MarkAfterJSFinalize();
   2023    }
   2024  }
   2025 
   2026 protected:
   2027  virtual void TraceJS(JSTracer* trc) = 0;
   2028  virtual void MarkAfterJSFinalize() = 0;
   2029 
   2030 private:
   2031  AutoMarkingPtr** mRoot;
   2032  AutoMarkingPtr* mNext;
   2033 };
   2034 
   2035 template <class T>
   2036 class TypedAutoMarkingPtr : public AutoMarkingPtr {
   2037 public:
   2038  explicit TypedAutoMarkingPtr(JSContext* cx)
   2039      : AutoMarkingPtr(cx), mPtr(nullptr) {}
   2040  TypedAutoMarkingPtr(JSContext* cx, T* ptr) : AutoMarkingPtr(cx), mPtr(ptr) {}
   2041 
   2042  T* get() const { return mPtr; }
   2043  operator T*() const { return mPtr; }
   2044  T* operator->() const { return mPtr; }
   2045 
   2046  TypedAutoMarkingPtr<T>& operator=(T* ptr) {
   2047    mPtr = ptr;
   2048    return *this;
   2049  }
   2050 
   2051 protected:
   2052  virtual void TraceJS(JSTracer* trc) override {
   2053    if (mPtr) {
   2054      mPtr->TraceJS(trc);
   2055      mPtr->AutoTrace(trc);
   2056    }
   2057  }
   2058 
   2059  virtual void MarkAfterJSFinalize() override {
   2060    if (mPtr) {
   2061      mPtr->Mark();
   2062    }
   2063  }
   2064 
   2065 private:
   2066  T* mPtr;
   2067 };
   2068 
   2069 using AutoMarkingWrappedNativePtr = TypedAutoMarkingPtr<XPCWrappedNative>;
   2070 using AutoMarkingWrappedNativeTearOffPtr =
   2071    TypedAutoMarkingPtr<XPCWrappedNativeTearOff>;
   2072 using AutoMarkingWrappedNativeProtoPtr =
   2073    TypedAutoMarkingPtr<XPCWrappedNativeProto>;
   2074 
   2075 /***************************************************************************/
   2076 // Definitions in XPCVariant.cpp.
   2077 
   2078 // {1809FD50-91E8-11d5-90F9-0010A4E73D9A}
   2079 #define XPCVARIANT_IID \
   2080  {0x1809fd50, 0x91e8, 0x11d5, {0x90, 0xf9, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a}}
   2081 
   2082 // {DC524540-487E-4501-9AC7-AAA784B17C1C}
   2083 #define XPCVARIANT_CID \
   2084  {0xdc524540, 0x487e, 0x4501, {0x9a, 0xc7, 0xaa, 0xa7, 0x84, 0xb1, 0x7c, 0x1c}}
   2085 
   2086 class XPCVariant : public nsIVariant {
   2087 public:
   2088  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   2089  NS_DECL_NSIVARIANT
   2090  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(XPCVariant)
   2091 
   2092  // If this class ever implements nsIWritableVariant, take special care with
   2093  // the case when mJSVal is JSVAL_STRING, since we don't own the data in
   2094  // that case.
   2095 
   2096  // We #define and iid so that out module local code can use QI to detect
   2097  // if a given nsIVariant is in fact an XPCVariant.
   2098  NS_INLINE_DECL_STATIC_IID(XPCVARIANT_IID)
   2099 
   2100  static already_AddRefed<XPCVariant> newVariant(JSContext* cx,
   2101                                                 const JS::Value& aJSVal);
   2102 
   2103  /**
   2104   * This getter clears the gray bit before handing out the Value if the Value
   2105   * represents a JSObject. That means that the object is guaranteed to be
   2106   * kept alive past the next CC.
   2107   */
   2108  JS::Value GetJSVal() const { return mJSVal; }
   2109 
   2110 protected:
   2111  /**
   2112   * This getter does not change the color of the Value (if it represents a
   2113   * JSObject) meaning that the value returned is not guaranteed to be kept
   2114   * alive past the next CC.
   2115   *
   2116   * This should only be called if you are certain that the return value won't
   2117   * be passed into a JS API function and that it won't be stored without
   2118   * being rooted (or otherwise signaling the stored value to the CC).
   2119   */
   2120  JS::Value GetJSValPreserveColor() const { return mJSVal.unbarrieredGet(); }
   2121 
   2122  XPCVariant(JSContext* cx, const JS::Value& aJSVal);
   2123 
   2124 public:
   2125  /**
   2126   * Convert a variant into a JS::Value.
   2127   *
   2128   * @param cx the context for the whole procedure
   2129   * @param variant the variant to convert
   2130   * @param scope the default scope to put on the new JSObject's parent chain
   2131   * @param pErr [out] relevant error code, if any.
   2132   * @param pJSVal [out] the resulting jsval.
   2133   */
   2134  static bool VariantDataToJS(JSContext* cx, nsIVariant* variant,
   2135                              nsresult* pErr, JS::MutableHandleValue pJSVal);
   2136 
   2137 protected:
   2138  virtual ~XPCVariant();
   2139 
   2140  bool InitializeData(JSContext* cx);
   2141 
   2142  void Cleanup();
   2143 
   2144  nsDiscriminatedUnion mData;
   2145  JS::Heap<JS::Value> mJSVal;
   2146  bool mReturnRawObject;
   2147 };
   2148 
   2149 /***************************************************************************/
   2150 // Utilities
   2151 
   2152 inline JSContext* xpc_GetSafeJSContext() {
   2153  return XPCJSContext::Get()->Context();
   2154 }
   2155 
   2156 namespace xpc {
   2157 
   2158 // JSNatives to expose atob and btoa in various non-DOM XPConnect scopes.
   2159 bool Atob(JSContext* cx, unsigned argc, JS::Value* vp);
   2160 
   2161 bool Btoa(JSContext* cx, unsigned argc, JS::Value* vp);
   2162 
   2163 // Helper function that creates a JSFunction that wraps a native function that
   2164 // forwards the call to the original 'callable'.
   2165 class FunctionForwarderOptions;
   2166 bool NewFunctionForwarder(JSContext* cx, JS::HandleId id,
   2167                          JS::HandleObject callable,
   2168                          FunctionForwarderOptions& options,
   2169                          JS::MutableHandleValue vp);
   2170 
   2171 // Old fashioned xpc error reporter. Try to use JS_ReportError instead.
   2172 nsresult ThrowAndFail(nsresult errNum, JSContext* cx, bool* retval);
   2173 
   2174 struct GlobalProperties {
   2175  GlobalProperties() { mozilla::PodZero(this); }
   2176  bool Parse(JSContext* cx, JS::HandleObject obj);
   2177  bool DefineInXPCComponents(JSContext* cx, JS::HandleObject obj);
   2178  bool DefineInSandbox(JSContext* cx, JS::HandleObject obj);
   2179 
   2180  // Interface objects we can expose.
   2181  bool AbortController : 1;
   2182  bool Blob : 1;
   2183  bool ChromeUtils : 1;
   2184  bool CSS : 1;
   2185  bool CSSPositionTryDescriptors : 1;
   2186  bool CSSRule : 1;
   2187  bool CustomStateSet : 1;
   2188  bool Directory : 1;
   2189  bool Document : 1;
   2190  bool DOMException : 1;
   2191  bool DOMParser : 1;
   2192  bool DOMTokenList : 1;
   2193  bool Element : 1;
   2194  bool Event : 1;
   2195  bool File : 1;
   2196  bool FileReader : 1;
   2197  bool FormData : 1;
   2198  bool Headers : 1;
   2199  bool IOUtils : 1;
   2200  bool InspectorCSSParser : 1;
   2201  bool InspectorUtils : 1;
   2202  bool MessageChannel : 1;
   2203  bool MIDIInputMap : 1;
   2204  bool MIDIOutputMap : 1;
   2205  bool Node : 1;
   2206  bool NodeFilter : 1;
   2207  bool PathUtils : 1;
   2208  bool Performance : 1;
   2209  bool PromiseDebugging : 1;
   2210  bool Range : 1;
   2211  bool Selection : 1;
   2212  bool TextDecoder : 1;
   2213  bool TextEncoder : 1;
   2214  bool TrustedHTML : 1;
   2215  bool TrustedScript : 1;
   2216  bool TrustedScriptURL : 1;
   2217  bool URL : 1;
   2218  bool URLSearchParams : 1;
   2219  bool XMLHttpRequest : 1;
   2220  bool WebSocket : 1;
   2221  bool Window : 1;
   2222  bool XMLSerializer : 1;
   2223  bool ReadableStream : 1;
   2224 
   2225  // Ad-hoc property names we implement.
   2226  bool atob : 1;
   2227  bool btoa : 1;
   2228  bool caches : 1;
   2229  bool crypto : 1;
   2230  bool fetch : 1;
   2231  bool storage : 1;
   2232  bool structuredClone : 1;
   2233  bool locks : 1;
   2234  bool indexedDB : 1;
   2235  bool isSecureContext : 1;
   2236  bool rtcIdentityProvider : 1;
   2237 
   2238 private:
   2239  bool Define(JSContext* cx, JS::HandleObject obj);
   2240 };
   2241 
   2242 // Infallible.
   2243 already_AddRefed<nsIXPCComponents_utils_Sandbox> NewSandboxConstructor();
   2244 
   2245 // Returns true if class of 'obj' is SandboxClass.
   2246 bool IsSandbox(JSObject* obj);
   2247 
   2248 class MOZ_STACK_CLASS OptionsBase {
   2249 public:
   2250  explicit OptionsBase(JSContext* cx = xpc_GetSafeJSContext(),
   2251                       JSObject* options = nullptr)
   2252      : mCx(cx), mObject(cx, options) {}
   2253 
   2254  virtual bool Parse() = 0;
   2255 
   2256 protected:
   2257  bool ParseValue(const char* name, JS::MutableHandleValue prop,
   2258                  bool* found = nullptr);
   2259  bool ParseBoolean(const char* name, bool* prop);
   2260  bool ParseObject(const char* name, JS::MutableHandleObject prop);
   2261  bool ParseJSString(const char* name, JS::MutableHandleString prop);
   2262  bool ParseString(const char* name, nsCString& prop);
   2263  bool ParseString(const char* name, nsString& prop);
   2264  bool ParseOptionalString(const char* name, mozilla::Maybe<nsString>& prop);
   2265  bool ParseId(const char* name, JS::MutableHandleId id);
   2266  bool ParseUInt32(const char* name, uint32_t* prop);
   2267 
   2268  JSContext* mCx;
   2269  JS::RootedObject mObject;
   2270 };
   2271 
   2272 class MOZ_STACK_CLASS SandboxOptions : public OptionsBase {
   2273 public:
   2274  explicit SandboxOptions(JSContext* cx = xpc_GetSafeJSContext(),
   2275                          JSObject* options = nullptr)
   2276      : OptionsBase(cx, options),
   2277        wantXrays(true),
   2278        allowWaivers(true),
   2279        wantComponents(true),
   2280        wantExportHelpers(false),
   2281        isWebExtensionContentScript(false),
   2282        proto(cx),
   2283        sameZoneAs(cx),
   2284        forceSecureContext(false),
   2285        freshCompartment(false),
   2286        freshZone(false),
   2287        isUAWidgetScope(false),
   2288        invisibleToDebugger(false),
   2289        discardSource(false),
   2290        metadata(cx),
   2291        userContextId(0),
   2292        originAttributes(cx),
   2293        alwaysUseFdlibm(false) {}
   2294 
   2295  virtual bool Parse() override;
   2296 
   2297  bool wantXrays;
   2298  bool allowWaivers;
   2299  bool wantComponents;
   2300  bool wantExportHelpers;
   2301  bool isWebExtensionContentScript;
   2302  JS::RootedObject proto;
   2303  mozilla::Maybe<nsString> sandboxContentSecurityPolicy;
   2304  nsCString sandboxName;
   2305  JS::RootedObject sameZoneAs;
   2306  bool forceSecureContext;
   2307  bool freshCompartment;
   2308  bool freshZone;
   2309  bool isUAWidgetScope;
   2310  bool invisibleToDebugger;
   2311  bool discardSource;
   2312  GlobalProperties globalProperties;
   2313  JS::RootedValue metadata;
   2314  uint32_t userContextId;
   2315  JS::RootedObject originAttributes;
   2316  bool alwaysUseFdlibm;
   2317 
   2318 protected:
   2319  bool ParseGlobalProperties();
   2320 };
   2321 
   2322 class MOZ_STACK_CLASS CreateObjectInOptions : public OptionsBase {
   2323 public:
   2324  explicit CreateObjectInOptions(JSContext* cx = xpc_GetSafeJSContext(),
   2325                                 JSObject* options = nullptr)
   2326      : OptionsBase(cx, options), defineAs(cx, JS::PropertyKey::Void()) {}
   2327 
   2328  virtual bool Parse() override { return ParseId("defineAs", &defineAs); }
   2329 
   2330  JS::RootedId defineAs;
   2331 };
   2332 
   2333 class MOZ_STACK_CLASS ExportFunctionOptions : public OptionsBase {
   2334 public:
   2335  explicit ExportFunctionOptions(JSContext* cx = xpc_GetSafeJSContext(),
   2336                                 JSObject* options = nullptr)
   2337      : OptionsBase(cx, options),
   2338        defineAs(cx, JS::PropertyKey::Void()),
   2339        allowCrossOriginArguments(false) {}
   2340 
   2341  virtual bool Parse() override {
   2342    return ParseId("defineAs", &defineAs) &&
   2343           ParseBoolean("allowCrossOriginArguments",
   2344                        &allowCrossOriginArguments);
   2345  }
   2346 
   2347  JS::RootedId defineAs;
   2348  bool allowCrossOriginArguments;
   2349 };
   2350 
   2351 class MOZ_STACK_CLASS FunctionForwarderOptions : public OptionsBase {
   2352 public:
   2353  explicit FunctionForwarderOptions(JSContext* cx = xpc_GetSafeJSContext(),
   2354                                    JSObject* options = nullptr)
   2355      : OptionsBase(cx, options), allowCrossOriginArguments(false) {}
   2356 
   2357  JSObject* ToJSObject(JSContext* cx) {
   2358    JS::RootedObject obj(cx, JS_NewObjectWithGivenProto(cx, nullptr, nullptr));
   2359    if (!obj) {
   2360      return nullptr;
   2361    }
   2362 
   2363    JS::RootedValue val(cx);
   2364    unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT;
   2365    val = JS::BooleanValue(allowCrossOriginArguments);
   2366    if (!JS_DefineProperty(cx, obj, "allowCrossOriginArguments", val, attrs)) {
   2367      return nullptr;
   2368    }
   2369 
   2370    return obj;
   2371  }
   2372 
   2373  virtual bool Parse() override {
   2374    return ParseBoolean("allowCrossOriginArguments",
   2375                        &allowCrossOriginArguments);
   2376  }
   2377 
   2378  bool allowCrossOriginArguments;
   2379 };
   2380 
   2381 class MOZ_STACK_CLASS StackScopedCloneOptions : public OptionsBase {
   2382 public:
   2383  explicit StackScopedCloneOptions(JSContext* cx = xpc_GetSafeJSContext(),
   2384                                   JSObject* options = nullptr)
   2385      : OptionsBase(cx, options),
   2386        wrapReflectors(false),
   2387        cloneFunctions(false),
   2388        deepFreeze(false) {}
   2389 
   2390  virtual bool Parse() override {
   2391    return ParseBoolean("wrapReflectors", &wrapReflectors) &&
   2392           ParseBoolean("cloneFunctions", &cloneFunctions) &&
   2393           ParseBoolean("deepFreeze", &deepFreeze);
   2394  }
   2395 
   2396  // When a reflector is encountered, wrap it rather than aborting the clone.
   2397  bool wrapReflectors;
   2398 
   2399  // When a function is encountered, clone it (exportFunction-style) rather than
   2400  // aborting the clone.
   2401  bool cloneFunctions;
   2402 
   2403  // If true, the resulting object is deep-frozen after being cloned.
   2404  bool deepFreeze;
   2405 };
   2406 
   2407 JSObject* CreateGlobalObject(JSContext* cx, const JSClass* clasp,
   2408                             nsIPrincipal* principal,
   2409                             JS::RealmOptions& aOptions);
   2410 
   2411 // Finish initializing an already-created, not-yet-exposed-to-script global
   2412 // object.  This will attach a Components object (if necessary) and call
   2413 // |JS_FireOnNewGlobalObject| (if necessary).
   2414 //
   2415 // If you must modify compartment options, see InitGlobalObjectOptions above.
   2416 bool InitGlobalObject(JSContext* aJSContext, JS::Handle<JSObject*> aGlobal,
   2417                      uint32_t aFlags);
   2418 
   2419 // Helper for creating a sandbox object to use for evaluating
   2420 // untrusted code completely separated from all other code in the
   2421 // system using EvalInSandbox(). Takes the JSContext on which to
   2422 // do setup etc on, puts the sandbox object in *vp (which must be
   2423 // rooted by the caller), and uses the principal that's either
   2424 // directly passed in prinOrSop or indirectly as an
   2425 // nsIScriptObjectPrincipal holding the principal. If no principal is
   2426 // reachable through prinOrSop, a new null principal will be created
   2427 // and used.
   2428 nsresult CreateSandboxObject(JSContext* cx, JS::MutableHandleValue vp,
   2429                             nsISupports* prinOrSop,
   2430                             xpc::SandboxOptions& options);
   2431 // Helper for evaluating scripts in a sandbox object created with
   2432 // CreateSandboxObject(). The caller is responsible of ensuring
   2433 // that *rval doesn't get collected during the call or usage after the
   2434 // call. This helper will use filename and lineNo for error reporting,
   2435 // and if no filename is provided it will use the codebase from the
   2436 // principal and line number 1 as a fallback.
   2437 nsresult EvalInSandbox(JSContext* cx, JS::HandleObject sandbox,
   2438                       const nsAString& source, const nsACString& filename,
   2439                       int32_t lineNo, bool enforceFilenameRestrictions,
   2440                       JS::MutableHandleValue rval);
   2441 
   2442 // Helper for retrieving metadata stored in a reserved slot. The metadata
   2443 // is set during the sandbox creation using the "metadata" option.
   2444 nsresult GetSandboxMetadata(JSContext* cx, JS::HandleObject sandboxArg,
   2445                            JS::MutableHandleValue rval);
   2446 
   2447 [[nodiscard]] nsresult SetSandboxMetadata(JSContext* cx,
   2448                                          JS::HandleObject sandboxArg,
   2449                                          JS::HandleValue metadata);
   2450 
   2451 [[nodiscard]] nsresult SetSandboxLocaleOverride(JSContext* cx,
   2452                                                JS::HandleObject sandboxArg,
   2453                                                const char* locale);
   2454 
   2455 [[nodiscard]] nsresult SetSandboxTimezoneOverride(JSContext* cx,
   2456                                                  JS::HandleObject sandboxArg,
   2457                                                  const char* timezone);
   2458 
   2459 bool CreateObjectIn(JSContext* cx, JS::HandleValue vobj,
   2460                    CreateObjectInOptions& options,
   2461                    JS::MutableHandleValue rval);
   2462 
   2463 bool EvalInWindow(JSContext* cx, const nsAString& source,
   2464                  JS::HandleObject scope, JS::MutableHandleValue rval);
   2465 
   2466 bool ExportFunction(JSContext* cx, JS::HandleValue vscope,
   2467                    JS::HandleValue vfunction, JS::HandleValue voptions,
   2468                    JS::MutableHandleValue rval);
   2469 
   2470 bool CloneInto(JSContext* cx, JS::HandleValue vobj, JS::HandleValue vscope,
   2471               JS::HandleValue voptions, JS::MutableHandleValue rval);
   2472 
   2473 bool StackScopedClone(JSContext* cx, StackScopedCloneOptions& options,
   2474                      JS::HandleObject sourceScope, JS::MutableHandleValue val);
   2475 
   2476 } /* namespace xpc */
   2477 
   2478 /***************************************************************************/
   2479 // Inlined utilities.
   2480 
   2481 inline bool xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj,
   2482                                     jsid id);
   2483 
   2484 inline jsid GetJSIDByIndex(JSContext* cx, unsigned index);
   2485 
   2486 namespace xpc {
   2487 
   2488 enum WrapperDenialType {
   2489  WrapperDenialForXray = 0,
   2490  WrapperDenialForCOW,
   2491  WrapperDenialTypeCount
   2492 };
   2493 bool ReportWrapperDenial(JSContext* cx, JS::HandleId id, WrapperDenialType type,
   2494                         const char* reason);
   2495 
   2496 class CompartmentOriginInfo {
   2497 public:
   2498  CompartmentOriginInfo(const CompartmentOriginInfo&) = delete;
   2499 
   2500  CompartmentOriginInfo(mozilla::BasePrincipal* aOrigin,
   2501                        const mozilla::SiteIdentifier& aSite)
   2502      : mOrigin(aOrigin), mSite(aSite) {
   2503    MOZ_ASSERT(aOrigin);
   2504    MOZ_ASSERT(aSite.IsInitialized());
   2505  }
   2506 
   2507  bool IsSameOrigin(nsIPrincipal* aOther) const;
   2508 
   2509  // Does the principal of compartment a subsume the principal of compartment b?
   2510  static bool Subsumes(JS::Compartment* aCompA, JS::Compartment* aCompB);
   2511  static bool SubsumesIgnoringFPD(JS::Compartment* aCompA,
   2512                                  JS::Compartment* aCompB);
   2513 
   2514  bool MightBeWebContent() const;
   2515 
   2516  // Note: this principal must not be used for subsumes/equality checks
   2517  // considering document.domain. See mOrigin.
   2518  mozilla::BasePrincipal* GetPrincipalIgnoringDocumentDomain() const {
   2519    return mOrigin;
   2520  }
   2521 
   2522  const mozilla::SiteIdentifier& SiteRef() const { return mSite; }
   2523 
   2524  bool HasChangedDocumentDomain() const { return mChangedDocumentDomain; }
   2525  void SetChangedDocumentDomain() { mChangedDocumentDomain = true; }
   2526 
   2527 private:
   2528  // All globals in the compartment must have this origin. Note that
   2529  // individual globals and principals can have their domain changed via
   2530  // document.domain, so this principal must not be used for things like
   2531  // subsumesConsideringDomain or equalsConsideringDomain. Use the realm's
   2532  // principal for that.
   2533  RefPtr<mozilla::BasePrincipal> mOrigin;
   2534 
   2535  // In addition to the origin we also store the SiteIdentifier. When realms
   2536  // in different compartments can become same-origin (via document.domain),
   2537  // these compartments must have equal SiteIdentifiers. (This is derived from
   2538  // mOrigin but we cache it here for performance reasons.)
   2539  mozilla::SiteIdentifier mSite;
   2540 
   2541  // True if any global in this compartment mutated document.domain.
   2542  bool mChangedDocumentDomain = false;
   2543 };
   2544 
   2545 // The CompartmentPrivate contains XPConnect-specific stuff related to each JS
   2546 // compartment. Since compartments are trust domains, this means mostly
   2547 // information needed to select the right security policy for cross-compartment
   2548 // wrappers.
   2549 class CompartmentPrivate {
   2550  CompartmentPrivate() = delete;
   2551  CompartmentPrivate(const CompartmentPrivate&) = delete;
   2552 
   2553 public:
   2554  CompartmentPrivate(JS::Compartment* c,
   2555                     mozilla::UniquePtr<XPCWrappedNativeScope> scope,
   2556                     mozilla::BasePrincipal* origin,
   2557                     const mozilla::SiteIdentifier& site);
   2558 
   2559  ~CompartmentPrivate();
   2560 
   2561  static CompartmentPrivate* Get(JS::Compartment* compartment) {
   2562    MOZ_ASSERT(compartment);
   2563    void* priv = JS_GetCompartmentPrivate(compartment);
   2564    return static_cast<CompartmentPrivate*>(priv);
   2565  }
   2566 
   2567  static CompartmentPrivate* Get(JS::Realm* realm) {
   2568    MOZ_ASSERT(realm);
   2569    JS::Compartment* compartment = JS::GetCompartmentForRealm(realm);
   2570    return Get(compartment);
   2571  }
   2572 
   2573  static CompartmentPrivate* Get(JSObject* object) {
   2574    JS::Compartment* compartment = JS::GetCompartment(object);
   2575    return Get(compartment);
   2576  }
   2577 
   2578  bool CanShareCompartmentWith(nsIPrincipal* principal) {
   2579    // Only share if we're same-origin with the principal.
   2580    if (!originInfo.IsSameOrigin(principal)) {
   2581      return false;
   2582    }
   2583 
   2584    // Don't share if we have any weird state set.
   2585    return !wantXrays && !isWebExtensionContentScript &&
   2586           !isUAWidgetCompartment && mScope->XBLScopeStateMatches(principal);
   2587  }
   2588 
   2589  CompartmentOriginInfo originInfo;
   2590 
   2591  // Controls whether this compartment gets Xrays to same-origin. This behavior
   2592  // is deprecated, but is still the default for sandboxes for compatibity
   2593  // reasons.
   2594  bool wantXrays;
   2595 
   2596  // Controls whether this compartment is allowed to waive Xrays to content
   2597  // that it subsumes. This should generally be true, except in cases where we
   2598  // want to prevent code from depending on Xray Waivers (which might make it
   2599  // more portable to other browser architectures).
   2600  bool allowWaivers;
   2601 
   2602  // This compartment corresponds to a WebExtension content script, and
   2603  // receives various bits of special compatibility behavior.
   2604  bool isWebExtensionContentScript;
   2605 
   2606  // True if this compartment is a UA widget compartment.
   2607  bool isUAWidgetCompartment;
   2608 
   2609  // See CompartmentHasExclusiveExpandos.
   2610  bool hasExclusiveExpandos;
   2611 
   2612  // Whether SystemIsBeingShutDown has been called on this compartment.
   2613  bool wasShutdown;
   2614 
   2615  JSObject2WrappedJSMap* GetWrappedJSMap() const { return mWrappedJSMap.get(); }
   2616  void UpdateWeakPointersAfterGC(JSTracer* trc);
   2617 
   2618  void SystemIsBeingShutDown();
   2619 
   2620  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
   2621 
   2622  struct MapEntryGCPolicy {
   2623    static bool traceWeak(JSTracer* trc, const void* /* unused */,
   2624                          JS::Heap<JSObject*>* value) {
   2625      return JS::GCPolicy<JS::Heap<JSObject*>>::traceWeak(trc, value);
   2626    }
   2627  };
   2628 
   2629  typedef JS::GCHashMap<const void*, JS::Heap<JSObject*>,
   2630                        mozilla::PointerHasher<const void*>,
   2631                        js::SystemAllocPolicy, MapEntryGCPolicy>
   2632      RemoteProxyMap;
   2633  RemoteProxyMap& GetRemoteProxyMap() { return mRemoteProxies; }
   2634 
   2635  XPCWrappedNativeScope* GetScope() { return mScope.get(); }
   2636 
   2637 private:
   2638  mozilla::UniquePtr<JSObject2WrappedJSMap> mWrappedJSMap;
   2639 
   2640  // Cache holding proxy objects for Window objects (and their Location object)
   2641  // that are loaded in a different process.
   2642  RemoteProxyMap mRemoteProxies;
   2643 
   2644  // Our XPCWrappedNativeScope.
   2645  mozilla::UniquePtr<XPCWrappedNativeScope> mScope;
   2646 };
   2647 
   2648 inline void CrashIfNotInAutomation() { MOZ_RELEASE_ASSERT(IsInAutomation()); }
   2649 
   2650 // XPConnect-specific data associated with each JavaScript realm. Per-Window
   2651 // settings live here; security-wrapper-related settings live in the
   2652 // CompartmentPrivate.
   2653 //
   2654 // Following the ECMAScript spec, a realm contains a global (e.g. an inner
   2655 // Window) and its associated scripts and objects; a compartment may contain
   2656 // several same-origin realms.
   2657 class RealmPrivate {
   2658  RealmPrivate() = delete;
   2659  RealmPrivate(const RealmPrivate&) = delete;
   2660 
   2661 public:
   2662  enum LocationHint { LocationHintRegular, LocationHintAddon };
   2663 
   2664  explicit RealmPrivate(JS::Realm* realm);
   2665 
   2666  // Creates the RealmPrivate and CompartmentPrivate (if needed) for a new
   2667  // global.
   2668  static void Init(JS::HandleObject aGlobal,
   2669                   const mozilla::SiteIdentifier& aSite);
   2670 
   2671  static RealmPrivate* Get(JS::Realm* realm) {
   2672    MOZ_ASSERT(realm);
   2673    void* priv = JS::GetRealmPrivate(realm);
   2674    return static_cast<RealmPrivate*>(priv);
   2675  }
   2676 
   2677  // Get the RealmPrivate for a given object.  `object` must not be a
   2678  // cross-compartment wrapper, as CCWs aren't dedicated to a particular
   2679  // realm.
   2680  static RealmPrivate* Get(JSObject* object) {
   2681    JS::Realm* realm = JS::GetObjectRealmOrNull(object);
   2682    return Get(realm);
   2683  }
   2684 
   2685  // The scriptability of this realm.
   2686  Scriptability scriptability;
   2687 
   2688  // Whether we've emitted a warning about a property that was filtered out
   2689  // by a security wrapper. See XrayWrapper.cpp.
   2690  bool wrapperDenialWarnings[WrapperDenialTypeCount];
   2691 
   2692  const nsACString& GetLocation() {
   2693    if (location.IsEmpty() && locationURI) {
   2694      nsCOMPtr<nsIXPConnectWrappedJS> jsLocationURI =
   2695          do_QueryInterface(locationURI);
   2696      if (jsLocationURI) {
   2697        // We cannot call into JS-implemented nsIURI objects, because
   2698        // we are iterating over the JS heap at this point.
   2699        location = "<JS-implemented nsIURI location>"_ns;
   2700      } else if (NS_FAILED(locationURI->GetSpec(location))) {
   2701        location = "<unknown location>"_ns;
   2702      }
   2703    }
   2704    return location;
   2705  }
   2706  bool GetLocationURI(LocationHint aLocationHint, nsIURI** aURI) {
   2707    if (locationURI) {
   2708      nsCOMPtr<nsIURI> rval = locationURI;
   2709      rval.forget(aURI);
   2710      return true;
   2711    }
   2712    return TryParseLocationURI(aLocationHint, aURI);
   2713  }
   2714  bool GetLocationURI(nsIURI** aURI) {
   2715    return GetLocationURI(LocationHintRegular, aURI);
   2716  }
   2717 
   2718  void SetLocation(const nsACString& aLocation) {
   2719    if (aLocation.IsEmpty()) {
   2720      return;
   2721    }
   2722    if (!location.IsEmpty() || locationURI) {
   2723      return;
   2724    }
   2725    location = aLocation;
   2726  }
   2727  void SetLocationURI(nsIURI* aLocationURI) {
   2728    if (!aLocationURI) {
   2729      return;
   2730    }
   2731    if (locationURI) {
   2732      return;
   2733    }
   2734    locationURI = aLocationURI;
   2735  }
   2736 
   2737  // JSStackFrames are tracked on a per-realm basis so they
   2738  // can be cleared when the associated window goes away.
   2739  void RegisterStackFrame(JSStackFrameBase* aFrame);
   2740  void UnregisterStackFrame(JSStackFrameBase* aFrame);
   2741  void NukeJSStackFrames();
   2742 
   2743 private:
   2744  nsCString location;
   2745  nsCOMPtr<nsIURI> locationURI;
   2746 
   2747  bool TryParseLocationURI(LocationHint aType, nsIURI** aURI);
   2748 
   2749  nsTHashtable<nsPtrHashKey<JSStackFrameBase>> mJSStackFrames;
   2750 };
   2751 
   2752 inline XPCWrappedNativeScope* ObjectScope(JSObject* obj) {
   2753  return CompartmentPrivate::Get(obj)->GetScope();
   2754 }
   2755 
   2756 JSObject* NewOutObject(JSContext* cx);
   2757 bool IsOutObject(JSContext* cx, JSObject* obj);
   2758 
   2759 nsresult HasInstance(JSContext* cx, JS::HandleObject objArg, const nsID* iid,
   2760                     bool* bp);
   2761 
   2762 // Returns the principal associated with |obj|'s realm. The object must not be a
   2763 // cross-compartment wrapper.
   2764 nsIPrincipal* GetObjectPrincipal(JSObject* obj);
   2765 
   2766 // Attempt to clean up the passed in value pointer. The pointer `value` must be
   2767 // a pointer to a value described by the type `nsXPTType`.
   2768 //
   2769 // This method expects a value of the following types:
   2770 //   TD_NSIDPTR
   2771 //     value : nsID* (free)
   2772 //   TD_ASTRING, TD_CSTRING, TD_UTF8STRING
   2773 //     value : ns[C]String* (truncate)
   2774 //   TD_PSTRING, TD_PWSTRING, TD_PSTRING_SIZE_IS, TD_PWSTRING_SIZE_IS
   2775 //     value : char[16_t]** (free)
   2776 //   TD_INTERFACE_TYPE, TD_INTERFACE_IS_TYPE
   2777 //     value : nsISupports** (release)
   2778 //   TD_LEGACY_ARRAY (NOTE: aArrayLen should be passed)
   2779 //     value : void** (destroy elements & free)
   2780 //   TD_ARRAY
   2781 //     value : nsTArray<T>* (destroy elements & Clear)
   2782 //   TD_DOMOBJECT
   2783 //     value : T** (cleanup)
   2784 //   TD_PROMISE
   2785 //     value : dom::Promise** (release)
   2786 //
   2787 // Other types are ignored.
   2788 inline void CleanupValue(const nsXPTType& aType, void* aValue,
   2789                         uint32_t aArrayLen = 0);
   2790 
   2791 // Out-of-line internals for xpc::CleanupValue. Defined in XPCConvert.cpp.
   2792 void InnerCleanupValue(const nsXPTType& aType, void* aValue,
   2793                       uint32_t aArrayLen);
   2794 
   2795 // In order to be able to safely call CleanupValue on a generated value, the
   2796 // data behind it needs to be initialized to a safe value. This method handles
   2797 // initializing the backing data to a safe value to use as an argument to
   2798 // XPCConvert methods, or xpc::CleanupValue.
   2799 //
   2800 // The pointer `aValue` must point to a block of memory at least aType.Stride()
   2801 // bytes large, and correctly aligned.
   2802 //
   2803 // This method accepts the same types as xpc::CleanupValue.
   2804 void InitializeValue(const nsXPTType& aType, void* aValue);
   2805 
   2806 // If a value was initialized with InitializeValue, it should be destroyed with
   2807 // DestructValue. This method acts like CleanupValue, except that destructors
   2808 // for complex types are also invoked, leaving them in an invalid state.
   2809 //
   2810 // This method should be called when destroying types initialized with
   2811 // InitializeValue.
   2812 //
   2813 // The pointer 'aValue' must point to a valid value of type 'aType'.
   2814 void DestructValue(const nsXPTType& aType, void* aValue,
   2815                   uint32_t aArrayLen = 0);
   2816 
   2817 bool SandboxCreateCrypto(JSContext* cx, JS::Handle<JSObject*> obj);
   2818 bool SandboxCreateFetch(JSContext* cx, JS::Handle<JSObject*> obj);
   2819 bool SandboxCreateStructuredClone(JSContext* cx, JS::Handle<JSObject*> obj);
   2820 bool SandboxCreateLocks(JSContext* cx, JS::Handle<JSObject*> obj);
   2821 
   2822 }  // namespace xpc
   2823 
   2824 namespace mozilla {
   2825 namespace dom {
   2826 extern bool DefineStaticJSVals(JSContext* cx);
   2827 }  // namespace dom
   2828 }  // namespace mozilla
   2829 
   2830 bool xpc_LocalizeRuntime(JSRuntime* rt);
   2831 void xpc_DelocalizeRuntime(JSRuntime* rt);
   2832 
   2833 /***************************************************************************/
   2834 // Inlines use the above - include last.
   2835 
   2836 #include "XPCInlines.h"
   2837 
   2838 /***************************************************************************/
   2839 
   2840 #endif /* xpcprivate_h___ */