tor-browser

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

Object.h (5143B)


      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 #ifndef js_public_Object_h
      8 #define js_public_Object_h
      9 
     10 #include "js/shadow/Object.h"  // JS::shadow::Object
     11 
     12 #include "mozilla/Assertions.h"  // MOZ_ASSERT
     13 
     14 #include <stddef.h>  // size_t
     15 #include <stdint.h>  // uint32_t
     16 
     17 #include "jstypes.h"  // JS_PUBLIC_API
     18 
     19 #include "js/Class.h"       // js::ESClass, JSCLASS_RESERVED_SLOTS
     20 #include "js/Realm.h"       // JS::GetCompartmentForRealm
     21 #include "js/RootingAPI.h"  // JS::{,Mutable}Handle
     22 #include "js/Value.h"       // JS::Value
     23 
     24 struct JS_PUBLIC_API JSContext;
     25 class JS_PUBLIC_API JSObject;
     26 
     27 namespace JS {
     28 
     29 class JS_PUBLIC_API Compartment;
     30 
     31 /**
     32 * Determine the ECMAScript "class" -- Date, String, RegExp, and all the other
     33 * builtin object types (described in ECMAScript in terms of an objecting having
     34 * "an [[ArrayBufferData]] internal slot" or similar language for other kinds of
     35 * object -- of the provided object.
     36 *
     37 * If this function is passed a wrapper that can be unwrapped, the determination
     38 * is performed on that object.  If the wrapper can't be unwrapped, and it's not
     39 * a wrapper that prefers to treat this operation as a failure, this function
     40 * will indicate that the object is |js::ESClass::Other|.
     41 */
     42 extern JS_PUBLIC_API bool GetBuiltinClass(JSContext* cx, Handle<JSObject*> obj,
     43                                          js::ESClass* cls);
     44 
     45 /** Get the |JSClass| of an object. */
     46 inline const JSClass* GetClass(const JSObject* obj) {
     47  return reinterpret_cast<const shadow::Object*>(obj)->shape->base->clasp;
     48 }
     49 
     50 /**
     51 * Get the |JS::Compartment*| of an object.
     52 *
     53 * Note that the compartment of an object in this realm, that is a
     54 * cross-compartment wrapper around an object from another realm, is the
     55 * compartment of this realm.
     56 */
     57 static MOZ_ALWAYS_INLINE Compartment* GetCompartment(JSObject* obj) {
     58  Realm* realm = reinterpret_cast<shadow::Object*>(obj)->shape->base->realm;
     59  return GetCompartmentForRealm(realm);
     60 }
     61 
     62 /**
     63 * Get the value stored in a reserved slot in an object.
     64 *
     65 * If |obj| is known to be a proxy and you're willing to use friend APIs,
     66 * |js::GetProxyReservedSlot| in "js/Proxy.h" is very slightly more efficient.
     67 */
     68 inline const Value& GetReservedSlot(JSObject* obj, size_t slot) {
     69  MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetClass(obj)));
     70  return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
     71 }
     72 
     73 namespace detail {
     74 
     75 extern JS_PUBLIC_API void SetReservedSlotWithBarrier(JSObject* obj, size_t slot,
     76                                                     const Value& value);
     77 
     78 }  // namespace detail
     79 
     80 /**
     81 * Store a value in an object's reserved slot.
     82 *
     83 * This can be used with both native objects and proxies.  However, if |obj| is
     84 * known to be a proxy, |js::SetProxyReservedSlot| in "js/Proxy.h" is very
     85 * slightly more efficient.
     86 */
     87 inline void SetReservedSlot(JSObject* obj, size_t slot, const Value& value) {
     88  MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetClass(obj)));
     89  auto* sobj = reinterpret_cast<shadow::Object*>(obj);
     90  if (sobj->slotRef(slot).isGCThing() || value.isGCThing()) {
     91    detail::SetReservedSlotWithBarrier(obj, slot, value);
     92  } else {
     93    sobj->slotRef(slot) = value;
     94  }
     95 }
     96 
     97 /**
     98 * Helper function to get the pointer value (or nullptr if not set) from an
     99 * object's reserved slot. The slot must contain either a PrivateValue(T*) or
    100 * UndefinedValue.
    101 */
    102 template <typename T>
    103 inline T* GetMaybePtrFromReservedSlot(JSObject* obj, size_t slot) {
    104  Value v = GetReservedSlot(obj, slot);
    105  return v.isUndefined() ? nullptr : static_cast<T*>(v.toPrivate());
    106 }
    107 
    108 /**
    109 * Helper function to get the pointer value (or nullptr if not set) from the
    110 * object's first reserved slot. Must only be used for objects with a JSClass
    111 * that has the JSCLASS_SLOT0_IS_NSISUPPORTS flag.
    112 */
    113 template <typename T>
    114 inline T* GetObjectISupports(JSObject* obj) {
    115  MOZ_ASSERT(GetClass(obj)->slot0IsISupports());
    116  return GetMaybePtrFromReservedSlot<T>(obj, 0);
    117 }
    118 
    119 /**
    120 * Helper function to store |PrivateValue(nsISupportsValue)| in the object's
    121 * first reserved slot. Must only be used for objects with a JSClass that has
    122 * the JSCLASS_SLOT0_IS_NSISUPPORTS flag.
    123 *
    124 * Note: the pointer is opaque to the JS engine (including the GC) so it's the
    125 * embedding's responsibility to trace or free this value.
    126 */
    127 inline void SetObjectISupports(JSObject* obj, void* nsISupportsValue) {
    128  MOZ_ASSERT(GetClass(obj)->slot0IsISupports());
    129  SetReservedSlot(obj, 0, PrivateValue(nsISupportsValue));
    130 }
    131 
    132 }  // namespace JS
    133 
    134 // JSObject* is an aligned pointer, but this information isn't available in the
    135 // public header. We specialize HasFreeLSB here so that JS::Result<JSObject*>
    136 // compiles.
    137 
    138 namespace mozilla {
    139 namespace detail {
    140 template <>
    141 struct HasFreeLSB<JSObject*> {
    142  static constexpr bool value = true;
    143 };
    144 }  // namespace detail
    145 }  // namespace mozilla
    146 
    147 #endif  // js_public_Object_h