Bug 815803. Now that JSSLOT_PROXY_PRIVATE == 0, simplify binding code that had to deal with different slot indices on proxy and non-proxy objects. r=peterv

This commit is contained in:
Boris Zbarsky 2012-12-06 15:21:19 -05:00
parent 0372b9fe22
commit f490c53f7d
9 changed files with 43 additions and 85 deletions

View File

@ -578,8 +578,8 @@ ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
inline const NativePropertyHooks*
GetNativePropertyHooks(JSContext *cx, JSObject *obj, DOMObjectType& type)
{
const DOMClass* domClass;
if (GetDOMClass(obj, domClass) != eNonDOMObject) {
const DOMClass* domClass = GetDOMClass(obj);
if (domClass) {
type = eInstance;
return domClass->mNativeHooks;
}

View File

@ -91,32 +91,17 @@ IsDOMIfaceAndProtoClass(const js::Class* clasp)
return IsDOMIfaceAndProtoClass(Jsvalify(clasp));
}
// It's ok for eRegularDOMObject and eProxyDOMObject to be the same, but
// eNonDOMObject should always be different from the other two. This enum
// shouldn't be used to differentiate between non-proxy and proxy bindings.
enum DOMObjectSlot {
eNonDOMObject = -1,
eRegularDOMObject = DOM_OBJECT_SLOT,
eProxyDOMObject = DOM_PROXY_OBJECT_SLOT
};
MOZ_STATIC_ASSERT(DOM_OBJECT_SLOT == js::JSSLOT_PROXY_PRIVATE,
"JSSLOT_PROXY_PRIVATE doesn't match DOM_OBJECT_SLOT. "
"Expect bad things");
template <class T>
inline T*
UnwrapDOMObject(JSObject* obj, DOMObjectSlot slot)
UnwrapDOMObject(JSObject* obj)
{
MOZ_ASSERT(slot != eNonDOMObject,
MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj)) || IsDOMProxy(obj),
"Don't pass non-DOM objects to this function");
#ifdef DEBUG
if (IsDOMClass(js::GetObjectClass(obj))) {
MOZ_ASSERT(slot == eRegularDOMObject);
} else {
MOZ_ASSERT(IsDOMProxy(obj));
MOZ_ASSERT(slot == eProxyDOMObject);
}
#endif
JS::Value val = js::GetReservedSlot(obj, slot);
JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
// XXXbz/khuey worker code tries to unwrap interface objects (which have
// nothing here). That needs to stop.
// XXX We don't null-check UnwrapObject's result; aren't we going to crash
@ -128,7 +113,6 @@ UnwrapDOMObject(JSObject* obj, DOMObjectSlot slot)
return static_cast<T*>(val.toPrivate());
}
// Only use this with a new DOM binding object (either proxy or regular).
inline const DOMClass*
GetDOMClass(JSObject* obj)
{
@ -137,41 +121,25 @@ GetDOMClass(JSObject* obj)
return &DOMJSClass::FromJSClass(clasp)->mClass;
}
MOZ_ASSERT(IsDOMProxy(obj));
js::BaseProxyHandler* handler = js::GetProxyHandler(obj);
return &static_cast<DOMProxyHandler*>(handler)->mClass;
}
inline DOMObjectSlot
GetDOMClass(JSObject* obj, const DOMClass*& result)
{
js::Class* clasp = js::GetObjectClass(obj);
if (IsDOMClass(clasp)) {
result = &DOMJSClass::FromJSClass(clasp)->mClass;
return eRegularDOMObject;
}
if (js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) {
js::BaseProxyHandler* handler = js::GetProxyHandler(obj);
if (handler->family() == ProxyFamily()) {
result = &static_cast<DOMProxyHandler*>(handler)->mClass;
return eProxyDOMObject;
return &static_cast<DOMProxyHandler*>(handler)->mClass;
}
}
return eNonDOMObject;
return nullptr;
}
inline bool
UnwrapDOMObjectToISupports(JSObject* obj, nsISupports*& result)
{
const DOMClass* clasp;
DOMObjectSlot slot = GetDOMClass(obj, clasp);
if (slot == eNonDOMObject || !clasp->mDOMObjectIsISupports) {
const DOMClass* clasp = GetDOMClass(obj);
if (!clasp || !clasp->mDOMObjectIsISupports) {
return false;
}
result = UnwrapDOMObject<nsISupports>(obj, slot);
result = UnwrapDOMObject<nsISupports>(obj);
return true;
}
@ -191,9 +159,8 @@ MOZ_ALWAYS_INLINE nsresult
UnwrapObject(JSContext* cx, JSObject* obj, U& value)
{
/* First check to see whether we have a DOM object */
const DOMClass* domClass;
DOMObjectSlot slot = GetDOMClass(obj, domClass);
if (slot == eNonDOMObject) {
const DOMClass* domClass = GetDOMClass(obj);
if (!domClass) {
/* Maybe we have a security wrapper or outer window? */
if (!js::IsWrapper(obj)) {
/* Not a DOM object, not a wrapper, just bail */
@ -205,8 +172,8 @@ UnwrapObject(JSContext* cx, JSObject* obj, U& value)
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
}
MOZ_ASSERT(!js::IsWrapper(obj));
slot = GetDOMClass(obj, domClass);
if (slot == eNonDOMObject) {
domClass = GetDOMClass(obj);
if (!domClass) {
/* We don't have a DOM object */
return NS_ERROR_XPC_BAD_CONVERT_JS;
}
@ -217,7 +184,7 @@ UnwrapObject(JSContext* cx, JSObject* obj, U& value)
class identified by protoID. */
if (domClass->mInterfaceChain[PrototypeTraits<PrototypeID>::Depth] ==
PrototypeID) {
value = UnwrapDOMObject<T>(obj, slot);
value = UnwrapDOMObject<T>(obj);
return NS_OK;
}
@ -543,11 +510,10 @@ WrapNewBindingObject(JSContext* cx, JSObject* scope, T* value, JS::Value* vp)
}
#ifdef DEBUG
const DOMClass* clasp = nullptr;
DOMObjectSlot slot = GetDOMClass(obj, clasp);
// slot can be eNonDOMObject if the cache contained a non-DOM object from a
const DOMClass* clasp = GetDOMClass(obj);
// clasp can be null if the cache contained a non-DOM object from a
// different compartment than scope.
if (slot != eNonDOMObject) {
if (clasp) {
// Some sanity asserts about our object. Specifically:
// 1) If our class claims we're nsISupports, we better be nsISupports
// XXXbz ideally, we could assert that reinterpret_cast to nsISupports

View File

@ -749,7 +749,7 @@ class CGAbstractClassHook(CGAbstractStaticMethod):
def definition_body_prologue(self):
return """
%s* self = UnwrapDOMObject<%s>(obj, eRegularDOMObject);
%s* self = UnwrapDOMObject<%s>(obj);
""" % (self.descriptor.nativeType, self.descriptor.nativeType)
def definition_body(self):

View File

@ -67,7 +67,7 @@ DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JSObject* obj)
}
nsWrapperCache* cache;
CallQueryInterface(UnwrapDOMObject<nsISupports>(obj, eProxyDOMObject), &cache);
CallQueryInterface(UnwrapDOMObject<nsISupports>(obj), &cache);
cache->SetPreservingWrapper(true);
js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando));

View File

@ -217,8 +217,7 @@ private:
Finalize(JSFreeOp* aFop, JSObject* aObj)
{
JS_ASSERT(JS_GetClass(aObj) == Class());
WorkerPrivate* worker =
UnwrapDOMObject<WorkerPrivate>(aObj, eRegularDOMObject);
WorkerPrivate* worker = UnwrapDOMObject<WorkerPrivate>(aObj);
if (worker) {
worker->_finalize(aFop);
}
@ -228,8 +227,7 @@ private:
Trace(JSTracer* aTrc, JSObject* aObj)
{
JS_ASSERT(JS_GetClass(aObj) == Class());
WorkerPrivate* worker =
UnwrapDOMObject<WorkerPrivate>(aObj, eRegularDOMObject);
WorkerPrivate* worker = UnwrapDOMObject<WorkerPrivate>(aObj);
if (worker) {
worker->_trace(aTrc);
}
@ -361,7 +359,7 @@ private:
if (aObj) {
JSClass* classPtr = JS_GetClass(aObj);
if (classPtr == Class()) {
return UnwrapDOMObject<WorkerPrivate>(aObj, eRegularDOMObject);
return UnwrapDOMObject<WorkerPrivate>(aObj);
}
}
@ -378,8 +376,7 @@ private:
Finalize(JSFreeOp* aFop, JSObject* aObj)
{
JS_ASSERT(JS_GetClass(aObj) == Class());
WorkerPrivate* worker =
UnwrapDOMObject<WorkerPrivate>(aObj, eRegularDOMObject);
WorkerPrivate* worker = UnwrapDOMObject<WorkerPrivate>(aObj);
if (worker) {
worker->_finalize(aFop);
}
@ -389,8 +386,7 @@ private:
Trace(JSTracer* aTrc, JSObject* aObj)
{
JS_ASSERT(JS_GetClass(aObj) == Class());
WorkerPrivate* worker =
UnwrapDOMObject<WorkerPrivate>(aObj, eRegularDOMObject);
WorkerPrivate* worker = UnwrapDOMObject<WorkerPrivate>(aObj);
if (worker) {
worker->_trace(aTrc);
}
@ -418,7 +414,7 @@ Worker::GetInstancePrivate(JSContext* aCx, JSObject* aObj,
{
JSClass* classPtr = JS_GetClass(aObj);
if (classPtr == Class() || classPtr == ChromeWorker::Class()) {
return UnwrapDOMObject<WorkerPrivate>(aObj, eRegularDOMObject);
return UnwrapDOMObject<WorkerPrivate>(aObj);
}
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,

View File

@ -770,8 +770,7 @@ private:
{
JSClass* classPtr = JS_GetClass(aObj);
if (classPtr == Class()) {
return UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj,
eRegularDOMObject);
return UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj);
}
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
@ -806,7 +805,7 @@ private:
{
JS_ASSERT(JS_GetClass(aObj) == Class());
DedicatedWorkerGlobalScope* scope =
UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj, eRegularDOMObject);
UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj);
if (scope) {
DestroyProtoAndIfaceCache(aObj);
scope->_finalize(aFop);
@ -818,7 +817,7 @@ private:
{
JS_ASSERT(JS_GetClass(aObj) == Class());
DedicatedWorkerGlobalScope* scope =
UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj, eRegularDOMObject);
UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj);
if (scope) {
TraceProtoAndIfaceCache(aTrc, aObj);
scope->_trace(aTrc);
@ -894,7 +893,7 @@ WorkerGlobalScope::GetInstancePrivate(JSContext* aCx, JSObject* aObj,
JS_ASSERT(classPtr != Class());
if (classPtr == DedicatedWorkerGlobalScope::Class()) {
return UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj, eRegularDOMObject);
return UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj);
}
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,

View File

@ -452,10 +452,9 @@ castNativeFromWrapper(JSContext *cx,
lccx->SetWrapper(cur);
}
} else if (cur && protoDepth >= 0) {
const mozilla::dom::DOMClass* domClass;
mozilla::dom::DOMObjectSlot slot =
mozilla::dom::GetDOMClass(cur, domClass);
native = mozilla::dom::UnwrapDOMObject<nsISupports>(cur, slot);
const mozilla::dom::DOMClass* domClass =
mozilla::dom::GetDOMClass(cur);
native = mozilla::dom::UnwrapDOMObject<nsISupports>(cur);
if (native &&
(uint32_t)domClass->mInterfaceChain[protoDepth] != protoID) {
native = nullptr;

View File

@ -335,10 +335,9 @@ SuspectDOMExpandos(nsPtrHashKey<JSObject> *key, void *arg)
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback *>(arg);
JSObject* obj = key->GetKey();
const dom::DOMClass* clasp;
dom::DOMObjectSlot slot = GetDOMClass(obj, clasp);
MOZ_ASSERT(slot != dom::eNonDOMObject && clasp->mDOMObjectIsISupports);
nsISupports* native = dom::UnwrapDOMObject<nsISupports>(obj, slot);
const dom::DOMClass* clasp = dom::GetDOMClass(obj);
MOZ_ASSERT(clasp && clasp->mDOMObjectIsISupports);
nsISupports* native = dom::UnwrapDOMObject<nsISupports>(obj);
cb->NoteXPCOMRoot(native);
return PL_DHASH_NEXT;
}

View File

@ -759,14 +759,13 @@ NoteGCThingXPCOMChildren(js::Class *clasp, JSObject *obj,
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "xpc_GetJSPrivate(obj)");
cb.NoteXPCOMChild(static_cast<nsISupports*>(xpc_GetJSPrivate(obj)));
} else {
const DOMClass* domClass;
DOMObjectSlot slot = GetDOMClass(obj, domClass);
if (slot != eNonDOMObject) {
const DOMClass* domClass = GetDOMClass(obj);
if (domClass) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "UnwrapDOMObject(obj)");
if (domClass->mDOMObjectIsISupports) {
cb.NoteXPCOMChild(UnwrapDOMObject<nsISupports>(obj, slot));
cb.NoteXPCOMChild(UnwrapDOMObject<nsISupports>(obj));
} else if (domClass->mParticipant) {
cb.NoteNativeChild(UnwrapDOMObject<void>(obj, slot),
cb.NoteNativeChild(UnwrapDOMObject<void>(obj),
domClass->mParticipant);
}
}