From cb66e04e698846faad3c085818ccc18b1b446b8a Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Wed, 6 Jun 2012 21:52:26 +0200 Subject: [PATCH] Fix for bug 785188 (Make Xrays work with newest DOM list bindings). r=mrbkap. --- dom/bindings/Codegen.py | 49 ++++++++++++++++++++++-- dom/bindings/DOMJSClass.h | 5 ++- dom/workers/Worker.cpp | 7 +++- js/xpconnect/wrappers/WrapperFactory.cpp | 14 +++---- js/xpconnect/wrappers/XrayWrapper.cpp | 33 +++++++++++----- 5 files changed, 86 insertions(+), 22 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 1fa399f1ebb1..88588f7974be 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -72,12 +72,17 @@ class CGNativePropertyHooks(CGThing): def define(self): if self.descriptor.workers: return "" + if self.descriptor.concrete and self.descriptor.proxy: + resolveOwnProperty = "ResolveOwnProperty" + enumerateOwnProperties = "EnumerateOwnProperties" + else: + enumerateOwnProperties = resolveOwnProperty = "NULL" parent = self.descriptor.interface.parent parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::NativeHooks" if parent else 'NULL') return """ -const NativePropertyHooks NativeHooks = { ResolveProperty, EnumerateProperties, %s }; -""" % parentHooks +const NativePropertyHooks NativeHooks = { %s, ResolveProperty, %s, EnumerateProperties, %s }; +""" % (resolveOwnProperty, enumerateOwnProperties, parentHooks) def DOMClass(descriptor): protoList = ['prototypes::id::' + proto for proto in descriptor.prototypeChain] @@ -4202,6 +4207,37 @@ class CGClass(CGThing): result = result + memberString return result +class CGResolveOwnProperty(CGAbstractMethod): + def __init__(self, descriptor): + args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'), + Argument('jsid', 'id'), Argument('bool', 'set'), + Argument('JSPropertyDescriptor*', 'desc')] + CGAbstractMethod.__init__(self, descriptor, "ResolveOwnProperty", "bool", args) + def definition_body(self): + return """ JSObject* obj = wrapper; + if (xpc::WrapperFactory::IsXrayWrapper(obj)) { + obj = js::UnwrapObject(obj); + } + // We rely on getOwnPropertyDescriptor not shadowing prototype properties by named + // properties. If that changes we'll need to filter here. + return js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, wrapper, id, set, desc); +""" + +class CGEnumerateOwnProperties(CGAbstractMethod): + def __init__(self, descriptor): + args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'), + Argument('JS::AutoIdVector&', 'props')] + CGAbstractMethod.__init__(self, descriptor, "EnumerateOwnProperties", "bool", args) + def definition_body(self): + return """ JSObject* obj = wrapper; + if (xpc::WrapperFactory::IsXrayWrapper(obj)) { + obj = js::UnwrapObject(obj); + } + // We rely on getOwnPropertyNames not shadowing prototype properties by named + // properties. If that changes we'll need to filter here. + return js::GetProxyHandler(obj)->getOwnPropertyNames(cx, wrapper, props); +""" + class CGXrayHelper(CGAbstractMethod): def __init__(self, descriptor, name, args, properties): CGAbstractMethod.__init__(self, descriptor, name, "bool", args) @@ -4256,7 +4292,8 @@ class CGResolveProperty(CGXrayHelper): class CGEnumerateProperties(CGXrayHelper): def __init__(self, descriptor, properties): - args = [Argument('JS::AutoIdVector&', 'props')] + args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'), + Argument('JS::AutoIdVector&', 'props')] CGXrayHelper.__init__(self, descriptor, "EnumerateProperties", args, properties) @@ -4478,6 +4515,9 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod): fillDescriptor = "FillPropertyDescriptor(desc, proxy, %s);\nreturn true;" % readonly templateValues = {'jsvalRef': 'desc->value', 'jsvalPtr': '&desc->value', 'obj': 'proxy', 'successCode': fillDescriptor} + # Once we start supporting OverrideBuiltins we need to make + # ResolveOwnProperty or EnumerateOwnProperties filter out named + # properties that shadow prototype properties. namedGet = ("\n" + "if (!set && JSID_IS_STRING(id) && !HasPropertyOnPrototype(cx, proxy, this, id)) {\n" + " JS::Value nameVal = STRING_TO_JSVAL(JSID_TO_STRING(id));\n" + @@ -4887,6 +4927,9 @@ class CGDescriptor(CGThing): # it in workers. if (descriptor.interface.hasInterfacePrototypeObject() and not descriptor.workers): + if descriptor.concrete and descriptor.proxy: + cgThings.append(CGResolveOwnProperty(descriptor)) + cgThings.append(CGEnumerateOwnProperties(descriptor)) cgThings.append(CGResolveProperty(descriptor, properties)) cgThings.append(CGEnumerateProperties(descriptor, properties)) diff --git a/dom/bindings/DOMJSClass.h b/dom/bindings/DOMJSClass.h index bbbf54732c9d..8b1a3f81e4e5 100644 --- a/dom/bindings/DOMJSClass.h +++ b/dom/bindings/DOMJSClass.h @@ -35,11 +35,14 @@ typedef bool (* ResolveProperty)(JSContext* cx, JSObject* wrapper, jsid id, bool set, JSPropertyDescriptor* desc); typedef bool -(* EnumerateProperties)(JS::AutoIdVector& props); +(* EnumerateProperties)(JSContext* cx, JSObject* wrapper, + JS::AutoIdVector& props); struct NativePropertyHooks { + ResolveProperty mResolveOwnProperty; ResolveProperty mResolveProperty; + EnumerateProperties mEnumerateOwnProperties; EnumerateProperties mEnumerateProperties; const NativePropertyHooks *mProtoHooks; diff --git a/dom/workers/Worker.cpp b/dom/workers/Worker.cpp index 5f434cfe9099..b090438f9fbe 100644 --- a/dom/workers/Worker.cpp +++ b/dom/workers/Worker.cpp @@ -33,12 +33,15 @@ WorkerResolveProperty(JSContext* cx, JSObject* wrapper, jsid id, bool set, return true; } bool -WorkerEnumerateProperties(JS::AutoIdVector& props) +WorkerEnumerateProperties(JSContext* cx, JSObject* wrapper, + JS::AutoIdVector& props) { return true; } NativePropertyHooks mozilla::dom::workers::sNativePropertyHooks = - { WorkerResolveProperty, WorkerEnumerateProperties, NULL }; + { WorkerResolveProperty, WorkerResolveProperty, + WorkerEnumerateProperties, WorkerEnumerateProperties, + NULL }; namespace { diff --git a/js/xpconnect/wrappers/WrapperFactory.cpp b/js/xpconnect/wrappers/WrapperFactory.cpp index 824f3725aa32..4d5a20ca3f76 100644 --- a/js/xpconnect/wrappers/WrapperFactory.cpp +++ b/js/xpconnect/wrappers/WrapperFactory.cpp @@ -290,13 +290,13 @@ enum XrayType { static XrayType GetXrayType(JSObject *obj) { - js::Class* clasp = js::GetObjectClass(obj); - if (mozilla::dom::IsDOMClass(Jsvalify(clasp))) { + if (mozilla::dom::IsDOMObject(obj)) return XrayForDOMObject; - } - if (mozilla::dom::oldproxybindings::instanceIsProxy(obj)) { + + if (mozilla::dom::oldproxybindings::instanceIsProxy(obj)) return XrayForDOMProxyObject; - } + + js::Class* clasp = js::GetObjectClass(obj); if (IS_WRAPPER_CLASS(clasp) || clasp->ext.innerObject) { NS_ASSERTION(clasp->ext.innerObject || IS_WN_WRAPPER_OBJECT(obj), "We forgot to Morph a slim wrapper!"); @@ -368,10 +368,10 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO wrapper = &FilteringWrapper::singleton; else wrapper = &FilteringWrapper::singleton; + } else if (mozilla::dom::IsDOMObject(obj)) { + wrapper = &FilteringWrapper::singleton; } else if (mozilla::dom::oldproxybindings::instanceIsProxy(obj)) { wrapper = &FilteringWrapper::singleton; - } else if (mozilla::dom::IsDOMClass(JS_GetClass(obj))) { - wrapper = &FilteringWrapper::singleton; } else if (IsComponentsObject(obj)) { wrapper = &FilteringWrapper::singleton; diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index 4b3b6e0f2048..d55f58e0374c 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -1036,12 +1036,13 @@ DOMXrayTraits::resolveNativeProperty(JSContext *cx, JSObject *wrapper, JSObject bool set, JSPropertyDescriptor *desc) { JSObject *obj = getInnerObject(wrapper); - const NativePropertyHooks *nativeHooks = - DOMJSClass::FromJSClass(JS_GetClass(obj))->mClass.mNativeHooks; + const NativePropertyHooks *nativeHooks = GetDOMClass(obj)->mNativeHooks; do { - if (nativeHooks->mResolveProperty(cx, wrapper, id, set, desc) && - desc->obj) { + if (!nativeHooks->mResolveProperty(cx, wrapper, id, set, desc)) + return false; + + if (desc->obj) { NS_ASSERTION(desc->obj == wrapper, "What did we resolve this on?"); return true; } @@ -1054,6 +1055,17 @@ bool DOMXrayTraits::resolveOwnProperty(JSContext *cx, js::Wrapper &jsWrapper, JSObject *wrapper, JSObject *holder, jsid id, bool set, JSPropertyDescriptor *desc) { + JSObject *obj = getInnerObject(wrapper); + const NativePropertyHooks *nativeHooks = GetDOMClass(obj)->mNativeHooks; + + if (nativeHooks->mResolveOwnProperty) { + if (!nativeHooks->mResolveOwnProperty(cx, wrapper, id, set, desc)) + return false; + + NS_ASSERTION(!desc->obj || desc->obj == wrapper, + "What did we resolve this on?"); + } + return true; } @@ -1082,16 +1094,19 @@ bool DOMXrayTraits::enumerateNames(JSContext *cx, JSObject *wrapper, unsigned flags, JS::AutoIdVector &props) { + JSObject *obj = getInnerObject(wrapper); + const NativePropertyHooks *nativeHooks = GetDOMClass(obj)->mNativeHooks; + + if (nativeHooks->mEnumerateOwnProperties && + !nativeHooks->mEnumerateOwnProperties(cx, wrapper, props)) + return false; + if (flags & (JSITER_OWNONLY | JSITER_HIDDEN)) // Probably need to return expandos on the Xray here! return true; - JSObject *obj = getInnerObject(wrapper); - const NativePropertyHooks *nativeHooks = - DOMJSClass::FromJSClass(JS_GetClass(obj))->mClass.mNativeHooks; - do { - if (!nativeHooks->mEnumerateProperties(props)) { + if (!nativeHooks->mEnumerateProperties(cx, wrapper, props)) { return false; } } while ((nativeHooks = nativeHooks->mProtoHooks));