Bug 787856 - Convert JS_GetPrototype to support lazy protos (r=bhackett)

This commit is contained in:
Bill McCloskey 2012-09-03 16:42:17 -07:00
parent 88913893e5
commit 2e75082f62
20 changed files with 266 additions and 90 deletions

View File

@ -83,8 +83,12 @@ nsSecurityNameSet::InitializeNameSet(nsIScriptContext* aScriptContext)
JSObject *obj = global;
JSObject *proto;
JSAutoRequest ar(cx);
while ((proto = JS_GetPrototype(obj)) != nullptr)
for (;;) {
MOZ_ALWAYS_TRUE(JS_GetPrototype(cx, obj, &proto));
if (!proto)
break;
obj = proto;
}
JSClass *objectClass = JS_GetClass(obj);
JS::Value v;

View File

@ -1217,7 +1217,9 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen
JSAutoCompartment ac(cx, scriptObject);
for ( ; true; base = proto) { // Will break out on null proto
proto = ::JS_GetPrototype(base);
if (!JS_GetPrototype(cx, base, &proto)) {
return;
}
if (!proto) {
break;
}
@ -1249,7 +1251,10 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen
// Alright! This is the right prototype. Pull it out of the
// proto chain.
JSObject* grandProto = ::JS_GetPrototype(proto);
JSObject* grandProto;
if (!JS_GetPrototype(cx, proto, &grandProto)) {
return;
}
::JS_SetPrototype(cx, base, grandProto);
break;
}
@ -1346,7 +1351,9 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
if (obj) {
// Retrieve the current prototype of obj.
parent_proto = ::JS_GetPrototype(obj);
if (!JS_GetPrototype(cx, obj, &parent_proto)) {
return NS_ERROR_FAILURE;
}
if (parent_proto) {
// We need to create a unique classname based on aClassName and
// parent_proto. Append a space (an invalid URI character) to ensure that

View File

@ -98,7 +98,9 @@ nsXBLDocGlobalObject::doCheckAccess(JSContext *cx, JSObject *obj, jsid id, uint3
// Make sure to actually operate on our object, and not some object further
// down on the proto chain.
while (JS_GetClass(obj) != &nsXBLDocGlobalObject::gSharedGlobalClass) {
obj = ::JS_GetPrototype(obj);
if (!::JS_GetPrototype(cx, obj, &obj)) {
return JS_FALSE;
}
if (!obj) {
::JS_ReportError(cx, "Invalid access to a global object property.");
return JS_FALSE;

View File

@ -5131,9 +5131,12 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
"Incorrect object class!");
}
NS_ASSERTION(::JS_GetPrototype(proto) &&
JS_GetClass(::JS_GetPrototype(proto)) == sObjectClass,
"Hmm, somebody did something evil?");
#ifdef DEBUG
JSObject *proto2;
JS_GetPrototype(cx, proto, &proto2);
NS_ASSERTION(proto2 && JS_GetClass(proto2) == sObjectClass,
"Hmm, somebody did something evil?");
#endif
#ifdef DEBUG
if (mData->mHasClassInterface && mData->mProtoChainInterface &&
@ -5462,7 +5465,10 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
return JS_TRUE;
}
JSObject *proto = ::JS_GetPrototype(obj);
JSObject *proto;
if (!::JS_GetPrototype(cx, obj, &proto)) {
return JS_FALSE;
}
JSBool hasProp;
if (!proto || !::JS_HasPropertyById(cx, proto, id, &hasProp) ||
@ -5505,14 +5511,21 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
}
// static
void
JSBool
nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
{
JSObject *proto;
JSAutoRequest ar(cx);
while ((proto = ::JS_GetPrototype(obj))) {
for (;;) {
if (!::JS_GetPrototype(cx, obj, &proto)) {
return JS_FALSE;
}
if (!proto) {
break;
}
if (JS_GetClass(proto) == &sGlobalScopePolluterClass) {
nsIHTMLDocument *doc = (nsIHTMLDocument *)::JS_GetPrivate(proto);
@ -5520,15 +5533,22 @@ nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
::JS_SetPrivate(proto, nullptr);
JSObject *proto_proto;
if (!::JS_GetPrototype(cx, proto, &proto_proto)) {
return JS_FALSE;
}
// Pull the global scope polluter out of the prototype chain so
// that it can be freed.
::JS_SplicePrototype(cx, obj, ::JS_GetPrototype(proto));
::JS_SplicePrototype(cx, obj, proto_proto);
break;
}
obj = proto;
}
return JS_TRUE;
}
// static
@ -5554,7 +5574,13 @@ nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
// Find the place in the prototype chain where we want this global
// scope polluter (right before Object.prototype).
while ((proto = ::JS_GetPrototype(o))) {
for (;;) {
if (!::JS_GetPrototype(cx, o, &proto)) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (!proto) {
break;
}
if (JS_GetClass(proto) == sObjectClass) {
// Set the global scope polluters prototype to Object.prototype
::JS_SplicePrototype(cx, gsp, proto);
@ -6322,8 +6348,14 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
JSObject *dot_prototype = JSVAL_TO_OBJECT(val);
JSObject *proto = JS_GetPrototype(dom_obj);
for ( ; proto; proto = JS_GetPrototype(proto)) {
JSObject *proto = dom_obj;
for (;;) {
if (!JS_GetPrototype(cx, proto, &proto)) {
return NS_ERROR_UNEXPECTED;
}
if (!proto) {
break;
}
if (proto == dot_prototype) {
*bp = true;
break;
@ -6682,7 +6714,10 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
if (dot_prototype) {
JSAutoCompartment ac(cx, dot_prototype);
JSObject *xpc_proto_proto = ::JS_GetPrototype(dot_prototype);
JSObject *xpc_proto_proto;
if (!::JS_GetPrototype(cx, dot_prototype, &xpc_proto_proto)) {
return NS_ERROR_UNEXPECTED;
}
if (proto &&
(!xpc_proto_proto ||
@ -8428,7 +8463,10 @@ nsNamedArraySH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
}
JSAutoCompartment ac(cx, realObj);
JSObject *proto = ::JS_GetPrototype(realObj);
JSObject *proto;
if (!::JS_GetPrototype(cx, realObj, &proto)) {
return NS_ERROR_FAILURE;
}
if (proto) {
JSBool hasProp;
@ -9144,14 +9182,17 @@ nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp)
}
static inline JSObject *
GetDocumentAllHelper(JSObject *obj)
static inline bool
GetDocumentAllHelper(JSContext *cx, JSObject *obj, JSObject **result)
{
while (obj && JS_GetClass(obj) != &sHTMLDocumentAllHelperClass) {
obj = ::JS_GetPrototype(obj);
if (!::JS_GetPrototype(cx, obj, &obj)) {
return false;
}
}
return obj;
*result = obj;
return true;
}
static inline void *
@ -9177,7 +9218,10 @@ nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj
return JS_TRUE;
}
JSObject *helper = GetDocumentAllHelper(obj);
JSObject *helper;
if (!GetDocumentAllHelper(cx, obj, &helper)) {
return JS_FALSE;
}
if (!helper) {
NS_ERROR("Uh, how'd we get here?");
@ -9235,7 +9279,10 @@ nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
{
if (nsDOMClassInfo::sAll_id == id) {
// document.all is resolved for the first time. Define it.
JSObject *helper = GetDocumentAllHelper(obj);
JSObject *helper;
if (!GetDocumentAllHelper(cx, obj, &helper)) {
return JS_FALSE;
}
if (helper) {
if (!::JS_DefineProperty(cx, helper, "all", JSVAL_VOID, nullptr, nullptr,
@ -9259,7 +9306,10 @@ nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
if (JSID_IS_STRING(id)) {
nsDocument *doc = GetDocument(obj);
JSObject *proto = ::JS_GetPrototype(obj);
JSObject *proto;
if (!::JS_GetPrototype(cx, obj, &proto)) {
return JS_FALSE;
}
if (NS_UNLIKELY(!proto)) {
return JS_TRUE;
}
@ -9338,9 +9388,19 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsIDocument *doc = static_cast<nsIDocument*>(wrapper->Native());
if (doc->GetCompatibilityMode() == eCompatibility_NavQuirks) {
JSObject *helper = GetDocumentAllHelper(::JS_GetPrototype(obj));
JSObject *proto;
if (!::JS_GetPrototype(cx, obj, &proto)) {
return NS_ERROR_FAILURE;
}
JSObject *proto = ::JS_GetPrototype(helper ? helper : obj);
JSObject *helper;
if (!GetDocumentAllHelper(cx, proto, &helper)) {
return NS_ERROR_FAILURE;
}
if (!::JS_GetPrototype(cx, helper ? helper : obj, &proto)) {
return NS_ERROR_FAILURE;
}
// Check if the property all is defined on obj's (or helper's
// if obj doesn't exist) prototype, if it is, don't expose our
@ -9355,11 +9415,14 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// Our helper's prototype now has an "all" property, remove
// the helper out of the prototype chain to prevent
// shadowing of the now defined "all" property.
JSObject *tmp = obj, *tmpProto;
JSObject *tmp = obj, *tmpProto = tmp;
while ((tmpProto = ::JS_GetPrototype(tmp)) != helper) {
do {
tmp = tmpProto;
}
if (!::JS_GetPrototype(cx, tmp, &tmpProto)) {
return NS_ERROR_UNEXPECTED;
}
} while (tmpProto != helper);
::JS_SetPrototype(cx, tmp, proto);
}
@ -9373,8 +9436,11 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// Print a warning so developers can stop using document.all
PrintWarningOnConsole(cx, "DocumentAllUsed");
if (!::JS_GetPrototype(cx, obj, &proto)) {
return NS_ERROR_UNEXPECTED;
}
helper = ::JS_NewObject(cx, &sHTMLDocumentAllHelperClass,
::JS_GetPrototype(obj),
proto,
::JS_GetGlobalForObject(cx, obj));
if (!helper) {
@ -9944,7 +10010,10 @@ nsHTMLPluginObjElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
{
JSAutoRequest ar(cx);
JSObject *pi_obj = ::JS_GetPrototype(obj);
JSObject *pi_obj;
if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
return NS_ERROR_UNEXPECTED;
}
if (NS_UNLIKELY(!pi_obj)) {
return NS_OK;
}
@ -9973,7 +10042,10 @@ nsHTMLPluginObjElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
{
JSAutoRequest ar(cx);
JSObject *pi_obj = ::JS_GetPrototype(obj);
JSObject *pi_obj;
if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
return NS_ERROR_UNEXPECTED;
}
if (NS_UNLIKELY(!pi_obj)) {
return NS_OK;
}
@ -10049,7 +10121,9 @@ nsHTMLPluginObjElementSH::GetPluginJSObject(JSContext *cx, JSObject *obj,
if (plugin_inst) {
plugin_inst->GetJSObject(cx, plugin_obj);
if (*plugin_obj) {
*plugin_proto = ::JS_GetPrototype(*plugin_obj);
if (!::JS_GetPrototype(cx, *plugin_obj, plugin_proto)) {
return NS_ERROR_UNEXPECTED;
}
}
}
@ -10394,7 +10468,10 @@ nsStorage2SH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
JSObject *proto = ::JS_GetPrototype(realObj);
JSObject *proto;
if (!::JS_GetPrototype(cx, realObj, &proto)) {
return NS_ERROR_FAILURE;
}
JSBool hasProp;
if (proto &&

View File

@ -420,7 +420,7 @@ public:
JSMutableHandleValue vp);
static JSBool SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
JSBool strict, JSMutableHandleValue vp);
static void InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
static JSBool InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
nsIHTMLDocument *doc);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)

View File

@ -1687,7 +1687,11 @@ nsGlobalWindow::SetOuterObject(JSContext* aCx, JSObject* aOuterObject)
// Set up the prototype for the outer object.
JSObject* inner = JS_GetParent(aOuterObject);
JS_SetPrototype(aCx, aOuterObject, JS_GetPrototype(inner));
JSObject* proto;
if (!JS_GetPrototype(aCx, inner, &proto)) {
return NS_ERROR_FAILURE;
}
JS_SetPrototype(aCx, aOuterObject, proto);
return NS_OK;
}
@ -1856,7 +1860,9 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if (aDocument != oldDoc) {
xpc_UnmarkGrayObject(currentInner->mJSObject);
nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
if (!nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject)) {
return NS_ERROR_FAILURE;
}
}
// We're reusing the inner window, but this still counts as a navigation,
@ -1992,7 +1998,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
JS_SetParent(cx, mJSObject, newInnerWindow->mJSObject);
SetOuterObject(cx, mJSObject);
rv = SetOuterObject(cx, mJSObject);
NS_ENSURE_SUCCESS(rv, rv);
JSCompartment *compartment = js::GetObjectCompartment(mJSObject);
xpc::CompartmentPrivate *priv =
@ -2049,9 +2056,13 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
// the global object's compartment as its default compartment,
// so update that now since it might have changed.
JS_SetGlobalObject(cx, mJSObject);
NS_ASSERTION(JS_GetPrototype(mJSObject) ==
JS_GetPrototype(newInnerJSObject),
#ifdef DEBUG
JSObject *proto1, *proto2;
JS_GetPrototype(cx, mJSObject, &proto1);
JS_GetPrototype(cx, newInnerJSObject, &proto2);
NS_ASSERTION(proto1 == proto2,
"outer and inner globals should have the same prototype");
#endif
nsCOMPtr<nsIContent> frame = do_QueryInterface(GetFrameElementInternal());
if (frame) {

View File

@ -759,13 +759,16 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
JSObject *objProto = &protov.toObject();
JSObject* instance = &vp.toObject();
JSObject* proto = JS_GetPrototype(instance);
JSObject* proto;
if (!JS_GetPrototype(cx, instance, &proto))
return false;
while (proto) {
if (proto == objProto) {
*bp = true;
return true;
}
proto = JS_GetPrototype(proto);
if (!JS_GetPrototype(cx, proto, &proto))
return false;
}
nsISupports* native =

View File

@ -1142,7 +1142,9 @@ GetNPObjectWrapper(JSContext *cx, JSObject *obj, bool wrapResult = true)
}
return obj;
}
obj = ::JS_GetPrototype(obj);
if (!::JS_GetPrototype(cx, obj, &obj)) {
return NULL;
}
}
return NULL;
}
@ -2054,12 +2056,20 @@ nsJSNPRuntime::OnPluginDestroy(NPP npp)
// be only one, but remove all instances found in case the page put
// more than one of the plugin's scriptable objects on the prototype
// chain).
while (obj && (proto = ::JS_GetPrototype(obj))) {
while (obj) {
if (!::JS_GetPrototype(cx, obj, &proto)) {
return;
}
if (!proto) {
break;
}
// Unwrap while checking the jsclass - if the prototype is a wrapper for
// an NP object, that counts too.
if (JS_GetClass(js::UnwrapObject(proto)) == &sNPObjectJSWrapperClass) {
// We found an NPObject on the proto chain, get its prototype...
proto = ::JS_GetPrototype(proto);
if (!::JS_GetPrototype(cx, proto, &proto)) {
return;
}
// ... and pull it out of the chain.
::JS_SetPrototype(cx, obj, proto);

View File

@ -422,14 +422,14 @@ ObjectWrapperChild::AnswerNewEnumerateInit(/* no in-parameters */
return false;
AutoObjectRooter tvr(cx, state);
for (JSObject* proto = mObj;
proto;
proto = JS_GetPrototype(proto))
{
for (JSObject* proto = mObj; proto; ) {
AutoIdArray ids(cx, JS_Enumerate(cx, proto));
for (size_t i = 0; i < ids.length(); ++i)
JS_DefinePropertyById(cx, state, ids[i], JSVAL_VOID,
NULL, NULL, JSPROP_ENUMERATE | JSPROP_SHARED);
if (!JS_GetPrototype(cx, proto, &proto))
return false;
}
InfallibleTArray<nsString>* strIds;

View File

@ -614,6 +614,7 @@ jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval)
JSDValue*
jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
{
JSContext* cx = jsdc->dumbContext;
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
{
JSObject* obj;
@ -623,7 +624,8 @@ jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
if(JSVAL_IS_PRIMITIVE(jsdval->val))
return NULL;
obj = JSVAL_TO_OBJECT(jsdval->val);
proto = JS_GetPrototype(obj);
if(!JS_GetPrototype(cx, obj, &proto))
return NULL;
if(!proto)
return NULL;
jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
@ -665,6 +667,7 @@ JSDValue*
jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
{
JSCompartment* oldCompartment = NULL;
JSContext* cx = jsdc->dumbContext;
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
{
@ -676,7 +679,8 @@ jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
if(JSVAL_IS_PRIMITIVE(jsdval->val))
return NULL;
obj = JSVAL_TO_OBJECT(jsdval->val);
proto = JS_GetPrototype(obj);
if(!JS_GetPrototype(cx, obj, &proto))
return NULL;
if(!proto)
return NULL;
JS_BeginRequest(jsdc->dumbContext);

View File

@ -717,7 +717,9 @@ InitCTypeClass(JSContext* cx, HandleObject parent)
return NULL;
RootedObject ctor(cx, JS_GetFunctionObject(fun));
RootedObject fnproto(cx, JS_GetPrototype(ctor));
RootedObject fnproto(cx);
if (!JS_GetPrototype(cx, ctor, fnproto.address()))
return NULL;
JS_ASSERT(ctor);
JS_ASSERT(fnproto);
@ -1928,11 +1930,15 @@ ConvertToJS(JSContext* cx,
if (!numeric_limits<type>::is_signed) { \
value = *static_cast<type*>(data); \
/* Get ctypes.UInt64.prototype from ctypes.CType.prototype. */ \
proto = CType::GetProtoFromType(typeObj, SLOT_UINT64PROTO); \
proto = CType::GetProtoFromType(cx, typeObj, SLOT_UINT64PROTO); \
if (!proto) \
return false; \
} else { \
value = int64_t(*static_cast<type*>(data)); \
/* Get ctypes.Int64.prototype from ctypes.CType.prototype. */ \
proto = CType::GetProtoFromType(typeObj, SLOT_INT64PROTO); \
proto = CType::GetProtoFromType(cx, typeObj, SLOT_INT64PROTO); \
if (!proto) \
return false; \
} \
\
JSObject* obj = Int64Base::Construct(cx, proto, value, \
@ -3357,17 +3363,20 @@ CType::GetProtoFromCtor(JSObject* obj, CTypeProtoSlot slot)
}
JSObject*
CType::GetProtoFromType(JSObject* obj, CTypeProtoSlot slot)
CType::GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
{
JS_ASSERT(IsCType(obj));
// Get the prototype of the type object.
JSObject* proto = JS_GetPrototype(obj);
JSObject* proto;
if (!JS_GetPrototype(cx, obj, &proto))
return NULL;
JS_ASSERT(proto);
JS_ASSERT(CType::IsCTypeProto(proto));
// Get the requested ctypes.{Pointer,Array,Struct,Function}Type.prototype.
jsval result = JS_GetReservedSlot(proto, slot);
JS_ASSERT(!JSVAL_IS_PRIMITIVE(result));
return JSVAL_TO_OBJECT(result);
}
@ -3538,7 +3547,11 @@ CType::HasInstance(JSContext* cx, JSHandleObject obj, JSMutableHandleValue v, JS
return JS_TRUE;
JSObject* proto = JSVAL_TO_OBJECT(v);
while ((proto = JS_GetPrototype(proto))) {
for (;;) {
if (!JS_GetPrototype(cx, proto, &proto))
return JS_FALSE;
if (!proto)
break;
if (proto == prototype) {
*bp = JS_TRUE;
break;
@ -3552,15 +3565,16 @@ CType::GetGlobalCTypes(JSContext* cx, JSObject* obj)
{
JS_ASSERT(CType::IsCType(obj));
JSObject *objTypeProto = JS_GetPrototype(obj);
if (!objTypeProto) {
}
JSObject *objTypeProto;
if (!JS_GetPrototype(cx, obj, &objTypeProto))
return NULL;
JS_ASSERT(objTypeProto);
JS_ASSERT(CType::IsCTypeProto(objTypeProto));
jsval valCTypes = JS_GetReservedSlot(objTypeProto, SLOT_CTYPES);
JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCTypes));
JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCTypes));
return JSVAL_TO_OBJECT(valCTypes);
}
@ -3653,8 +3667,12 @@ PointerType::CreateInternal(JSContext* cx, HandleObject baseType)
// of this type, or ctypes.FunctionType.prototype for function pointers.
CTypeProtoSlot slotId = CType::GetTypeCode(baseType) == TYPE_function ?
SLOT_FUNCTIONDATAPROTO : SLOT_POINTERDATAPROTO;
RootedObject dataProto(cx, CType::GetProtoFromType(baseType, slotId));
RootedObject typeProto(cx, CType::GetProtoFromType(baseType, SLOT_POINTERPROTO));
RootedObject dataProto(cx, CType::GetProtoFromType(cx, baseType, slotId));
if (!dataProto)
return NULL;
RootedObject typeProto(cx, CType::GetProtoFromType(cx, baseType, SLOT_POINTERPROTO));
if (!typeProto)
return NULL;
// Create a new CType object with the common properties and slots.
JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_pointer,
@ -3971,8 +3989,12 @@ ArrayType::CreateInternal(JSContext* cx,
{
// Get ctypes.ArrayType.prototype and the common prototype for CData objects
// of this type, from ctypes.CType.prototype.
RootedObject typeProto(cx, CType::GetProtoFromType(baseType, SLOT_ARRAYPROTO));
RootedObject dataProto(cx, CType::GetProtoFromType(baseType, SLOT_ARRAYDATAPROTO));
RootedObject typeProto(cx, CType::GetProtoFromType(cx, baseType, SLOT_ARRAYPROTO));
if (!typeProto)
return NULL;
RootedObject dataProto(cx, CType::GetProtoFromType(cx, baseType, SLOT_ARRAYDATAPROTO));
if (!dataProto)
return NULL;
// Determine the size of the array from the base type, if possible.
// The size of the base type must be defined.
@ -4515,7 +4537,9 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
// Get the common prototype for CData objects of this type from
// ctypes.CType.prototype.
RootedObject dataProto(cx, CType::GetProtoFromType(typeObj, SLOT_STRUCTDATAPROTO));
RootedObject dataProto(cx, CType::GetProtoFromType(cx, typeObj, SLOT_STRUCTDATAPROTO));
if (!dataProto)
return JS_FALSE;
// Set up the 'prototype' and 'prototype.constructor' properties.
// The prototype will reflect the struct fields as properties on CData objects
@ -5372,10 +5396,14 @@ FunctionType::CreateInternal(JSContext* cx,
// Get ctypes.FunctionType.prototype and the common prototype for CData objects
// of this type, from ctypes.CType.prototype.
RootedObject typeProto(cx, CType::GetProtoFromType(fninfo->mReturnType,
RootedObject typeProto(cx, CType::GetProtoFromType(cx, fninfo->mReturnType,
SLOT_FUNCTIONPROTO));
RootedObject dataProto(cx, CType::GetProtoFromType(fninfo->mReturnType,
if (!typeProto)
return NULL;
RootedObject dataProto(cx, CType::GetProtoFromType(cx, fninfo->mReturnType,
SLOT_FUNCTIONDATAPROTO));
if (!dataProto)
return NULL;
// Create a new CType object with the common properties and slots.
JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_function,
@ -5590,6 +5618,8 @@ FunctionType::Call(JSContext* cx,
// Store the error value for later consultation with |ctypes.getStatus|
JSObject *objCTypes = CType::GetGlobalCTypes(cx, typeObj);
if (!objCTypes)
return false;
JS_SetReservedSlot(objCTypes, SLOT_ERRNO, INT_TO_JSVAL(errnoStatus));
#if defined(XP_WIN)
@ -5740,7 +5770,9 @@ CClosure::Create(JSContext* cx,
// Get the prototype of the FunctionType object, of class CTypeProto,
// which stores our JSContext for use with the closure.
JSObject* proto = JS_GetPrototype(typeObj);
JSObject* proto;
if (!JS_GetPrototype(cx, typeObj, &proto))
return NULL;
JS_ASSERT(proto);
JS_ASSERT(CType::IsCTypeProto(proto));
@ -6906,6 +6938,8 @@ CDataFinalizer::Methods::Dispose(JSContext* cx, unsigned argc, jsval *vp)
JS_ASSERT(!JSVAL_IS_PRIMITIVE(valType));
JSObject *objCTypes = CType::GetGlobalCTypes(cx, JSVAL_TO_OBJECT(valType));
if (!objCTypes)
return JS_FALSE;
jsval valCodePtrType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_CODETYPE);
JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCodePtrType));

View File

@ -428,7 +428,7 @@ namespace CType {
ffi_type* GetFFIType(JSContext* cx, JSObject* obj);
JSString* GetName(JSContext* cx, JSHandleObject obj);
JSObject* GetProtoFromCtor(JSObject* obj, CTypeProtoSlot slot);
JSObject* GetProtoFromType(JSObject* obj, CTypeProtoSlot slot);
JSObject* GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot);
JSCTypesCallbacks* GetCallbacksFromType(JSObject* obj);
}

View File

@ -30,7 +30,8 @@ BEGIN_TEST(testTypedArrays)
RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes));
CHECK(JS_IsArrayBufferObject(buffer, cx));
RootedObject proto(cx, JS_GetPrototype(buffer));
RootedObject proto(cx);
JS_GetPrototype(cx, buffer, proto.address());
CHECK(!JS_IsArrayBufferObject(proto, cx));
RootedObject dummy(cx, JS_GetParent(proto));
CHECK(!JS_IsArrayBufferObject(dummy, cx));
@ -60,7 +61,8 @@ TestPlainTypedArray(JSContext *cx)
{
RootedObject array(cx, Create(cx, 7));
CHECK(JS_IsTypedArrayObject(array, cx));
RootedObject proto(cx, JS_GetPrototype(array));
RootedObject proto(cx);
JS_GetPrototype(cx, array, proto.address());
CHECK(!JS_IsTypedArrayObject(proto, cx));
RootedObject dummy(cx, JS_GetParent(proto));
CHECK(!JS_IsTypedArrayObject(dummy, cx));

View File

@ -3268,11 +3268,14 @@ JS_GetInstancePrivate(JSContext *cx, JSObject *objArg, JSClass *clasp, jsval *ar
return obj->getPrivate();
}
JS_PUBLIC_API(JSObject *)
JS_GetPrototype(RawObject obj)
JS_PUBLIC_API(JSBool)
JS_GetPrototype(JSContext *cx, JSObject *objArg, JSObject **protop)
{
/* FIXME! */
return obj->getProto();
RootedObject obj(cx, objArg);
RootedObject proto(cx);
bool rv = JSObject::getProto(cx, obj, &proto);
*protop = proto;
return rv;
}
JS_PUBLIC_API(JSBool)

View File

@ -4334,8 +4334,8 @@ extern JS_PUBLIC_API(void *)
JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
jsval *argv);
extern JS_PUBLIC_API(JSObject *)
JS_GetPrototype(JSRawObject obj);
extern JS_PUBLIC_API(JSBool)
JS_GetPrototype(JSContext *cx, JSObject *obj, JSObject **protop);
extern JS_PUBLIC_API(JSBool)
JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto);

View File

@ -405,11 +405,10 @@ GetObjectProto(JSContext *cx, JSObject *obj, JSObject **proto)
clasp == &js::OuterWindowProxyClass ||
clasp == &js::FunctionProxyClass)
{
/* FIXME */
*proto = reinterpret_cast<const shadow::Object*>(obj)->type->proto;
} else {
*proto = reinterpret_cast<const shadow::Object*>(obj)->type->proto;
return JS_GetPrototype(cx, obj, proto);
}
*proto = reinterpret_cast<const shadow::Object*>(obj)->type->proto;
return true;
}

View File

@ -288,7 +288,11 @@ interface_hasInstance(JSContext *cx, JSHandleObject obj, JSMutableHandleValue vp
} else {
JSObject *protoObj = JSVAL_TO_OBJECT(prototype);
JSObject *proto = other;
while ((proto = JS_GetPrototype(proto))) {
for (;;) {
if (!JS_GetPrototype(cx, proto, &proto))
return false;
if (!proto)
break;
if (proto == protoObj) {
*bp = true;
return true;
@ -697,8 +701,9 @@ template<class LC>
bool
ListBase<LC>::enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props)
{
JSObject *proto = JS_GetPrototype(proxy);
return getOwnPropertyNames(cx, proxy, props) &&
JSObject *proto;
return JS_GetPrototype(cx, proxy, &proto) &&
getOwnPropertyNames(cx, proxy, props) &&
(!proto || js::GetPropertyNames(cx, proto, 0, &props));
}

View File

@ -44,7 +44,9 @@ ChromeObjectWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapper,
desc->obj = NULL;
// If we found something, were doing a set, or have no proto, we're done.
JSObject *wrapperProto = JS_GetPrototype(wrapper);
JSObject *wrapperProto;
if (!JS_GetPrototype(cx, wrapper, &wrapperProto))
return false;
if (desc->obj || set || !wrapperProto)
return true;
@ -61,7 +63,9 @@ ChromeObjectWrapper::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
return false;
// If we found something or have no prototype, we're done.
JSObject *wrapperProto = JS_GetPrototype(wrapper);
JSObject *wrapperProto;
if (!JS_GetPrototype(cx, wrapper, &wrapperProto))
return false;
if (*bp || !wrapperProto)
return true;
@ -102,7 +106,9 @@ ChromeObjectWrapper::get(JSContext *cx, JSObject *wrapper, JSObject *receiver,
}
// If we have no proto, we're done.
JSObject *wrapperProto = JS_GetPrototype(wrapper);
JSObject *wrapperProto;
if (!JS_GetPrototype(cx, wrapper, &wrapperProto))
return false;
if (!wrapperProto)
return true;

View File

@ -569,8 +569,11 @@ WrapperFactory::WaiveXrayAndWrap(JSContext *cx, jsval *vp)
JSObject *
WrapperFactory::WrapSOWObject(JSContext *cx, JSObject *obj)
{
JSObject *proto;
if (!JS_GetPrototype(cx, obj, &proto))
return NULL;
JSObject *wrapperObj =
Wrapper::New(cx, obj, JS_GetPrototype(obj), JS_GetGlobalForObject(cx, obj),
Wrapper::New(cx, obj, proto, JS_GetGlobalForObject(cx, obj),
&FilteringWrapper<SameCompartmentSecurityWrapper,
OnlyIfSubjectIsSystem>::singleton);
return wrapperObj;
@ -586,8 +589,11 @@ WrapperFactory::IsComponentsObject(JSObject *obj)
JSObject *
WrapperFactory::WrapComponentsObject(JSContext *cx, JSObject *obj)
{
JSObject *proto;
if (!JS_GetPrototype(cx, obj, &proto))
return NULL;
JSObject *wrapperObj =
Wrapper::New(cx, obj, JS_GetPrototype(obj), JS_GetGlobalForObject(cx, obj),
Wrapper::New(cx, obj, proto, JS_GetGlobalForObject(cx, obj),
&FilteringWrapper<SameCompartmentSecurityWrapper, ComponentsObjectPolicy>::singleton);
return wrapperObj;

View File

@ -719,8 +719,11 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, JSObject *wrapp
// this problem for mozMatchesSelector. See: bug 763897.
desc->obj = wrapper;
desc->attrs = JSPROP_ENUMERATE;
JSObject *proto;
if (!JS_GetPrototype(cx, wrapper, &proto))
return false;
JSFunction *fun = JS_NewFunction(cx, mozMatchesSelectorStub,
1, 0, JS_GetPrototype(wrapper),
1, 0, proto,
"mozMatchesSelector");
NS_ENSURE_TRUE(fun, false);
desc->value = OBJECT_TO_JSVAL(JS_GetFunctionObject(fun));