From 4804da54ff217e06726c2580ab031faed4955ef3 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Sat, 15 Feb 2014 22:12:34 +0100 Subject: [PATCH] Bug 1005898 - Make WebIDL properties on all globals own properties. r=bz. --HG-- extra : rebase_source : 3eb201d073b090b2627814264a126a1a4281207f --- dom/base/nsDOMClassInfo.cpp | 13 +++++-- dom/bindings/BindingUtils.cpp | 58 +++++++++++++++++++----------- dom/bindings/BindingUtils.h | 35 ++++++++++++++++-- dom/bindings/Codegen.py | 27 +++++++++++--- js/xpconnect/src/XPCQuickStubs.cpp | 4 +-- 5 files changed, 106 insertions(+), 31 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 94f629ff9ee9..c1fcffc06973 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -1813,8 +1813,17 @@ nsWindowSH::PostCreate(nsIXPConnectWrappedNative *wrapper, const NativeProperties* eventTargetProperties = EventTargetBinding::sNativePropertyHooks->mNativeProperties.regular; - return DefineWebIDLBindingPropertiesOnXPCObject(cx, window, windowProperties, true) && - DefineWebIDLBindingPropertiesOnXPCObject(cx, window, eventTargetProperties, true) ? + if (!DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(cx, window, windowProperties) || + !DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(cx, window, eventTargetProperties)) { + return NS_ERROR_FAILURE; + } + + if (!GlobalPropertiesAreOwn()) { + return NS_OK; + } + + return DefineWebIDLBindingPropertiesOnXPCObject(cx, window, windowProperties) && + DefineWebIDLBindingPropertiesOnXPCObject(cx, window, eventTargetProperties) ? NS_OK : NS_ERROR_FAILURE; } diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index bf9edb95e27e..c28d59fe8903 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -543,11 +543,23 @@ CreateInterfaceObject(JSContext* cx, JS::Handle global, return constructor; } +bool +DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(JSContext* cx, + JS::Handle obj, + const NativeProperties* properties) +{ + if (properties->unforgeableAttributes && + !DefinePrefable(cx, obj, properties->unforgeableAttributes)) { + return false; + } + + return true; +} + bool DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx, JS::Handle obj, - const NativeProperties* properties, - bool defineUnforgeableAttributes) + const NativeProperties* properties) { if (properties->methods && !DefinePrefable(cx, obj, properties->methods)) { @@ -559,11 +571,6 @@ DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx, return false; } - if (defineUnforgeableAttributes && properties->unforgeableAttributes && - !DefinePrefable(cx, obj, properties->unforgeableAttributes)) { - return false; - } - return true; } @@ -576,45 +583,54 @@ CreateInterfacePrototypeObject(JSContext* cx, JS::Handle global, { JS::Rooted ourProto(cx, JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global)); - if (!ourProto) { + if (!ourProto || + !DefineProperties(cx, ourProto, properties, chromeOnlyProperties)) { return nullptr; } + return ourProto; +} + +bool +DefineProperties(JSContext* cx, JS::Handle obj, + const NativeProperties* properties, + const NativeProperties* chromeOnlyProperties) +{ if (properties) { if (properties->methods && - !DefinePrefable(cx, ourProto, properties->methods)) { - return nullptr; + !DefinePrefable(cx, obj, properties->methods)) { + return false; } if (properties->attributes && - !DefinePrefable(cx, ourProto, properties->attributes)) { - return nullptr; + !DefinePrefable(cx, obj, properties->attributes)) { + return false; } if (properties->constants && - !DefinePrefable(cx, ourProto, properties->constants)) { - return nullptr; + !DefinePrefable(cx, obj, properties->constants)) { + return false; } } if (chromeOnlyProperties) { if (chromeOnlyProperties->methods && - !DefinePrefable(cx, ourProto, chromeOnlyProperties->methods)) { - return nullptr; + !DefinePrefable(cx, obj, chromeOnlyProperties->methods)) { + return false; } if (chromeOnlyProperties->attributes && - !DefinePrefable(cx, ourProto, chromeOnlyProperties->attributes)) { - return nullptr; + !DefinePrefable(cx, obj, chromeOnlyProperties->attributes)) { + return false; } if (chromeOnlyProperties->constants && - !DefinePrefable(cx, ourProto, chromeOnlyProperties->constants)) { - return nullptr; + !DefinePrefable(cx, obj, chromeOnlyProperties->constants)) { + return false; } } - return ourProto; + return true; } void diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 97db5fa44fc7..216d297672bb 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -581,6 +581,24 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle global, const NativeProperties* chromeOnlyProperties, const char* name, bool defineOnGlobal); +/** + * Define the properties (regular and chrome-only) on obj. + * + * obj the object to instal the properties on. This should be the interface + * prototype object for regular interfaces and the instance object for + * interfaces marked with Global. + * properties contains the methods, attributes and constants to be defined on + * objects in any compartment. + * chromeProperties contains the methods, attributes and constants to be defined + * on objects in chrome compartments. This must be null if the + * interface doesn't have any ChromeOnly properties or if the + * object is being created in non-chrome compartment. + */ +bool +DefineProperties(JSContext* cx, JS::Handle obj, + const NativeProperties* properties, + const NativeProperties* chromeOnlyProperties); + /* * Define the unforgeable attributes on an object. */ @@ -588,11 +606,15 @@ bool DefineUnforgeableAttributes(JSContext* cx, JS::Handle obj, const Prefable* props); +bool +DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(JSContext* cx, + JS::Handle obj, + const NativeProperties* properties); + bool DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx, JS::Handle obj, - const NativeProperties* properties, - bool defineUnforgeableAttributes); + const NativeProperties* properties); #ifdef _MSC_VER #define HAS_MEMBER_CHECK(_name) \ @@ -2661,6 +2683,15 @@ ConvertExceptionToPromise(JSContext* cx, JSObject* promiseScope, JS::MutableHandle rval); +// While we wait for the outcome of spec discussions on whether properties for +// DOM global objects live on the object or the prototype, we supply this one +// place to switch the behaviour, so we can easily turn this off on branches. +inline bool +GlobalPropertiesAreOwn() +{ + return true; +} + } // namespace dom } // namespace mozilla diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 71838a27aedc..e12671238e35 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -2482,13 +2482,17 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): else: domClass = "nullptr" - if self.properties.hasNonChromeOnly(): + isGlobal = self.descriptor.interface.getExtendedAttribute("Global") is not None + if not isGlobal and self.properties.hasNonChromeOnly(): properties = "&sNativeProperties" + elif self.properties.hasNonChromeOnly(): + properties = "!GlobalPropertiesAreOwn() ? &sNativeProperties : nullptr" else: properties = "nullptr" - if self.properties.hasChromeOnly(): - accessCheck = "nsContentUtils::ThreadsafeIsCallerChrome()" - chromeProperties = accessCheck + " ? &sChromeOnlyNativeProperties : nullptr" + if not isGlobal and self.properties.hasChromeOnly(): + chromeProperties = "nsContentUtils::ThreadsafeIsCallerChrome() ? &sChromeOnlyNativeProperties : nullptr" + elif self.properties.hasChromeOnly(): + chromeProperties = "!GlobalPropertiesAreOwn() && nsContentUtils::ThreadsafeIsCallerChrome() ? &sChromeOnlyNativeProperties : nullptr" else: chromeProperties = "nullptr" @@ -2963,6 +2967,15 @@ class CGWrapGlobalMethod(CGAbstractMethod): self.properties = properties def definition_body(self): + if self.properties.hasNonChromeOnly(): + properties = "GlobalPropertiesAreOwn() ? &sNativeProperties : nullptr" + else: + properties = "nullptr" + if self.properties.hasChromeOnly(): + chromeProperties = "GlobalPropertiesAreOwn() && nsContentUtils::ThreadsafeIsCallerChrome() ? &sChromeOnlyNativeProperties : nullptr" + else: + chromeProperties = "nullptr" + return fill( """ ${assertions} @@ -2980,6 +2993,10 @@ class CGWrapGlobalMethod(CGAbstractMethod): // obj is a new global, so has a new compartment. Enter it // before doing anything with it. JSAutoCompartment ac(aCx, obj); + + if (!DefineProperties(aCx, obj, ${properties}, ${chromeProperties})) { + return nullptr; + } $*{unforgeable} $*{slots} @@ -2991,6 +3008,8 @@ class CGWrapGlobalMethod(CGAbstractMethod): """, assertions=AssertInheritanceChain(self.descriptor), nativeType=self.descriptor.nativeType, + properties=properties, + chromeProperties=chromeProperties, unforgeable=InitUnforgeableProperties(self.descriptor, self.properties), slots=InitMemberSlots(self.descriptor, True)) diff --git a/js/xpconnect/src/XPCQuickStubs.cpp b/js/xpconnect/src/XPCQuickStubs.cpp index a6981dfcbb13..419ad34c7a1c 100644 --- a/js/xpconnect/src/XPCQuickStubs.cpp +++ b/js/xpconnect/src/XPCQuickStubs.cpp @@ -143,11 +143,11 @@ xpc_qsDefineQuickStubs(JSContext *cx, JSObject *protoArg, unsigned flags, if (entry->newBindingProperties) { if (entry->newBindingProperties->regular) { - mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx, proto, entry->newBindingProperties->regular, false); + mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx, proto, entry->newBindingProperties->regular); } if (entry->newBindingProperties->chromeOnly && xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) { - mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx, proto, entry->newBindingProperties->chromeOnly, false); + mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx, proto, entry->newBindingProperties->chromeOnly); } } // Next.