Backed out changeset 7b2b90efe57d -- the patch was landed against a tree with a lot of orange. This will hinder the orange resolution.

This commit is contained in:
Igor Bukanov 2010-07-28 14:36:06 +02:00
parent a69fd0a49f
commit 181c2cdf3a
60 changed files with 1506 additions and 1602 deletions

View File

@ -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<const JSExtendedClass*>(jsClass)->equality :
nsnull;
if (op == sXPCWrappedNativeEqualityOps) {
result = sXPConnect->GetPrincipal(aObj,
#ifdef DEBUG
aAllowShortCircuit

View File

@ -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.

View File

@ -72,8 +72,6 @@
#include <gdk/gdkx.h>
#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<JSExtendedClass*>(clasp);
if (JSObjectOp outerize = xclasp->outerObject)
*rval = OBJECT_TO_JSVAL(outerize(cx, parent));
}
}
cc->SetReturnValueWasSet(PR_TRUE);

View File

@ -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<js::Class *>(&ObjectWrapperParent::sCPOW_JSClass);
if (!mObj && (mObj = JS_NewObject(cx, js::Jsvalify(clasp), NULL, NULL))) {
JSClass* clasp = const_cast<JSClass*>(&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;

View File

@ -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:

View File

@ -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);

View File

@ -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));

View File

@ -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 *)

View File

@ -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;

View File

@ -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 *>(&JSObjectMap::sharedNonNative);
obj->map = const_cast<JSObjectMap *>(&SharedArrayMap);
obj->init(&js_ArrayClass, proto, proto->getParent(), NullValue());
obj->setArrayLength(len);
obj->setDenseArrayCapacity(0);

View File

@ -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

View File

@ -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)

View File

@ -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 */

View File

@ -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 {

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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, &current))
JS_ASSERT(obj->map->ops->lookupProperty == js_LookupProperty);
if (!js_HasOwnProperty(cx, js_LookupProperty, obj, desc.id, &obj2, &current))
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<JSObject *>(this)))
return obj;
Class *clasp = getClass();
if (clasp->flags & JSCLASS_IS_EXTENDED) {
if (JSObjectOp wrappedObject = reinterpret_cast<JSExtendedClass *>(clasp)->wrappedObject) {
if (JSObject *obj = wrappedObject(cx, const_cast<JSObject *>(this)))
return obj;
}
}
return const_cast<JSObject *>(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;
}

View File

@ -170,62 +170,73 @@ namespace js {
typedef Vector<PropDesc, 1> 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<Native>(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);

View File

@ -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 *>(&JSObjectMap::sharedNonNative);
JS_ASSERT(ops->objectMap->ops == ops);
obj->map = const_cast<JSObjectMap *>(ops->objectMap);
}
out:

View File

@ -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

View File

@ -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 *)

View File

@ -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___ */

View File

@ -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

View File

@ -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<JSResolveOp>(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<JSResolveOp>(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};

View File

@ -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<JSScope>(obj);
JSScope *scope = cx->create<JSScope>(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<JSEmptyScope>(cx, clasp); \
#define INIT_EMPTY_SCOPE_WITH_FREESLOT(Name,NAME,ops,clasp,slot) \
SCOPE(Name) = cx->create<JSEmptyScope>(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

View File

@ -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

View File

@ -53,7 +53,7 @@ JSScope::createEmptyScope(JSContext *cx, js::Class *clasp)
{
JS_ASSERT(!isSharedEmpty());
JS_ASSERT(!emptyScope);
emptyScope = cx->create<JSEmptyScope>(cx, clasp);
emptyScope = cx->create<JSEmptyScope>(cx, ops, clasp);
return emptyScope;
}

View File

@ -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
};
/*

View File

@ -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) \

View File

@ -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));

View File

@ -493,6 +493,9 @@ class TypedArrayTemplate
static const bool ArrayTypeIsUnsigned() { return TypeIsUnsigned<NativeType>(); }
static const bool ArrayTypeIsFloatingPoint() { return TypeIsFloatingPoint<NativeType>(); }
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 *>(&JSObjectMap::sharedNonNative);
obj->map = &fastObjectMap;
}
public:
@ -1256,14 +1264,9 @@ TypedArrayTemplate<double>::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) \

View File

@ -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<Native>(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; }

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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<JSExtendedClass *>(clasp);
if (JSObjectOp outerize = xclasp->outerObject)
*vp = OBJECT_TO_JSVAL(outerize(cx, parent));
}
}
return JS_TRUE;

View File

@ -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''

View File

@ -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 *

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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<JSObject*>(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<JSObject*>(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 =

View File

@ -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;
}

View File

@ -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<JSExtendedClass *>(clasp);
if (JSObjectOp outerize = xclasp->outerObject)
*rval = OBJECT_TO_JSVAL(outerize(cx, obj));
}
cc->SetReturnValueWasSet(PR_TRUE);
return NS_OK;

View File

@ -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<JSExtendedClass*>(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;}

View File

@ -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))

View File

@ -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);

View File

@ -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;
};

View File

@ -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);

View File

@ -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))