LCOV - code coverage report
Current view: top level - js/public - Class.h (source / functions) Hit Total Coverage
Test: output.info Lines: 149 164 90.9 %
Date: 2017-07-14 16:53:18 Functions: 114 124 91.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       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             : /* JSClass definition and its component types, plus related interfaces. */
       8             : 
       9             : #ifndef js_Class_h
      10             : #define js_Class_h
      11             : 
      12             : #include "jstypes.h"
      13             : 
      14             : #include "js/CallArgs.h"
      15             : #include "js/Id.h"
      16             : #include "js/TypeDecls.h"
      17             : 
      18             : /*
      19             :  * A JSClass acts as a vtable for JS objects that allows JSAPI clients to
      20             :  * control various aspects of the behavior of an object like property lookup.
      21             :  * js::Class is an engine-private extension that allows more control over
      22             :  * object behavior and, e.g., allows custom slow layout.
      23             :  */
      24             : 
      25             : struct JSAtomState;
      26             : struct JSFreeOp;
      27             : struct JSFunctionSpec;
      28             : 
      29             : namespace js {
      30             : 
      31             : struct Class;
      32             : class FreeOp;
      33             : class Shape;
      34             : 
      35             : // This is equal to JSFunction::class_.  Use it in places where you don't want
      36             : // to #include jsfun.h.
      37             : extern JS_FRIEND_DATA(const js::Class* const) FunctionClassPtr;
      38             : 
      39             : } // namespace js
      40             : 
      41             : namespace JS {
      42             : 
      43             : class AutoIdVector;
      44             : 
      45             : /**
      46             :  * The answer to a successful query as to whether an object is an Array per
      47             :  * ES6's internal |IsArray| operation (as exposed by |Array.isArray|).
      48             :  */
      49             : enum class IsArrayAnswer
      50             : {
      51             :     Array,
      52             :     NotArray,
      53             :     RevokedProxy
      54             : };
      55             : 
      56             : /**
      57             :  * ES6 7.2.2.
      58             :  *
      59             :  * Returns false on failure, otherwise returns true and sets |*isArray|
      60             :  * indicating whether the object passes ECMAScript's IsArray test.  This is the
      61             :  * same test performed by |Array.isArray|.
      62             :  *
      63             :  * This is NOT the same as asking whether |obj| is an Array or a wrapper around
      64             :  * one.  If |obj| is a proxy created by |Proxy.revocable()| and has been
      65             :  * revoked, or if |obj| is a proxy whose target (at any number of hops) is a
      66             :  * revoked proxy, this method throws a TypeError and returns false.
      67             :  */
      68             : extern JS_PUBLIC_API(bool)
      69             : IsArray(JSContext* cx, HandleObject obj, bool* isArray);
      70             : 
      71             : /**
      72             :  * Identical to IsArray above, but the nature of the object (if successfully
      73             :  * determined) is communicated via |*answer|.  In particular this method
      74             :  * returns true and sets |*answer = IsArrayAnswer::RevokedProxy| when called on
      75             :  * a revoked proxy.
      76             :  *
      77             :  * Most users will want the overload above, not this one.
      78             :  */
      79             : extern JS_PUBLIC_API(bool)
      80             : IsArray(JSContext* cx, HandleObject obj, IsArrayAnswer* answer);
      81             : 
      82             : /**
      83             :  * Per ES6, the [[DefineOwnProperty]] internal method has three different
      84             :  * possible outcomes:
      85             :  *
      86             :  * -   It can throw an exception (which we indicate by returning false).
      87             :  *
      88             :  * -   It can return true, indicating unvarnished success.
      89             :  *
      90             :  * -   It can return false, indicating "strict failure". The property could
      91             :  *     not be defined. It's an error, but no exception was thrown.
      92             :  *
      93             :  * It's not just [[DefineOwnProperty]]: all the mutating internal methods have
      94             :  * the same three outcomes. (The other affected internal methods are [[Set]],
      95             :  * [[Delete]], [[SetPrototypeOf]], and [[PreventExtensions]].)
      96             :  *
      97             :  * If you think this design is awful, you're not alone.  But as it's the
      98             :  * standard, we must represent these boolean "success" values somehow.
      99             :  * ObjectOpSuccess is the class for this. It's like a bool, but when it's false
     100             :  * it also stores an error code.
     101             :  *
     102             :  * Typical usage:
     103             :  *
     104             :  *     ObjectOpResult result;
     105             :  *     if (!DefineProperty(cx, obj, id, ..., result))
     106             :  *         return false;
     107             :  *     if (!result)
     108             :  *         return result.reportError(cx, obj, id);
     109             :  *
     110             :  * Users don't have to call `result.report()`; another possible ending is:
     111             :  *
     112             :  *     argv.rval().setBoolean(bool(result));
     113             :  *     return true;
     114             :  */
     115             : class ObjectOpResult
     116             : {
     117             :   private:
     118             :     /**
     119             :      * code_ is either one of the special codes OkCode or Uninitialized, or
     120             :      * an error code. For now the error codes are private to the JS engine;
     121             :      * they're defined in js/src/js.msg.
     122             :      *
     123             :      * code_ is uintptr_t (rather than uint32_t) for the convenience of the
     124             :      * JITs, which would otherwise have to deal with either padding or stack
     125             :      * alignment on 64-bit platforms.
     126             :      */
     127             :     uintptr_t code_;
     128             : 
     129             :   public:
     130             :     enum SpecialCodes : uintptr_t {
     131             :         OkCode = 0,
     132             :         Uninitialized = uintptr_t(-1)
     133             :     };
     134             : 
     135      142171 :     ObjectOpResult() : code_(Uninitialized) {}
     136             : 
     137             :     /* Return true if succeed() was called. */
     138      139593 :     bool ok() const {
     139      139593 :         MOZ_ASSERT(code_ != Uninitialized);
     140      139593 :         return code_ == OkCode;
     141             :     }
     142             : 
     143      124890 :     explicit operator bool() const { return ok(); }
     144             : 
     145             :     /* Set this ObjectOpResult to true and return true. */
     146      140768 :     bool succeed() {
     147      140768 :         code_ = OkCode;
     148      140768 :         return true;
     149             :     }
     150             : 
     151             :     /*
     152             :      * Set this ObjectOpResult to false with an error code.
     153             :      *
     154             :      * Always returns true, as a convenience. Typical usage will be:
     155             :      *
     156             :      *     if (funny condition)
     157             :      *         return result.fail(JSMSG_CANT_DO_THE_THINGS);
     158             :      *
     159             :      * The true return value indicates that no exception is pending, and it
     160             :      * would be OK to ignore the failure and continue.
     161             :      */
     162          11 :     bool fail(uint32_t msg) {
     163          11 :         MOZ_ASSERT(msg != OkCode);
     164          11 :         code_ = msg;
     165          11 :         return true;
     166             :     }
     167             : 
     168             :     JS_PUBLIC_API(bool) failCantRedefineProp();
     169             :     JS_PUBLIC_API(bool) failReadOnly();
     170             :     JS_PUBLIC_API(bool) failGetterOnly();
     171             :     JS_PUBLIC_API(bool) failCantDelete();
     172             : 
     173             :     JS_PUBLIC_API(bool) failCantSetInterposed();
     174             :     JS_PUBLIC_API(bool) failCantDefineWindowElement();
     175             :     JS_PUBLIC_API(bool) failCantDeleteWindowElement();
     176             :     JS_PUBLIC_API(bool) failCantDeleteWindowNamedProperty();
     177             :     JS_PUBLIC_API(bool) failCantPreventExtensions();
     178             :     JS_PUBLIC_API(bool) failCantSetProto();
     179             :     JS_PUBLIC_API(bool) failNoNamedSetter();
     180             :     JS_PUBLIC_API(bool) failNoIndexedSetter();
     181             : 
     182           0 :     uint32_t failureCode() const {
     183           0 :         MOZ_ASSERT(!ok());
     184           0 :         return uint32_t(code_);
     185             :     }
     186             : 
     187             :     /*
     188             :      * Report an error or warning if necessary; return true to proceed and
     189             :      * false if an error was reported. Call this when failure should cause
     190             :      * a warning if extraWarnings are enabled.
     191             :      *
     192             :      * The precise rules are like this:
     193             :      *
     194             :      * -   If ok(), then we succeeded. Do nothing and return true.
     195             :      * -   Otherwise, if |strict| is true, or if cx has both extraWarnings and
     196             :      *     werrorOption enabled, throw a TypeError and return false.
     197             :      * -   Otherwise, if cx has extraWarnings enabled, emit a warning and
     198             :      *     return true.
     199             :      * -   Otherwise, do nothing and return true.
     200             :      */
     201       10783 :     bool checkStrictErrorOrWarning(JSContext* cx, HandleObject obj, HandleId id, bool strict) {
     202       10783 :         if (ok())
     203       10783 :             return true;
     204           0 :         return reportStrictErrorOrWarning(cx, obj, id, strict);
     205             :     }
     206             : 
     207             :     /*
     208             :      * The same as checkStrictErrorOrWarning(cx, id, strict), except the
     209             :      * operation is not associated with a particular property id. This is
     210             :      * used for [[PreventExtensions]] and [[SetPrototypeOf]]. failureCode()
     211             :      * must not be an error that has "{0}" in the error message.
     212             :      */
     213        3399 :     bool checkStrictErrorOrWarning(JSContext* cx, HandleObject obj, bool strict) {
     214        3399 :         return ok() || reportStrictErrorOrWarning(cx, obj, strict);
     215             :     }
     216             : 
     217             :     /* Throw a TypeError. Call this only if !ok(). */
     218           0 :     bool reportError(JSContext* cx, HandleObject obj, HandleId id) {
     219           0 :         return reportStrictErrorOrWarning(cx, obj, id, true);
     220             :     }
     221             : 
     222             :     /*
     223             :      * The same as reportError(cx, obj, id), except the operation is not
     224             :      * associated with a particular property id.
     225             :      */
     226             :     bool reportError(JSContext* cx, HandleObject obj) {
     227             :         return reportStrictErrorOrWarning(cx, obj, true);
     228             :     }
     229             : 
     230             :     /* Helper function for checkStrictErrorOrWarning's slow path. */
     231             :     JS_PUBLIC_API(bool) reportStrictErrorOrWarning(JSContext* cx, HandleObject obj, HandleId id, bool strict);
     232             :     JS_PUBLIC_API(bool) reportStrictErrorOrWarning(JSContext* cx, HandleObject obj, bool strict);
     233             : 
     234             :     /*
     235             :      * Convenience method. Return true if ok() or if strict is false; otherwise
     236             :      * throw a TypeError and return false.
     237             :      */
     238        2944 :     bool checkStrict(JSContext* cx, HandleObject obj, HandleId id) {
     239        2944 :         return checkStrictErrorOrWarning(cx, obj, id, true);
     240             :     }
     241             : 
     242             :     /*
     243             :      * Convenience method. The same as checkStrict(cx, id), except the
     244             :      * operation is not associated with a particular property id.
     245             :      */
     246        3399 :     bool checkStrict(JSContext* cx, HandleObject obj) {
     247        3399 :         return checkStrictErrorOrWarning(cx, obj, true);
     248             :     }
     249             : };
     250             : 
     251             : class PropertyResult
     252             : {
     253             :     union {
     254             :         js::Shape* shape_;
     255             :         uintptr_t bits_;
     256             :     };
     257             : 
     258             :     static const uintptr_t NotFound = 0;
     259             :     static const uintptr_t NonNativeProperty = 1;
     260             :     static const uintptr_t DenseOrTypedArrayElement = 1;
     261             : 
     262             :   public:
     263      259710 :     PropertyResult() : bits_(NotFound) {}
     264             : 
     265         725 :     explicit PropertyResult(js::Shape* propertyShape)
     266         725 :       : shape_(propertyShape)
     267             :     {
     268         725 :         MOZ_ASSERT(!isFound() || isNativeProperty());
     269         725 :     }
     270             : 
     271      433336 :     explicit operator bool() const {
     272      433336 :         return isFound();
     273             :     }
     274             : 
     275      666551 :     bool isFound() const {
     276      666551 :         return bits_ != NotFound;
     277             :     }
     278             : 
     279      227795 :     bool isNonNativeProperty() const {
     280      227795 :         return bits_ == NonNativeProperty;
     281             :     }
     282             : 
     283       87503 :     bool isDenseOrTypedArrayElement() const {
     284       87503 :         return bits_ == DenseOrTypedArrayElement;
     285             :     }
     286             : 
     287      223368 :     bool isNativeProperty() const {
     288      223368 :         return isFound() && !isNonNativeProperty();
     289             :     }
     290             : 
     291        3915 :     js::Shape* maybeShape() const {
     292        3915 :         MOZ_ASSERT(!isNonNativeProperty());
     293        3915 :         return isFound() ? shape_ : nullptr;
     294             :     }
     295             : 
     296      126610 :     js::Shape* shape() const {
     297      126610 :         MOZ_ASSERT(isNativeProperty());
     298      126610 :         return shape_;
     299             :     }
     300             : 
     301      258120 :     void setNotFound() {
     302      258120 :         bits_ = NotFound;
     303      258120 :     }
     304             : 
     305       95971 :     void setNativeProperty(js::Shape* propertyShape) {
     306       95971 :         shape_ = propertyShape;
     307       95971 :         MOZ_ASSERT(isNativeProperty());
     308       95971 :     }
     309             : 
     310          59 :     void setNonNativeProperty() {
     311          59 :         bits_ = NonNativeProperty;
     312          59 :     }
     313             : 
     314        4267 :     void setDenseOrTypedArrayElement() {
     315        4267 :         bits_ = DenseOrTypedArrayElement;
     316        4267 :     }
     317             : 
     318             :     void trace(JSTracer* trc);
     319             : };
     320             : 
     321             : } // namespace JS
     322             : 
     323             : namespace js {
     324             : 
     325             : template <class Wrapper>
     326      562479 : class WrappedPtrOperations<JS::PropertyResult, Wrapper>
     327             : {
     328      530417 :     const JS::PropertyResult& value() const { return static_cast<const Wrapper*>(this)->get(); }
     329             : 
     330             :   public:
     331        5060 :     bool isFound() const { return value().isFound(); }
     332      358668 :     explicit operator bool() const { return bool(value()); }
     333             :     js::Shape* maybeShape() const { return value().maybeShape(); }
     334       92927 :     js::Shape* shape() const { return value().shape(); }
     335           0 :     bool isNativeProperty() const { return value().isNativeProperty(); }
     336          44 :     bool isNonNativeProperty() const { return value().isNonNativeProperty(); }
     337       73710 :     bool isDenseOrTypedArrayElement() const { return value().isDenseOrTypedArrayElement(); }
     338             :     js::Shape* asTaggedShape() const { return value().asTaggedShape(); }
     339             : };
     340             : 
     341             : template <class Wrapper>
     342      545122 : class MutableWrappedPtrOperations<JS::PropertyResult, Wrapper>
     343             :   : public WrappedPtrOperations<JS::PropertyResult, Wrapper>
     344             : {
     345      350521 :     JS::PropertyResult& value() { return static_cast<Wrapper*>(this)->get(); }
     346             : 
     347             :   public:
     348      254791 :     void setNotFound() {
     349      254791 :         value().setNotFound();
     350      254791 :     }
     351       91414 :     void setNativeProperty(js::Shape* shape) {
     352       91414 :         value().setNativeProperty(shape);
     353       91414 :     }
     354          51 :     void setNonNativeProperty() {
     355          51 :         value().setNonNativeProperty();
     356          51 :     }
     357        4267 :     void setDenseOrTypedArrayElement() {
     358        4267 :         value().setDenseOrTypedArrayElement();
     359        4267 :     }
     360             : };
     361             : 
     362             : } // namespace js
     363             : 
     364             : // JSClass operation signatures.
     365             : 
     366             : /**
     367             :  * Get a property named by id in obj.  Note the jsid id type -- id may
     368             :  * be a string (Unicode property identifier) or an int (element index).  The
     369             :  * *vp out parameter, on success, is the new property value after the action.
     370             :  */
     371             : typedef bool
     372             : (* JSGetterOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
     373             :                JS::MutableHandleValue vp);
     374             : 
     375             : /** Add a property named by id to obj. */
     376             : typedef bool
     377             : (* JSAddPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v);
     378             : 
     379             : /**
     380             :  * Set a property named by id in obj, treating the assignment as strict
     381             :  * mode code if strict is true. Note the jsid id type -- id may be a string
     382             :  * (Unicode property identifier) or an int (element index). The *vp out
     383             :  * parameter, on success, is the new property value after the
     384             :  * set.
     385             :  */
     386             : typedef bool
     387             : (* JSSetterOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
     388             :                JS::MutableHandleValue vp, JS::ObjectOpResult& result);
     389             : 
     390             : /**
     391             :  * Delete a property named by id in obj.
     392             :  *
     393             :  * If an error occurred, return false as per normal JSAPI error practice.
     394             :  *
     395             :  * If no error occurred, but the deletion attempt wasn't allowed (perhaps
     396             :  * because the property was non-configurable), call result.fail() and
     397             :  * return true.  This will cause |delete obj[id]| to evaluate to false in
     398             :  * non-strict mode code, and to throw a TypeError in strict mode code.
     399             :  *
     400             :  * If no error occurred and the deletion wasn't disallowed (this is *not* the
     401             :  * same as saying that a deletion actually occurred -- deleting a non-existent
     402             :  * property, or an inherited property, is allowed -- it's just pointless),
     403             :  * call result.succeed() and return true.
     404             :  */
     405             : typedef bool
     406             : (* JSDeletePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
     407             :                        JS::ObjectOpResult& result);
     408             : 
     409             : /**
     410             :  * The type of ObjectOps::enumerate. This callback overrides a portion of
     411             :  * SpiderMonkey's default [[Enumerate]] internal method. When an ordinary object
     412             :  * is enumerated, that object and each object on its prototype chain is tested
     413             :  * for an enumerate op, and those ops are called in order. The properties each
     414             :  * op adds to the 'properties' vector are added to the set of values the for-in
     415             :  * loop will iterate over. All of this is nonstandard.
     416             :  *
     417             :  * An object is "enumerated" when it's the target of a for-in loop or
     418             :  * JS_Enumerate(). The callback's job is to populate 'properties' with the
     419             :  * object's property keys. If `enumerableOnly` is true, the callback should only
     420             :  * add enumerable properties.
     421             :  */
     422             : typedef bool
     423             : (* JSNewEnumerateOp)(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
     424             :                      bool enumerableOnly);
     425             : 
     426             : /**
     427             :  * The old-style JSClass.enumerate op should define all lazy properties not
     428             :  * yet reflected in obj.
     429             :  */
     430             : typedef bool
     431             : (* JSEnumerateOp)(JSContext* cx, JS::HandleObject obj);
     432             : 
     433             : /**
     434             :  * The type of ObjectOps::funToString.  This callback allows an object to
     435             :  * provide a custom string to use when Function.prototype.toString is invoked on
     436             :  * that object.  A null return value means OOM.
     437             :  */
     438             : typedef JSString*
     439             : (* JSFunToStringOp)(JSContext* cx, JS::HandleObject obj, unsigned indent);
     440             : 
     441             : /**
     442             :  * Resolve a lazy property named by id in obj by defining it directly in obj.
     443             :  * Lazy properties are those reflected from some peer native property space
     444             :  * (e.g., the DOM attributes for a given node reflected as obj) on demand.
     445             :  *
     446             :  * JS looks for a property in an object, and if not found, tries to resolve
     447             :  * the given id. *resolvedp should be set to true iff the property was defined
     448             :  * on |obj|.
     449             :  */
     450             : typedef bool
     451             : (* JSResolveOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
     452             :                 bool* resolvedp);
     453             : 
     454             : /**
     455             :  * A class with a resolve hook can optionally have a mayResolve hook. This hook
     456             :  * must have no side effects and must return true for a given id if the resolve
     457             :  * hook may resolve this id. This is useful when we're doing a "pure" lookup: if
     458             :  * mayResolve returns false, we know we don't have to call the effectful resolve
     459             :  * hook.
     460             :  *
     461             :  * maybeObj, if non-null, is the object on which we're doing the lookup. This
     462             :  * can be nullptr: during JIT compilation we sometimes know the Class but not
     463             :  * the object.
     464             :  */
     465             : typedef bool
     466             : (* JSMayResolveOp)(const JSAtomState& names, jsid id, JSObject* maybeObj);
     467             : 
     468             : /**
     469             :  * Finalize obj, which the garbage collector has determined to be unreachable
     470             :  * from other live objects or from GC roots.  Obviously, finalizers must never
     471             :  * store a reference to obj.
     472             :  */
     473             : typedef void
     474             : (* JSFinalizeOp)(JSFreeOp* fop, JSObject* obj);
     475             : 
     476             : /**
     477             :  * Finalizes external strings created by JS_NewExternalString. The finalizer
     478             :  * can be called off the main thread.
     479             :  */
     480             : struct JSStringFinalizer {
     481             :     void (*finalize)(const JSStringFinalizer* fin, char16_t* chars);
     482             : };
     483             : 
     484             : /**
     485             :  * Check whether v is an instance of obj.  Return false on error or exception,
     486             :  * true on success with true in *bp if v is an instance of obj, false in
     487             :  * *bp otherwise.
     488             :  */
     489             : typedef bool
     490             : (* JSHasInstanceOp)(JSContext* cx, JS::HandleObject obj, JS::MutableHandleValue vp,
     491             :                     bool* bp);
     492             : 
     493             : /**
     494             :  * Function type for trace operation of the class called to enumerate all
     495             :  * traceable things reachable from obj's private data structure. For each such
     496             :  * thing, a trace implementation must call JS::TraceEdge on the thing's
     497             :  * location.
     498             :  *
     499             :  * JSTraceOp implementation can assume that no other threads mutates object
     500             :  * state. It must not change state of the object or corresponding native
     501             :  * structures. The only exception for this rule is the case when the embedding
     502             :  * needs a tight integration with GC. In that case the embedding can check if
     503             :  * the traversal is a part of the marking phase through calling
     504             :  * JS_IsGCMarkingTracer and apply a special code like emptying caches or
     505             :  * marking its native structures.
     506             :  */
     507             : typedef void
     508             : (* JSTraceOp)(JSTracer* trc, JSObject* obj);
     509             : 
     510             : typedef JSObject*
     511             : (* JSWeakmapKeyDelegateOp)(JSObject* obj);
     512             : 
     513             : typedef void
     514             : (* JSObjectMovedOp)(JSObject* obj, const JSObject* old);
     515             : 
     516             : /* js::Class operation signatures. */
     517             : 
     518             : namespace js {
     519             : 
     520             : typedef bool
     521             : (* LookupPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
     522             :                      JS::MutableHandleObject objp, JS::MutableHandle<JS::PropertyResult> propp);
     523             : typedef bool
     524             : (* DefinePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
     525             :                      JS::Handle<JS::PropertyDescriptor> desc,
     526             :                      JS::ObjectOpResult& result);
     527             : typedef bool
     528             : (* HasPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
     529             : typedef bool
     530             : (* GetPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleValue receiver, JS::HandleId id,
     531             :                   JS::MutableHandleValue vp);
     532             : typedef bool
     533             : (* SetPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
     534             :                   JS::HandleValue receiver, JS::ObjectOpResult& result);
     535             : typedef bool
     536             : (* GetOwnPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
     537             :                      JS::MutableHandle<JS::PropertyDescriptor> desc);
     538             : typedef bool
     539             : (* DeletePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
     540             :                      JS::ObjectOpResult& result);
     541             : 
     542             : typedef bool
     543             : (* WatchOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
     544             : 
     545             : typedef bool
     546             : (* UnwatchOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id);
     547             : 
     548          35 : class JS_FRIEND_API(ElementAdder)
     549             : {
     550             :   public:
     551             :     enum GetBehavior {
     552             :         // Check if the element exists before performing the Get and preserve
     553             :         // holes.
     554             :         CheckHasElemPreserveHoles,
     555             : 
     556             :         // Perform a Get operation, like obj[index] in JS.
     557             :         GetElement
     558             :     };
     559             : 
     560             :   private:
     561             :     // Only one of these is used.
     562             :     JS::RootedObject resObj_;
     563             :     JS::Value* vp_;
     564             : 
     565             :     uint32_t index_;
     566             : #ifdef DEBUG
     567             :     uint32_t length_;
     568             : #endif
     569             :     GetBehavior getBehavior_;
     570             : 
     571             :   public:
     572           0 :     ElementAdder(JSContext* cx, JSObject* obj, uint32_t length, GetBehavior behavior)
     573           0 :       : resObj_(cx, obj), vp_(nullptr), index_(0),
     574             : #ifdef DEBUG
     575             :         length_(length),
     576             : #endif
     577           0 :         getBehavior_(behavior)
     578           0 :     {}
     579          35 :     ElementAdder(JSContext* cx, JS::Value* vp, uint32_t length, GetBehavior behavior)
     580          35 :       : resObj_(cx), vp_(vp), index_(0),
     581             : #ifdef DEBUG
     582             :         length_(length),
     583             : #endif
     584          35 :         getBehavior_(behavior)
     585          35 :     {}
     586             : 
     587         132 :     GetBehavior getBehavior() const { return getBehavior_; }
     588             : 
     589             :     bool append(JSContext* cx, JS::HandleValue v);
     590             :     void appendHole();
     591             : };
     592             : 
     593             : typedef bool
     594             : (* GetElementsOp)(JSContext* cx, JS::HandleObject obj, uint32_t begin, uint32_t end,
     595             :                   ElementAdder* adder);
     596             : 
     597             : typedef void
     598             : (* FinalizeOp)(FreeOp* fop, JSObject* obj);
     599             : 
     600             : // The special treatment of |finalize| and |trace| is necessary because if we
     601             : // assign either of those hooks to a local variable and then call it -- as is
     602             : // done with the other hooks -- the GC hazard analysis gets confused.
     603             : #define JS_CLASS_MEMBERS(ClassOpsType, FreeOpType) \
     604             :     const char* name; \
     605             :     uint32_t flags; \
     606             :     const ClassOpsType* cOps; \
     607             :     \
     608             :     JSAddPropertyOp    getAddProperty() const { return cOps ? cOps->addProperty : nullptr; } \
     609             :     JSDeletePropertyOp getDelProperty() const { return cOps ? cOps->delProperty : nullptr; } \
     610             :     JSGetterOp         getGetProperty() const { return cOps ? cOps->getProperty : nullptr; } \
     611             :     JSSetterOp         getSetProperty() const { return cOps ? cOps->setProperty : nullptr; } \
     612             :     JSEnumerateOp      getEnumerate()   const { return cOps ? cOps->enumerate   : nullptr; } \
     613             :     JSNewEnumerateOp   getNewEnumerate()const { return cOps ? cOps->newEnumerate: nullptr; } \
     614             :     JSResolveOp        getResolve()     const { return cOps ? cOps->resolve     : nullptr; } \
     615             :     JSMayResolveOp     getMayResolve()  const { return cOps ? cOps->mayResolve  : nullptr; } \
     616             :     JSNative           getCall()        const { return cOps ? cOps->call        : nullptr; } \
     617             :     JSHasInstanceOp    getHasInstance() const { return cOps ? cOps->hasInstance : nullptr; } \
     618             :     JSNative           getConstruct()   const { return cOps ? cOps->construct   : nullptr; } \
     619             :     \
     620             :     bool hasFinalize() const { return cOps && cOps->finalize; } \
     621             :     bool hasTrace()    const { return cOps && cOps->trace;    } \
     622             :     \
     623             :     bool isTrace(JSTraceOp trace) const { return cOps && cOps->trace == trace; } \
     624             :     \
     625             :     void doFinalize(FreeOpType* fop, JSObject* obj) const { \
     626             :         MOZ_ASSERT(cOps && cOps->finalize); \
     627             :         cOps->finalize(fop, obj); \
     628             :     } \
     629             :     void doTrace(JSTracer* trc, JSObject* obj) const { \
     630             :         MOZ_ASSERT(cOps && cOps->trace); \
     631             :         cOps->trace(trc, obj); \
     632             :     }
     633             : 
     634             : // XXX: MOZ_NONHEAP_CLASS allows objects to be created statically or on the
     635             : // stack. We actually want to ban stack objects too, but that's currently not
     636             : // possible. So we define JS_STATIC_CLASS to make the intention clearer.
     637             : #define JS_STATIC_CLASS MOZ_NONHEAP_CLASS
     638             : 
     639             : struct JS_STATIC_CLASS ClassOps
     640             : {
     641             :     /* Function pointer members (may be null). */
     642             :     JSAddPropertyOp     addProperty;
     643             :     JSDeletePropertyOp  delProperty;
     644             :     JSGetterOp          getProperty;
     645             :     JSSetterOp          setProperty;
     646             :     JSEnumerateOp       enumerate;
     647             :     JSNewEnumerateOp    newEnumerate;
     648             :     JSResolveOp         resolve;
     649             :     JSMayResolveOp      mayResolve;
     650             :     FinalizeOp          finalize;
     651             :     JSNative            call;
     652             :     JSHasInstanceOp     hasInstance;
     653             :     JSNative            construct;
     654             :     JSTraceOp           trace;
     655             : };
     656             : 
     657             : /** Callback for the creation of constructor and prototype objects. */
     658             : typedef JSObject* (*ClassObjectCreationOp)(JSContext* cx, JSProtoKey key);
     659             : 
     660             : /** Callback for custom post-processing after class initialization via ClassSpec. */
     661             : typedef bool (*FinishClassInitOp)(JSContext* cx, JS::HandleObject ctor,
     662             :                                   JS::HandleObject proto);
     663             : 
     664             : const size_t JSCLASS_CACHED_PROTO_WIDTH = 6;
     665             : 
     666             : struct JS_STATIC_CLASS ClassSpec
     667             : {
     668             :     ClassObjectCreationOp createConstructor;
     669             :     ClassObjectCreationOp createPrototype;
     670             :     const JSFunctionSpec* constructorFunctions;
     671             :     const JSPropertySpec* constructorProperties;
     672             :     const JSFunctionSpec* prototypeFunctions;
     673             :     const JSPropertySpec* prototypeProperties;
     674             :     FinishClassInitOp finishInit;
     675             :     uintptr_t flags;
     676             : 
     677             :     static const size_t ProtoKeyWidth = JSCLASS_CACHED_PROTO_WIDTH;
     678             : 
     679             :     static const uintptr_t ProtoKeyMask = (1 << ProtoKeyWidth) - 1;
     680             :     static const uintptr_t DontDefineConstructor = 1 << ProtoKeyWidth;
     681             : 
     682        3023 :     bool defined() const { return !!createConstructor; }
     683             : 
     684             :     // The ProtoKey this class inherits from.
     685          71 :     JSProtoKey inheritanceProtoKey() const {
     686          71 :         MOZ_ASSERT(defined());
     687             :         static_assert(JSProto_Null == 0, "zeroed key must be null");
     688             : 
     689             :         // Default: Inherit from Object.
     690          71 :         if (!(flags & ProtoKeyMask))
     691          71 :             return JSProto_Object;
     692             : 
     693           0 :         return JSProtoKey(flags & ProtoKeyMask);
     694             :     }
     695             : 
     696        1403 :     bool shouldDefineConstructor() const {
     697        1403 :         MOZ_ASSERT(defined());
     698        1403 :         return !(flags & DontDefineConstructor);
     699             :     }
     700             : };
     701             : 
     702             : struct JS_STATIC_CLASS ClassExtension
     703             : {
     704             :     /**
     705             :      * If an object is used as a key in a weakmap, it may be desirable for the
     706             :      * garbage collector to keep that object around longer than it otherwise
     707             :      * would. A common case is when the key is a wrapper around an object in
     708             :      * another compartment, and we want to avoid collecting the wrapper (and
     709             :      * removing the weakmap entry) as long as the wrapped object is alive. In
     710             :      * that case, the wrapped object is returned by the wrapper's
     711             :      * weakmapKeyDelegateOp hook. As long as the wrapper is used as a weakmap
     712             :      * key, it will not be collected (and remain in the weakmap) until the
     713             :      * wrapped object is collected.
     714             :      */
     715             :     JSWeakmapKeyDelegateOp weakmapKeyDelegateOp;
     716             : 
     717             :     /**
     718             :      * Optional hook called when an object is moved by a compacting GC.
     719             :      *
     720             :      * There may exist weak pointers to an object that are not traced through
     721             :      * when the normal trace APIs are used, for example objects in the wrapper
     722             :      * cache. This hook allows these pointers to be updated.
     723             :      *
     724             :      * Note that this hook can be called before JS_NewObject() returns if a GC
     725             :      * is triggered during construction of the object. This can happen for
     726             :      * global objects for example.
     727             :      */
     728             :     JSObjectMovedOp objectMovedOp;
     729             : };
     730             : 
     731             : #define JS_NULL_CLASS_SPEC  nullptr
     732             : #define JS_NULL_CLASS_EXT   nullptr
     733             : 
     734             : struct JS_STATIC_CLASS ObjectOps
     735             : {
     736             :     LookupPropertyOp lookupProperty;
     737             :     DefinePropertyOp defineProperty;
     738             :     HasPropertyOp    hasProperty;
     739             :     GetPropertyOp    getProperty;
     740             :     SetPropertyOp    setProperty;
     741             :     GetOwnPropertyOp getOwnPropertyDescriptor;
     742             :     DeletePropertyOp deleteProperty;
     743             :     WatchOp          watch;
     744             :     UnwatchOp        unwatch;
     745             :     GetElementsOp    getElements;
     746             :     JSFunToStringOp  funToString;
     747             : };
     748             : 
     749             : #define JS_NULL_OBJECT_OPS nullptr
     750             : 
     751             : } // namespace js
     752             : 
     753             : // Classes, objects, and properties.
     754             : 
     755             : typedef void (*JSClassInternal)();
     756             : 
     757             : struct JS_STATIC_CLASS JSClassOps
     758             : {
     759             :     /* Function pointer members (may be null). */
     760             :     JSAddPropertyOp     addProperty;
     761             :     JSDeletePropertyOp  delProperty;
     762             :     JSGetterOp          getProperty;
     763             :     JSSetterOp          setProperty;
     764             :     JSEnumerateOp       enumerate;
     765             :     JSNewEnumerateOp    newEnumerate;
     766             :     JSResolveOp         resolve;
     767             :     JSMayResolveOp      mayResolve;
     768             :     JSFinalizeOp        finalize;
     769             :     JSNative            call;
     770             :     JSHasInstanceOp     hasInstance;
     771             :     JSNative            construct;
     772             :     JSTraceOp           trace;
     773             : };
     774             : 
     775             : #define JS_NULL_CLASS_OPS nullptr
     776             : 
     777             : struct JSClass {
     778       10960 :     JS_CLASS_MEMBERS(JSClassOps, JSFreeOp);
     779             : 
     780             :     void* reserved[3];
     781             : };
     782             : 
     783             : // Objects have private slot.
     784             : static const uint32_t JSCLASS_HAS_PRIVATE = 1 << 0;
     785             : 
     786             : // Class's initialization code will call `SetNewObjectMetadata` itself.
     787             : static const uint32_t JSCLASS_DELAY_METADATA_BUILDER = 1 << 1;
     788             : 
     789             : // Class is an XPCWrappedNative. WeakMaps use this to override the wrapper
     790             : // disposal mechanism.
     791             : static const uint32_t JSCLASS_IS_WRAPPED_NATIVE = 1 << 2;
     792             : 
     793             : // Private is `nsISupports*`.
     794             : static const uint32_t JSCLASS_PRIVATE_IS_NSISUPPORTS = 1 << 3;
     795             : 
     796             : // Objects are DOM.
     797             : static const uint32_t JSCLASS_IS_DOMJSCLASS = 1 << 4;
     798             : 
     799             : // If wrapped by an xray wrapper, the builtin class's constructor won't be
     800             : // unwrapped and invoked. Instead, the constructor is resolved in the caller's
     801             : // compartment and invoked with a wrapped newTarget. The constructor has to
     802             : // detect and handle this situation. See PromiseConstructor for details.
     803             : static const uint32_t JSCLASS_HAS_XRAYED_CONSTRUCTOR = 1 << 5;
     804             : 
     805             : // Objects of this class act like the value undefined, in some contexts.
     806             : static const uint32_t JSCLASS_EMULATES_UNDEFINED = 1 << 6;
     807             : 
     808             : // Reserved for embeddings.
     809             : static const uint32_t JSCLASS_USERBIT1 = 1 << 7;
     810             : 
     811             : // To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or
     812             : // JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where n
     813             : // is a constant in [1, 255]. Reserved slots are indexed from 0 to n-1.
     814             : 
     815             : // Room for 8 flags below ...
     816             : static const uintptr_t JSCLASS_RESERVED_SLOTS_SHIFT = 8;
     817             : // ... and 16 above this field.
     818             : static const uint32_t JSCLASS_RESERVED_SLOTS_WIDTH = 8;
     819             : 
     820             : static const uint32_t JSCLASS_RESERVED_SLOTS_MASK = JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH);
     821             : 
     822             : #define JSCLASS_HAS_RESERVED_SLOTS(n)   (((n) & JSCLASS_RESERVED_SLOTS_MASK)  \
     823             :                                          << JSCLASS_RESERVED_SLOTS_SHIFT)
     824             : #define JSCLASS_RESERVED_SLOTS(clasp)   (((clasp)->flags                      \
     825             :                                           >> JSCLASS_RESERVED_SLOTS_SHIFT)    \
     826             :                                          & JSCLASS_RESERVED_SLOTS_MASK)
     827             : 
     828             : #define JSCLASS_HIGH_FLAGS_SHIFT        (JSCLASS_RESERVED_SLOTS_SHIFT +       \
     829             :                                          JSCLASS_RESERVED_SLOTS_WIDTH)
     830             : 
     831             : static const uint32_t JSCLASS_IS_ANONYMOUS =            1 << (JSCLASS_HIGH_FLAGS_SHIFT + 0);
     832             : static const uint32_t JSCLASS_IS_GLOBAL =               1 << (JSCLASS_HIGH_FLAGS_SHIFT + 1);
     833             : static const uint32_t JSCLASS_INTERNAL_FLAG2 =          1 << (JSCLASS_HIGH_FLAGS_SHIFT + 2);
     834             : static const uint32_t JSCLASS_INTERNAL_FLAG3 =          1 << (JSCLASS_HIGH_FLAGS_SHIFT + 3);
     835             : static const uint32_t JSCLASS_IS_PROXY =                1 << (JSCLASS_HIGH_FLAGS_SHIFT + 4);
     836             : static const uint32_t JSCLASS_SKIP_NURSERY_FINALIZE =   1 << (JSCLASS_HIGH_FLAGS_SHIFT + 5);
     837             : 
     838             : // Reserved for embeddings.
     839             : static const uint32_t JSCLASS_USERBIT2 =                1 << (JSCLASS_HIGH_FLAGS_SHIFT + 6);
     840             : static const uint32_t JSCLASS_USERBIT3 =                1 << (JSCLASS_HIGH_FLAGS_SHIFT + 7);
     841             : 
     842             : static const uint32_t JSCLASS_BACKGROUND_FINALIZE =     1 << (JSCLASS_HIGH_FLAGS_SHIFT + 8);
     843             : static const uint32_t JSCLASS_FOREGROUND_FINALIZE =     1 << (JSCLASS_HIGH_FLAGS_SHIFT + 9);
     844             : 
     845             : // Bits 26 through 31 are reserved for the CACHED_PROTO_KEY mechanism, see
     846             : // below.
     847             : 
     848             : // ECMA-262 requires that most constructors used internally create objects
     849             : // with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
     850             : // member initial value.  The "original ... value" verbiage is there because
     851             : // in ECMA-262, global properties naming class objects are read/write and
     852             : // deleteable, for the most part.
     853             : //
     854             : // Implementing this efficiently requires that global objects have classes
     855             : // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
     856             : // previously allowed, but is now an ES5 violation and thus unsupported.
     857             : //
     858             : // JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
     859             : // the beginning of every global object's slots for use by the
     860             : // application.
     861             : static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
     862             : static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
     863             :     JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 37;
     864             : 
     865             : #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                              \
     866             :     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
     867             : #define JSCLASS_GLOBAL_FLAGS                                                  \
     868             :     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
     869             : #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
     870             :   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
     871             :    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
     872             : 
     873             : // Fast access to the original value of each standard class's prototype.
     874             : static const uint32_t JSCLASS_CACHED_PROTO_SHIFT = JSCLASS_HIGH_FLAGS_SHIFT + 10;
     875             : static const uint32_t JSCLASS_CACHED_PROTO_MASK = JS_BITMASK(js::JSCLASS_CACHED_PROTO_WIDTH);
     876             : 
     877             : #define JSCLASS_HAS_CACHED_PROTO(key)   (uint32_t(key) << JSCLASS_CACHED_PROTO_SHIFT)
     878             : #define JSCLASS_CACHED_PROTO_KEY(clasp) ((JSProtoKey)                         \
     879             :                                          (((clasp)->flags                     \
     880             :                                            >> JSCLASS_CACHED_PROTO_SHIFT)     \
     881             :                                           & JSCLASS_CACHED_PROTO_MASK))
     882             : 
     883             : // Initializer for unused members of statically initialized JSClass structs.
     884             : #define JSCLASS_NO_INTERNAL_MEMBERS     {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
     885             : #define JSCLASS_NO_OPTIONAL_MEMBERS     0,0,0,0,0,JSCLASS_NO_INTERNAL_MEMBERS
     886             : 
     887             : namespace js {
     888             : 
     889             : struct JS_STATIC_CLASS Class
     890             : {
     891     1094886 :     JS_CLASS_MEMBERS(js::ClassOps, FreeOp);
     892             :     const ClassSpec* spec;
     893             :     const ClassExtension* ext;
     894             :     const ObjectOps* oOps;
     895             : 
     896             :     /*
     897             :      * Objects of this class aren't native objects. They don't have Shapes that
     898             :      * describe their properties and layout. Classes using this flag must
     899             :      * provide their own property behavior, either by being proxy classes (do
     900             :      * this) or by overriding all the ObjectOps except getElements, watch and
     901             :      * unwatch (don't do this).
     902             :      */
     903             :     static const uint32_t NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
     904             : 
     905     3584655 :     bool isNative() const {
     906     3584655 :         return !(flags & NON_NATIVE);
     907             :     }
     908             : 
     909      168273 :     bool hasPrivate() const {
     910      168273 :         return !!(flags & JSCLASS_HAS_PRIVATE);
     911             :     }
     912             : 
     913       13788 :     bool emulatesUndefined() const {
     914       13788 :         return flags & JSCLASS_EMULATES_UNDEFINED;
     915             :     }
     916             : 
     917      131379 :     bool isJSFunction() const {
     918      131379 :         return this == js::FunctionClassPtr;
     919             :     }
     920             : 
     921           1 :     bool nonProxyCallable() const {
     922           1 :         MOZ_ASSERT(!isProxy());
     923           1 :         return isJSFunction() || getCall();
     924             :     }
     925             : 
     926     8312126 :     bool isProxy() const {
     927     8312126 :         return flags & JSCLASS_IS_PROXY;
     928             :     }
     929             : 
     930        9584 :     bool isDOMClass() const {
     931        9584 :         return flags & JSCLASS_IS_DOMJSCLASS;
     932             :     }
     933             : 
     934      178162 :     bool shouldDelayMetadataBuilder() const {
     935      178162 :         return flags & JSCLASS_DELAY_METADATA_BUILDER;
     936             :     }
     937             : 
     938      127538 :     bool isWrappedNative() const {
     939      127538 :         return flags & JSCLASS_IS_WRAPPED_NATIVE;
     940             :     }
     941             : 
     942         126 :     static size_t offsetOfFlags() { return offsetof(Class, flags); }
     943             : 
     944        1796 :     bool specDefined()         const { return spec ? spec->defined()   : false; }
     945          71 :     JSProtoKey specInheritanceProtoKey()
     946          71 :                                const { return spec ? spec->inheritanceProtoKey() : JSProto_Null; }
     947        1403 :     bool specShouldDefineConstructor()
     948        1403 :                                const { return spec ? spec->shouldDefineConstructor() : true; }
     949        1414 :     ClassObjectCreationOp specCreateConstructorHook()
     950        1414 :                                const { return spec ? spec->createConstructor        : nullptr; }
     951        1414 :     ClassObjectCreationOp specCreatePrototypeHook()
     952        1414 :                                const { return spec ? spec->createPrototype          : nullptr; }
     953        1405 :     const JSFunctionSpec* specConstructorFunctions()
     954        1405 :                                const { return spec ? spec->constructorFunctions     : nullptr; }
     955        1405 :     const JSPropertySpec* specConstructorProperties()
     956        1405 :                                const { return spec ? spec->constructorProperties    : nullptr; }
     957        1448 :     const JSFunctionSpec* specPrototypeFunctions()
     958        1448 :                                const { return spec ? spec->prototypeFunctions       : nullptr; }
     959        1448 :     const JSPropertySpec* specPrototypeProperties()
     960        1448 :                                const { return spec ? spec->prototypeProperties      : nullptr; }
     961        1403 :     FinishClassInitOp specFinishInitHook()
     962        1403 :                                const { return spec ? spec->finishInit               : nullptr; }
     963             : 
     964         117 :     JSWeakmapKeyDelegateOp extWeakmapKeyDelegateOp()
     965         117 :                                const { return ext ? ext->weakmapKeyDelegateOp        : nullptr; }
     966       25276 :     JSObjectMovedOp extObjectMovedOp()
     967       25276 :                                const { return ext ? ext->objectMovedOp               : nullptr; }
     968             : 
     969       49334 :     LookupPropertyOp getOpsLookupProperty() const { return oOps ? oOps->lookupProperty : nullptr; }
     970       98392 :     DefinePropertyOp getOpsDefineProperty() const { return oOps ? oOps->defineProperty : nullptr; }
     971       20665 :     HasPropertyOp    getOpsHasProperty()    const { return oOps ? oOps->hasProperty    : nullptr; }
     972       98787 :     GetPropertyOp    getOpsGetProperty()    const { return oOps ? oOps->getProperty    : nullptr; }
     973       10540 :     SetPropertyOp    getOpsSetProperty()    const { return oOps ? oOps->setProperty    : nullptr; }
     974       20160 :     GetOwnPropertyOp getOpsGetOwnPropertyDescriptor()
     975       20160 :                                             const { return oOps ? oOps->getOwnPropertyDescriptor
     976       20160 :                                                                                      : nullptr; }
     977         874 :     DeletePropertyOp getOpsDeleteProperty() const { return oOps ? oOps->deleteProperty : nullptr; }
     978           0 :     WatchOp          getOpsWatch()          const { return oOps ? oOps->watch          : nullptr; }
     979           0 :     UnwatchOp        getOpsUnwatch()        const { return oOps ? oOps->unwatch        : nullptr; }
     980          84 :     GetElementsOp    getOpsGetElements()    const { return oOps ? oOps->getElements    : nullptr; }
     981           0 :     JSFunToStringOp  getOpsFunToString()    const { return oOps ? oOps->funToString    : nullptr; }
     982             : };
     983             : 
     984             : static_assert(offsetof(JSClassOps, addProperty) == offsetof(ClassOps, addProperty),
     985             :               "ClassOps and JSClassOps must be consistent");
     986             : static_assert(offsetof(JSClassOps, delProperty) == offsetof(ClassOps, delProperty),
     987             :               "ClassOps and JSClassOps must be consistent");
     988             : static_assert(offsetof(JSClassOps, getProperty) == offsetof(ClassOps, getProperty),
     989             :               "ClassOps and JSClassOps must be consistent");
     990             : static_assert(offsetof(JSClassOps, setProperty) == offsetof(ClassOps, setProperty),
     991             :               "ClassOps and JSClassOps must be consistent");
     992             : static_assert(offsetof(JSClassOps, enumerate) == offsetof(ClassOps, enumerate),
     993             :               "ClassOps and JSClassOps must be consistent");
     994             : static_assert(offsetof(JSClassOps, newEnumerate) == offsetof(ClassOps, newEnumerate),
     995             :               "ClassOps and JSClassOps must be consistent");
     996             : static_assert(offsetof(JSClassOps, resolve) == offsetof(ClassOps, resolve),
     997             :               "ClassOps and JSClassOps must be consistent");
     998             : static_assert(offsetof(JSClassOps, mayResolve) == offsetof(ClassOps, mayResolve),
     999             :               "ClassOps and JSClassOps must be consistent");
    1000             : static_assert(offsetof(JSClassOps, finalize) == offsetof(ClassOps, finalize),
    1001             :               "ClassOps and JSClassOps must be consistent");
    1002             : static_assert(offsetof(JSClassOps, call) == offsetof(ClassOps, call),
    1003             :               "ClassOps and JSClassOps must be consistent");
    1004             : static_assert(offsetof(JSClassOps, construct) == offsetof(ClassOps, construct),
    1005             :               "ClassOps and JSClassOps must be consistent");
    1006             : static_assert(offsetof(JSClassOps, hasInstance) == offsetof(ClassOps, hasInstance),
    1007             :               "ClassOps and JSClassOps must be consistent");
    1008             : static_assert(offsetof(JSClassOps, trace) == offsetof(ClassOps, trace),
    1009             :               "ClassOps and JSClassOps must be consistent");
    1010             : static_assert(sizeof(JSClassOps) == sizeof(ClassOps),
    1011             :               "ClassOps and JSClassOps must be consistent");
    1012             : 
    1013             : static_assert(offsetof(JSClass, name) == offsetof(Class, name),
    1014             :               "Class and JSClass must be consistent");
    1015             : static_assert(offsetof(JSClass, flags) == offsetof(Class, flags),
    1016             :               "Class and JSClass must be consistent");
    1017             : static_assert(offsetof(JSClass, cOps) == offsetof(Class, cOps),
    1018             :               "Class and JSClass must be consistent");
    1019             : static_assert(sizeof(JSClass) == sizeof(Class),
    1020             :               "Class and JSClass must be consistent");
    1021             : 
    1022             : static MOZ_ALWAYS_INLINE const JSClass*
    1023       65702 : Jsvalify(const Class* c)
    1024             : {
    1025       65702 :     return (const JSClass*)c;
    1026             : }
    1027             : 
    1028             : static MOZ_ALWAYS_INLINE const Class*
    1029        9199 : Valueify(const JSClass* c)
    1030             : {
    1031        9199 :     return (const Class*)c;
    1032             : }
    1033             : 
    1034             : /**
    1035             :  * Enumeration describing possible values of the [[Class]] internal property
    1036             :  * value of objects.
    1037             :  */
    1038             : enum class ESClass {
    1039             :     Object,
    1040             :     Array,
    1041             :     Number,
    1042             :     String,
    1043             :     Boolean,
    1044             :     RegExp,
    1045             :     ArrayBuffer,
    1046             :     SharedArrayBuffer,
    1047             :     Date,
    1048             :     Set,
    1049             :     Map,
    1050             :     Promise,
    1051             :     MapIterator,
    1052             :     SetIterator,
    1053             :     Arguments,
    1054             :     Error,
    1055             : 
    1056             :     /** None of the above. */
    1057             :     Other
    1058             : };
    1059             : 
    1060             : /* Fills |vp| with the unboxed value for boxed types, or undefined otherwise. */
    1061             : bool
    1062             : Unbox(JSContext* cx, JS::HandleObject obj, JS::MutableHandleValue vp);
    1063             : 
    1064             : #ifdef DEBUG
    1065             : JS_FRIEND_API(bool)
    1066             : HasObjectMovedOp(JSObject* obj);
    1067             : #endif
    1068             : 
    1069             : }  /* namespace js */
    1070             : 
    1071             : #endif  /* js_Class_h */

Generated by: LCOV version 1.13