diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index bf21e3ebbb52..1a13488f795d 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -78,9 +78,7 @@ def idlTypeNeedsCycleCollection(type): def wantsAddProperty(desc): - return (desc.concrete and - desc.wrapperCache and - not desc.interface.getExtendedAttribute("Global")) + return (desc.concrete and desc.wrapperCache and not desc.isGlobal()) # We'll want to insert the indent at the beginnings of lines, but we @@ -372,7 +370,7 @@ class CGDOMJSClass(CGThing): JS_NULL_CLASS_EXT, JS_NULL_OBJECT_OPS """ - if self.descriptor.interface.getExtendedAttribute("Global"): + if self.descriptor.isGlobal(): classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS) | JSCLASS_IMPLEMENTS_BARRIERS" traceHook = "JS_GlobalObjectTraceHook" reservedSlots = "JSCLASS_GLOBAL_APPLICATION_SLOTS" @@ -415,7 +413,7 @@ JS_NULL_OBJECT_OPS newResolveHook = "(JSResolveOp)" + NEWRESOLVE_HOOK_NAME classFlags += " | JSCLASS_NEW_RESOLVE" enumerateHook = ENUMERATE_HOOK_NAME - elif self.descriptor.interface.getExtendedAttribute("Global"): + elif self.descriptor.isGlobal(): newResolveHook = "(JSResolveOp) mozilla::dom::ResolveGlobal" classFlags += " | JSCLASS_NEW_RESOLVE" enumerateHook = "mozilla::dom::EnumerateGlobal" @@ -1521,7 +1519,7 @@ def finalizeHook(descriptor, hookName, freeOp): finalize += "ClearWrapper(self, self);\n" if descriptor.interface.getExtendedAttribute('OverrideBuiltins'): finalize += "self->mExpandoAndGeneration.expando = JS::UndefinedValue();\n" - if descriptor.interface.getExtendedAttribute("Global"): + if descriptor.isGlobal(): finalize += "mozilla::dom::FinalizeGlobal(CastToJSFreeOp(%s), obj);\n" % freeOp finalize += ("AddForDeferredFinalization<%s, %s >(self);\n" % (descriptor.nativeType, DeferredFinalizeSmartPtr(descriptor))) @@ -2599,7 +2597,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): interfaceClass = "nullptr" interfaceCache = "nullptr" - isGlobal = self.descriptor.interface.getExtendedAttribute("Global") is not None + isGlobal = self.descriptor.isGlobal() is not None if not isGlobal and self.properties.hasNonChromeOnly(): properties = "&sNativeProperties" elif self.properties.hasNonChromeOnly(): @@ -7323,7 +7321,7 @@ class CGNewResolveHook(CGAbstractBindingMethod): """)) def definition_body(self): - if self.descriptor.interface.getExtendedAttribute("Global"): + if self.descriptor.isGlobal(): # Resolve standard classes prefix = dedent(""" if (!ResolveGlobal(cx, obj, id, objp)) { @@ -7372,7 +7370,7 @@ class CGEnumerateHook(CGAbstractBindingMethod): """)) def definition_body(self): - if self.descriptor.interface.getExtendedAttribute("Global"): + if self.descriptor.isGlobal(): # Enumerate standard classes prefix = dedent(""" if (!EnumerateGlobal(cx, obj)) { @@ -10666,7 +10664,7 @@ class CGDescriptor(CGThing): if descriptor.interface.hasMembersInSlots(): cgThings.append(CGUpdateMemberSlotsMethod(descriptor)) - if descriptor.interface.getExtendedAttribute("Global"): + if descriptor.isGlobal(): assert descriptor.wrapperCache cgThings.append(CGWrapGlobalMethod(descriptor, properties)) elif descriptor.wrapperCache: diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index 6fca0b42d28c..20364185b578 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -563,6 +563,14 @@ class Descriptor(DescriptorProvider): """ return self.hasXPConnectImpls or self.interface.isOnGlobalProtoChain() + def isGlobal(self): + """ + Returns true if this is the primary interface for a global object + of some sort. + """ + return (self.interface.getExtendedAttribute("Global") or + self.interface.getExtendedAttribute("PrimaryGlobal")) + # Some utility methods def getTypesFromDescriptor(descriptor): """ diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index 3ff018ea080b..c48f8df06bd5 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -224,6 +224,8 @@ class IDLScope(IDLObject): # A mapping from global name to the set of global interfaces # that have that global name. self.globalNameMapping = defaultdict(set) + self.primaryGlobalAttr = None + self.primaryGlobalName = None def __str__(self): return self.QName() @@ -643,8 +645,10 @@ class IDLInterface(IDLObjectWithScope): self.totalMembersInSlots = self.parent.totalMembersInSlots - # Interfaces with [Global] must not have anything inherit from them - if self.parent.getExtendedAttribute("Global"): + # Interfaces with [Global] or [PrimaryGlobal] must not + # have anything inherit from them + if (self.parent.getExtendedAttribute("Global") or + self.parent.getExtendedAttribute("PrimaryGlobal")): # Note: This is not a self.parent.isOnGlobalProtoChain() check # because ancestors of a [Global] interface can have other # descendants. @@ -1106,6 +1110,20 @@ class IDLInterface(IDLObjectWithScope): for globalName in self.globalNames: self.parentScope.globalNameMapping[globalName].add(self.identifier.name) self._isOnGlobalProtoChain = True + elif identifier == "PrimaryGlobal": + if not attr.noArguments(): + raise WebIDLError("[PrimaryGlobal] must take no arguments", + [attr.location]) + if self.parentScope.primaryGlobalAttr is not None: + raise WebIDLError( + "[PrimaryGlobal] specified twice", + [attr.location, + self.parentScope.primaryGlobalAttr.location]) + self.parentScope.primaryGlobalAttr = attr + self.parentScope.primaryGlobalName = self.identifier.name + self.parentScope.globalNames.add(self.identifier.name) + self.parentScope.globalNameMapping[self.identifier.name].add(self.identifier.name) + self._isOnGlobalProtoChain = True elif (identifier == "NeedNewResolve" or identifier == "OverrideBuiltins" or identifier == "ChromeOnly" or diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index 33b4f3332cc9..660e3aaeaa48 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -24,7 +24,7 @@ interface nsIDOMCrypto; typedef any Transferable; // http://www.whatwg.org/specs/web-apps/current-work/ -[Global, NeedNewResolve] +[PrimaryGlobal, NeedNewResolve] /*sealed*/ interface Window : EventTarget { // the current browsing context [Unforgeable, Throws,