Bug 861022 part 1. Root the non-globals in WebIDL prototype and interface object setup. r=peterv,terrence

This commit is contained in:
Boris Zbarsky 2013-05-01 23:44:11 -04:00
parent c3b61c3b32
commit e418358f16
5 changed files with 52 additions and 40 deletions

View File

@ -2979,7 +2979,7 @@ nsObjectLoadingContent::SetupProtoChain(JSContext* aCx, JSObject* aObject)
// If we got an xpconnect-wrapped plugin object, set obj's
// prototype's prototype to the scriptable plugin.
JSObject *my_proto =
JS::Handle<JSObject*> my_proto =
GetDOMClass(aObject)->mGetProto(aCx, JS_GetGlobalForObject(aCx, aObject));
MOZ_ASSERT(my_proto);

View File

@ -294,7 +294,7 @@ CreateConstructor(JSContext* cx, JSObject* global, const char* name,
static bool
DefineConstructor(JSContext* cx, JSObject* global, const char* name,
JSObject* constructor)
JS::Handle<JSObject*> constructor)
{
JSBool alreadyDefined;
if (!JS_AlreadyHasOwnProperty(cx, global, name, &alreadyDefined)) {
@ -312,12 +312,12 @@ CreateInterfaceObject(JSContext* cx, JSObject* global,
JSClass* constructorClass,
const JSNativeHolder* constructorNative,
unsigned ctorNargs, const NamedConstructor* namedConstructors,
JSObject* proto,
JS::Handle<JSObject*> proto,
const NativeProperties* properties,
const NativeProperties* chromeOnlyProperties,
const char* name)
{
JSObject* constructor;
JS::Rooted<JSObject*> constructor(cx);
bool isCallbackInterface = constructorClass == js::Jsvalify(&js::ObjectClass);
if (constructorClass) {
JSObject* constructorProto;
@ -342,22 +342,23 @@ CreateInterfaceObject(JSContext* cx, JSObject* global,
if (constructorClass && !isCallbackInterface) {
// Have to shadow Function.prototype.toString, since that throws
// on things that are not js::FunctionClass.
JSFunction* toString = js::DefineFunctionWithReserved(cx, constructor,
"toString",
InterfaceObjectToString,
0, 0);
JS::Rooted<JSFunction*> toString(cx,
js::DefineFunctionWithReserved(cx, constructor,
"toString",
InterfaceObjectToString,
0, 0));
if (!toString) {
return NULL;
}
JSObject* toStringObj = JS_GetFunctionObject(toString);
js::SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT,
PRIVATE_TO_JSVAL(constructorClass));
JSString *str = ::JS_InternString(cx, name);
if (!str) {
return NULL;
}
JSObject* toStringObj = JS_GetFunctionObject(toString);
js::SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT,
PRIVATE_TO_JSVAL(constructorClass));
js::SetFunctionNativeReserved(toStringObj, TOSTRING_NAME_RESERVED_SLOT,
STRING_TO_JSVAL(str));
@ -413,10 +414,10 @@ CreateInterfaceObject(JSContext* cx, JSObject* global,
if (namedConstructors) {
int namedConstructorSlot = DOM_INTERFACE_SLOTS_BASE;
while (namedConstructors->mName) {
JSObject* namedConstructor = CreateConstructor(cx, global,
namedConstructors->mName,
&namedConstructors->mHolder,
namedConstructors->mNargs);
JS::Rooted<JSObject*> namedConstructor(cx,
CreateConstructor(cx, global, namedConstructors->mName,
&namedConstructors->mHolder,
namedConstructors->mNargs));
if (!namedConstructor ||
!JS_DefineProperty(cx, namedConstructor, "prototype",
JS::ObjectValue(*proto), JS_PropertyStub,
@ -453,12 +454,13 @@ DefineWebIDLBindingPropertiesOnXPCProto(JSContext* cx, JSObject* proto, const Na
static JSObject*
CreateInterfacePrototypeObject(JSContext* cx, JSObject* global,
JSObject* parentProto, JSClass* protoClass,
JS::Handle<JSObject*> parentProto,
JSClass* protoClass,
const NativeProperties* properties,
const NativeProperties* chromeOnlyProperties)
{
JSObject* ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto,
global);
JS::Rooted<JSObject*> ourProto(cx,
JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global));
if (!ourProto) {
return NULL;
}
@ -501,7 +503,8 @@ CreateInterfacePrototypeObject(JSContext* cx, JSObject* global,
}
void
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* protoProto,
CreateInterfaceObjects(JSContext* cx, JSObject* global,
JS::Handle<JSObject*> protoProto,
JSClass* protoClass, JSObject** protoCache,
JSClass* constructorClass, const JSNativeHolder* constructor,
unsigned ctorNargs, const NamedConstructor* namedConstructors,
@ -535,10 +538,11 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* protoProto,
"If, and only if, there is an interface object we need to cache "
"it");
JSObject* proto;
JS::Rooted<JSObject*> proto(cx);
if (protoClass) {
proto = CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
properties, chromeOnlyProperties);
proto =
CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
properties, chromeOnlyProperties);
if (!proto) {
return;
}
@ -549,7 +553,7 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* protoProto,
*protoCache = proto;
}
else {
proto = NULL;
MOZ_ASSERT(!proto);
}
JSObject* interface;
@ -1470,7 +1474,7 @@ ReparentWrapper(JSContext* aCx, JS::HandleObject aObjArg)
// return early we must avoid ending up with two reflectors pointing to the
// same native. Other than that, the objects we create will just go away.
JSObject *proto =
JS::Handle<JSObject*> proto =
(domClass->mGetProto)(aCx,
js::GetGlobalForObjectCrossCompartment(newParent));
if (!proto) {

View File

@ -331,7 +331,8 @@ struct NamedConstructor
* |name|, which must also be non-null.
*/
void
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* protoProto,
CreateInterfaceObjects(JSContext* cx, JSObject* global,
JS::Handle<JSObject*> protoProto,
JSClass* protoClass, JSObject** protoCache,
JSClass* constructorClass, const JSNativeHolder* constructor,
unsigned ctorNargs, const NamedConstructor* namedConstructors,

View File

@ -1679,11 +1679,13 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
def definition_body(self):
protoChain = self.descriptor.prototypeChain
if len(protoChain) == 1:
getParentProto = "JS_GetObjectPrototype(aCx, aGlobal)"
getParentProto = "aCx, JS_GetObjectPrototype(aCx, aGlobal)"
parentProtoType = "Rooted"
else:
parentProtoName = self.descriptor.prototypeChain[-2]
getParentProto = ("%s::GetProtoObject(aCx, aGlobal)" %
toBindingNamespace(parentProtoName))
parentProtoType = "Handle"
needInterfaceObject = self.descriptor.interface.hasInterfaceObject()
needInterfacePrototypeObject = self.descriptor.interface.hasInterfacePrototypeObject()
@ -1751,10 +1753,10 @@ if (!unforgeableHolder) {
else:
createUnforgeableHolder = None
getParentProto = ("JSObject* parentProto = %s;\n" +
getParentProto = ("JS::%s<JSObject*> parentProto(%s);\n" +
"if (!parentProto) {\n" +
" return;\n" +
"}\n") % getParentProto
"}\n") % (parentProtoType, getParentProto)
if (needInterfaceObject and
self.descriptor.needsConstructHookHolder()):
@ -1842,25 +1844,24 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
def __init__(self, descriptor, name, idPrefix=""):
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
CGAbstractMethod.__init__(self, descriptor, name,
'JSObject*', args, inline=True)
'JS::Handle<JSObject*>', args, inline=True)
self.id = idPrefix + "id::" + self.descriptor.name
def definition_body(self):
return """
return ("""
/* Make sure our global is sane. Hopefully we can remove this sometime */
if (!(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL)) {
return NULL;
return JS::NullPtr();
}
/* Check to see whether the interface objects are already installed */
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
JSObject* cachedObject = protoAndIfaceArray[%s];
if (!cachedObject) {
if (!protoAndIfaceArray[%s]) {
CreateInterfaceObjects(aCx, aGlobal, protoAndIfaceArray);
cachedObject = protoAndIfaceArray[%s];
}
/* cachedObject might _still_ be null, but that's OK */
return cachedObject;""" % (self.id, self.id)
/* The object might _still_ be null, but that's OK */
return JS::Handle<JSObject*>::fromMarkedLocation(&protoAndIfaceArray[%s]);""" %
(self.id, self.id))
class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
"""
@ -2113,7 +2114,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
JSAutoCompartment ac(aCx, parent);
JSObject* global = JS_GetGlobalForObject(aCx, parent);
JSObject* proto = GetProtoObject(aCx, global);
JS::Handle<JSObject*> proto = GetProtoObject(aCx, global);
if (!proto) {
return NULL;
}
@ -2160,7 +2161,7 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
def definition_body(self):
return """%s
JSObject* global = JS_GetGlobalForObject(aCx, aScope);
JSObject* proto = GetProtoObject(aCx, global);
JS::Handle<JSObject*> proto = GetProtoObject(aCx, global);
if (!proto) {
return NULL;
}

View File

@ -157,7 +157,13 @@ enum DOMObjectType {
};
typedef JSObject* (*ParentGetter)(JSContext* aCx, JS::Handle<JSObject*> aObj);
typedef JSObject* (*ProtoGetter)(JSContext* aCx, JSObject* aGlobal);
/**
* Returns a handle to the relevent WebIDL prototype object for the given global
* (which may be a handle to null on out of memory). Once allocated, the
* prototype object is guaranteed to exist as long as the global does, since the
* global traces its array of WebIDL prototypes and constructors.
*/
typedef JS::Handle<JSObject*> (*ProtoGetter)(JSContext* aCx, JSObject* aGlobal);
struct DOMClass
{