1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/public/Class.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,542 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* JSClass definition and its component types, plus related interfaces. */ 1.11 + 1.12 +#ifndef js_Class_h 1.13 +#define js_Class_h 1.14 + 1.15 +#include "mozilla/NullPtr.h" 1.16 + 1.17 +#include "jstypes.h" 1.18 + 1.19 +#include "js/CallArgs.h" 1.20 +#include "js/Id.h" 1.21 +#include "js/TypeDecls.h" 1.22 + 1.23 +/* 1.24 + * A JSClass acts as a vtable for JS objects that allows JSAPI clients to 1.25 + * control various aspects of the behavior of an object like property lookup. 1.26 + * js::Class is an engine-private extension that allows more control over 1.27 + * object behavior and, e.g., allows custom slow layout. 1.28 + */ 1.29 + 1.30 +class JSFreeOp; 1.31 +struct JSFunctionSpec; 1.32 + 1.33 +namespace js { 1.34 + 1.35 +class Class; 1.36 +class FreeOp; 1.37 +class PropertyName; 1.38 +class Shape; 1.39 + 1.40 +// This is equal to JSFunction::class_. Use it in places where you don't want 1.41 +// to #include jsfun.h. 1.42 +extern JS_FRIEND_DATA(const js::Class* const) FunctionClassPtr; 1.43 + 1.44 +} // namespace js 1.45 + 1.46 +// JSClass operation signatures. 1.47 + 1.48 +// Add or get a property named by id in obj. Note the jsid id type -- id may 1.49 +// be a string (Unicode property identifier) or an int (element index). The 1.50 +// *vp out parameter, on success, is the new property value after the action. 1.51 +typedef bool 1.52 +(* JSPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, 1.53 + JS::MutableHandleValue vp); 1.54 + 1.55 +// Set a property named by id in obj, treating the assignment as strict 1.56 +// mode code if strict is true. Note the jsid id type -- id may be a string 1.57 +// (Unicode property identifier) or an int (element index). The *vp out 1.58 +// parameter, on success, is the new property value after the 1.59 +// set. 1.60 +typedef bool 1.61 +(* JSStrictPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, 1.62 + bool strict, JS::MutableHandleValue vp); 1.63 + 1.64 +// Delete a property named by id in obj. 1.65 +// 1.66 +// If an error occurred, return false as per normal JSAPI error practice. 1.67 +// 1.68 +// If no error occurred, but the deletion attempt wasn't allowed (perhaps 1.69 +// because the property was non-configurable), set *succeeded to false and 1.70 +// return true. This will cause |delete obj[id]| to evaluate to false in 1.71 +// non-strict mode code, and to throw a TypeError in strict mode code. 1.72 +// 1.73 +// If no error occurred and the deletion wasn't disallowed (this is *not* the 1.74 +// same as saying that a deletion actually occurred -- deleting a non-existent 1.75 +// property, or an inherited property, is allowed -- it's just pointless), 1.76 +// set *succeeded to true and return true. 1.77 +typedef bool 1.78 +(* JSDeletePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, 1.79 + bool *succeeded); 1.80 + 1.81 +// This function type is used for callbacks that enumerate the properties of 1.82 +// a JSObject. The behavior depends on the value of enum_op: 1.83 +// 1.84 +// JSENUMERATE_INIT 1.85 +// A new, opaque iterator state should be allocated and stored in *statep. 1.86 +// (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored). 1.87 +// 1.88 +// The number of properties that will be enumerated should be returned as 1.89 +// an integer jsval in *idp, if idp is non-null, and provided the number of 1.90 +// enumerable properties is known. If idp is non-null and the number of 1.91 +// enumerable properties can't be computed in advance, *idp should be set 1.92 +// to JSVAL_ZERO. 1.93 +// 1.94 +// JSENUMERATE_INIT_ALL 1.95 +// Used identically to JSENUMERATE_INIT, but exposes all properties of the 1.96 +// object regardless of enumerability. 1.97 +// 1.98 +// JSENUMERATE_NEXT 1.99 +// A previously allocated opaque iterator state is passed in via statep. 1.100 +// Return the next jsid in the iteration using *idp. The opaque iterator 1.101 +// state pointed at by statep is destroyed and *statep is set to JSVAL_NULL 1.102 +// if there are no properties left to enumerate. 1.103 +// 1.104 +// JSENUMERATE_DESTROY 1.105 +// Destroy the opaque iterator state previously allocated in *statep by a 1.106 +// call to this function when enum_op was JSENUMERATE_INIT or 1.107 +// JSENUMERATE_INIT_ALL. 1.108 +// 1.109 +// The return value is used to indicate success, with a value of false 1.110 +// indicating failure. 1.111 +typedef bool 1.112 +(* JSNewEnumerateOp)(JSContext *cx, JS::HandleObject obj, JSIterateOp enum_op, 1.113 + JS::MutableHandleValue statep, JS::MutableHandleId idp); 1.114 + 1.115 +// The old-style JSClass.enumerate op should define all lazy properties not 1.116 +// yet reflected in obj. 1.117 +typedef bool 1.118 +(* JSEnumerateOp)(JSContext *cx, JS::HandleObject obj); 1.119 + 1.120 +// Resolve a lazy property named by id in obj by defining it directly in obj. 1.121 +// Lazy properties are those reflected from some peer native property space 1.122 +// (e.g., the DOM attributes for a given node reflected as obj) on demand. 1.123 +// 1.124 +// JS looks for a property in an object, and if not found, tries to resolve 1.125 +// the given id. If resolve succeeds, the engine looks again in case resolve 1.126 +// defined obj[id]. If no such property exists directly in obj, the process 1.127 +// is repeated with obj's prototype, etc. 1.128 +// 1.129 +// NB: JSNewResolveOp provides a cheaper way to resolve lazy properties. 1.130 +typedef bool 1.131 +(* JSResolveOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id); 1.132 + 1.133 +// Like JSResolveOp, except the *objp out parameter, on success, should be null 1.134 +// to indicate that id was not resolved; and non-null, referring to obj or one 1.135 +// of its prototypes, if id was resolved. The hook may assume *objp is null on 1.136 +// entry. 1.137 +// 1.138 +// This hook instead of JSResolveOp is called via the JSClass.resolve member 1.139 +// if JSCLASS_NEW_RESOLVE is set in JSClass.flags. 1.140 +typedef bool 1.141 +(* JSNewResolveOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, 1.142 + JS::MutableHandleObject objp); 1.143 + 1.144 +// Convert obj to the given type, returning true with the resulting value in 1.145 +// *vp on success, and returning false on error or exception. 1.146 +typedef bool 1.147 +(* JSConvertOp)(JSContext *cx, JS::HandleObject obj, JSType type, 1.148 + JS::MutableHandleValue vp); 1.149 + 1.150 +// Finalize obj, which the garbage collector has determined to be unreachable 1.151 +// from other live objects or from GC roots. Obviously, finalizers must never 1.152 +// store a reference to obj. 1.153 +typedef void 1.154 +(* JSFinalizeOp)(JSFreeOp *fop, JSObject *obj); 1.155 + 1.156 +// Finalizes external strings created by JS_NewExternalString. 1.157 +struct JSStringFinalizer { 1.158 + void (*finalize)(const JSStringFinalizer *fin, jschar *chars); 1.159 +}; 1.160 + 1.161 +// Check whether v is an instance of obj. Return false on error or exception, 1.162 +// true on success with true in *bp if v is an instance of obj, false in 1.163 +// *bp otherwise. 1.164 +typedef bool 1.165 +(* JSHasInstanceOp)(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue vp, 1.166 + bool *bp); 1.167 + 1.168 +// Function type for trace operation of the class called to enumerate all 1.169 +// traceable things reachable from obj's private data structure. For each such 1.170 +// thing, a trace implementation must call one of the JS_Call*Tracer variants 1.171 +// on the thing. 1.172 +// 1.173 +// JSTraceOp implementation can assume that no other threads mutates object 1.174 +// state. It must not change state of the object or corresponding native 1.175 +// structures. The only exception for this rule is the case when the embedding 1.176 +// needs a tight integration with GC. In that case the embedding can check if 1.177 +// the traversal is a part of the marking phase through calling 1.178 +// JS_IsGCMarkingTracer and apply a special code like emptying caches or 1.179 +// marking its native structures. 1.180 +typedef void 1.181 +(* JSTraceOp)(JSTracer *trc, JSObject *obj); 1.182 + 1.183 +// A generic type for functions mapping an object to another object, or null 1.184 +// if an error or exception was thrown on cx. 1.185 +typedef JSObject * 1.186 +(* JSObjectOp)(JSContext *cx, JS::HandleObject obj); 1.187 + 1.188 +// Hook that creates an iterator object for a given object. Returns the 1.189 +// iterator object or null if an error or exception was thrown on cx. 1.190 +typedef JSObject * 1.191 +(* JSIteratorOp)(JSContext *cx, JS::HandleObject obj, bool keysonly); 1.192 + 1.193 +typedef JSObject * 1.194 +(* JSWeakmapKeyDelegateOp)(JSObject *obj); 1.195 + 1.196 +/* js::Class operation signatures. */ 1.197 + 1.198 +namespace js { 1.199 + 1.200 +typedef bool 1.201 +(* LookupGenericOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, 1.202 + JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp); 1.203 +typedef bool 1.204 +(* LookupPropOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name, 1.205 + JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp); 1.206 +typedef bool 1.207 +(* LookupElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, 1.208 + JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp); 1.209 +typedef bool 1.210 +(* DefineGenericOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value, 1.211 + JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs); 1.212 +typedef bool 1.213 +(* DefinePropOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name, 1.214 + JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter, 1.215 + unsigned attrs); 1.216 +typedef bool 1.217 +(* DefineElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value, 1.218 + JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs); 1.219 +typedef bool 1.220 +(* GenericIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id, 1.221 + JS::MutableHandleValue vp); 1.222 +typedef bool 1.223 +(* PropertyIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, 1.224 + JS::Handle<PropertyName*> name, JS::MutableHandleValue vp); 1.225 +typedef bool 1.226 +(* ElementIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, uint32_t index, 1.227 + JS::MutableHandleValue vp); 1.228 +typedef bool 1.229 +(* StrictGenericIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, 1.230 + JS::MutableHandleValue vp, bool strict); 1.231 +typedef bool 1.232 +(* StrictPropertyIdOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name, 1.233 + JS::MutableHandleValue vp, bool strict); 1.234 +typedef bool 1.235 +(* StrictElementIdOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, 1.236 + JS::MutableHandleValue vp, bool strict); 1.237 +typedef bool 1.238 +(* GenericAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp); 1.239 +typedef bool 1.240 +(* PropertyAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name, 1.241 + unsigned *attrsp); 1.242 +typedef bool 1.243 +(* DeletePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name, 1.244 + bool *succeeded); 1.245 +typedef bool 1.246 +(* DeleteElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded); 1.247 + 1.248 +typedef bool 1.249 +(* WatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable); 1.250 + 1.251 +typedef bool 1.252 +(* UnwatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id); 1.253 + 1.254 +typedef bool 1.255 +(* SliceOp)(JSContext *cx, JS::HandleObject obj, uint32_t begin, uint32_t end, 1.256 + JS::HandleObject result); // result is actually preallocted. 1.257 + 1.258 +typedef JSObject * 1.259 +(* ObjectOp)(JSContext *cx, JS::HandleObject obj); 1.260 +typedef void 1.261 +(* FinalizeOp)(FreeOp *fop, JSObject *obj); 1.262 + 1.263 +#define JS_CLASS_MEMBERS(FinalizeOpType) \ 1.264 + const char *name; \ 1.265 + uint32_t flags; \ 1.266 + \ 1.267 + /* Mandatory function pointer members. */ \ 1.268 + JSPropertyOp addProperty; \ 1.269 + JSDeletePropertyOp delProperty; \ 1.270 + JSPropertyOp getProperty; \ 1.271 + JSStrictPropertyOp setProperty; \ 1.272 + JSEnumerateOp enumerate; \ 1.273 + JSResolveOp resolve; \ 1.274 + JSConvertOp convert; \ 1.275 + \ 1.276 + /* Optional members (may be null). */ \ 1.277 + FinalizeOpType finalize; \ 1.278 + JSNative call; \ 1.279 + JSHasInstanceOp hasInstance; \ 1.280 + JSNative construct; \ 1.281 + JSTraceOp trace 1.282 + 1.283 +// Callback for the creation of constructor and prototype objects. 1.284 +typedef JSObject *(*ClassObjectCreationOp)(JSContext *cx, JSProtoKey key); 1.285 + 1.286 +// Callback for custom post-processing after class initialization via ClassSpec. 1.287 +typedef bool (*FinishClassInitOp)(JSContext *cx, JS::HandleObject ctor, 1.288 + JS::HandleObject proto); 1.289 + 1.290 +struct ClassSpec 1.291 +{ 1.292 + ClassObjectCreationOp createConstructor; 1.293 + ClassObjectCreationOp createPrototype; 1.294 + const JSFunctionSpec *constructorFunctions; 1.295 + const JSFunctionSpec *prototypeFunctions; 1.296 + FinishClassInitOp finishInit; 1.297 + bool defined() const { return !!createConstructor; } 1.298 +}; 1.299 + 1.300 +struct ClassExtension 1.301 +{ 1.302 + JSObjectOp outerObject; 1.303 + JSObjectOp innerObject; 1.304 + JSIteratorOp iteratorObject; 1.305 + 1.306 + /* 1.307 + * isWrappedNative is true only if the class is an XPCWrappedNative. 1.308 + * WeakMaps use this to override the wrapper disposal optimization. 1.309 + */ 1.310 + bool isWrappedNative; 1.311 + 1.312 + /* 1.313 + * If an object is used as a key in a weakmap, it may be desirable for the 1.314 + * garbage collector to keep that object around longer than it otherwise 1.315 + * would. A common case is when the key is a wrapper around an object in 1.316 + * another compartment, and we want to avoid collecting the wrapper (and 1.317 + * removing the weakmap entry) as long as the wrapped object is alive. In 1.318 + * that case, the wrapped object is returned by the wrapper's 1.319 + * weakmapKeyDelegateOp hook. As long as the wrapper is used as a weakmap 1.320 + * key, it will not be collected (and remain in the weakmap) until the 1.321 + * wrapped object is collected. 1.322 + */ 1.323 + JSWeakmapKeyDelegateOp weakmapKeyDelegateOp; 1.324 +}; 1.325 + 1.326 +#define JS_NULL_CLASS_SPEC {nullptr,nullptr,nullptr,nullptr,nullptr} 1.327 +#define JS_NULL_CLASS_EXT {nullptr,nullptr,nullptr,false,nullptr} 1.328 + 1.329 +struct ObjectOps 1.330 +{ 1.331 + LookupGenericOp lookupGeneric; 1.332 + LookupPropOp lookupProperty; 1.333 + LookupElementOp lookupElement; 1.334 + DefineGenericOp defineGeneric; 1.335 + DefinePropOp defineProperty; 1.336 + DefineElementOp defineElement; 1.337 + GenericIdOp getGeneric; 1.338 + PropertyIdOp getProperty; 1.339 + ElementIdOp getElement; 1.340 + StrictGenericIdOp setGeneric; 1.341 + StrictPropertyIdOp setProperty; 1.342 + StrictElementIdOp setElement; 1.343 + GenericAttributesOp getGenericAttributes; 1.344 + GenericAttributesOp setGenericAttributes; 1.345 + DeletePropertyOp deleteProperty; 1.346 + DeleteElementOp deleteElement; 1.347 + WatchOp watch; 1.348 + UnwatchOp unwatch; 1.349 + SliceOp slice; // Optimized slice, can be null. 1.350 + 1.351 + JSNewEnumerateOp enumerate; 1.352 + ObjectOp thisObject; 1.353 +}; 1.354 + 1.355 +#define JS_NULL_OBJECT_OPS \ 1.356 + {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \ 1.357 + nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \ 1.358 + nullptr,nullptr} 1.359 + 1.360 +} // namespace js 1.361 + 1.362 +// Classes, objects, and properties. 1.363 + 1.364 +typedef void (*JSClassInternal)(); 1.365 + 1.366 +struct JSClass { 1.367 + JS_CLASS_MEMBERS(JSFinalizeOp); 1.368 + 1.369 + void *reserved[31]; 1.370 +}; 1.371 + 1.372 +#define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot 1.373 +#define JSCLASS_NEW_ENUMERATE (1<<1) // has JSNewEnumerateOp hook 1.374 +#define JSCLASS_NEW_RESOLVE (1<<2) // has JSNewResolveOp hook 1.375 +#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) // private is (nsISupports *) 1.376 +#define JSCLASS_IS_DOMJSCLASS (1<<4) // objects are DOM 1.377 +#define JSCLASS_IMPLEMENTS_BARRIERS (1<<5) // Correctly implements GC read 1.378 + // and write barriers 1.379 +#define JSCLASS_EMULATES_UNDEFINED (1<<6) // objects of this class act 1.380 + // like the value undefined, 1.381 + // in some contexts 1.382 +#define JSCLASS_USERBIT1 (1<<7) // Reserved for embeddings. 1.383 + 1.384 +// To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or 1.385 +// JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where 1.386 +// n is a constant in [1, 255]. Reserved slots are indexed from 0 to n-1. 1.387 +#define JSCLASS_RESERVED_SLOTS_SHIFT 8 // room for 8 flags below */ 1.388 +#define JSCLASS_RESERVED_SLOTS_WIDTH 8 // and 16 above this field */ 1.389 +#define JSCLASS_RESERVED_SLOTS_MASK JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH) 1.390 +#define JSCLASS_HAS_RESERVED_SLOTS(n) (((n) & JSCLASS_RESERVED_SLOTS_MASK) \ 1.391 + << JSCLASS_RESERVED_SLOTS_SHIFT) 1.392 +#define JSCLASS_RESERVED_SLOTS(clasp) (((clasp)->flags \ 1.393 + >> JSCLASS_RESERVED_SLOTS_SHIFT) \ 1.394 + & JSCLASS_RESERVED_SLOTS_MASK) 1.395 + 1.396 +#define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \ 1.397 + JSCLASS_RESERVED_SLOTS_WIDTH) 1.398 + 1.399 +#define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0)) 1.400 +#define JSCLASS_IS_GLOBAL (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1)) 1.401 +#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2)) 1.402 +#define JSCLASS_INTERNAL_FLAG3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3)) 1.403 + 1.404 +#define JSCLASS_IS_PROXY (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4)) 1.405 + 1.406 +// Bit 22 unused. 1.407 + 1.408 +// Reserved for embeddings. 1.409 +#define JSCLASS_USERBIT2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6)) 1.410 +#define JSCLASS_USERBIT3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+7)) 1.411 + 1.412 +#define JSCLASS_BACKGROUND_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+8)) 1.413 + 1.414 +// Bits 26 through 31 are reserved for the CACHED_PROTO_KEY mechanism, see 1.415 +// below. 1.416 + 1.417 +// ECMA-262 requires that most constructors used internally create objects 1.418 +// with "the original Foo.prototype value" as their [[Prototype]] (__proto__) 1.419 +// member initial value. The "original ... value" verbiage is there because 1.420 +// in ECMA-262, global properties naming class objects are read/write and 1.421 +// deleteable, for the most part. 1.422 +// 1.423 +// Implementing this efficiently requires that global objects have classes 1.424 +// with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was 1.425 +// previously allowed, but is now an ES5 violation and thus unsupported. 1.426 +// 1.427 +#define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 31) 1.428 +#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \ 1.429 + (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n))) 1.430 +#define JSCLASS_GLOBAL_FLAGS \ 1.431 + JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0) 1.432 +#define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp) \ 1.433 + (((clasp)->flags & JSCLASS_IS_GLOBAL) \ 1.434 + && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT) 1.435 + 1.436 +// Fast access to the original value of each standard class's prototype. 1.437 +#define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 10) 1.438 +#define JSCLASS_CACHED_PROTO_WIDTH 6 1.439 +#define JSCLASS_CACHED_PROTO_MASK JS_BITMASK(JSCLASS_CACHED_PROTO_WIDTH) 1.440 +#define JSCLASS_HAS_CACHED_PROTO(key) (uint32_t(key) << JSCLASS_CACHED_PROTO_SHIFT) 1.441 +#define JSCLASS_CACHED_PROTO_KEY(clasp) ((JSProtoKey) \ 1.442 + (((clasp)->flags \ 1.443 + >> JSCLASS_CACHED_PROTO_SHIFT) \ 1.444 + & JSCLASS_CACHED_PROTO_MASK)) 1.445 + 1.446 +// Initializer for unused members of statically initialized JSClass structs. 1.447 +#define JSCLASS_NO_INTERNAL_MEMBERS {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} 1.448 +#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,JSCLASS_NO_INTERNAL_MEMBERS 1.449 + 1.450 +namespace js { 1.451 + 1.452 +struct Class 1.453 +{ 1.454 + JS_CLASS_MEMBERS(FinalizeOp); 1.455 + ClassSpec spec; 1.456 + ClassExtension ext; 1.457 + ObjectOps ops; 1.458 + 1.459 + /* Class is not native and its map is not a scope. */ 1.460 + static const uint32_t NON_NATIVE = JSCLASS_INTERNAL_FLAG2; 1.461 + 1.462 + bool isNative() const { 1.463 + return !(flags & NON_NATIVE); 1.464 + } 1.465 + 1.466 + bool hasPrivate() const { 1.467 + return !!(flags & JSCLASS_HAS_PRIVATE); 1.468 + } 1.469 + 1.470 + bool emulatesUndefined() const { 1.471 + return flags & JSCLASS_EMULATES_UNDEFINED; 1.472 + } 1.473 + 1.474 + bool isJSFunction() const { 1.475 + return this == js::FunctionClassPtr; 1.476 + } 1.477 + 1.478 + bool isCallable() const { 1.479 + return isJSFunction() || call; 1.480 + } 1.481 + 1.482 + bool isProxy() const { 1.483 + return flags & JSCLASS_IS_PROXY; 1.484 + } 1.485 + 1.486 + bool isDOMClass() const { 1.487 + return flags & JSCLASS_IS_DOMJSCLASS; 1.488 + } 1.489 + 1.490 + static size_t offsetOfFlags() { return offsetof(Class, flags); } 1.491 +}; 1.492 + 1.493 +JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name)); 1.494 +JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags)); 1.495 +JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty)); 1.496 +JS_STATIC_ASSERT(offsetof(JSClass, delProperty) == offsetof(Class, delProperty)); 1.497 +JS_STATIC_ASSERT(offsetof(JSClass, getProperty) == offsetof(Class, getProperty)); 1.498 +JS_STATIC_ASSERT(offsetof(JSClass, setProperty) == offsetof(Class, setProperty)); 1.499 +JS_STATIC_ASSERT(offsetof(JSClass, enumerate) == offsetof(Class, enumerate)); 1.500 +JS_STATIC_ASSERT(offsetof(JSClass, resolve) == offsetof(Class, resolve)); 1.501 +JS_STATIC_ASSERT(offsetof(JSClass, convert) == offsetof(Class, convert)); 1.502 +JS_STATIC_ASSERT(offsetof(JSClass, finalize) == offsetof(Class, finalize)); 1.503 +JS_STATIC_ASSERT(offsetof(JSClass, call) == offsetof(Class, call)); 1.504 +JS_STATIC_ASSERT(offsetof(JSClass, construct) == offsetof(Class, construct)); 1.505 +JS_STATIC_ASSERT(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance)); 1.506 +JS_STATIC_ASSERT(offsetof(JSClass, trace) == offsetof(Class, trace)); 1.507 +JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class)); 1.508 + 1.509 +static MOZ_ALWAYS_INLINE const JSClass * 1.510 +Jsvalify(const Class *c) 1.511 +{ 1.512 + return (const JSClass *)c; 1.513 +} 1.514 + 1.515 +static MOZ_ALWAYS_INLINE const Class * 1.516 +Valueify(const JSClass *c) 1.517 +{ 1.518 + return (const Class *)c; 1.519 +} 1.520 + 1.521 +/* 1.522 + * Enumeration describing possible values of the [[Class]] internal property 1.523 + * value of objects. 1.524 + */ 1.525 +enum ESClassValue { 1.526 + ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean, 1.527 + ESClass_RegExp, ESClass_ArrayBuffer, ESClass_Date 1.528 +}; 1.529 + 1.530 +/* 1.531 + * Return whether the given object has the given [[Class]] internal property 1.532 + * value. Beware, this query says nothing about the js::Class of the JSObject 1.533 + * so the caller must not assume anything about obj's representation (e.g., obj 1.534 + * may be a proxy). 1.535 + */ 1.536 +inline bool 1.537 +ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx); 1.538 + 1.539 +/* Just a helper that checks v.isObject before calling ObjectClassIs. */ 1.540 +inline bool 1.541 +IsObjectWithClass(const JS::Value &v, ESClassValue classValue, JSContext *cx); 1.542 + 1.543 +} /* namespace js */ 1.544 + 1.545 +#endif /* js_Class_h */