From 9f982e86a6f17050ba19059fad52053b89757b72 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Fri, 5 Oct 2012 18:59:23 +0200 Subject: [PATCH] Bug 761695 - Implement expando traps for ProxyXrayTraits DOMXrayTraits. r=peterv For new DOM proxies, we could probably use the Xray expando machinery for the regular expando object as well, and free up one of the reserved slots. That's more than I want to bite off for the moment, though. I also decided not to block on bug 760095 and just kick the problem of globals with new binding down the road a little bit. --- dom/bindings/BindingUtils.cpp | 21 +++++++++++++++++++++ dom/bindings/BindingUtils.h | 5 +++++ dom/bindings/Codegen.py | 4 +++- dom/bindings/DOMJSClass.h | 5 +++++ dom/bindings/DOMJSProxyHandler.h | 3 ++- dom/workers/Worker.cpp | 4 ++-- dom/workers/WorkerScope.cpp | 2 ++ js/xpconnect/src/dombindings.cpp | 16 +++++++++++++++- js/xpconnect/src/dombindings.h | 3 +++ js/xpconnect/wrappers/XrayWrapper.cpp | 11 +++++------ 10 files changed, 63 insertions(+), 11 deletions(-) diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 27ac92e3596..10f92f4f292 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -629,5 +629,26 @@ HasPropertyOnPrototype(JSContext* cx, JSObject* proxy, DOMProxyHandler* handler, return !GetPropertyOnPrototype(cx, proxy, id, &found, NULL) || found; } +JSObject* +GetXrayExpandoChain(JSObject* obj) +{ + MOZ_ASSERT(IsDOMObject(obj)); + JS::Value v = IsDOMProxy(obj) ? js::GetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO) + : js::GetReservedSlot(obj, DOM_XRAY_EXPANDO_SLOT); + return v.isUndefined() ? nullptr : &v.toObject(); +} + +void +SetXrayExpandoChain(JSObject* obj, JSObject* chain) +{ + MOZ_ASSERT(IsDOMObject(obj)); + JS::Value v = chain ? JS::ObjectValue(*chain) : JSVAL_VOID; + if (IsDOMProxy(obj)) { + js::SetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO, v); + } else { + js::SetReservedSlot(obj, DOM_XRAY_EXPANDO_SLOT, v); + } +} + } // namespace dom } // namespace mozilla diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index ad6a061603d..eb718f9f5b8 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -1167,6 +1167,11 @@ MustInheritFromNonRefcountedDOMObject(NonRefcountedDOMObject*) { } +// Set the chain of expando objects for various consumers of the given object. +// For Paris Bindings only. See the relevant infrastructure in XrayWrapper.cpp. +JSObject* GetXrayExpandoChain(JSObject *obj); +void SetXrayExpandoChain(JSObject *obj, JSObject *chain); + } // namespace dom } // namespace mozilla diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 75e684e75ff..f845bf8d5f4 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -106,6 +106,8 @@ class CGDOMJSClass(CGThing): def __init__(self, descriptor): CGThing.__init__(self) self.descriptor = descriptor + # Our current reserved slot situation is unsafe for globals. Fix bug 760095! + assert "Window" not in descriptor.interface.identifier.name def declare(self): return "extern DOMJSClass Class;\n" def define(self): @@ -113,7 +115,7 @@ class CGDOMJSClass(CGThing): return """ DOMJSClass Class = { { "%s", - JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1), + JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2), %s, /* addProperty */ JS_PropertyStub, /* delProperty */ JS_PropertyStub, /* getProperty */ diff --git a/dom/bindings/DOMJSClass.h b/dom/bindings/DOMJSClass.h index 151960b5901..b59787a5ca4 100644 --- a/dom/bindings/DOMJSClass.h +++ b/dom/bindings/DOMJSClass.h @@ -15,6 +15,11 @@ // globals and non-globals. #define DOM_OBJECT_SLOT 0 +// We use slot 1 for holding the expando object. This is not safe for globals +// until bug 760095 is fixed, so that bug blocks converting Window to new +// bindings. +#define DOM_XRAY_EXPANDO_SLOT 1 + // All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. We have to // start at 1 past JSCLASS_GLOBAL_SLOT_COUNT because XPConnect uses // that one. diff --git a/dom/bindings/DOMJSProxyHandler.h b/dom/bindings/DOMJSProxyHandler.h index 394e2dc4d2f..d575a4a4505 100644 --- a/dom/bindings/DOMJSProxyHandler.h +++ b/dom/bindings/DOMJSProxyHandler.h @@ -19,7 +19,8 @@ namespace mozilla { namespace dom { enum { - JSPROXYSLOT_EXPANDO = 0 + JSPROXYSLOT_EXPANDO = 0, + JSPROXYSLOT_XRAY_EXPANDO }; template struct Prefable; diff --git a/dom/workers/Worker.cpp b/dom/workers/Worker.cpp index befac26429a..0fcdfcf2f7d 100644 --- a/dom/workers/Worker.cpp +++ b/dom/workers/Worker.cpp @@ -304,7 +304,7 @@ MOZ_STATIC_ASSERT(prototypes::MaxProtoChainLength == 3, DOMJSClass Worker::sClass = { { "Worker", - JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1) | + JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IMPLEMENTS_BARRIERS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize, @@ -429,7 +429,7 @@ MOZ_STATIC_ASSERT(prototypes::MaxProtoChainLength == 3, // sNativePropertyHooks then sNativePropertyHooks should be removed too. DOMJSClass ChromeWorker::sClass = { { "ChromeWorker", - JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1) | + JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IMPLEMENTS_BARRIERS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize, diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 6c27b3edb7d..d28490ffbfa 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -856,6 +856,8 @@ MOZ_STATIC_ASSERT(prototypes::MaxProtoChainLength == 3, // sNativePropertyHooks then sNativePropertyHooks should be removed too. DOMJSClass DedicatedWorkerGlobalScope::sClass = { { + // We don't have to worry about Xray expando slots here because we'll never + // have an Xray wrapper to a worker global scope. "DedicatedWorkerGlobalScope", JSCLASS_DOM_GLOBAL | JSCLASS_IS_DOMJSCLASS | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(3) | JSCLASS_NEW_RESOLVE, diff --git a/js/xpconnect/src/dombindings.cpp b/js/xpconnect/src/dombindings.cpp index 610c53e25e9..4ca44c53284 100644 --- a/js/xpconnect/src/dombindings.cpp +++ b/js/xpconnect/src/dombindings.cpp @@ -28,7 +28,8 @@ namespace dom { namespace oldproxybindings { enum { - JSPROXYSLOT_EXPANDO = 0 + JSPROXYSLOT_EXPANDO = 0, + JSPROXYSLOT_XRAY_EXPANDO }; static jsid s_prototype_id = JSID_VOID; @@ -1013,6 +1014,19 @@ NoBase::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, JSObject *rece return JS_GetObjectPrototype(cx, receiver); } +JSObject* +GetXrayExpandoChain(JSObject *obj) { + MOZ_ASSERT(instanceIsProxy(obj)); + js::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO); + return v.isUndefined() ? nullptr : &v.toObject(); +} + +void +SetXrayExpandoChain(JSObject *obj, JSObject *chain) { + MOZ_ASSERT(instanceIsProxy(obj)); + js::Value v = chain ? JS::ObjectValue(*chain) : JSVAL_VOID; + js::SetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO, v); +} } } diff --git a/js/xpconnect/src/dombindings.h b/js/xpconnect/src/dombindings.h index 70e04deb230..38e074e78f3 100644 --- a/js/xpconnect/src/dombindings.h +++ b/js/xpconnect/src/dombindings.h @@ -213,6 +213,9 @@ struct nsISupportsResult nsWrapperCache *mCache; }; +JSObject* GetXrayExpandoChain(JSObject *obj); +void SetXrayExpandoChain(JSObject *obj, JSObject *chain); + } } } diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index 7645967a306..a7df215dfe9 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -22,6 +22,7 @@ #include "nsJSUtils.h" #include "mozilla/dom/BindingUtils.h" +#include "dombindings.h" using namespace mozilla::dom; @@ -238,11 +239,10 @@ public: virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper); virtual JSObject* getExpandoChain(JSObject *obj) { - MOZ_NOT_REACHED("Expando chain not yet implemented for non-WN objects"); - return NULL; + return mozilla::dom::oldproxybindings::GetXrayExpandoChain(obj); } virtual void setExpandoChain(JSObject *obj, JSObject *chain) { - MOZ_NOT_REACHED("Expando chain not yet implemented for non-WN objects"); + mozilla::dom::oldproxybindings::SetXrayExpandoChain(obj, chain); } static ProxyXrayTraits singleton; @@ -274,11 +274,10 @@ public: virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper); virtual JSObject* getExpandoChain(JSObject *obj) { - MOZ_NOT_REACHED("Expando chain not yet implemented for non-WN objects"); - return NULL; + return mozilla::dom::GetXrayExpandoChain(obj); } virtual void setExpandoChain(JSObject *obj, JSObject *chain) { - MOZ_NOT_REACHED("Expando chain not yet implemented for non-WN objects"); + mozilla::dom::SetXrayExpandoChain(obj, chain); } static DOMXrayTraits singleton;