From 181c2cdf3a8cd9d5e404f229d42c1ee18dbef767 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Wed, 28 Jul 2010 14:36:06 +0200 Subject: [PATCH] Backed out changeset 7b2b90efe57d -- the patch was landed against a tree with a lot of orange. This will hinder the orange resolution. --- caps/src/nsScriptSecurityManager.cpp | 6 +- content/base/src/nsContentUtils.cpp | 5 +- dom/base/nsDOMWindowUtils.cpp | 12 +- js/ipc/ObjectWrapperParent.cpp | 50 ++- js/ipc/ObjectWrapperParent.h | 3 +- js/jsd/jsd_val.c | 18 +- js/src/jsapi-tests/testExtendedEq.cpp | 38 +- js/src/jsapi.cpp | 57 +-- js/src/jsapi.h | 69 +-- js/src/jsarray.cpp | 78 ++-- js/src/jsbool.cpp | 11 +- js/src/jsbuiltins.cpp | 2 +- js/src/jsdate.cpp | 10 +- js/src/jsexn.cpp | 19 +- js/src/jsfun.cpp | 79 ++-- js/src/jsgc.cpp | 3 +- js/src/jsinterp.cpp | 38 +- js/src/jsiter.cpp | 150 +++---- js/src/jsiter.h | 6 +- js/src/jslock.h | 4 +- js/src/jsmath.cpp | 10 +- js/src/jsnum.cpp | 10 +- js/src/jsobj.cpp | 171 ++++---- js/src/jsobj.h | 211 +++++---- js/src/jsobjinlines.h | 22 +- js/src/json.cpp | 10 +- js/src/jsproxy.cpp | 162 ++++--- js/src/jsprvtd.h | 21 - js/src/jspubtd.h | 44 +- js/src/jsregexp.cpp | 23 +- js/src/jsscope.cpp | 37 +- js/src/jsscope.h | 15 +- js/src/jsscopeinlines.h | 2 +- js/src/jsscript.cpp | 19 +- js/src/jsstr.cpp | 10 +- js/src/jstracer.cpp | 28 +- js/src/jstypedarray.cpp | 84 ++-- js/src/jsvalue.h | 134 +++--- js/src/jswrapper.cpp | 2 +- js/src/jsxml.cpp | 263 +++++------ js/src/jsxml.h | 21 +- js/src/shell/js.cpp | 80 ++-- .../xpconnect/loader/mozJSSubScriptLoader.cpp | 14 +- .../xpconnect/src/XPCChromeObjectWrapper.cpp | 64 +-- .../xpconnect/src/XPCCrossOriginWrapper.cpp | 74 ++-- js/src/xpconnect/src/XPCNativeWrapper.cpp | 97 ++-- js/src/xpconnect/src/XPCNativeWrapper.h | 16 +- .../xpconnect/src/XPCSafeJSObjectWrapper.cpp | 59 ++- js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp | 91 ++-- js/src/xpconnect/src/XPCWrapper.cpp | 55 +-- js/src/xpconnect/src/XPCWrapper.h | 16 +- js/src/xpconnect/src/nsXPConnect.cpp | 15 +- js/src/xpconnect/src/xpcJSWeakReference.cpp | 4 +- js/src/xpconnect/src/xpccomponents.cpp | 10 +- js/src/xpconnect/src/xpcprivate.h | 82 +--- js/src/xpconnect/src/xpcquickstubs.cpp | 8 +- js/src/xpconnect/src/xpcwrappednative.cpp | 23 +- .../xpconnect/src/xpcwrappednativejsops.cpp | 414 ++++++++++-------- .../xpconnect/src/xpcwrappednativeproto.cpp | 4 +- .../xpconnect/src/xpcwrappednativescope.cpp | 25 +- 60 files changed, 1506 insertions(+), 1602 deletions(-) diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index 2f3441aa6ee..36ae51c1f91 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -2417,7 +2417,11 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj // NOTE: These class and equality hook checks better match // what IS_WRAPPER_CLASS() does in xpconnect! - if (jsClass->ext.equality == js::Valueify(sXPCWrappedNativeEqualityOps)) { + JSEqualityOp op = + (jsClass->flags & JSCLASS_IS_EXTENDED) ? + reinterpret_cast(jsClass)->equality : + nsnull; + if (op == sXPCWrappedNativeEqualityOps) { result = sXPConnect->GetPrincipal(aObj, #ifdef DEBUG aAllowShortCircuit diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 8be6b2ef02a..b8cc7b4fc65 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -5703,8 +5703,11 @@ CloneSimpleValues(JSContext* cx, } // Security wrapped objects are not allowed either. - if (obj->getClass()->ext.wrappedObject) + JSClass* clasp = JS_GET_CLASS(cx, obj); + if ((clasp->flags & JSCLASS_IS_EXTENDED) && + ((JSExtendedClass*)clasp)->wrappedObject) { return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } // See if this JSObject is backed by some C++ object. If it is then we assume // that it is inappropriate to clone. diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index e05d88ea06e..79150c9c880 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -72,8 +72,6 @@ #include #endif -#include "jsobj.h" - static PRBool IsUniversalXPConnectCapable() { PRBool hasCap = PR_FALSE; @@ -1349,10 +1347,14 @@ nsDOMWindowUtils::GetParent() JSObject *parent = JS_GetParent(cx, JSVAL_TO_OBJECT(argv[0])); *rval = OBJECT_TO_JSVAL(parent); - // Outerize if necessary. + // Outerize if necessary. Embrace the ugliness! if (parent) { - if (JSObjectOp outerize = parent->getClass()->ext.outerObject) - *rval = OBJECT_TO_JSVAL(outerize(cx, parent)); + JSClass* clasp = JS_GET_CLASS(cx, parent); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + JSExtendedClass* xclasp = reinterpret_cast(clasp); + if (JSObjectOp outerize = xclasp->outerObject) + *rval = OBJECT_TO_JSVAL(outerize(cx, parent)); + } } cc->SetReturnValueWasSet(PR_TRUE); diff --git a/js/ipc/ObjectWrapperParent.cpp b/js/ipc/ObjectWrapperParent.cpp index 0f63d586523..6c9c6cefd48 100644 --- a/js/ipc/ObjectWrapperParent.cpp +++ b/js/ipc/ObjectWrapperParent.cpp @@ -169,32 +169,36 @@ with_error(JSContext* cx, return rval; } -const js::Class ObjectWrapperParent::sCPOW_JSClass = { - "CrossProcessObjectWrapper", - JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | +const JSExtendedClass ObjectWrapperParent::sCPOW_JSClass = { + // JSClass (JSExtendedClass.base) initialization + { "CrossProcessObjectWrapper", + JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_IS_EXTENDED | JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(sNumSlots), - js::Valueify(ObjectWrapperParent::CPOW_AddProperty), - js::Valueify(ObjectWrapperParent::CPOW_DelProperty), - js::Valueify(ObjectWrapperParent::CPOW_GetProperty), - js::Valueify(ObjectWrapperParent::CPOW_SetProperty), + ObjectWrapperParent::CPOW_AddProperty, + ObjectWrapperParent::CPOW_DelProperty, + ObjectWrapperParent::CPOW_GetProperty, + ObjectWrapperParent::CPOW_SetProperty, (JSEnumerateOp) ObjectWrapperParent::CPOW_NewEnumerate, - (JSResolveOp) ObjectWrapperParent::CPOW_NewResolve, - js::Valueify(ObjectWrapperParent::CPOW_Convert), + (JSResolveOp) ObjectWrapperParent::CPOW_NewResolve, + ObjectWrapperParent::CPOW_Convert, ObjectWrapperParent::CPOW_Finalize, - nsnull, // reserved1 + nsnull, // getObjectOps nsnull, // checkAccess - js::Valueify(ObjectWrapperParent::CPOW_Call), - js::Valueify(ObjectWrapperParent::CPOW_Construct), + ObjectWrapperParent::CPOW_Call, + ObjectWrapperParent::CPOW_Construct, nsnull, // xdrObject - js::Valueify(ObjectWrapperParent::CPOW_HasInstance), + ObjectWrapperParent::CPOW_HasInstance, nsnull, // mark - { - js::Valueify(ObjectWrapperParent::CPOW_Equality), - nsnull, // outerObject - nsnull, // innerObject - nsnull, // iteratorObject - nsnull, // wrappedObject - } + nsnull, // reserveSlots + }, + + // JSExtendedClass initialization + ObjectWrapperParent::CPOW_Equality, + nsnull, // outerObject + nsnull, // innerObject + nsnull, // iterator + nsnull, // wrappedObject + JSCLASS_NO_RESERVED_MEMBERS }; void @@ -216,8 +220,8 @@ ObjectWrapperParent::Manager() JSObject* ObjectWrapperParent::GetJSObject(JSContext* cx) const { - js::Class *clasp = const_cast(&ObjectWrapperParent::sCPOW_JSClass); - if (!mObj && (mObj = JS_NewObject(cx, js::Jsvalify(clasp), NULL, NULL))) { + JSClass* clasp = const_cast(&ObjectWrapperParent::sCPOW_JSClass.base); + if (!mObj && (mObj = JS_NewObject(cx, clasp, NULL, NULL))) { JS_SetPrivate(cx, mObj, (void*)this); JS_SetReservedSlot(cx, mObj, sFlagsSlot, JSVAL_ZERO); } @@ -227,7 +231,7 @@ ObjectWrapperParent::GetJSObject(JSContext* cx) const static ObjectWrapperParent* Unwrap(JSContext* cx, JSObject* obj) { - while (obj->getClass() != &ObjectWrapperParent::sCPOW_JSClass) + while (obj->getJSClass() != &ObjectWrapperParent::sCPOW_JSClass.base) if (!(obj = obj->getProto())) return NULL; diff --git a/js/ipc/ObjectWrapperParent.h b/js/ipc/ObjectWrapperParent.h index 8856160b088..da90172b26b 100644 --- a/js/ipc/ObjectWrapperParent.h +++ b/js/ipc/ObjectWrapperParent.h @@ -43,7 +43,6 @@ #include "mozilla/jsipc/PObjectWrapperParent.h" #include "jsapi.h" -#include "jsvalue.h" #include "nsAutoJSValHolder.h" namespace mozilla { @@ -76,7 +75,7 @@ public: void CheckOperation(JSContext* cx, OperationStatus* status); - static const js::Class sCPOW_JSClass; + static const JSExtendedClass sCPOW_JSClass; protected: diff --git a/js/jsd/jsd_val.c b/js/jsd/jsd_val.c index f756eda6773..44a33f95112 100644 --- a/js/jsd/jsd_val.c +++ b/js/jsd/jsd_val.c @@ -42,7 +42,20 @@ #include "jsd.h" #include "jsapi.h" #include "jspubtd.h" -#include "jsprvtd.h" + +/* + * Lifted with slight modification from jsobj.h + */ + +#define OBJ_TO_OUTER_OBJECT(cx, obj) \ +do { \ + JSClass *clasp_ = JS_GetClass(cx, obj); \ + if (clasp_->flags & JSCLASS_IS_EXTENDED) { \ + JSExtendedClass *xclasp_ = (JSExtendedClass*) clasp_; \ + if (xclasp_->outerObject) \ + obj = xclasp_->outerObject(cx, obj); \ + } \ +} while(0) #ifdef DEBUG void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval) @@ -301,7 +314,8 @@ jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval) jsval val = jsdval->val; if (!JSVAL_IS_PRIMITIVE(val)) { cx = JSD_GetDefaultJSContext(jsdc); - obj = js_ObjectToOuterObject(cx, JSVAL_TO_OBJECT(val)); + obj = JSVAL_TO_OBJECT(val); + OBJ_TO_OUTER_OBJECT(cx, obj); if (!obj) { JS_ClearPendingException(cx); diff --git a/js/src/jsapi-tests/testExtendedEq.cpp b/js/src/jsapi-tests/testExtendedEq.cpp index 40d32e02faa..d8b7c4c381d 100644 --- a/js/src/jsapi-tests/testExtendedEq.cpp +++ b/js/src/jsapi-tests/testExtendedEq.cpp @@ -6,7 +6,6 @@ */ #include "tests.h" -#include "jsobj.h" static JSBool my_Equality(JSContext *cx, JSObject *obj, const jsval *, JSBool *bp) @@ -15,37 +14,24 @@ my_Equality(JSContext *cx, JSObject *obj, const jsval *, JSBool *bp) return JS_TRUE; } -js::Class TestExtendedEq_JSClass = { - "TestExtendedEq", - 0, - js::PropertyStub, /* addProperty */ - js::PropertyStub, /* delProperty */ - js::PropertyStub, /* getProperty */ - js::PropertyStub, /* setProperty */ - JS_EnumerateStub, - JS_ResolveStub, - NULL, /* convert */ - NULL, /* finalize */ - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* mark */ - { - js::Valueify(my_Equality), - NULL, /* outerObject */ - NULL, /* innerObject */ - NULL, /* iteratorObject */ - NULL, /* wrappedObject */ - } +JSExtendedClass TestExtendedEq_JSClass = { + { "TestExtendedEq", + JSCLASS_IS_EXTENDED, + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL + }, + // JSExtendedClass initialization + my_Equality, + NULL, NULL, NULL, NULL, JSCLASS_NO_RESERVED_MEMBERS }; BEGIN_TEST(testExtendedEq_bug530489) { JSClass *clasp = (JSClass *) &TestExtendedEq_JSClass; + JSObject *global = JS_GetGlobalObject(cx); CHECK(JS_InitClass(cx, global, global, clasp, NULL, 0, NULL, NULL, NULL, NULL)); CHECK(JS_DefineObject(cx, global, "obj1", clasp, NULL, 0)); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 7afc472a623..f890e45089a 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1342,10 +1342,11 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj) } #define CLASP(name) (&js_##name##Class) -#define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type]) +#define XCLASP(name) (&js_##name##Class.base) #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name) +#define EAGER_ATOM_AND_XCLASP(name) EAGER_CLASS_ATOM(name), XCLASP(name) #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str typedef struct JSStdName { @@ -1391,8 +1392,8 @@ static JSStdName standard_class_atoms[] = { {js_InitRegExpClass, EAGER_ATOM_AND_CLASP(RegExp)}, #if JS_HAS_XML_SUPPORT {js_InitXMLClass, EAGER_ATOM_AND_CLASP(XML)}, - {js_InitNamespaceClass, EAGER_ATOM_AND_CLASP(Namespace)}, - {js_InitQNameClass, EAGER_ATOM_AND_CLASP(QName)}, + {js_InitNamespaceClass, EAGER_ATOM_AND_XCLASP(Namespace)}, + {js_InitQNameClass, EAGER_ATOM_AND_XCLASP(QName)}, #endif #if JS_HAS_GENERATORS {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(StopIteration)}, @@ -1447,22 +1448,21 @@ static JSStdName standard_class_names[] = { #endif #if JS_HAS_GENERATORS - {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Iterator)}, - {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Generator)}, + {js_InitIteratorClasses, EAGER_ATOM_AND_XCLASP(Iterator)}, + {js_InitIteratorClasses, EAGER_ATOM_AND_XCLASP(Generator)}, #endif /* Typed Arrays */ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::jsclass}, - {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int8Array), TYPED_ARRAY_CLASP(TYPE_INT8)}, - {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8Array), TYPED_ARRAY_CLASP(TYPE_UINT8)}, - {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int16Array), TYPED_ARRAY_CLASP(TYPE_INT16)}, - {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint16Array), TYPED_ARRAY_CLASP(TYPE_UINT16)}, - {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int32Array), TYPED_ARRAY_CLASP(TYPE_INT32)}, - {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint32Array), TYPED_ARRAY_CLASP(TYPE_UINT32)}, - {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float32Array), TYPED_ARRAY_CLASP(TYPE_FLOAT32)}, - {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float64Array), TYPED_ARRAY_CLASP(TYPE_FLOAT64)}, - {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8ClampedArray), - TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED)}, + {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int8Array), &TypedArray::fastClasses[TypedArray::TYPE_INT8]}, + {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8Array), &TypedArray::fastClasses[TypedArray::TYPE_UINT8]}, + {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int16Array), &TypedArray::fastClasses[TypedArray::TYPE_INT16]}, + {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint16Array), &TypedArray::fastClasses[TypedArray::TYPE_UINT16]}, + {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int32Array), &TypedArray::fastClasses[TypedArray::TYPE_INT32]}, + {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint32Array), &TypedArray::fastClasses[TypedArray::TYPE_UINT32]}, + {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float32Array), &TypedArray::fastClasses[TypedArray::TYPE_FLOAT32]}, + {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float64Array), &TypedArray::fastClasses[TypedArray::TYPE_FLOAT64]}, + {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8ClampedArray), &TypedArray::fastClasses[TypedArray::TYPE_UINT8_CLAMPED]}, {js_InitProxyClass, EAGER_ATOM_AND_CLASP(Proxy)}, @@ -3707,12 +3707,8 @@ JS_ClearScope(JSContext *cx, JSObject *obj) CHECK_REQUEST(cx); assertSameCompartment(cx, obj); - JSFinalizeOp clearOp = obj->getOps()->clear; - if (clearOp) - clearOp(cx, obj); - - if (obj->isNative()) - js_ClearNative(cx, obj); + if (obj->map->ops->clear) + obj->map->ops->clear(cx, obj); /* Clear cached class objects on the global object. */ if (obj->getClass()->flags & JSCLASS_IS_GLOBAL) { @@ -3785,21 +3781,10 @@ static Class prop_iter_class = { "PropertyIterator", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_MARK_IS_TRACE, - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - prop_iter_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - JS_CLASS_TRACE(prop_iter_trace) + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, prop_iter_finalize, + NULL, NULL, NULL, NULL, + NULL, NULL, JS_CLASS_TRACE(prop_iter_trace), NULL }; JS_PUBLIC_API(JSObject *) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 380797351c2..d37d12ce037 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1595,34 +1595,45 @@ JS_SetScriptStackQuota(JSContext *cx, size_t quota); /* * Classes, objects, and properties. */ -typedef void (*JSClassInternal)(); /* For detailed comments on the function pointer types, see jspubtd.h. */ struct JSClass { - const char *name; \ - uint32 flags; \ - \ - /* Mandatory non-null function pointer members. */ \ - JSPropertyOp addProperty; \ - JSPropertyOp delProperty; \ - JSPropertyOp getProperty; \ - JSPropertyOp setProperty; \ - JSEnumerateOp enumerate; \ - JSResolveOp resolve; \ - JSConvertOp convert; \ - JSFinalizeOp finalize; \ - \ - /* Optionally non-null members start here. */ \ - JSClassInternal reserved0; \ - JSCheckAccessOp checkAccess; \ - JSNative call; \ - JSNative construct; \ - JSXDRObjectOp xdrObject; \ - JSHasInstanceOp hasInstance; \ - JSMarkOp mark; + const char *name; + uint32 flags; - JSClassInternal reserved1; - void *reserved[19]; + /* Mandatory non-null function pointer members. */ + JSPropertyOp addProperty; + JSPropertyOp delProperty; + JSPropertyOp getProperty; + JSPropertyOp setProperty; + JSEnumerateOp enumerate; + JSResolveOp resolve; + JSConvertOp convert; + JSFinalizeOp finalize; + + /* Optionally non-null members start here. */ + JSGetObjectOps getObjectOps; + JSCheckAccessOp checkAccess; + JSNative call; + JSNative construct; + JSXDRObjectOp xdrObject; + JSHasInstanceOp hasInstance; + JSMarkOp mark; + void (*reserved0)(void); +}; + +struct JSExtendedClass { + JSClass base; + JSEqualityOp equality; + JSObjectOp outerObject; + JSObjectOp innerObject; + JSIteratorOp iteratorObject; + JSObjectOp wrappedObject; /* NB: infallible, null + returns are treated as + the original object */ + void (*reserved0)(void); + void (*reserved1)(void); + void (*reserved2)(void); }; #define JSCLASS_HAS_PRIVATE (1<<0) /* objects have private slot */ @@ -1655,13 +1666,15 @@ struct JSClass { #define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \ JSCLASS_RESERVED_SLOTS_WIDTH) -#define JSCLASS_INTERNAL_FLAG1 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0)) +/* True if JSClass is really a JSExtendedClass. */ +#define JSCLASS_IS_EXTENDED (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0)) #define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1)) #define JSCLASS_IS_GLOBAL (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2)) /* Indicates that JSClass.mark is a tracer with JSTraceOp type. */ #define JSCLASS_MARK_IS_TRACE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3)) -#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4)) + +#define JSCLASS_LAST_API_FLAG_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT+3) /* * ECMA-262 requires that most constructors used internally create objects @@ -1691,8 +1704,8 @@ struct JSClass { & JSCLASS_CACHED_PROTO_MASK)) /* Initializer for unused members of statically initialized JSClass structs. */ -#define JSCLASS_NO_INTERNAL_MEMBERS 0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} -#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,JSCLASS_NO_INTERNAL_MEMBERS +#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,0 +#define JSCLASS_NO_RESERVED_MEMBERS 0,0,0 struct JSIdArray { jsint length; diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 10da996bf72..3cddd564f58 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -1004,53 +1004,49 @@ array_trace(JSTracer *trc, JSObject *obj) } } +extern JSObjectOps js_ArrayObjectOps; + +static const JSObjectMap SharedArrayMap(&js_ArrayObjectOps, JSObjectMap::SHAPELESS); + +JSObjectOps js_ArrayObjectOps = { + &SharedArrayMap, + array_lookupProperty, + array_defineProperty, + array_getProperty, + array_setProperty, + array_getAttributes, + array_setAttributes, + array_deleteProperty, + js_Enumerate, + array_typeOf, + array_trace, + NULL, /* thisObject */ + NULL /* clear */ +}; + +static JSObjectOps * +array_getObjectOps(JSContext *cx, Class *clasp) +{ + return &js_ArrayObjectOps; +} + Class js_ArrayClass = { "Array", - Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(JSObject::DENSE_ARRAY_FIXED_RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_Array), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - js_TryValueOf, - array_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* mark */ - JS_NULL_CLASS_EXT, - { - array_lookupProperty, - array_defineProperty, - array_getProperty, - array_setProperty, - array_getAttributes, - array_setAttributes, - array_deleteProperty, - NULL, /* enumerate */ - array_typeOf, - array_trace, - NULL, /* thisObject */ - NULL, /* clear */ - } + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, js_TryValueOf, array_finalize, + array_getObjectOps, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; Class js_SlowArrayClass = { "Array", - JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array), - slowarray_addProperty, - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - js_TryValueOf + JSCLASS_HAS_PRIVATE | + JSCLASS_HAS_CACHED_PROTO(JSProto_Array), + slowarray_addProperty, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, js_TryValueOf, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; /* @@ -1076,7 +1072,7 @@ JSObject::makeDenseArraySlow(JSContext *cx) JS_ASSERT(arrayProto->getClass() == &js_SlowArrayClass); emptyShape = arrayProto->scope()->emptyScope->shape; } - JSScope *scope = JSScope::create(cx, &js_SlowArrayClass, obj, emptyShape); + JSScope *scope = JSScope::create(cx, &js_ObjectOps, &js_SlowArrayClass, obj, emptyShape); if (!scope) return JS_FALSE; @@ -2995,7 +2991,7 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto, int32 len) return NULL; /* Initialize all fields of JSObject. */ - obj->map = const_cast(&JSObjectMap::sharedNonNative); + obj->map = const_cast(&SharedArrayMap); obj->init(&js_ArrayClass, proto, proto->getParent(), NullValue()); obj->setArrayLength(len); obj->setDenseArrayCapacity(0); diff --git a/js/src/jsbool.cpp b/js/src/jsbool.cpp index 50c9384da80..82949bdd025 100644 --- a/js/src/jsbool.cpp +++ b/js/src/jsbool.cpp @@ -56,18 +56,15 @@ #include "jsobjinlines.h" + using namespace js; Class js_BooleanClass = { "Boolean", JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; #if JS_HAS_TOSOURCE diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index e2801222f07..1ddaf17762d 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -256,7 +256,7 @@ HasProperty(JSContext* cx, JSObject* obj, jsid id) { // Check that we know how the lookup op will behave. for (JSObject* pobj = obj; pobj; pobj = pobj->getProto()) { - if (pobj->getOps()->lookupProperty) + if (pobj->map->ops->lookupProperty != js_LookupProperty) return JS_NEITHER; Class* clasp = pobj->getClass(); if (clasp->resolve != JS_ResolveStub && clasp != &js_StringClass) diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp index 9c3a0074acc..9abd13b3b64 100644 --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -485,13 +485,9 @@ Class js_DateClass = { js_Date_str, JSCLASS_HAS_RESERVED_SLOTS(JSObject::DATE_FIXED_RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_Date), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; /* for use by date_parse */ diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 7a5479f909c..f16e0b28ea5 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -88,21 +88,10 @@ Class js_ErrorClass = { js_Error_str, JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Error), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - exn_enumerate, - (JSResolveOp)exn_resolve, - ConvertStub, - exn_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - Exception, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - JS_CLASS_TRACE(exn_trace) + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + exn_enumerate, (JSResolveOp)exn_resolve, ConvertStub, exn_finalize, + NULL, NULL, NULL, Exception, + NULL, NULL, JS_CLASS_TRACE(exn_trace), NULL }; typedef struct JSStackTraceElem { diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 9495db6008e..8af8a5d7a77 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -681,21 +681,14 @@ Class js_ArgumentsClass = { JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(JSObject::ARGS_FIXED_RESERVED_SLOTS) | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object), - PropertyStub, /* addProperty */ - args_delProperty, - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - args_enumerate, - (JSResolveOp) args_resolve, - ConvertStub, - NULL, /* finalize */ - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - JS_CLASS_TRACE(args_or_call_trace) + PropertyStub, args_delProperty, + PropertyStub, PropertyStub, + args_enumerate, (JSResolveOp) args_resolve, + ConvertStub, NULL, + NULL, NULL, + NULL, NULL, + NULL, NULL, + JS_CLASS_TRACE(args_or_call_trace), NULL }; const uint32 JSSLOT_CALLEE = JSSLOT_PRIVATE + 1; @@ -709,13 +702,9 @@ const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS = 2; Class js_DeclEnvClass = { js_Object_str, JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; static JSBool @@ -1273,21 +1262,14 @@ JS_PUBLIC_DATA(Class) js_CallClass = { JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(CALL_CLASS_FIXED_RESERVED_SLOTS) | JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS | JSCLASS_MARK_IS_TRACE, - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - call_enumerate, - (JSResolveOp)call_resolve, - NULL, /* convert */ - NULL, /* finalize */ - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - JS_CLASS_TRACE(args_or_call_trace) + PropertyStub, PropertyStub, + PropertyStub, PropertyStub, + call_enumerate, (JSResolveOp)call_resolve, + NULL, NULL, + NULL, NULL, + NULL, NULL, + NULL, NULL, + JS_CLASS_TRACE(args_or_call_trace), NULL }; bool @@ -1923,21 +1905,14 @@ JS_PUBLIC_DATA(Class) js_FunctionClass = { JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(JSObject::FUN_FIXED_RESERVED_SLOTS) | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Function), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - fun_enumerate, - (JSResolveOp)fun_resolve, - ConvertStub, - fun_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - js_XDRFunctionObject, - fun_hasInstance, - JS_CLASS_TRACE(fun_trace) + PropertyStub, PropertyStub, + PropertyStub, PropertyStub, + fun_enumerate, (JSResolveOp)fun_resolve, + ConvertStub, fun_finalize, + NULL, NULL, + NULL, NULL, + js_XDRFunctionObject, fun_hasInstance, + JS_CLASS_TRACE(fun_trace), NULL }; namespace js { diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 63f2e611713..b7fd54dc75e 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1855,8 +1855,7 @@ JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind) JSObject *obj = (JSObject *) thing; if (!obj->map) break; - JSTraceOp op = obj->getOps()->trace; - (op ? op : js_TraceObject)(trc, obj); + obj->map->ops->trace(trc, obj); break; } diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index edaedaa36aa..aefdd244b67 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -336,13 +336,9 @@ const uint32 JSSLOT_SAVED_ID = JSSLOT_PRIVATE + 1; Class js_NoSuchMethodClass = { "NoSuchMethod", JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS, - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* @@ -624,7 +620,7 @@ DoSlowCall(JSContext *cx, uintN argc, Value *vp) JSObject *callee = &JS_CALLEE(cx, vp).toObject(); Class *clasp = callee->getClass(); - JS_ASSERT(!(clasp->flags & Class::CALL_IS_FAST)); + JS_ASSERT(!(clasp->flags & CLASS_CALL_IS_FAST)); if (!clasp->call) { js_ReportIsNotFunction(cx, &vp[0], 0); return JS_FALSE; @@ -727,7 +723,7 @@ Invoke(JSContext *cx, const InvokeArgsGuard &args, uintN flags) } return InvokeCommon(cx, NULL, NULL, DoConstruct, args, flags); } - CallOp callOp = (clasp->flags & Class::CALL_IS_FAST) ? (CallOp) clasp->call : DoSlowCall; + CallOp callOp = (clasp->flags & CLASS_CALL_IS_FAST) ? (CallOp) clasp->call : DoSlowCall; return InvokeCommon(cx, NULL, NULL, callOp, args, flags); } @@ -877,7 +873,7 @@ Execute(JSContext *cx, JSObject *chain, JSScript *script, ? chain->getGlobal() : chain; } - JS_ASSERT(!initialVarObj->getOps()->defineProperty); + JS_ASSERT(initialVarObj->map->ops->defineProperty == js_DefineProperty); fp->script = script; fp->imacpc = NULL; @@ -1116,7 +1112,7 @@ TypeOfValue(JSContext *cx, const Value &vref) if (v.isUndefined()) return JSTYPE_VOID; if (v.isObject()) - return v.toObject().typeOf(cx); + return v.toObject().map->ops->typeOf(cx, &v.toObject()); JS_ASSERT(v.isBoolean()); return JSTYPE_BOOLEAN; } @@ -2028,7 +2024,7 @@ JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEDEC_LENGTH); static inline bool IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval) { - if (iterobj->getClass() == &js_IteratorClass) { + if (iterobj->getClass() == &js_IteratorClass.base) { NativeIterator *ni = (NativeIterator *) iterobj->getPrivate(); *cond = (ni->props_cursor < ni->props_end); } else { @@ -2042,7 +2038,7 @@ IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval) static inline bool IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval) { - if (iterobj->getClass() == &js_IteratorClass) { + if (iterobj->getClass() == &js_IteratorClass.base) { NativeIterator *ni = (NativeIterator *) iterobj->getPrivate(); JS_ASSERT(ni->props_cursor < ni->props_end); if (ni->isKeyIter()) { @@ -3218,8 +3214,9 @@ END_CASE(JSOP_BITAND) } else #define EXTENDED_EQUALITY_OP(OP) \ - if (EqualityOp eq = l->getClass()->ext.equality) { \ - if (!eq(cx, l, &rval, &cond)) \ + if (((clasp = l->getClass())->flags & JSCLASS_IS_EXTENDED) && \ + ((ExtendedClass *)clasp)->equality) { \ + if (!((ExtendedClass *)clasp)->equality(cx, l, &rval, &cond)) \ goto error; \ cond = cond OP JS_TRUE; \ } else @@ -3230,6 +3227,7 @@ END_CASE(JSOP_BITAND) #define EQUALITY_OP(OP, IFNAN) \ JS_BEGIN_MACRO \ + Class *clasp; \ JSBool cond; \ Value rval = regs.sp[-1]; \ Value lval = regs.sp[-2]; \ @@ -4048,7 +4046,7 @@ BEGIN_CASE(JSOP_GETXPROP) } jsid id = ATOM_TO_JSID(atom); - if (JS_LIKELY(!aobj->getOps()->getProperty) + if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty) ? !js_GetPropertyHelper(cx, obj, id, (fp->imacpc || regs.pc[JSOP_GETPROP_LENGTH + i] == JSOP_IFEQ) @@ -4152,7 +4150,7 @@ BEGIN_CASE(JSOP_CALLPROP) PUSH_NULL(); if (lval.isObject()) { if (!js_GetMethod(cx, &objv.toObject(), id, - JS_LIKELY(!aobj->getOps()->getProperty) + JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty) ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER : JSGET_NO_METHOD_BARRIER, &rval)) { @@ -4161,7 +4159,7 @@ BEGIN_CASE(JSOP_CALLPROP) regs.sp[-1] = objv; regs.sp[-2] = rval; } else { - JS_ASSERT(!objv.toObject().getOps()->getProperty); + JS_ASSERT(objv.toObject().map->ops->getProperty == js_GetProperty); if (!js_GetPropertyHelper(cx, &objv.toObject(), id, JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER, &rval)) { @@ -4385,7 +4383,7 @@ BEGIN_CASE(JSOP_SETMETHOD) if (!atom) LOAD_ATOM(0, atom); jsid id = ATOM_TO_JSID(atom); - if (entry && JS_LIKELY(!obj->getOps()->setProperty)) { + if (entry && JS_LIKELY(obj->map->ops->setProperty == js_SetProperty)) { uintN defineHow; if (op == JSOP_SETMETHOD) defineHow = JSDNP_CACHE_RESULT | JSDNP_SET_METHOD; @@ -5359,7 +5357,7 @@ BEGIN_CASE(JSOP_DEFVAR) */ index += atoms - script->atomMap.vector; JSObject *obj = fp->varobj(cx); - JS_ASSERT(!obj->getOps()->defineProperty); + JS_ASSERT(obj->map->ops->defineProperty == js_DefineProperty); uintN attrs = JSPROP_ENUMERATE; if (!(fp->flags & JSFRAME_EVAL)) attrs |= JSPROP_PERMANENT; diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 472cd6a752e..6b4e478b168 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -85,31 +85,19 @@ static void iterator_finalize(JSContext *cx, JSObject *obj); static void iterator_trace(JSTracer *trc, JSObject *obj); static JSObject *iterator_iterator(JSContext *cx, JSObject *obj, JSBool keysonly); -Class js_IteratorClass = { - "Iterator", - JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator) | JSCLASS_MARK_IS_TRACE, - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - iterator_finalize, - NULL, /* reserved */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - JS_CLASS_TRACE(iterator_trace), - { - NULL, /* equality */ - NULL, /* outerObject */ - NULL, /* innerObject */ - iterator_iterator, - NULL /* wrappedObject */ - } +ExtendedClass js_IteratorClass = { + { "Iterator", + JSCLASS_HAS_PRIVATE | + JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator) | + JSCLASS_MARK_IS_TRACE | + JSCLASS_IS_EXTENDED, + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, iterator_finalize, + NULL, NULL, NULL, NULL, + NULL, NULL, JS_CLASS_TRACE(iterator_trace), NULL }, + NULL, NULL, NULL, iterator_iterator, + NULL, + JSCLASS_NO_RESERVED_MEMBERS }; void @@ -130,7 +118,7 @@ NativeIterator::mark(JSTracer *trc) static void iterator_finalize(JSContext *cx, JSObject *obj) { - JS_ASSERT(obj->getClass() == &js_IteratorClass); + JS_ASSERT(obj->getClass() == &js_IteratorClass.base); /* Avoid double work if the iterator was closed by JSOP_ENDITER. */ NativeIterator *ni = obj->getNativeIterator(); @@ -320,7 +308,7 @@ Snapshot(JSContext *cx, JSObject *obj, uintN flags, typename EnumPolicy::ResultV do { Class *clasp = pobj->getClass(); if (pobj->isNative() && - !pobj->getOps()->enumerate && + pobj->map->ops->enumerate == js_Enumerate && !(clasp->flags & JSCLASS_NEW_ENUMERATE)) { if (!clasp->enumerate(cx, pobj)) return false; @@ -461,11 +449,11 @@ NewIteratorObject(JSContext *cx, uintN flags) if (!obj) return false; obj->map = cx->runtime->emptyEnumeratorScope->hold(); - obj->init(&js_IteratorClass, NULL, NULL, NullValue()); + obj->init(&js_IteratorClass.base, NULL, NULL, NullValue()); return obj; } - return NewBuiltinClassInstance(cx, &js_IteratorClass); + return NewBuiltinClassInstance(cx, &js_IteratorClass.base); } NativeIterator * @@ -622,7 +610,7 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp) JSObject *pobj = obj; do { if (!pobj->isNative() || - obj->getOps()->enumerate || + obj->map->ops->enumerate != js_Enumerate || pobj->getClass()->enumerate != JS_EnumerateStub) { shapes.clear(); goto miss; @@ -710,7 +698,7 @@ iterator_next(JSContext *cx, uintN argc, Value *vp) JSObject *obj; obj = ComputeThisFromVp(cx, vp); - if (!InstanceOf(cx, obj, &js_IteratorClass, vp + 2)) + if (!InstanceOf(cx, obj, &js_IteratorClass.base, vp + 2)) return false; if (!js_IteratorMore(cx, obj, vp)) @@ -772,14 +760,18 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp) AutoObjectRooter tvr(cx, obj); - /* Enumerate Iterator.prototype directly. */ - JSIteratorOp op = obj->getClass()->ext.iteratorObject; - if (op && (obj->getClass() != &js_IteratorClass || obj->getNativeIterator())) { - JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH)); - if (!iterobj) - return false; - vp->setObject(*iterobj); - return true; + Class *clasp = obj->getClass(); + ExtendedClass *xclasp; + if ((clasp->flags & JSCLASS_IS_EXTENDED) && + (xclasp = (ExtendedClass *) clasp)->iteratorObject) { + /* Enumerate Iterator.prototype directly. */ + if (clasp != &js_IteratorClass.base || obj->getNativeIterator()) { + JSObject *iterobj = xclasp->iteratorObject(cx, obj, !(flags & JSITER_FOREACH)); + if (!iterobj) + return false; + vp->setObject(*iterobj); + return true; + } } return GetIterator(cx, obj, flags, vp); @@ -796,7 +788,7 @@ js_CloseIterator(JSContext *cx, JSObject *obj) cx->iterValue.setMagic(JS_NO_ITER_VALUE); Class *clasp = obj->getClass(); - if (clasp == &js_IteratorClass) { + if (clasp == &js_IteratorClass.base) { /* Remove enumerators from the active list, which is a stack. */ NativeIterator *ni = obj->getNativeIterator(); if (ni->flags & JSITER_ENUMERATE) { @@ -816,7 +808,7 @@ js_CloseIterator(JSContext *cx, JSObject *obj) } } #if JS_HAS_GENERATORS - else if (clasp == &js_GeneratorClass) { + else if (clasp == &js_GeneratorClass.base) { return CloseGenerator(cx, obj); } #endif @@ -901,7 +893,7 @@ JSBool js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval) { /* Fast path for native iterators */ - if (iterobj->getClass() == &js_IteratorClass) { + if (iterobj->getClass() == &js_IteratorClass.base) { /* * Implement next directly as all the methods of native iterator are * read-only and permanent. @@ -945,7 +937,7 @@ JSBool js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval) { /* Fast path for native iterators */ - if (iterobj->getClass() == &js_IteratorClass) { + if (iterobj->getClass() == &js_IteratorClass.base) { /* * Implement next directly as all the methods of the native iterator are * read-only and permanent. @@ -994,20 +986,14 @@ stopiter_hasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp) Class js_StopIterationClass = { js_StopIteration_str, JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - NULL, /* finalize */ - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - stopiter_hasInstance + PropertyStub, PropertyStub, + PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, + ConvertStub, NULL, + NULL, NULL, + NULL, NULL, + NULL, stopiter_hasInstance, + NULL, NULL }; #if JS_HAS_GENERATORS @@ -1050,32 +1036,20 @@ generator_trace(JSTracer *trc, JSObject *obj) MarkValueRange(trc, fp->slots(), gen->savedRegs.sp, "generator slots"); } -Class js_GeneratorClass = { - js_Generator_str, - JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Generator) | - JSCLASS_IS_ANONYMOUS | JSCLASS_MARK_IS_TRACE, - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - generator_finalize, - NULL, /* reserved */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - JS_CLASS_TRACE(generator_trace), - { - NULL, /* equality */ - NULL, /* outerObject */ - NULL, /* innerObject */ - iterator_iterator, - NULL, /* wrappedObject */ - } +ExtendedClass js_GeneratorClass = { + { js_Generator_str, + JSCLASS_HAS_PRIVATE | + JSCLASS_HAS_CACHED_PROTO(JSProto_Generator) | + JSCLASS_IS_ANONYMOUS | + JSCLASS_MARK_IS_TRACE | + JSCLASS_IS_EXTENDED, + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, generator_finalize, + NULL, NULL, NULL, NULL, + NULL, NULL, JS_CLASS_TRACE(generator_trace), NULL }, + NULL, NULL, NULL, iterator_iterator, + NULL, + JSCLASS_NO_RESERVED_MEMBERS }; /* @@ -1089,7 +1063,7 @@ Class js_GeneratorClass = { JS_REQUIRES_STACK JSObject * js_NewGenerator(JSContext *cx) { - JSObject *obj = NewBuiltinClassInstance(cx, &js_GeneratorClass); + JSObject *obj = NewBuiltinClassInstance(cx, &js_GeneratorClass.base); if (!obj) return NULL; @@ -1331,7 +1305,7 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj, static JS_REQUIRES_STACK JSBool CloseGenerator(JSContext *cx, JSObject *obj) { - JS_ASSERT(obj->getClass() == &js_GeneratorClass); + JS_ASSERT(obj->getClass() == &js_GeneratorClass.base); JSGenerator *gen = (JSGenerator *) obj->getPrivate(); if (!gen) { @@ -1355,7 +1329,7 @@ generator_op(JSContext *cx, JSGeneratorOp op, Value *vp, uintN argc) LeaveTrace(cx); obj = ComputeThisFromVp(cx, vp); - if (!InstanceOf(cx, obj, &js_GeneratorClass, vp + 2)) + if (!InstanceOf(cx, obj, &js_GeneratorClass.base, vp + 2)) return JS_FALSE; JSGenerator *gen = (JSGenerator *) obj->getPrivate(); @@ -1450,14 +1424,14 @@ js_InitIteratorClasses(JSContext *cx, JSObject *obj) if (stop) return stop; - proto = js_InitClass(cx, obj, NULL, &js_IteratorClass, Iterator, 2, + proto = js_InitClass(cx, obj, NULL, &js_IteratorClass.base, Iterator, 2, NULL, iterator_methods, NULL, NULL); if (!proto) return NULL; #if JS_HAS_GENERATORS /* Initialize the generator internals if configured. */ - if (!js_InitClass(cx, obj, NULL, &js_GeneratorClass, NULL, 0, + if (!js_InitClass(cx, obj, NULL, &js_GeneratorClass.base, NULL, 0, NULL, generator_methods, NULL, NULL)) { return NULL; } diff --git a/js/src/jsiter.h b/js/src/jsiter.h index ba1ce58ad52..f6a478d3278 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -249,9 +249,9 @@ js_LiveFrameIfGenerator(JSStackFrame *fp) #endif -extern js::Class js_GeneratorClass; -extern js::Class js_IteratorClass; -extern js::Class js_StopIterationClass; +extern js::ExtendedClass js_GeneratorClass; +extern js::ExtendedClass js_IteratorClass; +extern js::Class js_StopIterationClass; static inline bool js_ValueIsStopIteration(const js::Value &v) diff --git a/js/src/jslock.h b/js/src/jslock.h index da0e0657de3..4a9ca6573b8 100644 --- a/js/src/jslock.h +++ b/js/src/jslock.h @@ -150,7 +150,9 @@ struct JSTitle { /* * NB: The JS_LOCK_OBJ and JS_UNLOCK_OBJ macros work *only* on native objects * (objects for which obj->isNative() returns true). All uses of these macros in - * the engine are predicated on obj->isNative or equivalent checks. + * the engine are predicated on obj->isNative or equivalent checks. These uses + * are for optimizations above the JSObjectOps layer, under which object locks + * normally hide. */ #define CX_OWNS_SCOPE_TITLE(cx,scope) ((scope)->title.ownercx == (cx)) diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index c9230a3fcfb..8a973934a80 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -97,13 +97,9 @@ static JSConstDoubleSpec math_constants[] = { Class js_MathClass = { js_Math_str, JSCLASS_HAS_CACHED_PROTO(JSProto_Math), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; static JSBool diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 7b87e2c1f89..8cf3c9c9db8 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -271,13 +271,9 @@ static JSFunctionSpec number_functions[] = { Class js_NumberClass = { js_Number_str, JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Number), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; static JSBool diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 9ed808044c4..b038683de69 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -102,27 +102,30 @@ using namespace js; -JS_FRIEND_DATA(const JSObjectMap) JSObjectMap::sharedNonNative(JSObjectMap::SHAPELESS); +JS_FRIEND_DATA(JSObjectOps) js_ObjectOps = { + NULL, + js_LookupProperty, + js_DefineProperty, + js_GetProperty, + js_SetProperty, + js_GetAttributes, + js_SetAttributes, + js_DeleteProperty, + js_Enumerate, + js_TypeOf, + js_TraceObject, + NULL, /* thisObject */ + js_Clear +}; Class js_ObjectClass = { js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_Object), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; -JS_FRIEND_API(JSObject *) -js_ObjectToOuterObject(JSContext *cx, JSObject *obj) -{ - OBJ_TO_OUTER_OBJECT(cx, obj); - return obj; -} - #if JS_HAS_OBJ_PROTO_PROP static JSBool @@ -914,6 +917,8 @@ js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj, JSObject * js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller) { + Class *clasp; + JSExtendedClass *xclasp; JSObject *inner; if (!scopeobj) @@ -923,12 +928,19 @@ js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller if (!scopeobj) return NULL; - /* XXX This is an awful gross hack. */ inner = scopeobj; + + /* XXX This is an awful gross hack. */ while (scopeobj) { - JSObjectOp op = scopeobj->getClass()->ext.innerObject; - if (op && op(cx, scopeobj) != scopeobj) - goto bad; + clasp = scopeobj->getClass(); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + xclasp = (JSExtendedClass*)clasp; + if (xclasp->innerObject && + xclasp->innerObject(cx, scopeobj) != scopeobj) { + goto bad; + } + } + scopeobj = scopeobj->getParent(); } @@ -1355,7 +1367,7 @@ obj_hasOwnProperty(JSContext *cx, uintN argc, Value *vp) { JSObject *obj = ComputeThisFromVp(cx, vp); return obj && - js_HasOwnPropertyHelper(cx, obj->getOps()->lookupProperty, argc, vp); + js_HasOwnPropertyHelper(cx, obj->map->ops->lookupProperty, argc, vp); } JSBool @@ -1394,7 +1406,7 @@ js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp) { JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING); - if (!(lookup ? lookup : js_LookupProperty)(cx, obj, id, objp, propp)) + if (!lookup(cx, obj, id, objp, propp)) return false; if (!*propp) return true; @@ -1402,10 +1414,14 @@ js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id, if (*objp == obj) return true; + JSExtendedClass *xclasp; + JSObject *outer; Class *clasp = (*objp)->getClass(); - JSObject *outer = NULL; - if (JSObjectOp op = (*objp)->getClass()->ext.outerObject) { - outer = op(cx, *objp); + if (!(clasp->flags & JSCLASS_IS_EXTENDED) || + !(xclasp = (JSExtendedClass *) clasp)->outerObject) { + outer = NULL; + } else { + outer = xclasp->outerObject(cx, *objp); if (!outer) return false; } @@ -1691,7 +1707,7 @@ js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, Value *vp) JSObject *pobj; JSProperty *prop; - if (!js_HasOwnProperty(cx, obj->getOps()->lookupProperty, obj, id, &pobj, &prop)) + if (!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &pobj, &prop)) return false; if (!prop) { vp->setUndefined(); @@ -1967,11 +1983,11 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, /* 8.12.9 step 1. */ JSProperty *current; JSObject *obj2; - JS_ASSERT(!obj->getOps()->lookupProperty); - if (!js_HasOwnProperty(cx, NULL, obj, desc.id, &obj2, ¤t)) + JS_ASSERT(obj->map->ops->lookupProperty == js_LookupProperty); + if (!js_HasOwnProperty(cx, js_LookupProperty, obj, desc.id, &obj2, ¤t)) return JS_FALSE; - JS_ASSERT(!obj->getOps()->defineProperty); + JS_ASSERT(obj->map->ops->defineProperty == js_DefineProperty); /* 8.12.9 steps 2-4. */ JSScope *scope = obj->scope(); @@ -1982,7 +1998,7 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, *rval = true; if (desc.isGenericDescriptor() || desc.isDataDescriptor()) { - JS_ASSERT(!obj->getOps()->defineProperty); + JS_ASSERT(obj->map->ops->defineProperty == js_DefineProperty); return js_DefineProperty(cx, obj, desc.id, &desc.value, PropertyStub, PropertyStub, desc.attrs); } @@ -2287,7 +2303,7 @@ DefineProperty(JSContext *cx, JSObject *obj, const PropDesc &desc, bool throwErr if (obj->isArray()) return DefinePropertyOnArray(cx, obj, desc, throwError, rval); - if (obj->getOps()->lookupProperty) { + if (obj->map->ops->lookupProperty != js_LookupProperty) { if (obj->isProxy()) return JSProxy::defineProperty(cx, obj, desc.id, desc.pd); return Reject(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval); @@ -2568,7 +2584,8 @@ JSObject* js_NewObjectWithClassProto(JSContext *cx, Class *clasp, JSObject *proto, const Value &privateSlotValue) { - JS_ASSERT(clasp->isNative()); + JS_ASSERT(!clasp->getObjectOps); + JS_ASSERT(proto->map->ops == &js_ObjectOps); JSObject* obj = js_NewGCObject(cx); if (!obj) @@ -2848,39 +2865,35 @@ with_ThisObject(JSContext *cx, JSObject *obj) return obj->getWithThis(); } +JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = { + NULL, + with_LookupProperty, + js_DefineProperty, + with_GetProperty, + with_SetProperty, + with_GetAttributes, + with_SetAttributes, + with_DeleteProperty, + with_Enumerate, + with_TypeOf, + js_TraceObject, + with_ThisObject, + js_Clear +}; + +static JSObjectOps * +with_getObjectOps(JSContext *cx, Class *clasp) +{ + return &js_WithObjectOps; +} + Class js_WithClass = { "With", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS, - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - NULL, /* finalize */ - NULL, /* reserved */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* mark */ - JS_NULL_CLASS_EXT, - { - with_LookupProperty, - NULL, /* defineProperty */ - with_GetProperty, - with_SetProperty, - with_GetAttributes, - with_SetAttributes, - with_DeleteProperty, - with_Enumerate, - with_TypeOf, - NULL, /* trace */ - with_ThisObject, - NULL, /* clear */ - } + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + with_getObjectOps, + 0,0,0,0,0,0,0 }; JS_REQUIRES_STACK JSObject * @@ -3227,13 +3240,9 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp) Class js_BlockClass = { "Block", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_IS_ANONYMOUS, - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; JSObject * @@ -4462,7 +4471,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult, for (scopeIndex = 0; parent ? js_IsCacheableNonGlobalScope(obj) - : !obj->getOps()->lookupProperty; + : obj->map->ops->lookupProperty == js_LookupProperty; ++scopeIndex) { protoIndex = js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, @@ -4843,11 +4852,8 @@ js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, Value *vp) { JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED); - PropertyIdOp op = obj->getOps()->getProperty; - if (!op) { -#if JS_HAS_XML_SUPPORT - JS_ASSERT(!obj->isXML()); -#endif + if (obj->map->ops == &js_ObjectOps || + obj->map->ops->getProperty == js_GetProperty) { return js_GetPropertyHelper(cx, obj, id, getHow, vp); } JS_ASSERT_IF(getHow & JSGET_CACHE_RESULT, obj->isDenseArray()); @@ -4855,7 +4861,7 @@ js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, Value *vp) if (obj->isXML()) return js_GetXMLMethod(cx, obj, id, vp); #endif - return op(cx, obj, id, vp); + return obj->getProperty(cx, id, vp); } JS_FRIEND_API(bool) @@ -5375,7 +5381,7 @@ DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp) } /* namespace js */ -JS_FRIEND_API(JSBool) +JSBool js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep, jsid *idp) { /* If the class has a custom JSCLASS_NEW_ENUMERATE hook, call it. */ @@ -5953,7 +5959,7 @@ js_TraceObject(JSTracer *trc, JSObject *obj) } void -js_ClearNative(JSContext *cx, JSObject *obj) +js_Clear(JSContext *cx, JSObject *obj) { JSScope *scope; uint32 i, n; @@ -6042,9 +6048,12 @@ js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, const Value &v) JSObject * JSObject::wrappedObject(JSContext *cx) const { - if (JSObjectOp op = getClass()->ext.wrappedObject) { - if (JSObject *obj = op(cx, const_cast(this))) - return obj; + Class *clasp = getClass(); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + if (JSObjectOp wrappedObject = reinterpret_cast(clasp)->wrappedObject) { + if (JSObject *obj = wrappedObject(cx, const_cast(this))) + return obj; + } } return const_cast(this); } @@ -6080,7 +6089,7 @@ JSObject::getCompartment(JSContext *cx) return cx->runtime->defaultCompartment; // The magic function namespace object is runtime-wide. - if (clasp == &js_NamespaceClass && + if (clasp == &js_NamespaceClass.base && obj->getNameURI() == ATOM_TO_JSVAL(cx->runtime->atomState.lazy.functionNamespaceURIAtom)) { return cx->runtime->defaultCompartment; } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index a8a72682b1b..05bef0a3df6 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -170,62 +170,73 @@ namespace js { typedef Vector PropDescArray; +/* + * Flag and type-safe cast helper to denote that Class::call is a fast native. + */ +const uint32 CLASS_CALL_IS_FAST = uint32(1) << (JSCLASS_LAST_API_FLAG_SHIFT + 1); + +inline Native CastCallOpAsNative(CallOp op) +{ + return reinterpret_cast(op); +} + } /* namespace js */ -struct JSObjectMap { - static JS_FRIEND_DATA(const JSObjectMap) sharedNonNative; +/* For detailed comments on these function pointer types, see jsprvtd.h. */ +struct JSObjectOps { + /* + * Custom shared object map for non-native objects. For native objects + * this should be null indicating, that JSObject.map is an instance of + * JSScope. + */ + const JSObjectMap *objectMap; + /* Mandatory non-null function pointer members. */ + JSLookupPropOp lookupProperty; + js::DefinePropOp defineProperty; + js::PropertyIdOp getProperty; + js::PropertyIdOp setProperty; + JSAttributesOp getAttributes; + JSAttributesOp setAttributes; + js::PropertyIdOp deleteProperty; + js::NewEnumerateOp enumerate; + JSTypeOfOp typeOf; + JSTraceOp trace; + + /* Optionally non-null members start here. */ + JSObjectOp thisObject; + JSFinalizeOp clear; + + bool inline isNative() const; +}; + +extern JS_FRIEND_DATA(JSObjectOps) js_ObjectOps; +extern JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps; + +/* + * Test whether the ops is native. FIXME bug 492938: consider how it would + * affect the performance to do just the !objectMap check. + */ +inline bool +JSObjectOps::isNative() const +{ + return JS_LIKELY(this == &js_ObjectOps) || !objectMap; +} + +struct JSObjectMap { + const JSObjectOps * const ops; /* high level object operation vtable */ uint32 shape; /* shape identifier */ - explicit JSObjectMap(uint32 shape) : shape(shape) {} + explicit JSObjectMap(const JSObjectOps *ops, uint32 shape) : ops(ops), shape(shape) {} enum { SHAPELESS = 0xffffffff }; - bool isNative() const { return this != &sharedNonNative; } - - private: +private: /* No copy or assignment semantics. */ JSObjectMap(JSObjectMap &); void operator=(JSObjectMap &); }; -/* - * Unlike js_DefineNativeProperty, propp must be non-null. On success, and if - * id was found, return true with *objp non-null and locked, and with a held - * property stored in *propp. If successful but id was not found, return true - * with both *objp and *propp null. Therefore all callers who receive a - * non-null *propp must later call (*objp)->dropProperty(cx, *propp). - */ -extern JS_FRIEND_API(JSBool) -js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp); - -extern JSBool -js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value, - js::PropertyOp getter, js::PropertyOp setter, uintN attrs); - -extern JSBool -js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); - -extern JSBool -js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); - -extern JSBool -js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); - -extern JSBool -js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); - -extern JSBool -js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *rval); - -extern JS_FRIEND_API(JSBool) -js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - js::Value *statep, jsid *idp); - -extern JSType -js_TypeOf(JSContext *cx, JSObject *obj); - struct NativeIterator; const uint32 JS_INITIAL_NSLOTS = 4; @@ -291,9 +302,7 @@ struct JSObject { #endif js::Value fslots[JS_INITIAL_NSLOTS]; /* small number of fixed slots */ - bool isNative() const { - return map->isNative(); - } + bool isNative() const { return map->ops->isNative(); } js::Class *getClass() const { return clasp; @@ -307,10 +316,6 @@ struct JSObject { return c == clasp; } - const js::ObjectOps *getOps() const { - return &getClass()->ops; - } - inline JSScope *scope() const; inline uint32 shape() const; @@ -682,62 +687,53 @@ struct JSObject { /* This method can only be called when hasSlotsArray() returns true. */ inline void freeSlotsArray(JSContext *cx); - JSBool lookupProperty(JSContext *cx, jsid id, JSObject **objp, JSProperty **propp) { - JSLookupPropOp op = getOps()->lookupProperty; - return (op ? op : js_LookupProperty)(cx, this, id, objp, propp); + JSBool lookupProperty(JSContext *cx, jsid id, + JSObject **objp, JSProperty **propp) { + return map->ops->lookupProperty(cx, this, id, objp, propp); } JSBool defineProperty(JSContext *cx, jsid id, const js::Value &value, js::PropertyOp getter = js::PropertyStub, js::PropertyOp setter = js::PropertyStub, uintN attrs = JSPROP_ENUMERATE) { - js::DefinePropOp op = getOps()->defineProperty; - return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs); + return map->ops->defineProperty(cx, this, id, &value, getter, setter, attrs); } JSBool getProperty(JSContext *cx, jsid id, js::Value *vp) { - js::PropertyIdOp op = getOps()->getProperty; - return (op ? op : js_GetProperty)(cx, this, id, vp); + return map->ops->getProperty(cx, this, id, vp); } JSBool setProperty(JSContext *cx, jsid id, js::Value *vp) { - js::PropertyIdOp op = getOps()->setProperty; - return (op ? op : js_SetProperty)(cx, this, id, vp); + return map->ops->setProperty(cx, this, id, vp); } JSBool getAttributes(JSContext *cx, jsid id, uintN *attrsp) { - JSAttributesOp op = getOps()->getAttributes; - return (op ? op : js_GetAttributes)(cx, this, id, attrsp); + return map->ops->getAttributes(cx, this, id, attrsp); } JSBool setAttributes(JSContext *cx, jsid id, uintN *attrsp) { - JSAttributesOp op = getOps()->setAttributes; - return (op ? op : js_SetAttributes)(cx, this, id, attrsp); + return map->ops->setAttributes(cx, this, id, attrsp); } JSBool deleteProperty(JSContext *cx, jsid id, js::Value *rval) { - js::PropertyIdOp op = getOps()->deleteProperty; - return (op ? op : js_DeleteProperty)(cx, this, id, rval); + return map->ops->deleteProperty(cx, this, id, rval); } - JSBool enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp) { - js::NewEnumerateOp op = getOps()->enumerate; - return (op ? op : js_Enumerate)(cx, this, iterop, statep, idp); + JSBool enumerate(JSContext *cx, JSIterateOp op, js::Value *statep, + jsid *idp) { + return map->ops->enumerate(cx, this, op, statep, idp); } JSType typeOf(JSContext *cx) { - JSTypeOfOp op = getOps()->typeOf; - return (op ? op : js_TypeOf)(cx, this); + return map->ops->typeOf(cx, this); } JSObject *wrappedObject(JSContext *cx) const; /* These four are time-optimized to avoid stub calls. */ JSObject *thisObject(JSContext *cx) { - JSObjectOp op = getOps()->thisObject; - return op ? op(cx, this) : this; + return map->ops->thisObject ? map->ops->thisObject(cx, this) : this; } - static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp); inline void dropProperty(JSContext *cx, JSProperty *prop); @@ -818,8 +814,12 @@ JS_STATIC_ASSERT(sizeof(JSObject) % JS_GCTHING_ALIGN == 0); inline void OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj) { - if (JSObjectOp op = obj->getClass()->ext.innerObject) - obj = op(cx, obj); + js::Class *clasp = obj->getClass(); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + js::ExtendedClass *xclasp = (js::ExtendedClass *) clasp; + if (xclasp->innerObject) + obj = xclasp->innerObject(cx, obj); + } } /* @@ -829,8 +829,12 @@ OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj) inline void OBJ_TO_OUTER_OBJECT(JSContext *cx, JSObject *&obj) { - if (JSObjectOp op = obj->getClass()->ext.outerObject) - obj = op(cx, obj); + js::Class *clasp = obj->getClass(); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + js::ExtendedClass *xclasp = (js::ExtendedClass *) clasp; + if (xclasp->outerObject) + obj = xclasp->outerObject(cx, obj); + } } class JSValueArray { @@ -1072,12 +1076,14 @@ js_CheckForStringIndex(jsid id); extern void js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id); -inline void +#ifdef __cplusplus /* Aargh, libgjs, bug 492720. */ +static JS_INLINE void js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id) { if (obj->isDelegate()) js_PurgeScopeChainHelper(cx, obj, id); } +#endif /* * Find or create a property named by id in obj's scope, with the given getter @@ -1098,6 +1104,10 @@ js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, uintN attrs, uintN mask, js::PropertyOp getter, js::PropertyOp setter); +extern JSBool +js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value, + js::PropertyOp getter, js::PropertyOp setter, uintN attrs); + extern JSBool js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value &descriptor, JSBool *bp); @@ -1127,6 +1137,17 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value & uintN flags, intN shortid, JSProperty **propp, uintN defineHow = 0); +/* + * Unlike js_DefineNativeProperty, propp must be non-null. On success, and if + * id was found, return true with *objp non-null and locked, and with a held + * property stored in *propp. If successful but id was not found, return true + * with both *objp and *propp null. Therefore all callers who receive a + * non-null *propp must later call (*objp)->dropProperty(cx, *propp). + */ +extern JS_FRIEND_API(JSBool) +js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, + JSProperty **propp); + /* * Specialized subroutine that allows caller to preset JSRESOLVE_* flags and * returns the index along the prototype chain in which *propp was found, or @@ -1142,7 +1163,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags, * non-global objects without prototype or with prototype that never mutates, * see bug 462734 and bug 487039. */ -inline bool +static inline bool js_IsCacheableNonGlobalScope(JSObject *obj) { extern JS_FRIEND_DATA(js::Class) js_CallClass; @@ -1154,7 +1175,7 @@ js_IsCacheableNonGlobalScope(JSObject *obj) clasp == &js_BlockClass || clasp == &js_DeclEnvClass); - JS_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty); + JS_ASSERT_IF(cacheable, obj->map->ops->lookupProperty == js_LookupProperty); return cacheable; } @@ -1214,6 +1235,9 @@ extern JSBool js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN getHow, js::Value *vp); +extern JSBool +js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); + extern JSBool js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); @@ -1233,6 +1257,15 @@ extern JSBool js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, js::Value *vp); +extern JSBool +js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); + +extern JSBool +js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); + +extern JSBool +js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); + /* * Change attributes for the given native property. The caller must ensure * that obj is locked and this function always unlocks obj on return. @@ -1241,16 +1274,30 @@ extern JSBool js_SetNativeAttributes(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, uintN attrs); +extern JSBool +js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *rval); + namespace js { extern JSBool DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp); +} + +extern JSBool +js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, + js::Value *statep, jsid *idp); + +namespace js { + extern JSBool CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, js::Value *vp, uintN *attrsp); -} /* namespace js */ +} + +extern JSType +js_TypeOf(JSContext *cx, JSObject *obj); extern bool js_IsDelegate(JSContext *cx, JSObject *obj, const js::Value &v); @@ -1305,7 +1352,7 @@ extern void js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize); extern void -js_ClearNative(JSContext *cx, JSObject *obj); +js_Clear(JSContext *cx, JSObject *obj); extern bool js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, js::Value *vp); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 1544797b888..e5fd335350f 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -493,9 +493,9 @@ class AutoPropertyDescriptorRooter : private AutoGCRooter, public PropertyDescri }; static inline bool -InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, JSObject* proto) +InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, JSObject* proto, JSObjectOps* ops) { - JS_ASSERT(clasp->isNative()); + JS_ASSERT(ops->isNative()); JS_ASSERT(proto == obj->getProto()); /* Share proto's emptyScope only if obj is similar to proto. */ @@ -504,7 +504,7 @@ InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, JSObject* pro if (proto && proto->isNative()) { JS_LOCK_OBJ(cx, proto); scope = proto->scope(); - if (scope->canProvideEmptyScope(clasp)) { + if (scope->canProvideEmptyScope(ops, clasp)) { JSScope *emptyScope = scope->getEmptyScope(cx, clasp); JS_UNLOCK_SCOPE(cx, scope); if (!emptyScope) @@ -517,7 +517,7 @@ InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, JSObject* pro } if (!scope) { - scope = JSScope::create(cx, clasp, obj, js_GenerateShape(cx, false)); + scope = JSScope::create(cx, ops, clasp, obj, js_GenerateShape(cx, false)); if (!scope) goto bad; uint32 freeslot = JSSLOT_FREE(clasp); @@ -570,7 +570,7 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, JSObject *p JS_LOCK_OBJ(cx, proto); JSScope *scope = proto->scope(); - JS_ASSERT(scope->canProvideEmptyScope(clasp)); + JS_ASSERT(scope->canProvideEmptyScope(&js_ObjectOps, clasp)); scope = scope->getEmptyScope(cx, clasp); JS_UNLOCK_OBJ(cx, proto); @@ -638,6 +638,11 @@ NewObjectWithGivenProto(JSContext *cx, Class *clasp, JSObject *proto, JSObject * { DTrace::ObjectCreationScope objectCreationScope(cx, cx->fp, clasp); + /* Always call the class's getObjectOps hook if it has one. */ + JSObjectOps *ops = clasp->getObjectOps + ? clasp->getObjectOps(cx, clasp) + : &js_ObjectOps; + /* * Allocate an object from the GC heap and initialize all its fields before * doing any operation that can potentially trigger GC. Functions have a @@ -667,13 +672,14 @@ NewObjectWithGivenProto(JSContext *cx, Class *clasp, JSObject *proto, JSObject * (!parent && proto) ? proto->getParent() : parent, JSObject::defaultPrivate(clasp)); - if (clasp->isNative()) { - if (!InitScopeForObject(cx, obj, clasp, proto)) { + if (ops->isNative()) { + if (!InitScopeForObject(cx, obj, clasp, proto, ops)) { obj = NULL; goto out; } } else { - obj->map = const_cast(&JSObjectMap::sharedNonNative); + JS_ASSERT(ops->objectMap->ops == ops); + obj->map = const_cast(ops->objectMap); } out: diff --git a/js/src/json.cpp b/js/src/json.cpp index 37699e06877..a72fdf9d93b 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -99,13 +99,9 @@ struct JSONParser Class js_JSONClass = { js_JSON_str, JSCLASS_HAS_CACHED_PROTO(JSProto_JSON), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; JSBool diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index cf457ad3e42..60074ceb0c5 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -905,6 +905,12 @@ proxy_TraceObject(JSTracer *trc, JSObject *obj) } } +static JSType +proxy_TypeOf_obj(JSContext *cx, JSObject *obj) +{ + return JSTYPE_OBJECT; +} + void proxy_Finalize(JSContext *cx, JSObject *obj) { @@ -913,39 +919,51 @@ proxy_Finalize(JSContext *cx, JSObject *obj) obj->getProxyHandler()->finalize(cx, obj); } +extern JSObjectOps js_ObjectProxyObjectOps; + +static const JSObjectMap SharedObjectProxyMap(&js_ObjectProxyObjectOps, JSObjectMap::SHAPELESS); + +JSObjectOps js_ObjectProxyObjectOps = { + &SharedObjectProxyMap, + proxy_LookupProperty, + proxy_DefineProperty, + proxy_GetProperty, + proxy_SetProperty, + proxy_GetAttributes, + proxy_SetAttributes, + proxy_DeleteProperty, + js_Enumerate, + proxy_TypeOf_obj, + proxy_TraceObject, + NULL, /* thisObject */ + proxy_Finalize +}; + +static JSObjectOps * +obj_proxy_getObjectOps(JSContext *cx, Class *clasp) +{ + return &js_ObjectProxyObjectOps; +} + JS_FRIEND_API(Class) ObjectProxyClass = { "Proxy", - Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(2), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ + JSCLASS_HAS_RESERVED_SLOTS(2), + PropertyStub, + PropertyStub, + PropertyStub, + PropertyStub, EnumerateStub, ResolveStub, ConvertStub, - NULL, /* finalize */ - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* mark */ - JS_NULL_CLASS_EXT, - { - proxy_LookupProperty, - proxy_DefineProperty, - proxy_GetProperty, - proxy_SetProperty, - proxy_GetAttributes, - proxy_SetAttributes, - proxy_DeleteProperty, - NULL, /* enumerate */ - NULL, /* typeof */ - proxy_TraceObject, - NULL, /* thisObject */ - proxy_Finalize, /* clear */ - } + NULL, + obj_proxy_getObjectOps, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL }; JSBool @@ -970,41 +988,53 @@ proxy_TypeOf_fun(JSContext *cx, JSObject *obj) return JSTYPE_FUNCTION; } +extern JSObjectOps js_FunctionProxyObjectOps; + +static const JSObjectMap SharedFunctionProxyMap(&js_FunctionProxyObjectOps, JSObjectMap::SHAPELESS); + #define proxy_HasInstance js_FunctionClass.hasInstance +JSObjectOps js_FunctionProxyObjectOps = { + &SharedFunctionProxyMap, + proxy_LookupProperty, + proxy_DefineProperty, + proxy_GetProperty, + proxy_SetProperty, + proxy_GetAttributes, + proxy_SetAttributes, + proxy_DeleteProperty, + js_Enumerate, + proxy_TypeOf_fun, + proxy_TraceObject, + NULL, /* thisObject */ + NULL /* clear */ +}; + +static JSObjectOps * +fun_proxy_getObjectOps(JSContext *cx, Class *clasp) +{ + return &js_FunctionProxyObjectOps; +} + JS_FRIEND_API(Class) FunctionProxyClass = { "Proxy", - Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(4) | Class::CALL_IS_FAST, - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ + JSCLASS_HAS_RESERVED_SLOTS(4) | CLASS_CALL_IS_FAST, + PropertyStub, + PropertyStub, + PropertyStub, + PropertyStub, EnumerateStub, ResolveStub, ConvertStub, - NULL, /* finalize */ - NULL, /* reserved0 */ - NULL, /* checkAccess */ + NULL, + fun_proxy_getObjectOps, + NULL, CastCallOpAsNative(proxy_Call), proxy_Construct, - NULL, /* xdrObject */ + NULL, proxy_HasInstance, - NULL, /* mark */ - JS_NULL_CLASS_EXT, - { - proxy_LookupProperty, - proxy_DefineProperty, - proxy_GetProperty, - proxy_SetProperty, - proxy_GetAttributes, - proxy_SetAttributes, - proxy_DeleteProperty, - NULL, /* enumerate */ - proxy_TypeOf_fun, - proxy_TraceObject, - NULL, /* thisObject */ - NULL, /* clear */ - } + NULL, + NULL }; JS_FRIEND_API(JSObject *) @@ -1213,18 +1243,10 @@ callable_Construct(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value Class CallableObjectClass = { "Function", JSCLASS_HAS_RESERVED_SLOTS(2), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - NULL, /* finalize */ - NULL, /* reserved0 */ - NULL, /* checkAccess */ - callable_Call, - callable_Construct, + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + NULL, NULL, callable_Call, callable_Construct, + NULL, NULL, NULL, NULL }; JS_FRIEND_API(JSBool) @@ -1282,13 +1304,9 @@ FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp) Class js_ProxyClass = { "Proxy", JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; JS_FRIEND_API(JSObject *) diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index b30fd26470d..220c3583613 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -345,20 +345,6 @@ typedef JSBool typedef JSBool (* JSCallOp)(JSContext *cx, uintN argc, jsval *vp); -/* - * A generic type for functions mapping an object to another object, or null - * if an error or exception was thrown on cx. - */ -typedef JSObject * -(* JSObjectOp)(JSContext *cx, JSObject *obj); - -/* - * Hook that creates an iterator object for a given object. Returns the - * iterator object or null if an error or exception was thrown on cx. - */ -typedef JSObject * -(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly); - /* * The following determines whether JS_EncodeCharacters and JS_DecodeBytes * treat char[] as utf-8 or simply as bytes that need to be inflated/deflated. @@ -369,13 +355,6 @@ typedef JSObject * extern JSBool js_CStringsAreUTF8; #endif -/* - * Hack to expose obj->getOps()->outer to the C implementation of the debugger - * interface. - */ -extern JS_FRIEND_API(JSObject *) -js_ObjectToOuterObject(JSContext *cx, JSObject *obj); - JS_END_EXTERN_C #endif /* jsprvtd_h___ */ diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 7c0bda6c6f5..e3df1494199 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -107,7 +107,7 @@ typedef enum JSProtoKey { JSProto_LIMIT } JSProtoKey; -/* js_CheckAccess mode enumeration. */ +/* JSObjectOps.checkAccess mode enumeration. */ typedef enum JSAccessMode { JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */ JSACC_PARENT = 1, /* XXXbe redundant w.r.t. id */ @@ -145,6 +145,7 @@ typedef enum JSIterateOp { /* Struct typedefs. */ typedef struct JSClass JSClass; +typedef struct JSExtendedClass JSExtendedClass; typedef struct JSConstDoubleSpec JSConstDoubleSpec; typedef struct JSContext JSContext; typedef struct JSErrorReport JSErrorReport; @@ -155,6 +156,7 @@ typedef struct JSIdArray JSIdArray; typedef struct JSPropertyDescriptor JSPropertyDescriptor; typedef struct JSPropertySpec JSPropertySpec; typedef struct JSObjectMap JSObjectMap; +typedef struct JSObjectOps JSObjectOps; typedef struct JSRuntime JSRuntime; typedef struct JSScript JSScript; typedef struct JSStackFrame JSStackFrame; @@ -301,6 +303,29 @@ typedef void typedef void (* JSStringFinalizeOp)(JSContext *cx, JSString *str); +/* + * The signature for JSClass.getObjectOps, used by JS_NewObject's internals + * to discover the set of high-level object operations to use for new objects + * of the given class. All native objects have a JSClass, which is stored as + * a private (int-tagged) pointer in obj slots. In contrast, all native and + * host objects have a JSObjectMap at obj->map, which may be shared among a + * number of objects, and which contains the JSObjectOps *ops pointer used to + * dispatch object operations from API calls. + * + * Thus JSClass (which pre-dates JSObjectOps in the API) provides a low-level + * interface to class-specific code and data, while JSObjectOps allows for a + * higher level of operation, which does not use the object's class except to + * find the class's JSObjectOps struct, by calling clasp->getObjectOps, and to + * finalize the object. + * + * If this seems backwards, that's because it is! API compatibility requires + * a JSClass *clasp parameter to JS_NewObject, etc. Most host objects do not + * need to implement the larger JSObjectOps, and can share the common JSScope + * code and data used by the native (js_ObjectOps, see jsobj.c) ops. + */ +typedef JSObjectOps * +(* JSGetObjectOps)(JSContext *cx, JSClass *clasp); + /* * JSClass.checkAccess type: check whether obj[id] may be accessed per mode, * returning false on error/exception, true on success with obj[id]'s last-got @@ -393,9 +418,26 @@ typedef void typedef void (* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize); +/* JSExtendedClass function pointer typedefs. */ + typedef JSBool (* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp); +/* + * A generic type for functions mapping an object to another object, or null + * if an error or exception was thrown on cx. Used by JSObjectOps.thisObject + * at present. + */ +typedef JSObject * +(* JSObjectOp)(JSContext *cx, JSObject *obj); + +/* + * Hook that creates an iterator object for a given object. Returns the + * iterator object or null if an error or exception was thrown on cx. + */ +typedef JSObject * +(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly); + /* Typedef for native functions called by the JS VM. */ typedef JSBool diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 4fb3ccde706..e94f9cee9ad 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -5417,21 +5417,14 @@ Class js_RegExpClass = { JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(JSObject::REGEXP_FIXED_RESERVED_SLOTS) | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - regexp_enumerate, - reinterpret_cast(regexp_resolve), - ConvertStub, - regexp_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - regexp_call, - NULL, /* construct */ - js_XDRRegExpObject, - NULL, /* hasInstance */ - JS_CLASS_TRACE(regexp_trace) + PropertyStub, PropertyStub, + PropertyStub, PropertyStub, + regexp_enumerate, reinterpret_cast(regexp_resolve), + ConvertStub, regexp_finalize, + NULL, NULL, + regexp_call, NULL, + js_XDRRegExpObject, NULL, + JS_CLASS_TRACE(regexp_trace), 0 }; static const jschar empty_regexp_ucstr[] = {'(', '?', ':', ')', 0}; diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 3728c21d36c..d39d717e698 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -99,7 +99,7 @@ js_GetMutableScope(JSContext *cx, JSObject *obj) if (!scope->isSharedEmpty()) return scope; - JSScope *newscope = JSScope::create(cx, obj->getClass(), obj, scope->shape); + JSScope *newscope = JSScope::create(cx, scope->ops, obj->getClass(), obj, scope->shape); if (!newscope) return NULL; @@ -211,11 +211,13 @@ JSScope::createTable(JSContext *cx, bool report) } JSScope * -JSScope::create(JSContext *cx, Class *clasp, JSObject *obj, uint32 shape) +JSScope::create(JSContext *cx, const JSObjectOps *ops, Class *clasp, + JSObject *obj, uint32 shape) { + JS_ASSERT(ops->isNative()); JS_ASSERT(obj); - JSScope *scope = cx->create(obj); + JSScope *scope = cx->create(ops, obj); if (!scope) return NULL; @@ -231,8 +233,9 @@ JSScope::create(JSContext *cx, Class *clasp, JSObject *obj, uint32 shape) return scope; } -JSEmptyScope::JSEmptyScope(JSContext *cx, Class *clasp) - : JSScope(NULL), clasp(clasp) +JSEmptyScope::JSEmptyScope(JSContext *cx, const JSObjectOps *ops, + Class *clasp) + : JSScope(ops, NULL), clasp(clasp) { /* * This scope holds a reference to the new empty scope. Our only caller, @@ -287,14 +290,14 @@ JSScope::initRuntimeState(JSContext *cx) #define SCOPE(Name) rt->empty##Name##Scope #define CLASP(Name) &js_##Name##Class -#define INIT_EMPTY_SCOPE(Name,NAME) \ - INIT_EMPTY_SCOPE_WITH_CLASS(Name, NAME, CLASP(Name)) +#define INIT_EMPTY_SCOPE(Name,NAME,ops) \ + INIT_EMPTY_SCOPE_WITH_CLASS(Name, NAME, ops, CLASP(Name)) -#define INIT_EMPTY_SCOPE_WITH_CLASS(Name,NAME,clasp) \ - INIT_EMPTY_SCOPE_WITH_FREESLOT(Name, NAME, clasp, JSSLOT_FREE(clasp)) +#define INIT_EMPTY_SCOPE_WITH_CLASS(Name,NAME,ops,clasp) \ + INIT_EMPTY_SCOPE_WITH_FREESLOT(Name, NAME, ops, clasp, JSSLOT_FREE(clasp)) -#define INIT_EMPTY_SCOPE_WITH_FREESLOT(Name,NAME,clasp,slot) \ - SCOPE(Name) = cx->create(cx, clasp); \ +#define INIT_EMPTY_SCOPE_WITH_FREESLOT(Name,NAME,ops,clasp,slot) \ + SCOPE(Name) = cx->create(cx, ops, clasp); \ if (!SCOPE(Name)) \ return false; \ JS_ASSERT(SCOPE(Name)->shape == JSScope::EMPTY_##NAME##_SHAPE); \ @@ -320,10 +323,10 @@ JSScope::initRuntimeState(JSContext *cx) * arguments objects. This helps ensure that any arguments object needing * its own mutable scope (with unique shape) is a rare event. */ - INIT_EMPTY_SCOPE_WITH_FREESLOT(Arguments, ARGUMENTS, CLASP(Arguments), + INIT_EMPTY_SCOPE_WITH_FREESLOT(Arguments, ARGUMENTS, &js_ObjectOps, CLASP(Arguments), JS_INITIAL_NSLOTS + JS_ARGS_LENGTH_MAX); - INIT_EMPTY_SCOPE(Block, BLOCK); + INIT_EMPTY_SCOPE(Block, BLOCK, &js_ObjectOps); /* * Initialize the shared scope for all empty Call objects so gets for args @@ -332,17 +335,17 @@ JSScope::initRuntimeState(JSContext *cx) * * See comment above for rt->emptyArgumentsScope->freeslot initialization. */ - INIT_EMPTY_SCOPE_WITH_FREESLOT(Call, CALL, CLASP(Call), + INIT_EMPTY_SCOPE_WITH_FREESLOT(Call, CALL, &js_ObjectOps, CLASP(Call), JS_INITIAL_NSLOTS + JSFunction::MAX_ARGS_AND_VARS); /* A DeclEnv object holds the name binding for a named function expression. */ - INIT_EMPTY_SCOPE(DeclEnv, DECL_ENV); + INIT_EMPTY_SCOPE(DeclEnv, DECL_ENV, &js_ObjectOps); /* Non-escaping native enumerator objects share this empty scope. */ - INIT_EMPTY_SCOPE_WITH_CLASS(Enumerator, ENUMERATOR, &js_IteratorClass); + INIT_EMPTY_SCOPE_WITH_CLASS(Enumerator, ENUMERATOR, &js_ObjectOps, &js_IteratorClass.base); /* Same drill for With objects. */ - INIT_EMPTY_SCOPE_WITH_CLASS(With, WITH, &js_WithClass); + INIT_EMPTY_SCOPE(With, WITH, &js_WithObjectOps); #undef SCOPE #undef CLASP diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 32100891c98..f5449683567 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -294,11 +294,12 @@ struct JSScope : public JSObjectMap JSScopeProperty **spp); public: - JSScope(JSObject *obj) - : JSObjectMap(0), object(obj) {} + JSScope(const JSObjectOps *ops, JSObject *obj) + : JSObjectMap(ops, 0), object(obj) {} /* Create a mutable, owned, empty scope. */ - static JSScope *create(JSContext *cx, js::Class *clasp, JSObject *obj, uint32 shape); + static JSScope *create(JSContext *cx, const JSObjectOps *ops, + js::Class *clasp, JSObject *obj, uint32 shape); void destroy(JSContext *cx); @@ -313,7 +314,7 @@ struct JSScope : public JSObjectMap inline bool ensureEmptyScope(JSContext *cx, js::Class *clasp); - inline bool canProvideEmptyScope(js::Class *clasp); + inline bool canProvideEmptyScope(JSObjectOps *ops, js::Class *clasp); JSScopeProperty *lookup(jsid id); @@ -527,7 +528,7 @@ struct JSEmptyScope : public JSScope js::Class * const clasp; jsrefcount nrefs; /* count of all referencing objects */ - JSEmptyScope(JSContext *cx, js::Class *clasp); + JSEmptyScope(JSContext *cx, const JSObjectOps *ops, js::Class *clasp); JSEmptyScope *hold() { /* The method is only called for already held objects. */ @@ -959,7 +960,7 @@ JSScope::search(jsid id, bool adding) #undef METER inline bool -JSScope::canProvideEmptyScope(js::Class *clasp) +JSScope::canProvideEmptyScope(JSObjectOps *ops, js::Class *clasp) { /* * An empty scope cannot provide another empty scope, or wrongful two-level @@ -967,7 +968,7 @@ JSScope::canProvideEmptyScope(js::Class *clasp) */ if (!object) return false; - return !emptyScope || emptyScope->clasp == clasp; + return this->ops == ops && (!emptyScope || emptyScope->clasp == clasp); } inline bool diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 3a914020f1c..fe95a9b54e3 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -53,7 +53,7 @@ JSScope::createEmptyScope(JSContext *cx, js::Class *clasp) { JS_ASSERT(!isSharedEmpty()); JS_ASSERT(!emptyScope); - emptyScope = cx->create(cx, clasp); + emptyScope = cx->create(cx, ops, clasp); return emptyScope; } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index fac571ba0a1..0e752e32ca0 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -413,21 +413,10 @@ Class js_ScriptClass = { "Script", JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - script_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - JS_CLASS_TRACE(script_trace) + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, script_finalize, + NULL, NULL, NULL, NULL,/*XXXbe xdr*/ + NULL, NULL, JS_CLASS_TRACE(script_trace), NULL }; /* diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 4a14e8c0ac3..68baa3c6d8b 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -806,13 +806,9 @@ Class js_StringClass = { js_String_str, JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_CACHED_PROTO(JSProto_String), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - str_getProperty, - PropertyStub, /* setProperty */ - str_enumerate, - (JSResolveOp)str_resolve, - ConvertStub + PropertyStub, PropertyStub, str_getProperty, PropertyStub, + str_enumerate, (JSResolveOp)str_resolve, ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS }; #define NORMALIZE_THIS(cx,vp,str) \ diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 5641da73eb7..576d0dd58ea 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -2911,7 +2911,7 @@ NativeToValue(JSContext* cx, Value& v, JSValueType type, double* slot) debug_only_printf(LC_TMTracer, "nullablestr<%p> ", v.isNull() ? NULL : (void *)&v.toObject()); break; case JSVAL_TYPE_BOXED: - debug_only_printf(LC_TMTracer, "box<%llx> ", (unsigned long long)v.asRawBits()); + debug_only_printf(LC_TMTracer, "box<%llx> ", v.asRawBits()); break; default: JS_NOT_REACHED("unexpected type"); @@ -8972,7 +8972,8 @@ TraceRecorder::equalityHelper(Value& l, Value& r, LIns* l_ins, LIns* r_ins, if (l.isNull()) op = LIR_eqp; } else if (l.isObject()) { - if (l.toObject().getClass()->ext.equality) + Class *clasp = l.toObject().getClass(); + if ((clasp->flags & JSCLASS_IS_EXTENDED) && ((JSExtendedClass*) clasp)->equality) RETURN_STOP_A("Can't trace extended class equality operator"); op = LIR_eqp; cond = (l == r); @@ -9382,6 +9383,8 @@ TraceRecorder::forgetGuardedShapes() guardedShapeTable.clear(); } +JS_STATIC_ASSERT(offsetof(JSObjectOps, objectMap) == 0); + inline LIns* TraceRecorder::map(LIns* obj_ins) { @@ -11382,7 +11385,7 @@ TraceRecorder::callNative(uintN argc, JSOp mode) if (clasp == &js_FunctionClass) RETURN_STOP("new Function"); - if (!clasp->isNative()) + if (clasp->getObjectOps) RETURN_STOP("new with non-native ops"); args[0] = INS_CONSTOBJ(funobj); @@ -11810,7 +11813,7 @@ TraceRecorder::record_JSOP_SETPROP() RETURN_STOP_A("primitive this for SETPROP"); JSObject* obj = &l.toObject(); - if (obj->getOps()->setProperty) + if (obj->map->ops->setProperty != js_SetProperty) RETURN_STOP_A("non-native JSObjectOps::setProperty"); return ARECORD_CONTINUE; } @@ -13513,7 +13516,7 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32 *slotp, LIns** v_insp, * object not having the same op must have a different class, and therefore * must differ in its shape (or not be the global object). */ - if (!obj->isDenseArray() && obj->getOps()->getProperty) + if (!obj->isDenseArray() && obj->map->ops->getProperty != js_GetProperty) RETURN_STOP_A("non-dense-array, non-native JSObjectOps::getProperty"); JS_ASSERT((slotp && v_insp && !outp) || (!slotp && !v_insp && outp)); @@ -14196,8 +14199,8 @@ TraceRecorder::record_JSOP_MOREITER() LIns* cond_ins; /* JSOP_FOR* already guards on this, but in certain rare cases we might record misformed loop traces. */ - if (iterobj->hasClass(&js_IteratorClass)) { - guardClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); + if (iterobj->hasClass(&js_IteratorClass.base)) { + guardClass(iterobj_ins, &js_IteratorClass.base, snapshot(BRANCH_EXIT), LOAD_NORMAL); NativeIterator *ni = (NativeIterator *) iterobj->getPrivate(); void *cursor = ni->props_cursor; void *end = ni->props_end; @@ -14213,7 +14216,7 @@ TraceRecorder::record_JSOP_MOREITER() cond = cursor < end; cond_ins = lir->ins2(LIR_ltp, cursor_ins, end_ins); } else { - guardNotClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); + guardNotClass(iterobj_ins, &js_IteratorClass.base, snapshot(BRANCH_EXIT), LOAD_NORMAL); enterDeepBailCall(); @@ -14311,8 +14314,8 @@ TraceRecorder::unboxNextValue(LIns* &v_ins) JSObject *iterobj = &iterobj_val.toObject(); LIns* iterobj_ins = get(&iterobj_val); - if (iterobj->hasClass(&js_IteratorClass)) { - guardClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); + if (iterobj->hasClass(&js_IteratorClass.base)) { + guardClass(iterobj_ins, &js_IteratorClass.base, snapshot(BRANCH_EXIT), LOAD_NORMAL); NativeIterator *ni = (NativeIterator *) iterobj->getPrivate(); LIns *ni_ins = stobj_get_const_private_ptr(iterobj_ins); @@ -14352,10 +14355,9 @@ TraceRecorder::unboxNextValue(LIns* &v_ins) cursor_ins = lir->ins2(LIR_addp, cursor_ins, INS_CONSTWORD(sizeof(Value))); } - lir->insStore(LIR_stp, cursor_ins, ni_ins, offsetof(NativeIterator, props_cursor), - ACCSET_OTHER); + lir->insStore(LIR_stp, cursor_ins, ni_ins, offsetof(NativeIterator, props_cursor), ACCSET_OTHER); } else { - guardNotClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); + guardNotClass(iterobj_ins, &js_IteratorClass.base, snapshot(BRANCH_EXIT), LOAD_NORMAL); v_ins = unbox_value(cx->iterValue, cx_ins, offsetof(JSContext, iterValue), snapshot(BRANCH_EXIT)); diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index f884685621a..a3b1e134240 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -493,6 +493,9 @@ class TypedArrayTemplate static const bool ArrayTypeIsUnsigned() { return TypeIsUnsigned(); } static const bool ArrayTypeIsFloatingPoint() { return TypeIsFloatingPoint(); } + static JSObjectOps fastObjectOps; + static JSObjectMap fastObjectMap; + static JSFunctionSpec jsfuncs[]; static inline Class *slowClass() @@ -505,6 +508,11 @@ class TypedArrayTemplate return &TypedArray::fastClasses[ArrayTypeID()]; } + static JSObjectOps *getObjectOps(JSContext *cx, Class *clasp) + { + return &fastObjectOps; + } + static JSBool obj_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { @@ -918,7 +926,7 @@ class TypedArrayTemplate JS_ASSERT(obj->getClass() == slowClass()); obj->setPrivate(tarray); obj->clasp = fastClass(); - obj->map = const_cast(&JSObjectMap::sharedNonNative); + obj->map = &fastObjectMap; } public: @@ -1256,14 +1264,9 @@ TypedArrayTemplate::copyIndexToValue(JSContext *cx, uint32 index, Value Class ArrayBuffer::jsclass = { "ArrayBuffer", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayBuffer), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - ArrayBuffer::class_finalize, + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, ArrayBuffer::class_finalize, + JSCLASS_NO_OPTIONAL_MEMBERS }; JSPropertySpec ArrayBuffer::jsprops[] = { @@ -1298,6 +1301,23 @@ JSPropertySpec TypedArray::jsprops[] = { */ #define IMPL_TYPED_ARRAY_STATICS(_typedArray) \ +template<> JSObjectMap _typedArray::fastObjectMap(&_typedArray::fastObjectOps, \ + JSObjectMap::SHAPELESS); \ +template<> JSObjectOps _typedArray::fastObjectOps = { \ + &_typedArray::fastObjectMap, \ + _typedArray::obj_lookupProperty, \ + _typedArray::obj_defineProperty, \ + _typedArray::obj_getProperty, \ + _typedArray::obj_setProperty, \ + _typedArray::obj_getAttributes, \ + _typedArray::obj_setAttributes, \ + _typedArray::obj_deleteProperty, \ + _typedArray::obj_enumerate, \ + _typedArray::obj_typeOf, \ + _typedArray::obj_trace, \ + NULL, /* thisObject */ \ + NULL /* clear */ \ +}; \ template<> JSFunctionSpec _typedArray::jsfuncs[] = { \ JS_FN("slice", _typedArray::fun_slice, 2, 0), \ JS_FS_END \ @@ -1307,50 +1327,20 @@ template<> JSFunctionSpec _typedArray::jsfuncs[] = { \ { \ #_typedArray, \ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \ - PropertyStub, /* addProperty */ \ - PropertyStub, /* delProperty */ \ - PropertyStub, /* getProperty */ \ - PropertyStub, /* setProperty */ \ - EnumerateStub, \ - ResolveStub, \ - ConvertStub, \ - FinalizeStub \ + PropertyStub, PropertyStub, PropertyStub, PropertyStub, \ + EnumerateStub, ResolveStub, ConvertStub, FinalizeStub, \ + JSCLASS_NO_OPTIONAL_MEMBERS \ } #define IMPL_TYPED_ARRAY_FAST_CLASS(_typedArray) \ { \ #_typedArray, \ - Class::NON_NATIVE | JSCLASS_HAS_PRIVATE, \ - PropertyStub, /* addProperty */ \ - PropertyStub, /* delProperty */ \ - PropertyStub, /* getProperty */ \ - PropertyStub, /* setProperty */ \ - EnumerateStub, \ - ResolveStub, \ - ConvertStub, \ + JSCLASS_HAS_PRIVATE, \ + PropertyStub, PropertyStub, PropertyStub, PropertyStub, \ + EnumerateStub, ResolveStub, ConvertStub, \ _typedArray::class_finalize, \ - NULL, /* reserved0 */ \ - NULL, /* checkAccess */ \ - NULL, /* call */ \ - NULL, /* construct */ \ - NULL, /* xdrObject */ \ - NULL, /* hasInstance */ \ - NULL, /* mark */ \ - JS_NULL_CLASS_EXT, \ - { \ - _typedArray::obj_lookupProperty, \ - _typedArray::obj_defineProperty, \ - _typedArray::obj_getProperty, \ - _typedArray::obj_setProperty, \ - _typedArray::obj_getAttributes, \ - _typedArray::obj_setAttributes, \ - _typedArray::obj_deleteProperty, \ - _typedArray::obj_enumerate, \ - _typedArray::obj_typeOf, \ - _typedArray::obj_trace, \ - NULL, /* thisObject */ \ - NULL, /* clear */ \ - } \ + _typedArray::getObjectOps, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL \ } #define INIT_TYPED_ARRAY_CLASS(_typedArray,_type) \ diff --git a/js/src/jsvalue.h b/js/src/jsvalue.h index 3d975f57c80..93c80d666a2 100644 --- a/js/src/jsvalue.h +++ b/js/src/jsvalue.h @@ -779,6 +779,8 @@ typedef JSBool typedef JSBool (* CheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, Value *vp); +typedef JSObjectOps * +(* GetObjectOps)(JSContext *cx, Class *clasp); typedef JSBool (* EqualityOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp); typedef JSBool @@ -803,6 +805,8 @@ static inline HasInstanceOp Valueify(JSHasInstanceOp f) { return (HasInsta static inline JSHasInstanceOp Jsvalify(HasInstanceOp f) { return (JSHasInstanceOp)f; } static inline CheckAccessOp Valueify(JSCheckAccessOp f) { return (CheckAccessOp)f; } static inline JSCheckAccessOp Jsvalify(CheckAccessOp f) { return (JSCheckAccessOp)f; } +static inline GetObjectOps Valueify(JSGetObjectOps f) { return (GetObjectOps)f; } +static inline JSGetObjectOps Jsvalify(GetObjectOps f) { return (JSGetObjectOps)f; } static inline EqualityOp Valueify(JSEqualityOp f); /* Same type as JSHasInstanceOp */ static inline JSEqualityOp Jsvalify(EqualityOp f); /* Same type as HasInstanceOp */ static inline DefinePropOp Valueify(JSDefinePropOp f) { return (DefinePropOp)f; } @@ -818,91 +822,30 @@ static const JSResolveOp ResolveStub = JS_ResolveStub; static const ConvertOp ConvertStub = (ConvertOp)JS_ConvertStub; static const JSFinalizeOp FinalizeStub = JS_FinalizeStub; -#define JS_CLASS_MEMBERS \ - const char *name; \ - uint32 flags; \ - \ - /* Mandatory non-null function pointer members. */ \ - PropertyOp addProperty; \ - PropertyOp delProperty; \ - PropertyOp getProperty; \ - PropertyOp setProperty; \ - JSEnumerateOp enumerate; \ - JSResolveOp resolve; \ - ConvertOp convert; \ - JSFinalizeOp finalize; \ - \ - /* Optionally non-null members start here. */ \ - JSClassInternal reserved0; \ - CheckAccessOp checkAccess; \ - Native call; \ - Native construct; \ - JSXDRObjectOp xdrObject; \ - HasInstanceOp hasInstance; \ - JSMarkOp mark - - -/* - * The helper struct to measure the size of JS_CLASS_MEMBERS to know how much - * we have to padd js::Class to match the size of JSClass; - */ -struct ClassSizeMeasurement { - JS_CLASS_MEMBERS; -}; - -struct ClassExtension { - EqualityOp equality; - JSObjectOp outerObject; - JSObjectOp innerObject; - JSIteratorOp iteratorObject; - JSObjectOp wrappedObject; /* NB: infallible, null returns are - treated as the original object */ -}; - -#define JS_NULL_CLASS_EXT {NULL,NULL,NULL,NULL,NULL} - -struct ObjectOps { - JSLookupPropOp lookupProperty; - js::DefinePropOp defineProperty; - js::PropertyIdOp getProperty; - js::PropertyIdOp setProperty; - JSAttributesOp getAttributes; - JSAttributesOp setAttributes; - js::PropertyIdOp deleteProperty; - js::NewEnumerateOp enumerate; - JSTypeOfOp typeOf; - JSTraceOp trace; - JSObjectOp thisObject; - JSFinalizeOp clear; -}; - -#define JS_NULL_OBJECT_OPS {NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL} - struct Class { - JS_CLASS_MEMBERS; - ClassExtension ext; - ObjectOps ops; - uint8 pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) - - sizeof(ClassExtension) - sizeof(ObjectOps)]; + const char *name; + uint32 flags; - /* Flag indicating that Class::call is a fast native. */ - static const uint32 CALL_IS_FAST = JSCLASS_INTERNAL_FLAG1; + /* Mandatory non-null function pointer members. */ + PropertyOp addProperty; + PropertyOp delProperty; + PropertyOp getProperty; + PropertyOp setProperty; + JSEnumerateOp enumerate; + JSResolveOp resolve; + ConvertOp convert; + JSFinalizeOp finalize; - /* Class is not native and its map is not a scope. */ - static const uint32 NON_NATIVE = JSCLASS_INTERNAL_FLAG2; - - bool isNative() const { - return !(flags & NON_NATIVE); - } + /* Optionally non-null members start here. */ + GetObjectOps getObjectOps; + CheckAccessOp checkAccess; + Native call; + Native construct; + JSXDRObjectOp xdrObject; + HasInstanceOp hasInstance; + JSMarkOp mark; + void (*reserved0)(void); }; - -/* Helper to initialize Class::call when Class::CALL_IS_FAST. */ -inline Native -CastCallOpAsNative(CallOp op) -{ - return reinterpret_cast(op); -} - JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name)); JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags)); JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty)); @@ -913,15 +856,40 @@ JS_STATIC_ASSERT(offsetof(JSClass, enumerate) == offsetof(Class, enumerate)); JS_STATIC_ASSERT(offsetof(JSClass, resolve) == offsetof(Class, resolve)); JS_STATIC_ASSERT(offsetof(JSClass, convert) == offsetof(Class, convert)); JS_STATIC_ASSERT(offsetof(JSClass, finalize) == offsetof(Class, finalize)); -JS_STATIC_ASSERT(offsetof(JSClass, reserved0) == offsetof(Class, reserved0)); +JS_STATIC_ASSERT(offsetof(JSClass, getObjectOps) == offsetof(Class, getObjectOps)); JS_STATIC_ASSERT(offsetof(JSClass, checkAccess) == offsetof(Class, checkAccess)); JS_STATIC_ASSERT(offsetof(JSClass, call) == offsetof(Class, call)); JS_STATIC_ASSERT(offsetof(JSClass, construct) == offsetof(Class, construct)); JS_STATIC_ASSERT(offsetof(JSClass, xdrObject) == offsetof(Class, xdrObject)); JS_STATIC_ASSERT(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance)); JS_STATIC_ASSERT(offsetof(JSClass, mark) == offsetof(Class, mark)); +JS_STATIC_ASSERT(offsetof(JSClass, reserved0) == offsetof(Class, reserved0)); JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class)); +struct ExtendedClass { + Class base; + EqualityOp equality; + JSObjectOp outerObject; + JSObjectOp innerObject; + JSIteratorOp iteratorObject; + JSObjectOp wrappedObject; /* NB: infallible, null + returns are treated as + the original object */ + void (*reserved0)(void); + void (*reserved1)(void); + void (*reserved2)(void); +}; +JS_STATIC_ASSERT(offsetof(JSExtendedClass, base) == offsetof(ExtendedClass, base)); +JS_STATIC_ASSERT(offsetof(JSExtendedClass, equality) == offsetof(ExtendedClass, equality)); +JS_STATIC_ASSERT(offsetof(JSExtendedClass, outerObject) == offsetof(ExtendedClass, outerObject)); +JS_STATIC_ASSERT(offsetof(JSExtendedClass, innerObject) == offsetof(ExtendedClass, innerObject)); +JS_STATIC_ASSERT(offsetof(JSExtendedClass, iteratorObject) == offsetof(ExtendedClass, iteratorObject)); +JS_STATIC_ASSERT(offsetof(JSExtendedClass, wrappedObject) == offsetof(ExtendedClass, wrappedObject)); +JS_STATIC_ASSERT(offsetof(JSExtendedClass, reserved0) == offsetof(ExtendedClass, reserved0)); +JS_STATIC_ASSERT(offsetof(JSExtendedClass, reserved1) == offsetof(ExtendedClass, reserved1)); +JS_STATIC_ASSERT(offsetof(JSExtendedClass, reserved2) == offsetof(ExtendedClass, reserved2)); +JS_STATIC_ASSERT(sizeof(JSExtendedClass) == sizeof(ExtendedClass)); + struct PropertyDescriptor { JSObject *obj; uintN attrs; @@ -940,6 +908,8 @@ JS_STATIC_ASSERT(sizeof(JSPropertyDescriptor) == sizeof(PropertyDescriptor)); static JS_ALWAYS_INLINE JSClass * Jsvalify(Class *c) { return (JSClass *)c; } static JS_ALWAYS_INLINE Class * Valueify(JSClass *c) { return (Class *)c; } +static JS_ALWAYS_INLINE JSExtendedClass * Jsvalify(ExtendedClass *c) { return (JSExtendedClass *)c; } +static JS_ALWAYS_INLINE ExtendedClass * Valueify(JSExtendedClass *c) { return (ExtendedClass *)c; } static JS_ALWAYS_INLINE JSPropertyDescriptor * Jsvalify(PropertyDescriptor *p) { return (JSPropertyDescriptor *) p; } static JS_ALWAYS_INLINE PropertyDescriptor * Valueify(JSPropertyDescriptor *p) { return (PropertyDescriptor *) p; } diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 063b42d1f15..ef43dcaa639 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -684,7 +684,7 @@ CanReify(Value *vp) { JSObject *obj; return vp->isObject() && - (obj = &vp->toObject())->getClass() == &js_IteratorClass && + (obj = &vp->toObject())->getClass() == &js_IteratorClass.base && (obj->getNativeIterator()->flags & JSITER_ENUMERATE); } diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 05fdb10ddcf..2290291a711 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -190,7 +190,7 @@ IsDeclared(const JSObject *obj) { jsval v; - JS_ASSERT(obj->getClass() == &js_NamespaceClass); + JS_ASSERT(obj->getClass() == &js_NamespaceClass.base); v = obj->getNamespaceDeclared(); JS_ASSERT(JSVAL_IS_VOID(v) || v == JSVAL_TRUE); return v == JSVAL_TRUE; @@ -224,9 +224,9 @@ AppendString(JSCharBuffer &cb, JSString *str) * Namespace class and library functions. */ DEFINE_GETTER(NamePrefix_getter, - if (obj->getClass() == &js_NamespaceClass) *vp = obj->getNamePrefix()) + if (obj->getClass() == &js_NamespaceClass.base) *vp = obj->getNamePrefix()) DEFINE_GETTER(NameURI_getter, - if (obj->getClass() == &js_NamespaceClass) *vp = obj->getNameURI()) + if (obj->getClass() == &js_NamespaceClass.base) *vp = obj->getNameURI()) static void namespace_finalize(JSContext *cx, JSObject *obj) @@ -242,39 +242,23 @@ namespace_equality(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp) JS_ASSERT(v->isObjectOrNull()); obj2 = v->toObjectOrNull(); - *bp = (!obj2 || obj2->getClass() != &js_NamespaceClass) + *bp = (!obj2 || obj2->getClass() != &js_NamespaceClass.base) ? JS_FALSE : js_EqualStrings(GetURI(obj), GetURI(obj2)); return JS_TRUE; } -JS_FRIEND_DATA(Class) js_NamespaceClass = { - "Namespace", - JSCLASS_CONSTRUCT_PROTOTYPE | +JS_FRIEND_DATA(ExtendedClass) js_NamespaceClass = { + { "Namespace", + JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED | JSCLASS_HAS_RESERVED_SLOTS(JSObject::NAMESPACE_FIXED_RESERVED_SLOTS) | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - namespace_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* mark */ - { - namespace_equality, - NULL, /* outerObject */ - NULL, /* innerObject */ - NULL, /* iteratorObject */ - NULL, /* wrappedObject */ - } + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, namespace_finalize, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }, + namespace_equality,NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; #define NAMESPACE_ATTRS \ @@ -292,7 +276,7 @@ namespace_toString(JSContext *cx, uintN argc, jsval *vp) JSObject *obj; obj = JS_THIS_OBJECT(cx, vp); - if (!JS_InstanceOf(cx, obj, Jsvalify(&js_NamespaceClass), vp + 2)) + if (!JS_InstanceOf(cx, obj, Jsvalify(&js_NamespaceClass.base), vp + 2)) return JS_FALSE; *vp = obj->getNameURI(); return JS_TRUE; @@ -308,7 +292,7 @@ NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared) { JSObject *obj; - obj = NewBuiltinClassInstance(cx, &js_NamespaceClass); + obj = NewBuiltinClassInstance(cx, &js_NamespaceClass.base); if (!obj) return JS_FALSE; JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefix())); @@ -328,10 +312,10 @@ NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared) * QName class and library functions. */ DEFINE_GETTER(QNameNameURI_getter, - if (obj->getClass() == &js_QNameClass) + if (obj->getClass() == &js_QNameClass.base) *vp = JSVAL_IS_VOID(obj->getNameURI()) ? JSVAL_NULL : obj->getNameURI()) DEFINE_GETTER(QNameLocalName_getter, - if (obj->getClass() == &js_QNameClass) + if (obj->getClass() == &js_QNameClass.base) *vp = obj->getQNameLocalName()) static void @@ -361,39 +345,23 @@ qname_equality(JSContext *cx, JSObject *qn, const Value *v, JSBool *bp) JSObject *obj2; obj2 = v->toObjectOrNull(); - *bp = (!obj2 || obj2->getClass() != &js_QNameClass) + *bp = (!obj2 || obj2->getClass() != &js_QNameClass.base) ? JS_FALSE : qname_identity(qn, obj2); return JS_TRUE; } -JS_FRIEND_DATA(Class) js_QNameClass = { - "QName", - JSCLASS_CONSTRUCT_PROTOTYPE | +JS_FRIEND_DATA(ExtendedClass) js_QNameClass = { + { "QName", + JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED | JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_FIXED_RESERVED_SLOTS) | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_QName), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - FinalizeStub, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* mark */ - { - qname_equality, - NULL, /* outerObject */ - NULL, /* innerObject */ - NULL, /* iteratorObject */ - NULL, /* wrappedObject */ - } + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }, + qname_equality, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; /* @@ -407,13 +375,10 @@ JS_FRIEND_DATA(Class) js_AttributeNameClass = { JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_FIXED_RESERVED_SLOTS) | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_AttributeName), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; JS_FRIEND_DATA(Class) js_AnyNameClass = { @@ -421,17 +386,14 @@ JS_FRIEND_DATA(Class) js_AnyNameClass = { JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_FIXED_RESERVED_SLOTS) | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_AnyName), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - anyname_finalize + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, anyname_finalize, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; -#define QNAME_ATTRS (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED) +#define QNAME_ATTRS \ + (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED) static JSPropertySpec qname_props[] = { {js_uri_str, 0, QNAME_ATTRS, QNameNameURI_getter, 0}, @@ -454,7 +416,7 @@ qname_toString(JSContext *cx, uintN argc, jsval *vp) clasp = obj->getClass(); if (clasp != &js_AttributeNameClass && clasp != &js_AnyNameClass && - !JS_InstanceOf(cx, obj, Jsvalify(&js_QNameClass), vp + 2)) { + !JS_InstanceOf(cx, obj, Jsvalify(&js_QNameClass.base), vp + 2)) { return JS_FALSE; } @@ -517,7 +479,7 @@ InitXMLQName(JSObject *obj, JSString *uri, JSString *prefix, static JSObject * NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix, JSString *localName, - Class *clasp = &js_QNameClass) + Class *clasp = &js_QNameClass.base) { JSObject *obj = NewBuiltinClassInstance(cx, clasp); if (!obj) @@ -545,7 +507,7 @@ js_ConstructXMLQNameObject(JSContext *cx, const Value &nsval, const Value &lnval argv[0] = nsval; } argv[1] = lnval; - return js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 2, argv); + return js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, argv); } static JSBool @@ -619,8 +581,8 @@ NamespaceHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv, if (!JSVAL_IS_PRIMITIVE(urival)) { uriobj = JSVAL_TO_OBJECT(urival); clasp = uriobj->getClass(); - isNamespace = (clasp == &js_NamespaceClass); - isQName = (clasp == &js_QNameClass); + isNamespace = (clasp == &js_NamespaceClass.base); + isQName = (clasp == &js_QNameClass.base); } } @@ -632,7 +594,7 @@ NamespaceHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv, return JS_TRUE; } - obj = NewBuiltinClassInstance(cx, &js_NamespaceClass); + obj = NewBuiltinClassInstance(cx, &js_NamespaceClass.base); if (!obj) return JS_FALSE; *rval = OBJECT_TO_JSVAL(obj); @@ -715,7 +677,7 @@ QNameHelper(JSContext *cx, JSObject *obj, Class *clasp, intN argc, JSString *uri, *prefix, *name; JSObject *obj2; - JS_ASSERT(clasp == &js_QNameClass || + JS_ASSERT(clasp == &js_QNameClass.base || clasp == &js_AttributeNameClass); if (argc <= 0) { nameval = JSVAL_VOID; @@ -724,7 +686,7 @@ QNameHelper(JSContext *cx, JSObject *obj, Class *clasp, intN argc, nameval = argv[argc > 1]; isQName = !JSVAL_IS_PRIMITIVE(nameval) && - JSVAL_TO_OBJECT(nameval)->getClass() == &js_QNameClass; + JSVAL_TO_OBJECT(nameval)->getClass() == &js_QNameClass.base; } if (!obj) { @@ -780,7 +742,7 @@ QNameHelper(JSContext *cx, JSObject *obj, Class *clasp, intN argc, return JS_FALSE; JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval)); JS_ASSERT(JSVAL_TO_OBJECT(nsval)->getClass() == - &js_NamespaceClass); + &js_NamespaceClass.base); } if (JSVAL_IS_NULL(nsval)) { @@ -798,8 +760,8 @@ QNameHelper(JSContext *cx, JSObject *obj, Class *clasp, intN argc, if (!JSVAL_IS_PRIMITIVE(nsval)) { obj2 = JSVAL_TO_OBJECT(nsval); clasp = obj2->getClass(); - isNamespace = (clasp == &js_NamespaceClass); - isQName = (clasp == &js_QNameClass); + isNamespace = (clasp == &js_NamespaceClass.base); + isQName = (clasp == &js_QNameClass.base); } #ifdef __GNUC__ /* suppress bogus gcc warnings */ else obj2 = NULL; @@ -832,7 +794,7 @@ static JSBool QName(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval) { return QNameHelper(cx, cx->isConstructing() ? obj : NULL, - &js_QNameClass, argc, Jsvalify(argv), Jsvalify(rval)); + &js_QNameClass.base, argc, Jsvalify(argv), Jsvalify(rval)); } static JSBool @@ -2197,7 +2159,7 @@ GetNamespace(JSContext *cx, JSObject *qn, const JSXMLArray *inScopeNSes) if (!match) { argv[0] = prefix ? STRING_TO_JSVAL(prefix) : JSVAL_VOID; argv[1] = STRING_TO_JSVAL(uri); - ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, NULL, + ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL, 2, Valueify(argv)); if (!ns) return NULL; @@ -2752,7 +2714,7 @@ ToAttributeName(JSContext *cx, jsval v) if (clasp == &js_AttributeNameClass) return obj; - if (clasp == &js_QNameClass) { + if (clasp == &js_QNameClass.base) { qn = obj; uri = GetURI(qn); prefix = GetPrefix(qn); @@ -2801,7 +2763,7 @@ IsFunctionQName(JSContext *cx, JSObject *qn, jsid *funidp) JSBool js_IsFunctionQName(JSContext *cx, JSObject *obj, jsid *funidp) { - if (obj->getClass() == &js_QNameClass) + if (obj->getClass() == &js_QNameClass.base) return IsFunctionQName(cx, obj, funidp); *funidp = JSID_VOID; return JS_TRUE; @@ -2826,7 +2788,7 @@ ToXMLName(JSContext *cx, jsval v, jsid *funidp) obj = JSVAL_TO_OBJECT(v); clasp = obj->getClass(); - if (clasp == &js_AttributeNameClass || clasp == &js_QNameClass) + if (clasp == &js_AttributeNameClass || clasp == &js_QNameClass.base) goto out; if (clasp == &js_AnyNameClass) { name = ATOM_TO_STRING(cx->runtime->atomState.starAtom); @@ -2867,7 +2829,7 @@ ToXMLName(JSContext *cx, jsval v, jsid *funidp) construct: v = STRING_TO_JSVAL(name); - obj = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1, Valueify(&v)); + obj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, Valueify(&v)); if (!obj) return NULL; @@ -4639,13 +4601,13 @@ xml_trace_vector(JSTracer *trc, JSXML **vec, uint32 len) } /* - * XML objects are native. Thus xml_lookupProperty must return a valid - * JSScopeProperty pointer parameter via *propp to signify "property found". - * Since the only call to xml_lookupProperty is via JSObject::lookupProperty, - * and then only from js_FindProperty (in jsobj.c, called from jsinterp.c) or - * from JSOP_IN case in the interpreter, the only time we add a - * JSScopeProperty here is when an unqualified name is being accessed or when - * "name in xml" is called. + * js_XMLObjectOps.newObjectMap is null, so XML objects appear to be native. + * Thus xml_lookupProperty must return a valid JSScopeProperty pointer + * parameter via *propp to signify "property found". Since the only call to + * xml_lookupProperty is via JSObject::lookupProperty, and then only from + * js_FindProperty (in jsobj.c, called from jsinterp.c) or from JSOP_IN case + * in the interpreter, the only time we add a JSScopeProperty here is when an + * unqualified name is being accessed or when "name in xml" is called. * * This scope property keeps the JSOP_NAME code in js_Interpret happy by * giving it an sprop with (getter, setter) == (GetProperty, PutProperty). @@ -5068,39 +5030,37 @@ out: return ok; } +/* Use NULL for objectMap so XML objects satisfy obj->isNative() tests. */ +JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps = { + NULL, + xml_lookupProperty, + xml_defineProperty, + xml_getProperty, + xml_setProperty, + xml_getAttributes, + xml_setAttributes, + xml_deleteProperty, + xml_enumerate, + xml_typeOf, + js_TraceObject, + NULL, /* thisObject */ + xml_clear +}; + +static JSObjectOps * +xml_getObjectOps(JSContext *cx, Class *clasp) +{ + return &js_XMLObjectOps; +} + JS_FRIEND_DATA(Class) js_XMLClass = { js_XML_str, - JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_XML), - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - xml_convert, - xml_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - xml_hasInstance, - JS_CLASS_TRACE(xml_trace), - JS_NULL_CLASS_EXT, - { - xml_lookupProperty, - xml_defineProperty, - xml_getProperty, - xml_setProperty, - xml_getAttributes, - xml_setAttributes, - xml_deleteProperty, - xml_enumerate, - xml_typeOf, - NULL, /* trace */ - NULL, /* thisObject */ - xml_clear - } + JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE | + JSCLASS_HAS_CACHED_PROTO(JSProto_XML), + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, xml_convert, xml_finalize, + xml_getObjectOps, NULL, NULL, NULL, + NULL, xml_hasInstance, JS_CLASS_TRACE(xml_trace), NULL }; static JSXML * @@ -6294,7 +6254,7 @@ xml_replace(JSContext *cx, uintN argc, jsval *vp) * Call function QName per spec, not ToXMLName, to avoid attribute * names. */ - if (!QNameHelper(cx, NULL, &js_QNameClass, argc == 0 ? -1 : 1, + if (!QNameHelper(cx, NULL, &js_QNameClass.base, argc == 0 ? -1 : 1, vp + 2, vp)) { return JS_FALSE; } @@ -6357,7 +6317,7 @@ xml_setLocalName(JSContext *cx, uintN argc, jsval *vp) } else { name = vp[2]; if (!JSVAL_IS_PRIMITIVE(name) && - JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass) { + JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass.base) { nameqn = JSVAL_TO_OBJECT(name); namestr = GetLocalName(nameqn); } else { @@ -6394,13 +6354,13 @@ xml_setName(JSContext *cx, uintN argc, jsval *vp) } else { name = vp[2]; if (!JSVAL_IS_PRIMITIVE(name) && - JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass && + JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass.base && !GetURI(nameqn = JSVAL_TO_OBJECT(name))) { name = vp[2] = nameqn->getQNameLocalName(); } } - nameqn = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1, Valueify(&name)); + nameqn = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, Valueify(&name)); if (!nameqn) return JS_FALSE; @@ -6499,7 +6459,7 @@ xml_setNamespace(JSContext *cx, uintN argc, jsval *vp) if (!xml) return JS_FALSE; - ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, obj, + ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj, argc == 0 ? 0 : 1, Valueify(vp + 2)); if (!ns) return JS_FALSE; @@ -6508,7 +6468,7 @@ xml_setNamespace(JSContext *cx, uintN argc, jsval *vp) qnargv[0] = vp[2] = OBJECT_TO_JSVAL(ns); qnargv[1] = OBJECT_TO_JSVAL(xml->name); - qn = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 2, Valueify(qnargv)); + qn = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, Valueify(qnargv)); if (!qn) return JS_FALSE; @@ -7035,14 +6995,14 @@ js_GetXMLObject(JSContext *cx, JSXML *xml) JSObject * js_InitNamespaceClass(JSContext *cx, JSObject *obj) { - return js_InitClass(cx, obj, NULL, &js_NamespaceClass, Namespace, 2, + return js_InitClass(cx, obj, NULL, &js_NamespaceClass.base, Namespace, 2, namespace_props, namespace_methods, NULL, NULL); } JSObject * js_InitQNameClass(JSContext *cx, JSObject *obj) { - return js_InitClass(cx, obj, NULL, &js_QNameClass, QName, 2, + return js_InitClass(cx, obj, NULL, &js_QNameClass.base, QName, 2, qname_props, qname_methods, NULL, NULL); } @@ -7238,7 +7198,7 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp) obj = tmp; } - ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, obj, 0, NULL); + ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj, 0, NULL); if (!ns) return JS_FALSE; v = OBJECT_TO_JSVAL(ns); @@ -7259,7 +7219,7 @@ js_SetDefaultXMLNamespace(JSContext *cx, const Value &v) argv[0].setString(cx->runtime->emptyString); argv[1] = v; - ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, NULL, 2, argv); + ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL, 2, argv); if (!ns) return JS_FALSE; @@ -7425,13 +7385,13 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i nameobj = &nameval.toObject(); if (nameobj->getClass() == &js_AnyNameClass) { v = ATOM_TO_JSVAL(cx->runtime->atomState.starAtom); - nameobj = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1, + nameobj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, Valueify(&v)); if (!nameobj) return JS_FALSE; } else { JS_ASSERT(nameobj->getClass() == &js_AttributeNameClass || - nameobj->getClass() == &js_QNameClass); + nameobj->getClass() == &js_QNameClass.base); } qn = nameobj; @@ -7606,21 +7566,10 @@ xmlfilter_finalize(JSContext *cx, JSObject *obj) Class js_XMLFilterClass = { "XMLFilter", JSCLASS_HAS_PRIVATE | JSCLASS_IS_ANONYMOUS | JSCLASS_MARK_IS_TRACE, - PropertyStub, /* addProperty */ - PropertyStub, /* delProperty */ - PropertyStub, /* getProperty */ - PropertyStub, /* setProperty */ - EnumerateStub, - ResolveStub, - ConvertStub, - xmlfilter_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - JS_CLASS_TRACE(xmlfilter_trace) + PropertyStub, PropertyStub, PropertyStub, PropertyStub, + EnumerateStub, ResolveStub, ConvertStub, xmlfilter_finalize, + NULL, NULL, NULL, NULL, + NULL, NULL, JS_CLASS_TRACE(xmlfilter_trace), NULL }; JSBool diff --git a/js/src/jsxml.h b/js/src/jsxml.h index a46851a1fe7..2f640664171 100644 --- a/js/src/jsxml.h +++ b/js/src/jsxml.h @@ -216,12 +216,13 @@ js_NewXMLObject(JSContext *cx, JSXMLClass xml_class); extern JSObject * js_GetXMLObject(JSContext *cx, JSXML *xml); -extern JS_FRIEND_DATA(js::Class) js_XMLClass; -extern JS_FRIEND_DATA(js::Class) js_NamespaceClass; -extern JS_FRIEND_DATA(js::Class) js_QNameClass; -extern JS_FRIEND_DATA(js::Class) js_AttributeNameClass; -extern JS_FRIEND_DATA(js::Class) js_AnyNameClass; -extern js::Class js_XMLFilterClass; +extern JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps; +extern JS_FRIEND_DATA(js::Class) js_XMLClass; +extern JS_FRIEND_DATA(js::ExtendedClass) js_NamespaceClass; +extern JS_FRIEND_DATA(js::ExtendedClass) js_QNameClass; +extern JS_FRIEND_DATA(js::Class) js_AttributeNameClass; +extern JS_FRIEND_DATA(js::Class) js_AnyNameClass; +extern js::Class js_XMLFilterClass; /* * Methods to test whether an object or a value is of type "xml" (per typeof). @@ -229,14 +230,14 @@ extern js::Class js_XMLFilterClass; inline bool JSObject::isXML() const { - return getClass() == &js_XMLClass; + return map->ops == &js_XMLObjectOps; } inline bool JSObject::isXMLId() const { js::Class *clasp = getClass(); - return clasp == &js_QNameClass || + return clasp == &js_QNameClass.base || clasp == &js_AttributeNameClass || clasp == &js_AnyNameClass; } @@ -246,14 +247,14 @@ JSObject::isXMLId() const inline bool JSObject::isNamespace() const { - return getClass() == &js_NamespaceClass; + return getClass() == &js_NamespaceClass.base; } inline bool JSObject::isQName() const { js::Class* clasp = getClass(); - return clasp == &js_QNameClass || + return clasp == &js_QNameClass.base || clasp == &js_AttributeNameClass || clasp == &js_AnyNameClass; } diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 3f5fa66108c..80e95593dd3 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1393,7 +1393,7 @@ ValueToScript(JSContext *cx, jsval v) if (clasp == Jsvalify(&js_ScriptClass)) { script = (JSScript *) JS_GetPrivate(cx, obj); - } else if (clasp == Jsvalify(&js_GeneratorClass)) { + } else if (clasp == Jsvalify(&js_GeneratorClass.base)) { JSGenerator *gen = (JSGenerator *) JS_GetPrivate(cx, obj); fun = gen->getFloatingFrame()->fun; script = FUN_SCRIPT(fun); @@ -2743,6 +2743,18 @@ split_thisObject(JSContext *cx, JSObject *obj) return obj; } +static JSObjectOps split_objectops; + +static JSObjectOps * +split_getObjectOps(JSContext *cx, JSClass *clasp) +{ + if (!split_objectops.thisObject) { + memcpy(&split_objectops, &js_ObjectOps, sizeof split_objectops); + split_objectops.thisObject = split_thisObject; + } + + return &split_objectops; +} static JSBool split_equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp); @@ -2760,45 +2772,19 @@ split_innerObject(JSContext *cx, JSObject *obj) return !cpx->isInner ? cpx->inner : obj; } -static Class split_global_class = { - "split_global", - JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS, - Valueify(split_addProperty), - Valueify(split_delProperty), - Valueify(split_getProperty), - Valueify(split_setProperty), +static JSExtendedClass split_global_class = { + {"split_global", + JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_PRIVATE | + JSCLASS_GLOBAL_FLAGS | JSCLASS_IS_EXTENDED, + split_addProperty, split_delProperty, + split_getProperty, split_setProperty, (JSEnumerateOp)split_enumerate, (JSResolveOp)split_resolve, - ConvertStub, - split_finalize, - NULL, /* reserved0 */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - split_mark, - { - Valueify(split_equality), - split_outerObject, - split_innerObject, - NULL, /* iteratorObject */ - NULL, /* wrappedObject */ - }, - { - NULL, /* lookupProperty */ - NULL, /* defineProperty */ - NULL, /* getProperty */ - NULL, /* setProperty */ - NULL, /* getAttributes */ - NULL, /* setAttributes */ - NULL, /* deleteProperty */ - NULL, /* enumerate */ - NULL, /* typeOf */ - NULL, /* trace */ - split_thisObject, - NULL, /* clear */ - }, + JS_ConvertStub, split_finalize, + split_getObjectOps, NULL, NULL, NULL, NULL, NULL, + split_mark, NULL}, + split_equality, split_outerObject, split_innerObject, + NULL, NULL, NULL, NULL, NULL }; static JSBool @@ -2809,7 +2795,7 @@ split_equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp) return JS_TRUE; JSObject *obj2 = JSVAL_TO_OBJECT(*v); - if (obj2->getClass() != &split_global_class) + if (JS_GET_CLASS(cx, obj2) != &split_global_class.base) return JS_TRUE; ComplexObject *cpx = (ComplexObject *) JS_GetPrivate(cx, obj2); @@ -2836,7 +2822,7 @@ split_create_outer(JSContext *cx) cpx->inner = NULL; cpx->outer = NULL; - obj = JS_NewGlobalObject(cx, Jsvalify(&split_global_class)); + obj = JS_NewGlobalObject(cx, &split_global_class.base); if (!obj || !JS_SetParent(cx, obj, NULL)) { JS_free(cx, cpx); return NULL; @@ -2856,7 +2842,7 @@ split_create_inner(JSContext *cx, JSObject *outer) ComplexObject *cpx, *outercpx; JSObject *obj; - JS_ASSERT(outer->getClass() == &split_global_class); + JS_ASSERT(JS_GET_CLASS(cx, outer) == &split_global_class.base); cpx = (ComplexObject *) JS_malloc(cx, sizeof *cpx); if (!cpx) @@ -2866,7 +2852,7 @@ split_create_inner(JSContext *cx, JSObject *outer) cpx->inner = NULL; cpx->outer = outer; - obj = JS_NewGlobalObject(cx, Jsvalify(&split_global_class)); + obj = JS_NewGlobalObject(cx, &split_global_class.base); if (!obj || !JS_SetParent(cx, obj, NULL) || !JS_SetPrivate(cx, obj, cpx)) { JS_free(cx, cpx); return NULL; @@ -2883,7 +2869,7 @@ static ComplexObject * split_get_private(JSContext *cx, JSObject *obj) { do { - if (obj->getClass() == &split_global_class) + if (JS_GET_CLASS(cx, obj) == &split_global_class.base) return (ComplexObject *) JS_GetPrivate(cx, obj); obj = JS_GetParent(cx, obj); } while (obj); @@ -3668,8 +3654,12 @@ Parent(JSContext *cx, uintN argc, jsval *vp) /* Outerize if necessary. Embrace the ugliness! */ if (parent) { - if (JSObjectOp op = parent->getClass()->ext.outerObject) - *vp = OBJECT_TO_JSVAL(op(cx, parent)); + JSClass *clasp = JS_GET_CLASS(cx, parent); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + JSExtendedClass *xclasp = reinterpret_cast(clasp); + if (JSObjectOp outerize = xclasp->outerObject) + *vp = OBJECT_TO_JSVAL(outerize(cx, parent)); + } } return JS_TRUE; diff --git a/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp b/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp index 0f12b0f81eb..10cccb78121 100644 --- a/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp +++ b/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp @@ -59,7 +59,6 @@ #include "jsapi.h" #include "jsdbgapi.h" -#include "jsobj.h" #include "mozilla/FunctionTimer.h" @@ -205,13 +204,18 @@ mozJSSubScriptLoader::LoadSubScript (const PRUnichar * aURL // Innerize the target_obj so that we compile the loaded script in the // correct (inner) scope. - if (JSObjectOp op = target_obj->getClass()->ext.innerObject) + JSClass *target_class = JS_GET_CLASS(cx, target_obj); + if (target_class->flags & JSCLASS_IS_EXTENDED) { - target_obj = op(cx, target_obj); - if (!target_obj) return NS_ERROR_FAILURE; + JSExtendedClass *extended = (JSExtendedClass*)target_class; + if (extended->innerObject) + { + target_obj = extended->innerObject(cx, target_obj); + if (!target_obj) return NS_ERROR_FAILURE; #ifdef DEBUG_rginda - fprintf (stderr, "Final global: %p\n", target_obj); + fprintf (stderr, "Final global: %p\n", target_obj); #endif + } } /* load up the url. From here on, failures are reflected as ``custom'' diff --git a/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp b/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp index 7a324a745f3..03748271bfe 100644 --- a/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp +++ b/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp @@ -251,34 +251,28 @@ using namespace XPCWrapper; namespace ChromeObjectWrapper { -js::Class COWClass = { - "ChromeObjectWrapper", - JSCLASS_NEW_RESOLVE | +JSExtendedClass COWClass = { + // JSClass (JSExtendedClass.base) initialization + { "ChromeObjectWrapper", + JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED | JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 1), - js::Valueify(XPC_COW_AddProperty), - js::Valueify(XPC_COW_DelProperty), - js::Valueify(XPC_COW_GetProperty), - js::Valueify(XPC_COW_SetProperty), - XPC_COW_Enumerate, - (JSResolveOp)XPC_COW_NewResolve, - js::Valueify(XPC_COW_Convert), - JS_FinalizeStub, - nsnull, // reserved0 - js::Valueify(XPC_COW_CheckAccess), - nsnull, // call - nsnull, // construct - nsnull, // xdrObject - nsnull, // hasInstance - nsnull, // mark + XPC_COW_AddProperty, XPC_COW_DelProperty, + XPC_COW_GetProperty, XPC_COW_SetProperty, + XPC_COW_Enumerate, (JSResolveOp)XPC_COW_NewResolve, + XPC_COW_Convert, JS_FinalizeStub, + nsnull, XPC_COW_CheckAccess, + nsnull, nsnull, + nsnull, nsnull, + nsnull, nsnull + }, - // ClassExtension - { - js::Valueify(XPC_COW_Equality), - nsnull, // outerObject - nsnull, // innerObject - XPC_COW_Iterator, - XPC_COW_WrappedObject - } + // JSExtendedClass initialization + XPC_COW_Equality, + nsnull, // outerObject + nsnull, // innerObject + XPC_COW_Iterator, + XPC_COW_WrappedObject, + JSCLASS_NO_RESERVED_MEMBERS }; JSBool @@ -289,7 +283,7 @@ WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp) } JSObject *wrapperObj = - JS_NewObjectWithGivenProto(cx, js::Jsvalify(&COWClass), NULL, parent); + JS_NewObjectWithGivenProto(cx, &COWClass.base, NULL, parent); if (!wrapperObj) { return JS_FALSE; } @@ -329,8 +323,13 @@ ThrowException(nsresult rv, JSContext *cx) static inline JSObject * GetWrappedJSObject(JSContext *cx, JSObject *obj) { - JSObjectOp op = obj->getClass()->ext.wrappedObject; - if (!op) { + JSClass *clasp = obj->getJSClass(); + if (!(clasp->flags & JSCLASS_IS_EXTENDED)) { + return obj; + } + + JSExtendedClass *xclasp = (JSExtendedClass *)clasp; + if (!xclasp->wrappedObject) { if (XPCNativeWrapper::IsNativeWrapper(obj)) { XPCWrappedNative *wn = XPCNativeWrapper::SafeGetWrappedNative(obj); return wn ? wn->GetFlatJSObject() : nsnull; @@ -339,7 +338,7 @@ GetWrappedJSObject(JSContext *cx, JSObject *obj) return obj; } - return op(cx, obj); + return xclasp->wrappedObject(cx, obj); } // Get the (possibly nonexistent) COW off of an object @@ -348,7 +347,7 @@ static inline JSObject * GetWrapper(JSObject *obj) { - while (obj->getClass() != &COWClass) { + while (obj->getJSClass() != &COWClass.base) { obj = obj->getProto(); if (!obj) { break; @@ -749,7 +748,8 @@ XPC_COW_Equality(JSContext *cx, JSObject *obj, const jsval *valp, JSBool *bp) obj = me->GetFlatJSObject(); test = other->GetFlatJSObject(); jsval testVal = OBJECT_TO_JSVAL(test); - return js::Jsvalify(obj->getClass()->ext.equality)(cx, obj, &testVal, bp); + return ((JSExtendedClass *)obj->getJSClass())-> + equality(cx, obj, &testVal, bp); } static JSObject * diff --git a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp index 8b7de253ed7..3ebbfb44483 100644 --- a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp +++ b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp @@ -125,7 +125,7 @@ static inline JSObject * GetWrapper(JSObject *obj) { - while (obj->getClass() != &XPCCrossOriginWrapper::XOWClass) { + while (obj->getJSClass() != &XPCCrossOriginWrapper::XOWClass.base) { obj = obj->getProto(); if (!obj) { break; @@ -156,34 +156,28 @@ static const PRUint32 FLAG_IS_CACHED = XPCWrapper::LAST_FLAG << 2; namespace XPCCrossOriginWrapper { -js::Class XOWClass = { - "XPCCrossOriginWrapper", - JSCLASS_NEW_RESOLVE | +JSExtendedClass XOWClass = { + // JSClass (JSExtendedClass.base) initialization + { "XPCCrossOriginWrapper", + JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED | JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 2), - js::Valueify(XPC_XOW_AddProperty), - js::Valueify(XPC_XOW_DelProperty), - js::Valueify(XPC_XOW_GetProperty), - js::Valueify(XPC_XOW_SetProperty), - XPC_XOW_Enumerate, - (JSResolveOp)XPC_XOW_NewResolve, - js::Valueify(XPC_XOW_Convert), - XPC_XOW_Finalize, - nsnull, // reserved0 - js::Valueify(XPC_XOW_CheckAccess), - js::Valueify(XPC_XOW_Call), - js::Valueify(XPC_XOW_Construct), - nsnull, // xdrObject - js::Valueify(XPC_XOW_HasInstance), - nsnull, // mark + XPC_XOW_AddProperty, XPC_XOW_DelProperty, + XPC_XOW_GetProperty, XPC_XOW_SetProperty, + XPC_XOW_Enumerate, (JSResolveOp)XPC_XOW_NewResolve, + XPC_XOW_Convert, XPC_XOW_Finalize, + nsnull, XPC_XOW_CheckAccess, + XPC_XOW_Call, XPC_XOW_Construct, + nsnull, XPC_XOW_HasInstance, + nsnull, nsnull + }, - // ClassExtension - { - js::Valueify(XPC_XOW_Equality), - nsnull, // outerObject - nsnull, // innerObject - XPC_XOW_Iterator, - XPC_XOW_WrappedObject - } + // JSExtendedClass initialization + XPC_XOW_Equality, + nsnull, // outerObject + nsnull, // innerObject + XPC_XOW_Iterator, + XPC_XOW_WrappedObject, + JSCLASS_NO_RESERVED_MEMBERS }; JSBool @@ -382,7 +376,7 @@ RewrapIfNeeded(JSContext *cx, JSObject *outerObj, jsval *vp) } XPCWrappedNative *wn = nsnull; - if (obj->getClass() == &XOWClass && + if (obj->getJSClass() == &XOWClass.base && outerObj->getParent() != obj->getParent()) { *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, obj)); } else if (!(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj))) { @@ -403,7 +397,7 @@ WrapObject(JSContext *cx, JSObject *parent, jsval *vp, XPCWrappedNative* wn) JSObject *wrappedObj; if (JSVAL_IS_PRIMITIVE(*vp) || !(wrappedObj = JSVAL_TO_OBJECT(*vp)) || - wrappedObj->getClass() == &XOWClass) { + wrappedObj->getJSClass() == &XOWClass.base) { return JS_TRUE; } @@ -451,7 +445,7 @@ WrapObject(JSContext *cx, JSObject *parent, jsval *vp, XPCWrappedNative* wn) outerObj = map->Find(wrappedObj); if (outerObj) { - NS_ASSERTION(outerObj->getClass() == &XOWClass, + NS_ASSERTION(outerObj->getJSClass() == &XOWClass.base, "What crazy object are we getting here?"); *vp = OBJECT_TO_JSVAL(outerObj); @@ -464,7 +458,7 @@ WrapObject(JSContext *cx, JSObject *parent, jsval *vp, XPCWrappedNative* wn) return JS_TRUE; } - outerObj = JS_NewObjectWithGivenProto(cx, js::Jsvalify(&XOWClass), nsnull, + outerObj = JS_NewObjectWithGivenProto(cx, &XOWClass.base, nsnull, parent); if (!outerObj) { return JS_FALSE; @@ -596,14 +590,14 @@ WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp) } JSObject *wrappedObj = JSVAL_TO_OBJECT(*vp); - js::Class *clasp = wrappedObj->getClass(); + JSClass *clasp = wrappedObj->getJSClass(); if (ClassNeedsXOW(clasp->name)) { return WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp); } // Check if wrappedObj is an XOW. If so, verify that it's from the // right scope. - if (clasp == &XOWClass && + if (clasp == &XOWClass.base && wrappedObj->getParent() != outerObj->getParent()) { *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, wrappedObj)); return WrapObject(cx, outerObj->getParent(), vp); @@ -626,7 +620,7 @@ XPC_XOW_AddProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) if (!JSVAL_IS_PRIMITIVE(*vp)) { JSObject *addedObj = JSVAL_TO_OBJECT(*vp); - if (addedObj->getClass() == &XOWClass && + if (addedObj->getJSClass() == &XOWClass.base && addedObj->getParent() != obj->getParent()) { *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, addedObj)); if (!WrapObject(cx, obj->getParent(), vp, nsnull)) { @@ -848,7 +842,7 @@ XPC_XOW_Enumerate(JSContext *cx, JSObject *obj) static JSObject * GetUXPCObject(JSContext *cx, JSObject *obj) { - NS_ASSERTION(obj->getClass() == &XOWClass, "wrong object"); + NS_ASSERTION(obj->getJSClass() == &XOWClass.base, "wrong object"); jsval v; if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &v)) { @@ -868,8 +862,7 @@ GetUXPCObject(JSContext *cx, JSObject *obj) } JSObject *uxpco = - JS_NewObjectWithGivenProto(cx, js::Jsvalify(&XOWClass), nsnull, - obj->getParent()); + JS_NewObjectWithGivenProto(cx, &XOWClass.base, nsnull, obj->getParent()); if (!uxpco) { return nsnull; } @@ -1188,7 +1181,7 @@ XPC_XOW_Equality(JSContext *cx, JSObject *obj, const jsval *valp, JSBool *bp) } JSObject *test = JSVAL_TO_OBJECT(v); - if (test->getClass() == &XOWClass) { + if (test->getJSClass() == &XOWClass.base) { if (!JS_GetReservedSlot(cx, test, sWrappedObjSlot, &v)) { return JS_FALSE; } @@ -1216,7 +1209,8 @@ XPC_XOW_Equality(JSContext *cx, JSObject *obj, const jsval *valp, JSBool *bp) obj = me->GetFlatJSObject(); test = other->GetFlatJSObject(); jsval testVal = OBJECT_TO_JSVAL(test); - return js::Jsvalify(obj->getClass()->ext.equality)(cx, obj, &testVal, bp); + return ((JSExtendedClass *)obj->getJSClass())-> + equality(cx, obj, &testVal, bp); } static JSObject * @@ -1246,7 +1240,7 @@ XPC_XOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly) return nsnull; } - JSObject *wrapperIter = JS_NewObject(cx, js::Jsvalify(&XOWClass), nsnull, + JSObject *wrapperIter = JS_NewObject(cx, &XOWClass.base, nsnull, JS_GetGlobalForObject(cx, obj)); if (!wrapperIter) { return nsnull; diff --git a/js/src/xpconnect/src/XPCNativeWrapper.cpp b/js/src/xpconnect/src/XPCNativeWrapper.cpp index e71dd94f258..67eb6d5030d 100644 --- a/js/src/xpconnect/src/XPCNativeWrapper.cpp +++ b/js/src/xpconnect/src/XPCNativeWrapper.cpp @@ -109,68 +109,56 @@ namespace XPCNativeWrapper { namespace internal { // JS class for XPCNativeWrapper (and this doubles as the constructor // for XPCNativeWrapper for the moment too...) -js::Class NW_NoCall_Class = { - "XPCNativeWrapper", +JSExtendedClass NW_NoCall_Class = { + // JSClass (JSExtendedClass.base) initialization + { "XPCNativeWrapper", JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | // Our one reserved slot holds a jsint of flag bits JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) | - JSCLASS_MARK_IS_TRACE | JSCLASS_CONSTRUCT_PROTOTYPE, - js::Valueify(XPC_NW_AddProperty), - js::Valueify(XPC_NW_DelProperty), - js::Valueify(XPC_NW_GetProperty), - js::Valueify(XPC_NW_SetProperty), - XPC_NW_Enumerate, - (JSResolveOp)XPC_NW_NewResolve, - js::Valueify(XPC_NW_Convert), - XPC_NW_Finalize, - nsnull, // reserved0 - js::Valueify(XPC_NW_CheckAccess), - nsnull, // call - js::Valueify(XPC_NW_Construct), - nsnull, // xdrObject - js::Valueify(XPC_NW_HasInstance), - JS_CLASS_TRACE(XPC_NW_Trace), + JSCLASS_MARK_IS_TRACE | JSCLASS_IS_EXTENDED | JSCLASS_CONSTRUCT_PROTOTYPE, + XPC_NW_AddProperty, XPC_NW_DelProperty, + XPC_NW_GetProperty, XPC_NW_SetProperty, + XPC_NW_Enumerate, (JSResolveOp)XPC_NW_NewResolve, + XPC_NW_Convert, XPC_NW_Finalize, + nsnull, XPC_NW_CheckAccess, + nsnull, XPC_NW_Construct, + nsnull, XPC_NW_HasInstance, + JS_CLASS_TRACE(XPC_NW_Trace), nsnull + }, - // ClassExtension - { - js::Valueify(XPC_NW_Equality), - nsnull, // outerObject - nsnull, // innerObject - XPC_NW_Iterator, - nsnull, // wrappedObject - } + // JSExtendedClass initialization + XPC_NW_Equality, + nsnull, // outerObject + nsnull, // innerObject + XPC_NW_Iterator, + nsnull, // wrappedObject + JSCLASS_NO_RESERVED_MEMBERS }; -js::Class NW_Call_Class = { - "XPCNativeWrapper", +JSExtendedClass NW_Call_Class = { + // JSClass (JSExtendedClass.base) initialization + { "XPCNativeWrapper", JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | // Our one reserved slot holds a jsint of flag bits JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) | - JSCLASS_MARK_IS_TRACE | JSCLASS_CONSTRUCT_PROTOTYPE, - js::Valueify(XPC_NW_AddProperty), - js::Valueify(XPC_NW_DelProperty), - js::Valueify(XPC_NW_GetProperty), - js::Valueify(XPC_NW_SetProperty), - XPC_NW_Enumerate, - (JSResolveOp)XPC_NW_NewResolve, - js::Valueify(XPC_NW_Convert), - XPC_NW_Finalize, - nsnull, // reserved0 - js::Valueify(XPC_NW_CheckAccess), - js::Valueify(XPC_NW_Call), - js::Valueify(XPC_NW_Construct), - nsnull, // xdrObject - js::Valueify(XPC_NW_HasInstance), - JS_CLASS_TRACE(XPC_NW_Trace), + JSCLASS_MARK_IS_TRACE | JSCLASS_IS_EXTENDED | JSCLASS_CONSTRUCT_PROTOTYPE, + XPC_NW_AddProperty, XPC_NW_DelProperty, + XPC_NW_GetProperty, XPC_NW_SetProperty, + XPC_NW_Enumerate, (JSResolveOp)XPC_NW_NewResolve, + XPC_NW_Convert, XPC_NW_Finalize, + nsnull, XPC_NW_CheckAccess, + XPC_NW_Call, XPC_NW_Construct, + nsnull, XPC_NW_HasInstance, + JS_CLASS_TRACE(XPC_NW_Trace), nsnull + }, - // ClassExtension - { - js::Valueify(XPC_NW_Equality), - nsnull, // outerObject - nsnull, // innerObject - XPC_NW_Iterator, - nsnull, // wrappedObject - } + // JSExtendedClass initialization + XPC_NW_Equality, + nsnull, // outerObject + nsnull, // innerObject + XPC_NW_Iterator, + nsnull, // wrappedObject + JSCLASS_NO_RESERVED_MEMBERS }; } // namespace internal @@ -1040,8 +1028,7 @@ XPCNativeWrapper::AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject) { JSObject *class_obj = - ::JS_InitClass(ccx, aGlobalObject, nsnull, - js::Jsvalify(&internal::NW_Call_Class), + ::JS_InitClass(ccx, aGlobalObject, nsnull, &internal::NW_Call_Class.base, XPCNativeWrapperCtor, 0, nsnull, nsnull, nsnull, static_functions); if (!class_obj) { @@ -1059,7 +1046,7 @@ XPCNativeWrapper::AttachNewConstructorObject(XPCCallContext &ccx, JSBool found; return ::JS_SetPropertyAttributes(ccx, aGlobalObject, - internal::NW_Call_Class.name, + internal::NW_Call_Class.base.name, JSPROP_READONLY | JSPROP_PERMANENT, &found); } diff --git a/js/src/xpconnect/src/XPCNativeWrapper.h b/js/src/xpconnect/src/XPCNativeWrapper.h index 927b9b05bf0..9c5ff2b654d 100644 --- a/js/src/xpconnect/src/XPCNativeWrapper.h +++ b/js/src/xpconnect/src/XPCNativeWrapper.h @@ -45,8 +45,8 @@ class nsIPrincipal; namespace XPCNativeWrapper { namespace internal { -extern js::Class NW_NoCall_Class; -extern js::Class NW_Call_Class; + extern JSExtendedClass NW_NoCall_Class; + extern JSExtendedClass NW_Call_Class; } PRBool @@ -59,16 +59,16 @@ JSBool CreateExplicitWrapper(JSContext *cx, XPCWrappedNative *wrapper, jsval *rval); inline PRBool -IsNativeWrapperClass(js::Class *clazz) +IsNativeWrapperClass(JSClass *clazz) { - return clazz == &internal::NW_NoCall_Class || - clazz == &internal::NW_Call_Class; + return clazz == &internal::NW_NoCall_Class.base || + clazz == &internal::NW_Call_Class.base; } inline PRBool IsNativeWrapper(JSObject *obj) { - return IsNativeWrapperClass(obj->getClass()); + return IsNativeWrapperClass(obj->getJSClass()); } JSBool @@ -86,8 +86,8 @@ inline JSClass * GetJSClass(bool call) { return call - ? js::Jsvalify(&internal::NW_Call_Class) - : js::Jsvalify(&internal::NW_NoCall_Class); + ? &internal::NW_Call_Class.base + : &internal::NW_NoCall_Class.base; } void diff --git a/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp b/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp index ab4431295c3..8423233f150 100644 --- a/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp +++ b/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp @@ -233,7 +233,7 @@ FindObjectPrincipals(JSContext *cx, JSObject *safeObj, JSObject *innerObj) static inline JSObject * FindSafeObject(JSObject *obj) { - while (obj->getClass() != &SJOWClass) { + while (obj->getJSClass() != &SJOWClass.base) { obj = obj->getProto(); if (!obj) { @@ -253,34 +253,27 @@ namespace XPCSafeJSObjectWrapper { // JS class for XPCSafeJSObjectWrapper (and this doubles as the // constructor for XPCSafeJSObjectWrapper for the moment too...) -js::Class SJOWClass = { - "XPCSafeJSObjectWrapper", - JSCLASS_NEW_RESOLVE | +JSExtendedClass SJOWClass = { + // JSClass (JSExtendedClass.base) initialization + { "XPCSafeJSObjectWrapper", + JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED | JSCLASS_HAS_RESERVED_SLOTS(sSJOWSlots), - js::Valueify(XPC_SJOW_AddProperty), - js::Valueify(XPC_SJOW_DelProperty), - js::Valueify(XPC_SJOW_GetProperty), - js::Valueify(XPC_SJOW_SetProperty), - XPC_SJOW_Enumerate, - (JSResolveOp)XPC_SJOW_NewResolve, - js::Valueify(XPC_SJOW_Convert), - XPC_SJOW_Finalize, - nsnull, // reserved0 - js::Valueify(XPC_SJOW_CheckAccess), - js::Valueify(XPC_SJOW_Call), - js::Valueify(XPC_SJOW_Create), - nsnull, // xdrObject - nsnull, // hasInstance - nsnull, // mark - - // ClassExtension - { - js::Valueify(XPC_SJOW_Equality), - nsnull, // outerObject - nsnull, // innerObject - XPC_SJOW_Iterator, - XPC_SJOW_WrappedObject - } + XPC_SJOW_AddProperty, XPC_SJOW_DelProperty, + XPC_SJOW_GetProperty, XPC_SJOW_SetProperty, + XPC_SJOW_Enumerate, (JSResolveOp)XPC_SJOW_NewResolve, + XPC_SJOW_Convert, XPC_SJOW_Finalize, + nsnull, XPC_SJOW_CheckAccess, + XPC_SJOW_Call, XPC_SJOW_Create, + nsnull, nsnull, + nsnull, nsnull + }, + // JSExtendedClass initialization + XPC_SJOW_Equality, + nsnull, // outerObject + nsnull, // innerObject + XPC_SJOW_Iterator, + XPC_SJOW_WrappedObject, + JSCLASS_NO_RESERVED_MEMBERS }; JSBool @@ -325,7 +318,7 @@ WrapObject(JSContext *cx, JSObject *scope, jsval v, jsval *vp) } JSObject *wrapperObj = - JS_NewObjectWithGivenProto(cx, js::Jsvalify(&SJOWClass), nsnull, scope); + JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull, scope); if (!wrapperObj) { // JS_NewObjectWithGivenProto already threw. @@ -353,7 +346,7 @@ AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject) } JSObject *class_obj = - ::JS_InitClass(ccx, aGlobalObject, nsnull, js::Jsvalify(&SJOWClass), + ::JS_InitClass(ccx, aGlobalObject, nsnull, &SJOWClass.base, XPC_SJOW_Construct, 0, nsnull, nsnull, nsnull, nsnull); if (!class_obj) { NS_WARNING("can't initialize the XPCSafeJSObjectWrapper class"); @@ -375,7 +368,7 @@ AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject) JSBool found; return ::JS_SetPropertyAttributes(ccx, aGlobalObject, - SJOWClass.name, + SJOWClass.base.name, JSPROP_READONLY | JSPROP_PERMANENT, &found); } @@ -453,7 +446,7 @@ WrapJSValue(JSContext *cx, JSObject *obj, jsval val, jsval *rval) // parent we pass in here, the construct hook will ensure we get // the right parent for the wrapper. JSObject *safeObj = JSVAL_TO_OBJECT(*rval); - if (safeObj->getClass() == &SJOWClass && + if (safeObj->getJSClass() == &SJOWClass.base && JS_GetGlobalForObject(cx, obj) != JS_GetGlobalForObject(cx, safeObj)) { // Check to see if the new object we just wrapped is accessible // from the unsafe object we got the new object through. If not, @@ -1037,7 +1030,7 @@ XPC_SJOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly) // Create our dummy SJOW. JSObject *wrapperIter = - JS_NewObjectWithGivenProto(cx, js::Jsvalify(&SJOWClass), nsnull, + JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull, JS_GetGlobalForObject(cx, obj)); if (!wrapperIter) { return nsnull; diff --git a/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp b/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp index ba67f2aa272..279c6153c18 100644 --- a/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp +++ b/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp @@ -98,34 +98,28 @@ static const char prefix[] = "chrome://global/"; namespace SystemOnlyWrapper { -js::Class SOWClass = { - "SystemOnlyWrapper", - JSCLASS_NEW_RESOLVE | +JSExtendedClass SOWClass = { + // JSClass (JSExtendedClass.base) initialization + { "SystemOnlyWrapper", + JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED | JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots), - js::Valueify(XPC_SOW_AddProperty), - js::Valueify(XPC_SOW_DelProperty), - js::Valueify(XPC_SOW_GetProperty), - js::Valueify(XPC_SOW_SetProperty), - XPC_SOW_Enumerate, - (JSResolveOp)XPC_SOW_NewResolve, - js::Valueify(XPC_SOW_Convert), - nsnull, // finalize - nsnull, // reserved0 - js::Valueify(XPC_SOW_CheckAccess), - nsnull, // call - nsnull, // construct - nsnull, // xdrObject - js::Valueify(XPC_SOW_HasInstance), - nsnull, // mark + XPC_SOW_AddProperty, XPC_SOW_DelProperty, + XPC_SOW_GetProperty, XPC_SOW_SetProperty, + XPC_SOW_Enumerate, (JSResolveOp)XPC_SOW_NewResolve, + XPC_SOW_Convert, nsnull, + nsnull, XPC_SOW_CheckAccess, + nsnull, nsnull, + nsnull, XPC_SOW_HasInstance, + nsnull, nsnull + }, - // ClassExtension - { - js::Valueify(XPC_SOW_Equality), - nsnull, // outerObject - nsnull, // innerObject - XPC_SOW_Iterator, - XPC_SOW_WrappedObject - } + // JSExtendedClass initialization + XPC_SOW_Equality, + nsnull, // outerObject + nsnull, // innerObject + XPC_SOW_Iterator, + XPC_SOW_WrappedObject, + JSCLASS_NO_RESERVED_MEMBERS }; JSBool @@ -139,7 +133,7 @@ WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp) } JSObject *wrapperObj = - JS_NewObjectWithGivenProto(cx, js::Jsvalify(&SOWClass), NULL, parent); + JS_NewObjectWithGivenProto(cx, &SOWClass.base, NULL, parent); if (!wrapperObj) { return JS_FALSE; } @@ -160,9 +154,9 @@ MakeSOW(JSContext *cx, JSObject *obj) { #ifdef DEBUG { - js::Class *clasp = obj->getClass(); - NS_ASSERTION(clasp != &SystemOnlyWrapper::SOWClass && - clasp != &XPCCrossOriginWrapper::XOWClass, + JSClass *clasp = obj->getJSClass(); + NS_ASSERTION(clasp != &SystemOnlyWrapper::SOWClass.base && + clasp != &XPCCrossOriginWrapper::XOWClass.base, "bad call"); } #endif @@ -274,9 +268,17 @@ using namespace SystemOnlyWrapper; static inline JSObject * GetWrappedJSObject(JSContext *cx, JSObject *obj) { - if (JSObjectOp op = obj->getClass()->ext.wrappedObject) - return op(cx, obj); - return obj; + JSClass *clasp = obj->getJSClass(); + if (!(clasp->flags & JSCLASS_IS_EXTENDED)) { + return obj; + } + + JSExtendedClass *xclasp = (JSExtendedClass *)clasp; + if (!xclasp->wrappedObject) { + return obj; + } + + return xclasp->wrappedObject(cx, obj); } // Get the (possibly nonexistent) SOW off of an object @@ -284,7 +286,7 @@ static inline JSObject * GetWrapper(JSObject *obj) { - while (obj->getClass() != &SOWClass) { + while (obj->getJSClass() != &SOWClass.base) { obj = obj->getProto(); if (!obj) { break; @@ -403,7 +405,7 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObject *wrapperObj, jsval *vp) return XPC_SOW_WrapFunction(cx, wrapperObj, obj, vp); } - if (obj->getClass() == &SOWClass) { + if (obj->getJSClass() == &SOWClass.base) { // We are extra careful about content-polluted wrappers here. I don't know // if it's possible to reach them through objects that we wrap, but figuring // that out is more expensive (and harder) than simply checking and @@ -428,7 +430,7 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObject *wrapperObj, jsval *vp) static JSBool XPC_SOW_AddProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - NS_ASSERTION(obj->getClass() == &SOWClass, "Wrong object"); + NS_ASSERTION(obj->getJSClass() == &SOWClass.base, "Wrong object"); jsval resolving; if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &resolving)) { @@ -651,16 +653,23 @@ XPC_SOW_Equality(JSContext *cx, JSObject *obj, const jsval *valp, JSBool *bp) } if (lhs) { - if (JSEqualityOp op = js::Jsvalify(lhs->getClass()->ext.equality)) { + // Delegate to our wrapped object if we can. + JSClass *clasp = lhs->getJSClass(); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + JSExtendedClass *xclasp = (JSExtendedClass *) clasp; + // NB: JSExtendedClass.equality is a required field. jsval rhsVal = OBJECT_TO_JSVAL(rhs); - return op(cx, lhs, &rhsVal, bp); + return xclasp->equality(cx, lhs, &rhsVal, bp); } } // We know rhs is non-null. - if (JSEqualityOp op = js::Jsvalify(rhs->getClass()->ext.equality)) { + JSClass *clasp = rhs->getJSClass(); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + JSExtendedClass *xclasp = (JSExtendedClass *) clasp; + // NB: JSExtendedClass.equality is a required field. jsval lhsVal = OBJECT_TO_JSVAL(lhs); - return op(cx, rhs, &lhsVal, bp); + return xclasp->equality(cx, rhs, &lhsVal, bp); } *bp = JS_FALSE; @@ -676,7 +685,7 @@ XPC_SOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly) return nsnull; } - JSObject *wrapperIter = JS_NewObject(cx, js::Jsvalify(&SOWClass), nsnull, + JSObject *wrapperIter = JS_NewObject(cx, &SOWClass.base, nsnull, JS_GetGlobalForObject(cx, obj)); if (!wrapperIter) { return nsnull; diff --git a/js/src/xpconnect/src/XPCWrapper.cpp b/js/src/xpconnect/src/XPCWrapper.cpp index 975e3eb52a0..ba536d33000 100644 --- a/js/src/xpconnect/src/XPCWrapper.cpp +++ b/js/src/xpconnect/src/XPCWrapper.cpp @@ -60,8 +60,8 @@ const PRUint32 sSecMgrGetProp = nsIXPCSecurityManager::ACCESS_GET_PROPERTY; JSObject * Unwrap(JSContext *cx, JSObject *wrapper) { - js::Class *clasp = wrapper->getClass(); - if (clasp == &XPCCrossOriginWrapper::XOWClass) { + JSClass *clasp = wrapper->getJSClass(); + if (clasp == &XPCCrossOriginWrapper::XOWClass.base) { return UnwrapXOW(cx, wrapper); } @@ -75,7 +75,7 @@ Unwrap(JSContext *cx, JSObject *wrapper) return wrappedObj->GetFlatJSObject(); } - if (clasp == &XPCSafeJSObjectWrapper::SJOWClass) { + if (clasp == &XPCSafeJSObjectWrapper::SJOWClass.base) { JSObject *wrappedObj = XPCSafeJSObjectWrapper::GetUnsafeObject(cx, wrapper); @@ -88,10 +88,10 @@ Unwrap(JSContext *cx, JSObject *wrapper) return wrappedObj; } - if (clasp == &SystemOnlyWrapper::SOWClass) { + if (clasp == &SystemOnlyWrapper::SOWClass.base) { return UnwrapSOW(cx, wrapper); } - if (clasp == &ChromeObjectWrapper::COWClass) { + if (clasp == &ChromeObjectWrapper::COWClass.base) { return UnwrapCOW(cx, wrapper); } @@ -160,33 +160,22 @@ IteratorIterator(JSContext *, JSObject *obj, JSBool) return obj; } -static js::Class IteratorClass = { - "Wrapper iterator", - JSCLASS_HAS_RESERVED_SLOTS(3), - js::PropertyStub, // addProperty - js::PropertyStub, // delProperty - js::PropertyStub, // getProperty - js::PropertyStub, // setProperty - JS_EnumerateStub, - JS_ResolveStub, - js::ConvertStub, - IteratorFinalize, - nsnull, // reserved0 - nsnull, // checkAccess - nsnull, // call - nsnull, // construct - nsnull, // xdrObject - nsnull, // hasInstance - nsnull, // mark +static JSExtendedClass IteratorClass = { + { "Wrapper iterator", + JSCLASS_HAS_RESERVED_SLOTS(3) | JSCLASS_IS_EXTENDED, + JS_PropertyStub, JS_PropertyStub, + JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, + JS_ConvertStub, IteratorFinalize, - // ClassExtension - { - nsnull, // equality - nsnull, // outerObject - nsnull, // innerObject - IteratorIterator, - nsnull, // wrappedObject - } + JSCLASS_NO_OPTIONAL_MEMBERS + }, + + nsnull, // equality + nsnull, nsnull, // innerObject/outerObject + IteratorIterator, + nsnull, // wrappedObject + JSCLASS_NO_RESERVED_MEMBERS }; JSBool @@ -342,7 +331,7 @@ CreateIteratorObj(JSContext *cx, JSObject *tempWrapper, // delegates (via the __proto__ link) to the wrapper. JSObject *iterObj = - JS_NewObjectWithGivenProto(cx, js::Jsvalify(&IteratorClass), tempWrapper, wrapperObj); + JS_NewObjectWithGivenProto(cx, &IteratorClass.base, tempWrapper, wrapperObj); if (!iterObj) { return nsnull; } @@ -405,7 +394,7 @@ JSObject * CreateSimpleIterator(JSContext *cx, JSObject *scope, JSBool keysonly, JSObject *propertyContainer) { - JSObject *iterObj = JS_NewObjectWithGivenProto(cx, js::Jsvalify(&IteratorClass), + JSObject *iterObj = JS_NewObjectWithGivenProto(cx, &IteratorClass.base, propertyContainer, scope); if (!iterObj) { return nsnull; diff --git a/js/src/xpconnect/src/XPCWrapper.h b/js/src/xpconnect/src/XPCWrapper.h index c8a5ab3589d..0143574de6f 100644 --- a/js/src/xpconnect/src/XPCWrapper.h +++ b/js/src/xpconnect/src/XPCWrapper.h @@ -162,10 +162,10 @@ CheckFilename(JSContext *cx, jsid id, JSStackFrame *fp); } -namespace ChromeObjectWrapper { extern js::Class COWClass; } -namespace XPCSafeJSObjectWrapper { extern js::Class SJOWClass; } -namespace SystemOnlyWrapper { extern js::Class SOWClass; } -namespace XPCCrossOriginWrapper { extern js::Class XOWClass; } +namespace ChromeObjectWrapper { extern JSExtendedClass COWClass; } +namespace XPCSafeJSObjectWrapper { extern JSExtendedClass SJOWClass; } +namespace SystemOnlyWrapper { extern JSExtendedClass SOWClass; } +namespace XPCCrossOriginWrapper { extern JSExtendedClass XOWClass; } extern nsIScriptSecurityManager *gScriptSecurityManager; @@ -321,7 +321,9 @@ MaybePreserveWrapper(JSContext *cx, XPCWrappedNative *wn, uintN flags) inline JSBool IsSecurityWrapper(JSObject *wrapper) { - return !!wrapper->getClass()->ext.wrappedObject; + JSClass *clasp = wrapper->getJSClass(); + return (clasp->flags & JSCLASS_IS_EXTENDED) && + ((JSExtendedClass*)clasp)->wrappedObject; } /** @@ -341,9 +343,9 @@ Unwrap(JSContext *cx, JSObject *wrapper); * Unwraps objects whose class is |xclasp|. */ inline JSObject * -UnwrapGeneric(JSContext *cx, const js::Class *xclasp, JSObject *wrapper) +UnwrapGeneric(JSContext *cx, const JSExtendedClass *xclasp, JSObject *wrapper) { - if (wrapper->getClass() != xclasp) { + if (wrapper->getJSClass() != &xclasp->base) { return nsnull; } diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 76fdbeec1ed..6177dcffc31 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -627,7 +627,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb) uint32 traceKind = js_GetGCThingTraceKind(p); JSObject *obj; - js::Class *clazz; + JSClass *clazz; // We do not want to add wrappers to the cycle collector if they're not // explicitly marked as main thread only, because the cycle collector isn't @@ -640,7 +640,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb) if(traceKind == JSTRACE_OBJECT) { obj = static_cast(p); - clazz = obj->getClass(); + clazz = obj->getJSClass(); if(clazz == &XPC_WN_Tearoff_JSClass) { @@ -689,7 +689,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb) if(traceKind == JSTRACE_OBJECT) { JSObject *obj = static_cast(p); - js::Class *clazz = obj->getClass(); + JSClass *clazz = obj->getJSClass(); if(XPCNativeWrapper::IsNativeWrapperClass(clazz)) { XPCWrappedNative* wn; @@ -749,7 +749,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb) JS_snprintf(name, sizeof(name), "JS Object (%s - %s)", clazz->name, si->GetJSClass()->name); } - else if(clazz == &js_ScriptClass) + else if(clazz == Jsvalify(&js_ScriptClass)) { JSScript* script = (JSScript*) xpc_GetJSPrivate(obj); if(script->filename) @@ -763,7 +763,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb) JS_snprintf(name, sizeof(name), "JS Object (Script)"); } } - else if(clazz == &js_FunctionClass) + else if(clazz == Jsvalify(&js_FunctionClass)) { JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj); JSString* str = JS_GetFunctionId(fun); @@ -1016,6 +1016,9 @@ nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj) xpc_InitJSxIDClassObjects(); + if(!xpc_InitWrappedNativeJSOps()) + return UnexpectedFailure(NS_ERROR_FAILURE); + XPCWrappedNativeScope* scope = XPCWrappedNativeScope::GetNewOrUsed(ccx, aGlobalJSObj); @@ -1914,7 +1917,7 @@ nsXPConnect::RestoreWrappedNativePrototype(JSContext * aJSContext, if(NS_FAILED(rv)) return UnexpectedFailure(rv); - if(!IS_PROTO_CLASS(protoJSObject->getClass())) + if(!IS_PROTO_CLASS(protoJSObject->getJSClass())) return UnexpectedFailure(NS_ERROR_INVALID_ARG); XPCWrappedNativeScope* scope = diff --git a/js/src/xpconnect/src/xpcJSWeakReference.cpp b/js/src/xpconnect/src/xpcJSWeakReference.cpp index b849889970e..82358ea2807 100644 --- a/js/src/xpconnect/src/xpcJSWeakReference.cpp +++ b/js/src/xpconnect/src/xpcJSWeakReference.cpp @@ -134,8 +134,8 @@ xpcJSWeakReference::Get() // arguments! It turns out that the thisObject hook on XPConnect // objects does the right thing though, so... - if (obj->getOps()->thisObject && - !(obj = obj->getOps()->thisObject(cx, obj))) + if (obj->map->ops->thisObject && + !(obj = obj->map->ops->thisObject(cx, obj))) { return NS_ERROR_FAILURE; } diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp index 9099cf87945..bc4956bcb68 100644 --- a/js/src/xpconnect/src/xpccomponents.cpp +++ b/js/src/xpconnect/src/xpccomponents.cpp @@ -3117,7 +3117,7 @@ sandbox_setProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp) JSObject *pobj = JSVAL_TO_OBJECT(*vp); if (pobj) { - if (pobj->getClass() == &XPCCrossOriginWrapper::XOWClass && + if (pobj->getJSClass() == &XPCCrossOriginWrapper::XOWClass.base && !XPCWrapper::RewrapObject(cx, obj, pobj, XPCWrapper::XPCNW_EXPLICIT, vp)) { return JS_FALSE; @@ -3825,9 +3825,13 @@ nsXPCComponents_Utils::GetGlobalForObject() JSObject *obj = JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(argv[0])); *rval = OBJECT_TO_JSVAL(obj); - // Outerize if necessary. - if (JSObjectOp outerize = obj->getClass()->ext.outerObject) + // Outerize if necessary. Embrace the ugliness! + JSClass *clasp = JS_GetClass(cx, obj); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + JSExtendedClass *xclasp = reinterpret_cast(clasp); + if (JSObjectOp outerize = xclasp->outerObject) *rval = OBJECT_TO_JSVAL(outerize(cx, obj)); + } cc->SetReturnValueWasSet(PR_TRUE); return NS_OK; diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index b08e77767b4..ea30d861635 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -1267,17 +1267,20 @@ private: // These are the various JSClasses and callbacks whose use that required // visibility from more than one .cpp file. -extern js::Class XPC_WN_NoHelper_JSClass; -extern js::Class XPC_WN_NoMods_WithCall_Proto_JSClass; -extern js::Class XPC_WN_NoMods_NoCall_Proto_JSClass; -extern js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass; -extern js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass; -extern js::Class XPC_WN_Tearoff_JSClass; -extern js::Class XPC_WN_NoHelper_Proto_JSClass; +extern JSExtendedClass XPC_WN_NoHelper_JSClass; +extern JSClass XPC_WN_NoMods_WithCall_Proto_JSClass; +extern JSClass XPC_WN_NoMods_NoCall_Proto_JSClass; +extern JSClass XPC_WN_ModsAllowed_WithCall_Proto_JSClass; +extern JSClass XPC_WN_ModsAllowed_NoCall_Proto_JSClass; +extern JSClass XPC_WN_Tearoff_JSClass; +extern JSClass XPC_WN_NoHelper_Proto_JSClass; extern JSBool XPC_WN_Equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp); +extern JSObjectOps * +XPC_WN_Proto_GetObjectOps(JSContext *cx, JSClass *clazz); + extern JSBool XPC_WN_CallMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp); @@ -1287,62 +1290,16 @@ XPC_WN_GetterSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp); extern JSBool -XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp); - -extern JSType -XPC_WN_JSOp_TypeOf_Object(JSContext *cx, JSObject *obj); - -extern JSType -XPC_WN_JSOp_TypeOf_Function(JSContext *cx, JSObject *obj); - -extern void -XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj); - -extern JSObject* -XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj); - -// Macros to initialize Object or Function like XPC_WN classes -#define XPC_WN_WithCall_ObjectOps \ - { \ - nsnull, /* lookupProperty */ \ - nsnull, /* defineProperty */ \ - nsnull, /* getProperty */ \ - nsnull, /* setProperty */ \ - nsnull, /* getAttributes */ \ - nsnull, /* setAttributes */ \ - nsnull, /* deleteProperty */ \ - js::Valueify(XPC_WN_JSOp_Enumerate), \ - XPC_WN_JSOp_TypeOf_Function, \ - nsnull, /* trace */ \ - XPC_WN_JSOp_ThisObject, \ - XPC_WN_JSOp_Clear \ - } - -#define XPC_WN_NoCall_ObjectOps \ - { \ - nsnull, /* lookupProperty */ \ - nsnull, /* defineProperty */ \ - nsnull, /* getProperty */ \ - nsnull, /* setProperty */ \ - nsnull, /* getAttributes */ \ - nsnull, /* setAttributes */ \ - nsnull, /* deleteProperty */ \ - js::Valueify(XPC_WN_JSOp_Enumerate), \ - XPC_WN_JSOp_TypeOf_Object, \ - nsnull, /* trace */ \ - XPC_WN_JSOp_ThisObject, \ - XPC_WN_JSOp_Clear \ - } +xpc_InitWrappedNativeJSOps(); // Maybe this macro should check for class->enumerate == // XPC_WN_Shared_Proto_Enumerate or something rather than checking for // 4 classes? #define IS_PROTO_CLASS(clazz) \ - ((clazz) == &XPC_WN_NoMods_WithCall_Proto_JSClass || \ - (clazz) == &XPC_WN_NoMods_NoCall_Proto_JSClass || \ - (clazz) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || \ - (clazz) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass) + ((clazz) == &XPC_WN_NoMods_WithCall_Proto_JSClass || \ + (clazz) == &XPC_WN_NoMods_NoCall_Proto_JSClass || \ + (clazz) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || \ + (clazz) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass) // NOTE!!! // @@ -1352,7 +1309,8 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj); // // NOTE!!! #define IS_WRAPPER_CLASS(clazz) \ - (clazz->ext.equality == js::Valueify(XPC_WN_Equality)) + (((clazz)->flags & JSCLASS_IS_EXTENDED) && \ + reinterpret_cast(clazz)->equality == XPC_WN_Equality) inline JSBool DebugCheckWrapperClass(JSObject* obj) @@ -1957,9 +1915,8 @@ public: // was a big problem when wrappers are reparented to different scopes (and // thus different protos (the DOM does this). -struct XPCNativeScriptableSharedJSClass +struct XPCNativeScriptableSharedJSClass : public JSExtendedClass { - js::Class base; PRUint32 interfacesBitmap; }; @@ -1969,8 +1926,7 @@ public: const XPCNativeScriptableFlags& GetFlags() const {return mFlags;} PRUint32 GetInterfacesBitmap() const {return mJSClass.interfacesBitmap;} - JSClass* GetJSClass() - {return js::Jsvalify(&mJSClass.base);} + JSClass* GetJSClass() {return &mJSClass.base;} JSClass* GetSlimJSClass() {if(mCanBeSlim) return GetJSClass(); return nsnull;} diff --git a/js/src/xpconnect/src/xpcquickstubs.cpp b/js/src/xpconnect/src/xpcquickstubs.cpp index 1bb049200c8..c016045387c 100644 --- a/js/src/xpconnect/src/xpcquickstubs.cpp +++ b/js/src/xpconnect/src/xpcquickstubs.cpp @@ -296,7 +296,7 @@ LookupGetterOrSetter(JSContext *cx, JSBool wantGetter, uintN argc, jsval *vp) ? JS_GetStringBytes(JSVAL_TO_STRING(idval)) : nsnull; if(!name || - !IS_PROTO_CLASS(desc.obj->getClass()) || + !IS_PROTO_CLASS(desc.obj->getJSClass()) || (desc.attrs & (JSPROP_GETTER | JSPROP_SETTER)) || !(desc.getter || desc.setter) || desc.setter == desc.obj->getJSClass()->setProperty) @@ -363,7 +363,7 @@ DefineGetterOrSetter(JSContext *cx, uintN argc, JSBool wantGetter, jsval *vp) if(!obj2 || (attrs & (JSPROP_GETTER | JSPROP_SETTER)) || !(getter || setter) || - !IS_PROTO_CLASS(obj2->getClass())) + !IS_PROTO_CLASS(obj2->getJSClass())) return forward(cx, argc, vp); // Reify the getter and setter... @@ -504,8 +504,8 @@ GetMemberInfo(JSObject *obj, // but this code often produces a more specific error message, e.g. *ifaceName = "Unknown"; - NS_ASSERTION(IS_WRAPPER_CLASS(obj->getClass()) || - obj->getClass() == &XPC_WN_Tearoff_JSClass, + NS_ASSERTION(IS_WRAPPER_CLASS(obj->getJSClass()) || + obj->getJSClass() == &XPC_WN_Tearoff_JSClass, "obj must be a wrapper"); XPCWrappedNativeProto *proto; if(IS_SLIM_WRAPPER(obj)) diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp index 589ae30b0f7..2eb1c8026b5 100644 --- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -1124,9 +1124,7 @@ XPCWrappedNative::Init(XPCCallContext& ccx, // create our flatJSObject - js::Class* jsclazz = si - ? js::Valueify(si->GetJSClass()) - : &XPC_WN_NoHelper_JSClass; + JSClass* jsclazz = si ? si->GetJSClass() : &XPC_WN_NoHelper_JSClass.base; if(isGlobal) { @@ -1160,8 +1158,8 @@ XPCWrappedNative::Init(XPCCallContext& ccx, return JS_FALSE; } - mFlatJSObject = xpc_NewSystemInheritingJSObject(ccx, js::Jsvalify(jsclazz), - protoJSObject, parent); + mFlatJSObject = xpc_NewSystemInheritingJSObject(ccx, jsclazz, protoJSObject, + parent); if(!mFlatJSObject) return JS_FALSE; @@ -1685,7 +1683,7 @@ XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx, JSObject* funObjParent = funobj->getParent(); NS_ASSERTION(funObjParent, "funobj has no parent"); - js::Class* funObjParentClass = funObjParent->getClass(); + JSClass* funObjParentClass = funObjParent->getJSClass(); if(IS_PROTO_CLASS(funObjParentClass)) { @@ -1715,8 +1713,8 @@ XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx, for(cur = obj; cur; cur = cur->getProto()) { // this is on two lines to make the compiler happy given the goto. - js::Class* clazz; - clazz = cur->getClass(); + JSClass* clazz; + clazz = cur->getJSClass(); if(IS_WRAPPER_CLASS(clazz)) { @@ -1773,9 +1771,12 @@ return_tearoff: // If we didn't find a wrapper using the given funobj and obj, try // again with obj's outer object, if it's got one. - if(JSObjectOp op = obj->getClass()->ext.outerObject) + JSClass *clazz = obj->getJSClass(); + + if((clazz->flags & JSCLASS_IS_EXTENDED) && + ((JSExtendedClass*)clazz)->outerObject) { - JSObject *outer = op(cx, obj); + JSObject *outer = ((JSExtendedClass*)clazz)->outerObject(cx, obj); if(outer && outer != obj) return GetWrappedNativeOfJSObject(cx, outer, funobj, pobj2, pTearOff); @@ -2117,7 +2118,7 @@ XPCWrappedNative::InitTearOffJSObject(XPCCallContext& ccx, // This is only called while locked (during XPCWrappedNative::FindTearOff). JSObject* obj = - xpc_NewSystemInheritingJSObject(ccx, js::Jsvalify(&XPC_WN_Tearoff_JSClass), + xpc_NewSystemInheritingJSObject(ccx, &XPC_WN_Tearoff_JSClass, GetScope()->GetPrototypeJSObject(), mFlatJSObject); diff --git a/js/src/xpconnect/src/xpcwrappednativejsops.cpp b/js/src/xpconnect/src/xpcwrappednativejsops.cpp index 0dc8568201d..c2dc6587ed4 100644 --- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp +++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp @@ -813,7 +813,7 @@ XPC_WN_Equality(JSContext *cx, JSObject *obj, const jsval *valp, JSBool *bp) return Throw(rv, cx); if(!*bp && !JSVAL_IS_PRIMITIVE(v) && - JSVAL_TO_OBJECT(v)->getClass() == &XPCSafeJSObjectWrapper::SJOWClass) + JSVAL_TO_OBJECT(v)->getJSClass() == &XPCSafeJSObjectWrapper::SJOWClass.base) { v = OBJECT_TO_JSVAL(XPCSafeJSObjectWrapper::GetUnsafeObject(cx, JSVAL_TO_OBJECT(v))); @@ -912,56 +912,41 @@ XPC_WN_InnerObject(JSContext *cx, JSObject *obj) return obj; } -js::Class XPC_WN_NoHelper_JSClass = { - "XPCWrappedNative_NoHelper", // name; - WRAPPER_SLOTS | - JSCLASS_PRIVATE_IS_NSISUPPORTS | - JSCLASS_MARK_IS_TRACE, // flags; +JSObjectOps *XPC_WN_GetObjectOpsNoCall(JSContext *cx, JSClass *clazz); - /* Mandatory non-null function pointer members. */ - js::Valueify(XPC_WN_OnlyIWrite_PropertyStub), // addProperty - js::Valueify(XPC_WN_CannotModifyPropertyStub),// delProperty - js::PropertyStub, // getProperty - js::Valueify(XPC_WN_OnlyIWrite_PropertyStub), // setProperty - - XPC_WN_Shared_Enumerate, // enumerate - XPC_WN_NoHelper_Resolve, // resolve - js::Valueify(XPC_WN_Shared_Convert), // convert - XPC_WN_NoHelper_Finalize, // finalize - - /* Optionally non-null members start here. */ - nsnull, // reserved0 - nsnull, // checkAccess - nsnull, // call - nsnull, // construct - nsnull, // xdrObject; - nsnull, // hasInstance - JS_CLASS_TRACE(XPC_WN_Shared_Trace), // mark/trace - - // ClassExtension +JSExtendedClass XPC_WN_NoHelper_JSClass = { { - js::Valueify(XPC_WN_Equality), - XPC_WN_OuterObject, - XPC_WN_InnerObject, - nsnull, // iteratorObject - nsnull, // wrappedObject + "XPCWrappedNative_NoHelper", // name; + WRAPPER_SLOTS | + JSCLASS_PRIVATE_IS_NSISUPPORTS | + JSCLASS_MARK_IS_TRACE | + JSCLASS_IS_EXTENDED, // flags; + + /* Mandatory non-null function pointer members. */ + XPC_WN_OnlyIWrite_PropertyStub, // addProperty; + XPC_WN_CannotModifyPropertyStub,// delProperty; + JS_PropertyStub, // getProperty; + XPC_WN_OnlyIWrite_PropertyStub, // setProperty; + + XPC_WN_Shared_Enumerate, // enumerate; + XPC_WN_NoHelper_Resolve, // resolve; + XPC_WN_Shared_Convert, // convert; + XPC_WN_NoHelper_Finalize, // finalize; + + /* Optionally non-null members start here. */ + XPC_WN_GetObjectOpsNoCall, // getObjectOps; + nsnull, // checkAccess; + nsnull, // call; + nsnull, // construct; + nsnull, // xdrObject; + nsnull, // hasInstance; + JS_CLASS_TRACE(XPC_WN_Shared_Trace), // mark/trace; + nsnull // spare; }, - - // ObjectOps - { - nsnull, // lookupProperty - nsnull, // defineProperty - nsnull, // getProperty - nsnull, // setProperty - nsnull, // getAttributes - nsnull, // setAttributes - nsnull, // deleteProperty - js::Valueify(XPC_WN_JSOp_Enumerate), - XPC_WN_JSOp_TypeOf_Object, - nsnull, // trace - XPC_WN_JSOp_ThisObject, - XPC_WN_JSOp_Clear - } + XPC_WN_Equality, + XPC_WN_OuterObject, + XPC_WN_InnerObject, + nsnull,nsnull,nsnull,nsnull,nsnull }; @@ -1253,6 +1238,11 @@ XPC_WN_Helper_NewResolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, /***************************************************************************/ +extern JS_IMPORT_DATA(JSObjectOps) js_ObjectOps; + +static JSObjectOps XPC_WN_WithCall_JSOps; +static JSObjectOps XPC_WN_NoCall_JSOps; + /* Here are the enumerator cases: @@ -1288,18 +1278,18 @@ XPC_WN_Helper_NewResolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, do shared enumerate - don't use this JSOp thing at all */ -JSBool +static JSBool XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, jsval *statep, jsid *idp) { - js::Class *clazz = obj->getClass(); - if(!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass) + JSClass *clazz = obj->getJSClass(); + if(!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) { // obj must be a prototype object or a wrapper w/o a - // helper. Short circuit this call to the default - // implementation. + // helper. Short circuit this call to + // js_ObjectOps.enumerate(). - return js_Enumerate(cx, obj, enum_op, js::Valueify(statep), idp); + return js_ObjectOps.enumerate(cx, obj, enum_op, js::Valueify(statep), idp); } MORPH_SLIM_WRAPPER(cx, obj); @@ -1366,28 +1356,28 @@ XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, return Throw(rv, cx); if(!retval) return JS_FALSE; - // Then fall through and call the default implementation... + // Then fall through and call js_ObjectOps.enumerate... } } // else call js_ObjectOps.enumerate... - return js_Enumerate(cx, obj, enum_op, js::Valueify(statep), idp); + return js_ObjectOps.enumerate(cx, obj, enum_op, js::Valueify(statep), idp); } -JSType +static JSType XPC_WN_JSOp_TypeOf_Object(JSContext *cx, JSObject *obj) { return JSTYPE_OBJECT; } -JSType +static JSType XPC_WN_JSOp_TypeOf_Function(JSContext *cx, JSObject *obj) { return JSTYPE_FUNCTION; } -void +static void XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj) { // We're likely to enter this JSOp with a wrapper prototype @@ -1406,6 +1396,8 @@ XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj) nsXPConnect* xpc = nsXPConnect::GetXPConnect(); xpc->UpdateXOWs(cx, wrapper, nsIXPConnect::XPC_XOW_CLEARSCOPE); } + + js_ObjectOps.clear(cx, obj); } namespace { @@ -1444,7 +1436,7 @@ private: } // namespace -JSObject* +static JSObject* XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj) { // None of the wrappers we could potentially hand out are threadsafe so @@ -1541,6 +1533,37 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj) return JSVAL_TO_OBJECT(retval.jsval_value()); } +JSObjectOps * +XPC_WN_GetObjectOpsNoCall(JSContext *cx, JSClass *clazz) +{ + return &XPC_WN_NoCall_JSOps; +} + +JSObjectOps * +XPC_WN_GetObjectOpsWithCall(JSContext *cx, JSClass *clazz) +{ + return &XPC_WN_WithCall_JSOps; +} + +JSBool xpc_InitWrappedNativeJSOps() +{ + if(!XPC_WN_NoCall_JSOps.lookupProperty) + { + memcpy(&XPC_WN_NoCall_JSOps, &js_ObjectOps, sizeof(JSObjectOps)); + XPC_WN_NoCall_JSOps.enumerate = js::Valueify(XPC_WN_JSOp_Enumerate); + XPC_WN_NoCall_JSOps.typeOf = XPC_WN_JSOp_TypeOf_Object; + XPC_WN_NoCall_JSOps.clear = XPC_WN_JSOp_Clear; + XPC_WN_NoCall_JSOps.thisObject = XPC_WN_JSOp_ThisObject; + + memcpy(&XPC_WN_WithCall_JSOps, &js_ObjectOps, sizeof(JSObjectOps)); + XPC_WN_WithCall_JSOps.enumerate = js::Valueify(XPC_WN_JSOp_Enumerate); + XPC_WN_WithCall_JSOps.typeOf = XPC_WN_JSOp_TypeOf_Function; + XPC_WN_WithCall_JSOps.clear = XPC_WN_JSOp_Clear; + XPC_WN_WithCall_JSOps.thisObject = XPC_WN_JSOp_ThisObject; + } + return JS_TRUE; +} + /***************************************************************************/ // static @@ -1591,54 +1614,49 @@ XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal) mJSClass.base.flags = WRAPPER_SLOTS | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_NEW_RESOLVE | - JSCLASS_MARK_IS_TRACE; + JSCLASS_MARK_IS_TRACE | + JSCLASS_IS_EXTENDED; if(isGlobal) mJSClass.base.flags |= JSCLASS_GLOBAL_FLAGS; - JSPropertyOp addProperty; if(mFlags.WantAddProperty()) - addProperty = XPC_WN_Helper_AddProperty; + mJSClass.base.addProperty = XPC_WN_Helper_AddProperty; else if(mFlags.UseJSStubForAddProperty()) - addProperty = JS_PropertyStub; + mJSClass.base.addProperty = JS_PropertyStub; else if(mFlags.AllowPropModsDuringResolve()) - addProperty = XPC_WN_MaybeResolvingPropertyStub; + mJSClass.base.addProperty = XPC_WN_MaybeResolvingPropertyStub; else - addProperty = XPC_WN_CannotModifyPropertyStub; - mJSClass.base.addProperty = js::Valueify(addProperty); + mJSClass.base.addProperty = XPC_WN_CannotModifyPropertyStub; - JSPropertyOp delProperty; if(mFlags.WantDelProperty()) - delProperty = XPC_WN_Helper_DelProperty; + mJSClass.base.delProperty = XPC_WN_Helper_DelProperty; else if(mFlags.UseJSStubForDelProperty()) - delProperty = JS_PropertyStub; + mJSClass.base.delProperty = JS_PropertyStub; else if(mFlags.AllowPropModsDuringResolve()) - delProperty = XPC_WN_MaybeResolvingPropertyStub; + mJSClass.base.delProperty = XPC_WN_MaybeResolvingPropertyStub; else - delProperty = XPC_WN_CannotModifyPropertyStub; - mJSClass.base.delProperty = js::Valueify(delProperty); + mJSClass.base.delProperty = XPC_WN_CannotModifyPropertyStub; if(mFlags.WantGetProperty()) - mJSClass.base.getProperty = js::Valueify(XPC_WN_Helper_GetProperty); + mJSClass.base.getProperty = XPC_WN_Helper_GetProperty; else - mJSClass.base.getProperty = js::PropertyStub; + mJSClass.base.getProperty = JS_PropertyStub; - JSPropertyOp setProperty; if(mFlags.WantSetProperty()) - setProperty = XPC_WN_Helper_SetProperty; + mJSClass.base.setProperty = XPC_WN_Helper_SetProperty; else if(mFlags.UseJSStubForSetProperty()) - setProperty = JS_PropertyStub; + mJSClass.base.setProperty = JS_PropertyStub; else if(mFlags.AllowPropModsDuringResolve()) - setProperty = XPC_WN_MaybeResolvingPropertyStub; + mJSClass.base.setProperty = XPC_WN_MaybeResolvingPropertyStub; else - setProperty = XPC_WN_CannotModifyPropertyStub; - mJSClass.base.setProperty = js::Valueify(setProperty); + mJSClass.base.setProperty = XPC_WN_CannotModifyPropertyStub; // We figure out most of the enumerate strategy at call time. if(mFlags.WantNewEnumerate() || mFlags.WantEnumerate() || mFlags.DontEnumStaticProps()) - mJSClass.base.enumerate = js::EnumerateStub; + mJSClass.base.enumerate = JS_EnumerateStub; else mJSClass.base.enumerate = XPC_WN_Shared_Enumerate; @@ -1646,9 +1664,9 @@ XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal) mJSClass.base.resolve = (JSResolveOp) XPC_WN_Helper_NewResolve; if(mFlags.WantConvert()) - mJSClass.base.convert = js::Valueify(XPC_WN_Helper_Convert); + mJSClass.base.convert = XPC_WN_Helper_Convert; else - mJSClass.base.convert = js::Valueify(XPC_WN_Shared_Convert); + mJSClass.base.convert = XPC_WN_Shared_Convert; if(mFlags.WantFinalize()) mJSClass.base.finalize = XPC_WN_Helper_Finalize; @@ -1657,46 +1675,46 @@ XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal) // We let the rest default to nsnull unless the helper wants them... if(mFlags.WantCheckAccess()) - mJSClass.base.checkAccess = js::Valueify(XPC_WN_Helper_CheckAccess); + mJSClass.base.checkAccess = XPC_WN_Helper_CheckAccess; - // Note that we *must* set the ObjectOps (even for the cases were it does - // not do much) because with these dynamically generated JSClasses, the - // code in XPCWrappedNative::GetWrappedNativeOfJSObject() needs to look - // for that these callback pointers in order to identify that a given + // Note that we *must* set + // mJSClass.base.getObjectOps = XPC_WN_GetObjectOpsNoCall + // or + // mJSClass.base.getObjectOps = XPC_WN_GetObjectOpsWithCall + // (even for the cases were it does not do much) because with these + // dynamically generated JSClasses, the code in + // XPCWrappedNative::GetWrappedNativeOfJSObject() needs to look for + // that this callback pointer in order to identify that a given // JSObject represents a wrapper. - js::ObjectOps *ops = &mJSClass.base.ops; - ops->enumerate = js::Valueify(XPC_WN_JSOp_Enumerate); - ops->clear = XPC_WN_JSOp_Clear; - ops->thisObject = XPC_WN_JSOp_ThisObject; if(mFlags.WantCall() || mFlags.WantConstruct()) { - ops->typeOf = XPC_WN_JSOp_TypeOf_Function; + mJSClass.base.getObjectOps = XPC_WN_GetObjectOpsWithCall; if(mFlags.WantCall()) - mJSClass.base.call = js::Valueify(XPC_WN_Helper_Call); + mJSClass.base.call = XPC_WN_Helper_Call; if(mFlags.WantConstruct()) - mJSClass.base.construct = js::Valueify(XPC_WN_Helper_Construct); + mJSClass.base.construct = XPC_WN_Helper_Construct; } else { - ops->typeOf = XPC_WN_JSOp_TypeOf_Object; + mJSClass.base.getObjectOps = XPC_WN_GetObjectOpsNoCall; } - // Equality is a required hook. - mJSClass.base.ext.equality = js::Valueify(XPC_WN_Equality); - if(mFlags.WantHasInstance()) - mJSClass.base.hasInstance = js::Valueify(XPC_WN_Helper_HasInstance); + mJSClass.base.hasInstance = XPC_WN_Helper_HasInstance; if(mFlags.WantTrace()) mJSClass.base.mark = JS_CLASS_TRACE(XPC_WN_Helper_Trace); else mJSClass.base.mark = JS_CLASS_TRACE(XPC_WN_Shared_Trace); + // Equality is a required hook. + mJSClass.equality = XPC_WN_Equality; + if(mFlags.WantOuterObject()) - mJSClass.base.ext.outerObject = XPC_WN_OuterObject; + mJSClass.outerObject = XPC_WN_OuterObject; if(mFlags.WantInnerObject()) - mJSClass.base.ext.innerObject = XPC_WN_InnerObject; + mJSClass.innerObject = XPC_WN_InnerObject; if(!(mFlags & (nsIXPCScriptable::WANT_OUTER_OBJECT | nsIXPCScriptable::WANT_INNER_OBJECT))) @@ -1788,10 +1806,12 @@ static JSBool XPC_WN_Shared_Proto_Enumerate(JSContext *cx, JSObject *obj) { NS_ASSERTION( - obj->getClass() == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || - obj->getClass() == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass || - obj->getClass() == &XPC_WN_NoMods_WithCall_Proto_JSClass || - obj->getClass() == &XPC_WN_NoMods_NoCall_Proto_JSClass, + JS_InstanceOf(cx, obj, &XPC_WN_ModsAllowed_WithCall_Proto_JSClass, + nsnull) || + JS_InstanceOf(cx, obj, &XPC_WN_ModsAllowed_NoCall_Proto_JSClass, + nsnull) || + JS_InstanceOf(cx, obj, &XPC_WN_NoMods_WithCall_Proto_JSClass, nsnull) || + JS_InstanceOf(cx, obj, &XPC_WN_NoMods_NoCall_Proto_JSClass, nsnull), "bad proto"); XPCWrappedNativeProto* self = (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); @@ -1859,9 +1879,11 @@ static JSBool XPC_WN_ModsAllowed_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id) { NS_ASSERTION( - obj->getClass() == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || - obj->getClass() == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass, - "bad proto"); + JS_InstanceOf(cx, obj, &XPC_WN_ModsAllowed_WithCall_Proto_JSClass, + nsnull) || + JS_InstanceOf(cx, obj, &XPC_WN_ModsAllowed_NoCall_Proto_JSClass, + nsnull), + "bad proto"); XPCWrappedNativeProto* self = (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); @@ -1883,58 +1905,83 @@ XPC_WN_ModsAllowed_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id) enumFlag, nsnull); } -js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass = { +// Give our proto classes object ops that match the respective +// wrappers so that the JS engine can share scope (maps) among +// wrappers. This essentially duplicates the number of JSClasses we +// use for prototype objects (from 2 to 4), but the scope sharing +// benefit is well worth it. +JSObjectOps * +XPC_WN_Proto_GetObjectOps(JSContext *cx, JSClass *clazz) +{ + // Protos for wrappers that want calls to their call() hooks get + // jsops with a call hook, others get jsops w/o a call hook. + + if(clazz == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || + clazz == &XPC_WN_NoMods_WithCall_Proto_JSClass) + return &XPC_WN_WithCall_JSOps; + + NS_ASSERTION(clazz == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass || + clazz == &XPC_WN_NoMods_NoCall_Proto_JSClass || + clazz == &XPC_WN_NoHelper_Proto_JSClass, + "bad proto"); + + return &XPC_WN_NoCall_JSOps; +} + +JSClass XPC_WN_ModsAllowed_WithCall_Proto_JSClass = { "XPC_WN_ModsAllowed_WithCall_Proto_JSClass", // name; WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags; /* Mandatory non-null function pointer members. */ - js::PropertyStub, // addProperty; - js::PropertyStub, // delProperty; - js::PropertyStub, // getProperty; - js::PropertyStub, // setProperty; - XPC_WN_Shared_Proto_Enumerate, // enumerate; - XPC_WN_ModsAllowed_Proto_Resolve, // resolve; - js::Valueify(XPC_WN_Shared_Proto_Convert), // convert; - XPC_WN_Shared_Proto_Finalize, // finalize; + JS_PropertyStub, // addProperty; + JS_PropertyStub, // delProperty; + JS_PropertyStub, // getProperty; + JS_PropertyStub, // setProperty; + XPC_WN_Shared_Proto_Enumerate, // enumerate; + XPC_WN_ModsAllowed_Proto_Resolve, // resolve; + XPC_WN_Shared_Proto_Convert, // convert; + XPC_WN_Shared_Proto_Finalize, // finalize; /* Optionally non-null members start here. */ - nsnull, // reserved0; + XPC_WN_Proto_GetObjectOps, // getObjectOps; nsnull, // checkAccess; nsnull, // call; nsnull, // construct; nsnull, // xdrObject; nsnull, // hasInstance; JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace; - - JS_NULL_CLASS_EXT, - XPC_WN_WithCall_ObjectOps + nsnull // spare; }; -js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass = { +JSObjectOps * +XPC_WN_ModsAllowedProto_NoCall_GetObjectOps(JSContext *cx, JSClass *clazz) +{ + return &XPC_WN_NoCall_JSOps; +} + +JSClass XPC_WN_ModsAllowed_NoCall_Proto_JSClass = { "XPC_WN_ModsAllowed_NoCall_Proto_JSClass", // name; WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags; /* Mandatory non-null function pointer members. */ - js::PropertyStub, // addProperty; - js::PropertyStub, // delProperty; - js::PropertyStub, // getProperty; - js::PropertyStub, // setProperty; - XPC_WN_Shared_Proto_Enumerate, // enumerate; - XPC_WN_ModsAllowed_Proto_Resolve,// resolve; - js::Valueify(XPC_WN_Shared_Proto_Convert), // convert; - XPC_WN_Shared_Proto_Finalize, // finalize; + JS_PropertyStub, // addProperty; + JS_PropertyStub, // delProperty; + JS_PropertyStub, // getProperty; + JS_PropertyStub, // setProperty; + XPC_WN_Shared_Proto_Enumerate, // enumerate; + XPC_WN_ModsAllowed_Proto_Resolve, // resolve; + XPC_WN_Shared_Proto_Convert, // convert; + XPC_WN_Shared_Proto_Finalize, // finalize; /* Optionally non-null members start here. */ - nsnull, // reserved0; + XPC_WN_Proto_GetObjectOps, // getObjectOps; nsnull, // checkAccess; nsnull, // call; nsnull, // construct; nsnull, // xdrObject; nsnull, // hasInstance; JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace; - - JS_NULL_CLASS_EXT, - XPC_WN_NoCall_ObjectOps + nsnull // spare; }; /***************************************************************************/ @@ -1942,8 +1989,9 @@ js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass = { static JSBool XPC_WN_OnlyIWrite_Proto_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - NS_ASSERTION(obj->getClass() == &XPC_WN_NoMods_WithCall_Proto_JSClass || - obj->getClass() == &XPC_WN_NoMods_NoCall_Proto_JSClass, + NS_ASSERTION( + JS_InstanceOf(cx, obj, &XPC_WN_NoMods_WithCall_Proto_JSClass, nsnull) || + JS_InstanceOf(cx, obj, &XPC_WN_NoMods_NoCall_Proto_JSClass, nsnull), "bad proto"); XPCWrappedNativeProto* self = @@ -1965,8 +2013,9 @@ XPC_WN_OnlyIWrite_Proto_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsva static JSBool XPC_WN_NoMods_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id) { - NS_ASSERTION(obj->getClass() == &XPC_WN_NoMods_WithCall_Proto_JSClass || - obj->getClass() == &XPC_WN_NoMods_NoCall_Proto_JSClass, + NS_ASSERTION( + JS_InstanceOf(cx, obj, &XPC_WN_NoMods_WithCall_Proto_JSClass, nsnull) || + JS_InstanceOf(cx, obj, &XPC_WN_NoMods_NoCall_Proto_JSClass, nsnull), "bad proto"); XPCWrappedNativeProto* self = @@ -1991,58 +2040,54 @@ XPC_WN_NoMods_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id) enumFlag, nsnull); } -js::Class XPC_WN_NoMods_WithCall_Proto_JSClass = { +JSClass XPC_WN_NoMods_WithCall_Proto_JSClass = { "XPC_WN_NoMods_WithCall_Proto_JSClass", // name; WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags; /* Mandatory non-null function pointer members. */ - js::Valueify(XPC_WN_OnlyIWrite_Proto_PropertyStub), // addProperty; - js::Valueify(XPC_WN_CannotModifyPropertyStub), // delProperty; - js::PropertyStub, // getProperty; - js::Valueify(XPC_WN_OnlyIWrite_Proto_PropertyStub), // setProperty; - XPC_WN_Shared_Proto_Enumerate, // enumerate; - XPC_WN_NoMods_Proto_Resolve, // resolve; - js::Valueify(XPC_WN_Shared_Proto_Convert), // convert; - XPC_WN_Shared_Proto_Finalize, // finalize; + XPC_WN_OnlyIWrite_Proto_PropertyStub, // addProperty; + XPC_WN_CannotModifyPropertyStub, // delProperty; + JS_PropertyStub, // getProperty; + XPC_WN_OnlyIWrite_Proto_PropertyStub, // setProperty; + XPC_WN_Shared_Proto_Enumerate, // enumerate; + XPC_WN_NoMods_Proto_Resolve, // resolve; + XPC_WN_Shared_Proto_Convert, // convert; + XPC_WN_Shared_Proto_Finalize, // finalize; /* Optionally non-null members start here. */ - nsnull, // reserved0; + XPC_WN_Proto_GetObjectOps, // getObjectOps; nsnull, // checkAccess; nsnull, // call; nsnull, // construct; nsnull, // xdrObject; nsnull, // hasInstance; JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace; - - JS_NULL_CLASS_EXT, - XPC_WN_WithCall_ObjectOps + nsnull // spare; }; -js::Class XPC_WN_NoMods_NoCall_Proto_JSClass = { - "XPC_WN_NoMods_NoCall_Proto_JSClass", // name; - WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags; +JSClass XPC_WN_NoMods_NoCall_Proto_JSClass = { + "XPC_WN_NoMods_NoCall_Proto_JSClass", // name; + WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags; /* Mandatory non-null function pointer members. */ - js::Valueify(XPC_WN_OnlyIWrite_Proto_PropertyStub), // addProperty; - js::Valueify(XPC_WN_CannotModifyPropertyStub), // delProperty; - js::PropertyStub, // getProperty; - js::Valueify(XPC_WN_OnlyIWrite_Proto_PropertyStub), // setProperty; - XPC_WN_Shared_Proto_Enumerate, // enumerate; - XPC_WN_NoMods_Proto_Resolve, // resolve; - js::Valueify(XPC_WN_Shared_Proto_Convert), // convert; - XPC_WN_Shared_Proto_Finalize, // finalize; + XPC_WN_OnlyIWrite_Proto_PropertyStub, // addProperty; + XPC_WN_CannotModifyPropertyStub, // delProperty; + JS_PropertyStub, // getProperty; + XPC_WN_OnlyIWrite_Proto_PropertyStub, // setProperty; + XPC_WN_Shared_Proto_Enumerate, // enumerate; + XPC_WN_NoMods_Proto_Resolve, // resolve; + XPC_WN_Shared_Proto_Convert, // convert; + XPC_WN_Shared_Proto_Finalize, // finalize; /* Optionally non-null members start here. */ - nsnull, // reserved0; + XPC_WN_Proto_GetObjectOps, // getObjectOps; nsnull, // checkAccess; nsnull, // call; nsnull, // construct; nsnull, // xdrObject; nsnull, // hasInstance; JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace; - - JS_NULL_CLASS_EXT, - XPC_WN_NoCall_ObjectOps + nsnull // spare; }; /***************************************************************************/ @@ -2103,16 +2148,27 @@ XPC_WN_TearOff_Finalize(JSContext *cx, JSObject *obj) p->JSObjectFinalized(); } -js::Class XPC_WN_Tearoff_JSClass = { - "WrappedNative_TearOff", // name; - WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags; +JSClass XPC_WN_Tearoff_JSClass = { + "WrappedNative_TearOff", // name; + WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags; - js::Valueify(XPC_WN_OnlyIWrite_PropertyStub), // addProperty; - js::Valueify(XPC_WN_CannotModifyPropertyStub), // delProperty; - js::PropertyStub, // getProperty; - js::Valueify(XPC_WN_OnlyIWrite_PropertyStub), // setProperty; - XPC_WN_TearOff_Enumerate, // enumerate; - XPC_WN_TearOff_Resolve, // resolve; - js::Valueify(XPC_WN_Shared_Convert), // convert; - XPC_WN_TearOff_Finalize // finalize; + /* Mandatory non-null function pointer members. */ + XPC_WN_OnlyIWrite_PropertyStub, // addProperty; + XPC_WN_CannotModifyPropertyStub, // delProperty; + JS_PropertyStub, // getProperty; + XPC_WN_OnlyIWrite_PropertyStub, // setProperty; + XPC_WN_TearOff_Enumerate, // enumerate; + XPC_WN_TearOff_Resolve, // resolve; + XPC_WN_Shared_Convert, // convert; + XPC_WN_TearOff_Finalize, // finalize; + + /* Optionally non-null members start here. */ + nsnull, // getObjectOps; + nsnull, // checkAccess; + nsnull, // call; + nsnull, // construct; + nsnull, // xdrObject; + nsnull, // hasInstance; + nsnull, // mark/trace; + nsnull // spare; }; diff --git a/js/src/xpconnect/src/xpcwrappednativeproto.cpp b/js/src/xpconnect/src/xpcwrappednativeproto.cpp index c7576eab895..657b0f0f235 100644 --- a/js/src/xpconnect/src/xpcwrappednativeproto.cpp +++ b/js/src/xpconnect/src/xpcwrappednativeproto.cpp @@ -104,7 +104,7 @@ XPCWrappedNativeProto::Init( return JS_FALSE; } - js::Class* jsclazz; + JSClass* jsclazz; if(mScriptableInfo) @@ -132,7 +132,7 @@ XPCWrappedNativeProto::Init( JSObject *parent = mScope->GetGlobalJSObject(); mJSProtoObject = - xpc_NewSystemInheritingJSObject(ccx, js::Jsvalify(jsclazz), + xpc_NewSystemInheritingJSObject(ccx, jsclazz, mScope->GetPrototypeJSObject(), parent); diff --git a/js/src/xpconnect/src/xpcwrappednativescope.cpp b/js/src/xpconnect/src/xpcwrappednativescope.cpp index 61ba696a318..29431164c05 100644 --- a/js/src/xpconnect/src/xpcwrappednativescope.cpp +++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp @@ -204,31 +204,29 @@ XPCWrappedNativeScope::SetComponents(nsXPCComponents* aComponents) // reserved slots in this class needs to match that of the wrappers // for the JS engine to share scopes. -js::Class XPC_WN_NoHelper_Proto_JSClass = { +JSClass XPC_WN_NoHelper_Proto_JSClass = { "XPC_WN_NoHelper_Proto_JSClass",// name; WRAPPER_SLOTS, // flags; /* Mandatory non-null function pointer members. */ - js::PropertyStub, // addProperty; - js::PropertyStub, // delProperty; - js::PropertyStub, // getProperty; - js::PropertyStub, // setProperty; - js::EnumerateStub, // enumerate; + JS_PropertyStub, // addProperty; + JS_PropertyStub, // delProperty; + JS_PropertyStub, // getProperty; + JS_PropertyStub, // setProperty; + JS_EnumerateStub, // enumerate; JS_ResolveStub, // resolve; - js::ConvertStub, // convert; + JS_ConvertStub, // convert; nsnull, // finalize; /* Optionally non-null members start here. */ - nsnull, // reserved0; + XPC_WN_Proto_GetObjectOps, // getObjectOps; nsnull, // checkAccess; nsnull, // call; nsnull, // construct; nsnull, // xdrObject; nsnull, // hasInstance; nsnull, // mark/trace; - - JS_NULL_CLASS_EXT, - XPC_WN_NoCall_ObjectOps + nsnull // spare; }; @@ -352,8 +350,7 @@ XPCWrappedNativeScope::GetPrototypeNoHelper(XPCCallContext& ccx) if(!mPrototypeNoHelper) { mPrototypeNoHelper = - xpc_NewSystemInheritingJSObject(ccx, - js::Jsvalify(&XPC_WN_NoHelper_Proto_JSClass), + xpc_NewSystemInheritingJSObject(ccx, &XPC_WN_NoHelper_Proto_JSClass, mPrototypeJSObject, mGlobalJSObject); @@ -728,7 +725,7 @@ XPCWrappedNativeScope* GetScopeOfObject(JSObject* obj) { nsISupports* supports; - js::Class* clazz = obj->getClass(); + JSClass* clazz = obj->getJSClass(); JSBool isWrapper = IS_WRAPPER_CLASS(clazz); if(isWrapper && IS_SLIM_WRAPPER_OBJECT(obj))