js/public/Class.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /* JSClass definition and its component types, plus related interfaces. */
michael@0 8
michael@0 9 #ifndef js_Class_h
michael@0 10 #define js_Class_h
michael@0 11
michael@0 12 #include "mozilla/NullPtr.h"
michael@0 13
michael@0 14 #include "jstypes.h"
michael@0 15
michael@0 16 #include "js/CallArgs.h"
michael@0 17 #include "js/Id.h"
michael@0 18 #include "js/TypeDecls.h"
michael@0 19
michael@0 20 /*
michael@0 21 * A JSClass acts as a vtable for JS objects that allows JSAPI clients to
michael@0 22 * control various aspects of the behavior of an object like property lookup.
michael@0 23 * js::Class is an engine-private extension that allows more control over
michael@0 24 * object behavior and, e.g., allows custom slow layout.
michael@0 25 */
michael@0 26
michael@0 27 class JSFreeOp;
michael@0 28 struct JSFunctionSpec;
michael@0 29
michael@0 30 namespace js {
michael@0 31
michael@0 32 class Class;
michael@0 33 class FreeOp;
michael@0 34 class PropertyName;
michael@0 35 class Shape;
michael@0 36
michael@0 37 // This is equal to JSFunction::class_. Use it in places where you don't want
michael@0 38 // to #include jsfun.h.
michael@0 39 extern JS_FRIEND_DATA(const js::Class* const) FunctionClassPtr;
michael@0 40
michael@0 41 } // namespace js
michael@0 42
michael@0 43 // JSClass operation signatures.
michael@0 44
michael@0 45 // Add or get a property named by id in obj. Note the jsid id type -- id may
michael@0 46 // be a string (Unicode property identifier) or an int (element index). The
michael@0 47 // *vp out parameter, on success, is the new property value after the action.
michael@0 48 typedef bool
michael@0 49 (* JSPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
michael@0 50 JS::MutableHandleValue vp);
michael@0 51
michael@0 52 // Set a property named by id in obj, treating the assignment as strict
michael@0 53 // mode code if strict is true. Note the jsid id type -- id may be a string
michael@0 54 // (Unicode property identifier) or an int (element index). The *vp out
michael@0 55 // parameter, on success, is the new property value after the
michael@0 56 // set.
michael@0 57 typedef bool
michael@0 58 (* JSStrictPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
michael@0 59 bool strict, JS::MutableHandleValue vp);
michael@0 60
michael@0 61 // Delete a property named by id in obj.
michael@0 62 //
michael@0 63 // If an error occurred, return false as per normal JSAPI error practice.
michael@0 64 //
michael@0 65 // If no error occurred, but the deletion attempt wasn't allowed (perhaps
michael@0 66 // because the property was non-configurable), set *succeeded to false and
michael@0 67 // return true. This will cause |delete obj[id]| to evaluate to false in
michael@0 68 // non-strict mode code, and to throw a TypeError in strict mode code.
michael@0 69 //
michael@0 70 // If no error occurred and the deletion wasn't disallowed (this is *not* the
michael@0 71 // same as saying that a deletion actually occurred -- deleting a non-existent
michael@0 72 // property, or an inherited property, is allowed -- it's just pointless),
michael@0 73 // set *succeeded to true and return true.
michael@0 74 typedef bool
michael@0 75 (* JSDeletePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
michael@0 76 bool *succeeded);
michael@0 77
michael@0 78 // This function type is used for callbacks that enumerate the properties of
michael@0 79 // a JSObject. The behavior depends on the value of enum_op:
michael@0 80 //
michael@0 81 // JSENUMERATE_INIT
michael@0 82 // A new, opaque iterator state should be allocated and stored in *statep.
michael@0 83 // (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
michael@0 84 //
michael@0 85 // The number of properties that will be enumerated should be returned as
michael@0 86 // an integer jsval in *idp, if idp is non-null, and provided the number of
michael@0 87 // enumerable properties is known. If idp is non-null and the number of
michael@0 88 // enumerable properties can't be computed in advance, *idp should be set
michael@0 89 // to JSVAL_ZERO.
michael@0 90 //
michael@0 91 // JSENUMERATE_INIT_ALL
michael@0 92 // Used identically to JSENUMERATE_INIT, but exposes all properties of the
michael@0 93 // object regardless of enumerability.
michael@0 94 //
michael@0 95 // JSENUMERATE_NEXT
michael@0 96 // A previously allocated opaque iterator state is passed in via statep.
michael@0 97 // Return the next jsid in the iteration using *idp. The opaque iterator
michael@0 98 // state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
michael@0 99 // if there are no properties left to enumerate.
michael@0 100 //
michael@0 101 // JSENUMERATE_DESTROY
michael@0 102 // Destroy the opaque iterator state previously allocated in *statep by a
michael@0 103 // call to this function when enum_op was JSENUMERATE_INIT or
michael@0 104 // JSENUMERATE_INIT_ALL.
michael@0 105 //
michael@0 106 // The return value is used to indicate success, with a value of false
michael@0 107 // indicating failure.
michael@0 108 typedef bool
michael@0 109 (* JSNewEnumerateOp)(JSContext *cx, JS::HandleObject obj, JSIterateOp enum_op,
michael@0 110 JS::MutableHandleValue statep, JS::MutableHandleId idp);
michael@0 111
michael@0 112 // The old-style JSClass.enumerate op should define all lazy properties not
michael@0 113 // yet reflected in obj.
michael@0 114 typedef bool
michael@0 115 (* JSEnumerateOp)(JSContext *cx, JS::HandleObject obj);
michael@0 116
michael@0 117 // Resolve a lazy property named by id in obj by defining it directly in obj.
michael@0 118 // Lazy properties are those reflected from some peer native property space
michael@0 119 // (e.g., the DOM attributes for a given node reflected as obj) on demand.
michael@0 120 //
michael@0 121 // JS looks for a property in an object, and if not found, tries to resolve
michael@0 122 // the given id. If resolve succeeds, the engine looks again in case resolve
michael@0 123 // defined obj[id]. If no such property exists directly in obj, the process
michael@0 124 // is repeated with obj's prototype, etc.
michael@0 125 //
michael@0 126 // NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
michael@0 127 typedef bool
michael@0 128 (* JSResolveOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
michael@0 129
michael@0 130 // Like JSResolveOp, except the *objp out parameter, on success, should be null
michael@0 131 // to indicate that id was not resolved; and non-null, referring to obj or one
michael@0 132 // of its prototypes, if id was resolved. The hook may assume *objp is null on
michael@0 133 // entry.
michael@0 134 //
michael@0 135 // This hook instead of JSResolveOp is called via the JSClass.resolve member
michael@0 136 // if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
michael@0 137 typedef bool
michael@0 138 (* JSNewResolveOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
michael@0 139 JS::MutableHandleObject objp);
michael@0 140
michael@0 141 // Convert obj to the given type, returning true with the resulting value in
michael@0 142 // *vp on success, and returning false on error or exception.
michael@0 143 typedef bool
michael@0 144 (* JSConvertOp)(JSContext *cx, JS::HandleObject obj, JSType type,
michael@0 145 JS::MutableHandleValue vp);
michael@0 146
michael@0 147 // Finalize obj, which the garbage collector has determined to be unreachable
michael@0 148 // from other live objects or from GC roots. Obviously, finalizers must never
michael@0 149 // store a reference to obj.
michael@0 150 typedef void
michael@0 151 (* JSFinalizeOp)(JSFreeOp *fop, JSObject *obj);
michael@0 152
michael@0 153 // Finalizes external strings created by JS_NewExternalString.
michael@0 154 struct JSStringFinalizer {
michael@0 155 void (*finalize)(const JSStringFinalizer *fin, jschar *chars);
michael@0 156 };
michael@0 157
michael@0 158 // Check whether v is an instance of obj. Return false on error or exception,
michael@0 159 // true on success with true in *bp if v is an instance of obj, false in
michael@0 160 // *bp otherwise.
michael@0 161 typedef bool
michael@0 162 (* JSHasInstanceOp)(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue vp,
michael@0 163 bool *bp);
michael@0 164
michael@0 165 // Function type for trace operation of the class called to enumerate all
michael@0 166 // traceable things reachable from obj's private data structure. For each such
michael@0 167 // thing, a trace implementation must call one of the JS_Call*Tracer variants
michael@0 168 // on the thing.
michael@0 169 //
michael@0 170 // JSTraceOp implementation can assume that no other threads mutates object
michael@0 171 // state. It must not change state of the object or corresponding native
michael@0 172 // structures. The only exception for this rule is the case when the embedding
michael@0 173 // needs a tight integration with GC. In that case the embedding can check if
michael@0 174 // the traversal is a part of the marking phase through calling
michael@0 175 // JS_IsGCMarkingTracer and apply a special code like emptying caches or
michael@0 176 // marking its native structures.
michael@0 177 typedef void
michael@0 178 (* JSTraceOp)(JSTracer *trc, JSObject *obj);
michael@0 179
michael@0 180 // A generic type for functions mapping an object to another object, or null
michael@0 181 // if an error or exception was thrown on cx.
michael@0 182 typedef JSObject *
michael@0 183 (* JSObjectOp)(JSContext *cx, JS::HandleObject obj);
michael@0 184
michael@0 185 // Hook that creates an iterator object for a given object. Returns the
michael@0 186 // iterator object or null if an error or exception was thrown on cx.
michael@0 187 typedef JSObject *
michael@0 188 (* JSIteratorOp)(JSContext *cx, JS::HandleObject obj, bool keysonly);
michael@0 189
michael@0 190 typedef JSObject *
michael@0 191 (* JSWeakmapKeyDelegateOp)(JSObject *obj);
michael@0 192
michael@0 193 /* js::Class operation signatures. */
michael@0 194
michael@0 195 namespace js {
michael@0 196
michael@0 197 typedef bool
michael@0 198 (* LookupGenericOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
michael@0 199 JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
michael@0 200 typedef bool
michael@0 201 (* LookupPropOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
michael@0 202 JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
michael@0 203 typedef bool
michael@0 204 (* LookupElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index,
michael@0 205 JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
michael@0 206 typedef bool
michael@0 207 (* DefineGenericOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
michael@0 208 JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
michael@0 209 typedef bool
michael@0 210 (* DefinePropOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
michael@0 211 JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
michael@0 212 unsigned attrs);
michael@0 213 typedef bool
michael@0 214 (* DefineElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
michael@0 215 JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
michael@0 216 typedef bool
michael@0 217 (* GenericIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
michael@0 218 JS::MutableHandleValue vp);
michael@0 219 typedef bool
michael@0 220 (* PropertyIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
michael@0 221 JS::Handle<PropertyName*> name, JS::MutableHandleValue vp);
michael@0 222 typedef bool
michael@0 223 (* ElementIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, uint32_t index,
michael@0 224 JS::MutableHandleValue vp);
michael@0 225 typedef bool
michael@0 226 (* StrictGenericIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
michael@0 227 JS::MutableHandleValue vp, bool strict);
michael@0 228 typedef bool
michael@0 229 (* StrictPropertyIdOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
michael@0 230 JS::MutableHandleValue vp, bool strict);
michael@0 231 typedef bool
michael@0 232 (* StrictElementIdOp)(JSContext *cx, JS::HandleObject obj, uint32_t index,
michael@0 233 JS::MutableHandleValue vp, bool strict);
michael@0 234 typedef bool
michael@0 235 (* GenericAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
michael@0 236 typedef bool
michael@0 237 (* PropertyAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
michael@0 238 unsigned *attrsp);
michael@0 239 typedef bool
michael@0 240 (* DeletePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
michael@0 241 bool *succeeded);
michael@0 242 typedef bool
michael@0 243 (* DeleteElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded);
michael@0 244
michael@0 245 typedef bool
michael@0 246 (* WatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
michael@0 247
michael@0 248 typedef bool
michael@0 249 (* UnwatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
michael@0 250
michael@0 251 typedef bool
michael@0 252 (* SliceOp)(JSContext *cx, JS::HandleObject obj, uint32_t begin, uint32_t end,
michael@0 253 JS::HandleObject result); // result is actually preallocted.
michael@0 254
michael@0 255 typedef JSObject *
michael@0 256 (* ObjectOp)(JSContext *cx, JS::HandleObject obj);
michael@0 257 typedef void
michael@0 258 (* FinalizeOp)(FreeOp *fop, JSObject *obj);
michael@0 259
michael@0 260 #define JS_CLASS_MEMBERS(FinalizeOpType) \
michael@0 261 const char *name; \
michael@0 262 uint32_t flags; \
michael@0 263 \
michael@0 264 /* Mandatory function pointer members. */ \
michael@0 265 JSPropertyOp addProperty; \
michael@0 266 JSDeletePropertyOp delProperty; \
michael@0 267 JSPropertyOp getProperty; \
michael@0 268 JSStrictPropertyOp setProperty; \
michael@0 269 JSEnumerateOp enumerate; \
michael@0 270 JSResolveOp resolve; \
michael@0 271 JSConvertOp convert; \
michael@0 272 \
michael@0 273 /* Optional members (may be null). */ \
michael@0 274 FinalizeOpType finalize; \
michael@0 275 JSNative call; \
michael@0 276 JSHasInstanceOp hasInstance; \
michael@0 277 JSNative construct; \
michael@0 278 JSTraceOp trace
michael@0 279
michael@0 280 // Callback for the creation of constructor and prototype objects.
michael@0 281 typedef JSObject *(*ClassObjectCreationOp)(JSContext *cx, JSProtoKey key);
michael@0 282
michael@0 283 // Callback for custom post-processing after class initialization via ClassSpec.
michael@0 284 typedef bool (*FinishClassInitOp)(JSContext *cx, JS::HandleObject ctor,
michael@0 285 JS::HandleObject proto);
michael@0 286
michael@0 287 struct ClassSpec
michael@0 288 {
michael@0 289 ClassObjectCreationOp createConstructor;
michael@0 290 ClassObjectCreationOp createPrototype;
michael@0 291 const JSFunctionSpec *constructorFunctions;
michael@0 292 const JSFunctionSpec *prototypeFunctions;
michael@0 293 FinishClassInitOp finishInit;
michael@0 294 bool defined() const { return !!createConstructor; }
michael@0 295 };
michael@0 296
michael@0 297 struct ClassExtension
michael@0 298 {
michael@0 299 JSObjectOp outerObject;
michael@0 300 JSObjectOp innerObject;
michael@0 301 JSIteratorOp iteratorObject;
michael@0 302
michael@0 303 /*
michael@0 304 * isWrappedNative is true only if the class is an XPCWrappedNative.
michael@0 305 * WeakMaps use this to override the wrapper disposal optimization.
michael@0 306 */
michael@0 307 bool isWrappedNative;
michael@0 308
michael@0 309 /*
michael@0 310 * If an object is used as a key in a weakmap, it may be desirable for the
michael@0 311 * garbage collector to keep that object around longer than it otherwise
michael@0 312 * would. A common case is when the key is a wrapper around an object in
michael@0 313 * another compartment, and we want to avoid collecting the wrapper (and
michael@0 314 * removing the weakmap entry) as long as the wrapped object is alive. In
michael@0 315 * that case, the wrapped object is returned by the wrapper's
michael@0 316 * weakmapKeyDelegateOp hook. As long as the wrapper is used as a weakmap
michael@0 317 * key, it will not be collected (and remain in the weakmap) until the
michael@0 318 * wrapped object is collected.
michael@0 319 */
michael@0 320 JSWeakmapKeyDelegateOp weakmapKeyDelegateOp;
michael@0 321 };
michael@0 322
michael@0 323 #define JS_NULL_CLASS_SPEC {nullptr,nullptr,nullptr,nullptr,nullptr}
michael@0 324 #define JS_NULL_CLASS_EXT {nullptr,nullptr,nullptr,false,nullptr}
michael@0 325
michael@0 326 struct ObjectOps
michael@0 327 {
michael@0 328 LookupGenericOp lookupGeneric;
michael@0 329 LookupPropOp lookupProperty;
michael@0 330 LookupElementOp lookupElement;
michael@0 331 DefineGenericOp defineGeneric;
michael@0 332 DefinePropOp defineProperty;
michael@0 333 DefineElementOp defineElement;
michael@0 334 GenericIdOp getGeneric;
michael@0 335 PropertyIdOp getProperty;
michael@0 336 ElementIdOp getElement;
michael@0 337 StrictGenericIdOp setGeneric;
michael@0 338 StrictPropertyIdOp setProperty;
michael@0 339 StrictElementIdOp setElement;
michael@0 340 GenericAttributesOp getGenericAttributes;
michael@0 341 GenericAttributesOp setGenericAttributes;
michael@0 342 DeletePropertyOp deleteProperty;
michael@0 343 DeleteElementOp deleteElement;
michael@0 344 WatchOp watch;
michael@0 345 UnwatchOp unwatch;
michael@0 346 SliceOp slice; // Optimized slice, can be null.
michael@0 347
michael@0 348 JSNewEnumerateOp enumerate;
michael@0 349 ObjectOp thisObject;
michael@0 350 };
michael@0 351
michael@0 352 #define JS_NULL_OBJECT_OPS \
michael@0 353 {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \
michael@0 354 nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \
michael@0 355 nullptr,nullptr}
michael@0 356
michael@0 357 } // namespace js
michael@0 358
michael@0 359 // Classes, objects, and properties.
michael@0 360
michael@0 361 typedef void (*JSClassInternal)();
michael@0 362
michael@0 363 struct JSClass {
michael@0 364 JS_CLASS_MEMBERS(JSFinalizeOp);
michael@0 365
michael@0 366 void *reserved[31];
michael@0 367 };
michael@0 368
michael@0 369 #define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot
michael@0 370 #define JSCLASS_NEW_ENUMERATE (1<<1) // has JSNewEnumerateOp hook
michael@0 371 #define JSCLASS_NEW_RESOLVE (1<<2) // has JSNewResolveOp hook
michael@0 372 #define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) // private is (nsISupports *)
michael@0 373 #define JSCLASS_IS_DOMJSCLASS (1<<4) // objects are DOM
michael@0 374 #define JSCLASS_IMPLEMENTS_BARRIERS (1<<5) // Correctly implements GC read
michael@0 375 // and write barriers
michael@0 376 #define JSCLASS_EMULATES_UNDEFINED (1<<6) // objects of this class act
michael@0 377 // like the value undefined,
michael@0 378 // in some contexts
michael@0 379 #define JSCLASS_USERBIT1 (1<<7) // Reserved for embeddings.
michael@0 380
michael@0 381 // To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or
michael@0 382 // JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where
michael@0 383 // n is a constant in [1, 255]. Reserved slots are indexed from 0 to n-1.
michael@0 384 #define JSCLASS_RESERVED_SLOTS_SHIFT 8 // room for 8 flags below */
michael@0 385 #define JSCLASS_RESERVED_SLOTS_WIDTH 8 // and 16 above this field */
michael@0 386 #define JSCLASS_RESERVED_SLOTS_MASK JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH)
michael@0 387 #define JSCLASS_HAS_RESERVED_SLOTS(n) (((n) & JSCLASS_RESERVED_SLOTS_MASK) \
michael@0 388 << JSCLASS_RESERVED_SLOTS_SHIFT)
michael@0 389 #define JSCLASS_RESERVED_SLOTS(clasp) (((clasp)->flags \
michael@0 390 >> JSCLASS_RESERVED_SLOTS_SHIFT) \
michael@0 391 & JSCLASS_RESERVED_SLOTS_MASK)
michael@0 392
michael@0 393 #define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \
michael@0 394 JSCLASS_RESERVED_SLOTS_WIDTH)
michael@0 395
michael@0 396 #define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
michael@0 397 #define JSCLASS_IS_GLOBAL (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1))
michael@0 398 #define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2))
michael@0 399 #define JSCLASS_INTERNAL_FLAG3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
michael@0 400
michael@0 401 #define JSCLASS_IS_PROXY (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
michael@0 402
michael@0 403 // Bit 22 unused.
michael@0 404
michael@0 405 // Reserved for embeddings.
michael@0 406 #define JSCLASS_USERBIT2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6))
michael@0 407 #define JSCLASS_USERBIT3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+7))
michael@0 408
michael@0 409 #define JSCLASS_BACKGROUND_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+8))
michael@0 410
michael@0 411 // Bits 26 through 31 are reserved for the CACHED_PROTO_KEY mechanism, see
michael@0 412 // below.
michael@0 413
michael@0 414 // ECMA-262 requires that most constructors used internally create objects
michael@0 415 // with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
michael@0 416 // member initial value. The "original ... value" verbiage is there because
michael@0 417 // in ECMA-262, global properties naming class objects are read/write and
michael@0 418 // deleteable, for the most part.
michael@0 419 //
michael@0 420 // Implementing this efficiently requires that global objects have classes
michael@0 421 // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
michael@0 422 // previously allowed, but is now an ES5 violation and thus unsupported.
michael@0 423 //
michael@0 424 #define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 31)
michael@0 425 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
michael@0 426 (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
michael@0 427 #define JSCLASS_GLOBAL_FLAGS \
michael@0 428 JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
michael@0 429 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp) \
michael@0 430 (((clasp)->flags & JSCLASS_IS_GLOBAL) \
michael@0 431 && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
michael@0 432
michael@0 433 // Fast access to the original value of each standard class's prototype.
michael@0 434 #define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 10)
michael@0 435 #define JSCLASS_CACHED_PROTO_WIDTH 6
michael@0 436 #define JSCLASS_CACHED_PROTO_MASK JS_BITMASK(JSCLASS_CACHED_PROTO_WIDTH)
michael@0 437 #define JSCLASS_HAS_CACHED_PROTO(key) (uint32_t(key) << JSCLASS_CACHED_PROTO_SHIFT)
michael@0 438 #define JSCLASS_CACHED_PROTO_KEY(clasp) ((JSProtoKey) \
michael@0 439 (((clasp)->flags \
michael@0 440 >> JSCLASS_CACHED_PROTO_SHIFT) \
michael@0 441 & JSCLASS_CACHED_PROTO_MASK))
michael@0 442
michael@0 443 // Initializer for unused members of statically initialized JSClass structs.
michael@0 444 #define JSCLASS_NO_INTERNAL_MEMBERS {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
michael@0 445 #define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,JSCLASS_NO_INTERNAL_MEMBERS
michael@0 446
michael@0 447 namespace js {
michael@0 448
michael@0 449 struct Class
michael@0 450 {
michael@0 451 JS_CLASS_MEMBERS(FinalizeOp);
michael@0 452 ClassSpec spec;
michael@0 453 ClassExtension ext;
michael@0 454 ObjectOps ops;
michael@0 455
michael@0 456 /* Class is not native and its map is not a scope. */
michael@0 457 static const uint32_t NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
michael@0 458
michael@0 459 bool isNative() const {
michael@0 460 return !(flags & NON_NATIVE);
michael@0 461 }
michael@0 462
michael@0 463 bool hasPrivate() const {
michael@0 464 return !!(flags & JSCLASS_HAS_PRIVATE);
michael@0 465 }
michael@0 466
michael@0 467 bool emulatesUndefined() const {
michael@0 468 return flags & JSCLASS_EMULATES_UNDEFINED;
michael@0 469 }
michael@0 470
michael@0 471 bool isJSFunction() const {
michael@0 472 return this == js::FunctionClassPtr;
michael@0 473 }
michael@0 474
michael@0 475 bool isCallable() const {
michael@0 476 return isJSFunction() || call;
michael@0 477 }
michael@0 478
michael@0 479 bool isProxy() const {
michael@0 480 return flags & JSCLASS_IS_PROXY;
michael@0 481 }
michael@0 482
michael@0 483 bool isDOMClass() const {
michael@0 484 return flags & JSCLASS_IS_DOMJSCLASS;
michael@0 485 }
michael@0 486
michael@0 487 static size_t offsetOfFlags() { return offsetof(Class, flags); }
michael@0 488 };
michael@0 489
michael@0 490 JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name));
michael@0 491 JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags));
michael@0 492 JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty));
michael@0 493 JS_STATIC_ASSERT(offsetof(JSClass, delProperty) == offsetof(Class, delProperty));
michael@0 494 JS_STATIC_ASSERT(offsetof(JSClass, getProperty) == offsetof(Class, getProperty));
michael@0 495 JS_STATIC_ASSERT(offsetof(JSClass, setProperty) == offsetof(Class, setProperty));
michael@0 496 JS_STATIC_ASSERT(offsetof(JSClass, enumerate) == offsetof(Class, enumerate));
michael@0 497 JS_STATIC_ASSERT(offsetof(JSClass, resolve) == offsetof(Class, resolve));
michael@0 498 JS_STATIC_ASSERT(offsetof(JSClass, convert) == offsetof(Class, convert));
michael@0 499 JS_STATIC_ASSERT(offsetof(JSClass, finalize) == offsetof(Class, finalize));
michael@0 500 JS_STATIC_ASSERT(offsetof(JSClass, call) == offsetof(Class, call));
michael@0 501 JS_STATIC_ASSERT(offsetof(JSClass, construct) == offsetof(Class, construct));
michael@0 502 JS_STATIC_ASSERT(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance));
michael@0 503 JS_STATIC_ASSERT(offsetof(JSClass, trace) == offsetof(Class, trace));
michael@0 504 JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class));
michael@0 505
michael@0 506 static MOZ_ALWAYS_INLINE const JSClass *
michael@0 507 Jsvalify(const Class *c)
michael@0 508 {
michael@0 509 return (const JSClass *)c;
michael@0 510 }
michael@0 511
michael@0 512 static MOZ_ALWAYS_INLINE const Class *
michael@0 513 Valueify(const JSClass *c)
michael@0 514 {
michael@0 515 return (const Class *)c;
michael@0 516 }
michael@0 517
michael@0 518 /*
michael@0 519 * Enumeration describing possible values of the [[Class]] internal property
michael@0 520 * value of objects.
michael@0 521 */
michael@0 522 enum ESClassValue {
michael@0 523 ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean,
michael@0 524 ESClass_RegExp, ESClass_ArrayBuffer, ESClass_Date
michael@0 525 };
michael@0 526
michael@0 527 /*
michael@0 528 * Return whether the given object has the given [[Class]] internal property
michael@0 529 * value. Beware, this query says nothing about the js::Class of the JSObject
michael@0 530 * so the caller must not assume anything about obj's representation (e.g., obj
michael@0 531 * may be a proxy).
michael@0 532 */
michael@0 533 inline bool
michael@0 534 ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx);
michael@0 535
michael@0 536 /* Just a helper that checks v.isObject before calling ObjectClassIs. */
michael@0 537 inline bool
michael@0 538 IsObjectWithClass(const JS::Value &v, ESClassValue classValue, JSContext *cx);
michael@0 539
michael@0 540 } /* namespace js */
michael@0 541
michael@0 542 #endif /* js_Class_h */

mercurial