diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 5fcc4935cdf5..708c18a383c1 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -291,13 +291,17 @@ IsConvertibleToCallbackInterface(JSContext* cx, JS::Handle obj) return IsNotDateOrRegExp(cx, obj); } -// The items in the protoAndIfaceCache are indexed by the prototypes::id::ID and -// constructors::id::ID enums, in that order. The end of the prototype objects -// should be the start of the interface objects. +// The items in the protoAndIfaceCache are indexed by the prototypes::id::ID, +// constructors::id::ID and namedpropertiesobjects::id::ID enums, in that order. +// The end of the prototype objects should be the start of the interface +// objects, and the end of the interface objects should be the start of the +// named properties objects. static_assert((size_t)constructors::id::_ID_Start == - (size_t)prototypes::id::_ID_Count, + (size_t)prototypes::id::_ID_Count && + (size_t)namedpropertiesobjects::id::_ID_Start == + (size_t)constructors::id::_ID_Count, "Overlapping or discontiguous indexes."); -const size_t kProtoAndIfaceCacheCount = constructors::id::_ID_Count; +const size_t kProtoAndIfaceCacheCount = namedpropertiesobjects::id::_ID_Count; class ProtoAndIfaceCache { diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 60e40f31d5df..686a47347e62 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -2581,8 +2581,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): def definition_body(self): parentProtoName = self.descriptor.parentPrototypeName if self.descriptor.hasNamedPropertiesObject: - parentProtoType = "Rooted" - getParentProto = "aCx, GetNamedPropertiesObject(aCx, aGlobal)" + parentProtoType = "Handle" + getParentProto = "GetNamedPropertiesObject(aCx, aGlobal)" elif parentProtoName is None: parentProtoType = "Rooted" if self.descriptor.interface.getExtendedAttribute("ArrayClass"): @@ -2856,7 +2856,7 @@ class CGGetNamedPropertiesObjectMethod(CGAbstractStaticMethod): Argument('JS::Handle', 'aGlobal')] CGAbstractStaticMethod.__init__(self, descriptor, 'GetNamedPropertiesObject', - 'JSObject*', args) + 'JS::Handle', args) def definition_body(self): parentProtoName = self.descriptor.parentPrototypeName @@ -2868,17 +2868,30 @@ class CGGetNamedPropertiesObjectMethod(CGAbstractStaticMethod): """ JS::Rooted parentProto(aCx, ${parent}::GetProtoObject(aCx, aGlobal)); if (!parentProto) { - return nullptr; + return js::NullPtr(); } """, parent=toBindingNamespace(parentProtoName)) parentProto = "parentProto" return fill( """ - $*{getParentProto} - return ${nativeType}::CreateNamedPropertiesObject(aCx, ${parentProto}); + /* Make sure our global is sane. Hopefully we can remove this sometime */ + if (!(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL)) { + return JS::NullPtr(); + } + + /* Check to see whether the named properties object has already been created */ + ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(aGlobal); + + JS::Heap& namedPropertiesObject = protoAndIfaceCache.EntrySlotOrCreate(namedpropertiesobjects::id::${ifaceName}); + if (!namedPropertiesObject) { + $*{getParentProto} + namedPropertiesObject = ${nativeType}::CreateNamedPropertiesObject(aCx, ${parentProto}); + } + return JS::Handle::fromMarkedLocation(namedPropertiesObject.address()); """, getParentProto=getParentProto, + ifaceName=self.descriptor.name, parentProto=parentProto, nativeType=self.descriptor.nativeType) @@ -14209,6 +14222,18 @@ class GlobalGenRoots(): curr.append(idEnum) + # Named properties object enum. + namedPropertiesObjects = [d.name for d in config.getDescriptors(hasNamedPropertiesObject=True)] + idEnum = CGNamespacedEnum('id', 'ID', ['_ID_Start'] + namedPropertiesObjects, + ['constructors::id::_ID_Count', '_ID_Start']) + + # Wrap all of that in our namespaces. + idEnum = CGNamespace.build(['mozilla', 'dom', 'namedpropertiesobjects'], + CGWrapper(idEnum, pre='\n')) + idEnum = CGWrapper(idEnum, post='\n') + + curr.append(idEnum) + traitsDecls = [CGGeneric(declare=dedent(""" template struct PrototypeTraits;