Bug 1172785 - Adding StaticClassOverride routing for JS implemented WebIDL draft
authorMartin Thomson <martin.thomson@gmail.com>
Tue, 30 Jun 2015 11:24:18 -0700
changeset 274804 a14f28f537a0061adc66a57c7587a7ea3c3c9f6d
parent 274803 82099594ef80e6102b058631c7f2c98378538a58
child 274805 21ccafad8c97728abb876c9e9f33741420c9ac24
push id3125
push usermartin.thomson@gmail.com
push dateTue, 30 Jun 2015 18:24:25 +0000
bugs1172785
milestone42.0a1
Bug 1172785 - Adding StaticClassOverride routing for JS implemented WebIDL
dom/bindings/Codegen.py
dom/bindings/parser/WebIDL.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1133,16 +1133,19 @@ class CGHeaders(CGWrapper):
                     return
 
                 if "::" in func:
                     # Strip out the function name and convert "::" to "/"
                     bindingHeaders.add("/".join(func.split("::")[:-1]) + ".h")
 
             for m in desc.interface.members:
                 addHeaderForFunc(PropertyDefiner.getStringAttr(m, "Func"))
+                staticTypeOverride = PropertyDefiner.getStringAttr(m, "StaticClassOverride")
+                if staticTypeOverride:
+                    bindingHeaders.add("/".join(staticTypeOverride.split("::")) + ".h")
             # getExtendedAttribute() returns a list, extract the entry.
             funcList = desc.interface.getExtendedAttribute("Func")
             if funcList is not None:
                 addHeaderForFunc(funcList[0])
 
         for desc in descriptors:
             if desc.interface.maplikeOrSetlike:
                 # We need ToJSValue.h for maplike/setlike type conversions
@@ -6766,18 +6769,21 @@ class CGPerSignatureCall(CGThing):
             if setter:
                 lenientFloatCode = "return true;\n"
             elif idlNode.isMethod():
                 lenientFloatCode = ("args.rval().setUndefined();\n"
                                     "return true;\n")
 
         argsPre = []
         if static:
-            nativeMethodName = "%s::%s" % (descriptor.nativeType,
-                                           nativeMethodName)
+            nativeType = descriptor.nativeType
+            staticTypeOverride = PropertyDefiner.getStringAttr(idlNode, "StaticClassOverride")
+            if (staticTypeOverride):
+                nativeType = staticTypeOverride
+            nativeMethodName = "%s::%s" % (nativeType, nativeMethodName)
             # If we're a constructor, "obj" may not be a function, so calling
             # XrayAwareCalleeGlobal() on it is not safe.  Of course in the
             # constructor case either "obj" is an Xray or we're already in the
             # content compartment, not the Xray compartment, so just
             # constructing the GlobalObject from "obj" is fine.
             if isConstructor:
                 objForGlobalObject = "obj"
             else:
@@ -6804,19 +6810,20 @@ class CGPerSignatureCall(CGThing):
 
         needsUnwrap = False
         argsPost = []
         if isConstructor:
             needsUnwrap = True
             needsUnwrappedVar = False
             unwrappedVar = "obj"
         elif descriptor.interface.isJSImplemented():
-            needsUnwrap = True
-            needsUnwrappedVar = True
-            argsPost.append("js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj)")
+            if not idlNode.isStatic():
+                needsUnwrap = True
+                needsUnwrappedVar = True
+                argsPost.append("js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj)")
         elif needScopeObject(returnType, arguments, self.extendedAttributes,
                              descriptor.wrapperCache, True,
                              idlNode.getExtendedAttribute("StoreInSlot")):
             needsUnwrap = True
             needsUnwrappedVar = True
             argsPre.append("unwrappedObj ? *unwrappedObj : obj")
 
         if needsUnwrap and needsUnwrappedVar:
@@ -13275,17 +13282,17 @@ class CGExampleSetter(CGNativeMember):
     def define(self, cgClass):
         return ''
 
 
 class CGBindingImplClass(CGClass):
     """
     Common codegen for generating a C++ implementation of a WebIDL interface
     """
-    def __init__(self, descriptor, cgMethod, cgGetter, cgSetter, wantGetParent=True, wrapMethodName="WrapObject"):
+    def __init__(self, descriptor, cgMethod, cgGetter, cgSetter, wantGetParent=True, wrapMethodName="WrapObject", skipStaticMethods=False):
         """
         cgMethod, cgGetter and cgSetter are classes used to codegen methods,
         getters and setters.
         """
         self.descriptor = descriptor
         self._deps = descriptor.interface.getDeps()
 
         iface = descriptor.interface
@@ -13306,17 +13313,18 @@ class CGBindingImplClass(CGClass):
         if iface.ctor():
             appendMethod(iface.ctor(), isConstructor=True)
         for n in iface.namedConstructors:
             appendMethod(n, isConstructor=True)
         for m in iface.members:
             if m.isMethod():
                 if m.isIdentifierLess():
                     continue
-                appendMethod(m)
+                if not m.isStatic() or not skipStaticMethods:
+                    appendMethod(m)
             elif m.isAttr():
                 self.methodDecls.append(cgGetter(descriptor, m))
                 if not m.readonly:
                     self.methodDecls.append(cgSetter(descriptor, m))
 
         # Now do the special operations
         def appendSpecialOperation(name, op):
             if op is None:
@@ -13778,17 +13786,17 @@ class CGJSImplSetter(CGJSImplMember):
                                                          [FakeArgument(self.member.type, self.member)])]
         return 'mImpl->%s(%s);\n' % (
             callbackSetterName(self.member, self.descriptorProvider),
             ", ".join(callbackArgs))
 
 
 class CGJSImplClass(CGBindingImplClass):
     def __init__(self, descriptor):
-        CGBindingImplClass.__init__(self, descriptor, CGJSImplMethod, CGJSImplGetter, CGJSImplSetter)
+        CGBindingImplClass.__init__(self, descriptor, CGJSImplMethod, CGJSImplGetter, CGJSImplSetter, skipStaticMethods=True)
 
         if descriptor.interface.parent:
             parentClass = descriptor.getDescriptor(
                 descriptor.interface.parent.identifier.name).jsImplParent
             baseClasses = [ClassBase(parentClass)]
             isupportsDecl = "NS_DECL_ISUPPORTS_INHERITED\n"
             ccDecl = ("NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(%s, %s)\n" %
                       (descriptor.name, parentClass))
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -3364,17 +3364,17 @@ class IDLInterfaceMember(IDLObjectWithId
             if self.affects == "Everything" and self.dependsOn != "Everything":
                 raise WebIDLError("Interface member is flagged as affecting "
                                   "everything but not depending on everything. "
                                   "That seems rather unlikely.",
                                   [self.location])
 
         if self.getExtendedAttribute("NewObject"):
             if self.dependsOn == "Nothing" or self.dependsOn == "DOMState":
-                raise WebIDLError("A [NewObject] method is not idempotent, " 
+                raise WebIDLError("A [NewObject] method is not idempotent, "
                                   "so it has to depend on something other than DOM state.",
                                   [self.location])
 
     def _setDependsOn(self, dependsOn):
         if self.dependsOn != "Everything":
             raise WebIDLError("Trying to specify multiple different DependsOn, "
                               "Pure, or Constant extended attributes for "
                               "attribute", [self.location])
@@ -4515,16 +4515,22 @@ class IDLMethod(IDLInterfaceMember, IDLS
                               [overloadWithPromiseReturnType.location,
                                overloadWithoutPromiseReturnType.location])
 
         if overloadWithPromiseReturnType and self._legacycaller:
             raise WebIDLError("May not have a Promise return type for a "
                               "legacycaller.",
                               [overloadWithPromiseReturnType.location])
 
+        if self.getExtendedAttribute("StaticClassOverride") and not \
+           (self.identifier.scope.isJSImplemented() and self.isStatic()):
+            raise WebIDLError("StaticClassOverride can be applied to static"
+                              " methods on JS-implemented classes only.",
+                              [self.location])
+
     def overloadsForArgCount(self, argc):
         return [overload for overload in self._overloads if
                 len(overload.arguments) == argc or
                 (len(overload.arguments) > argc and
                  all(arg.optional for arg in overload.arguments[argc:])) or
                 (len(overload.arguments) < argc and
                  len(overload.arguments) > 0 and
                  overload.arguments[-1].variadic)]
@@ -4632,17 +4638,18 @@ class IDLMethod(IDLInterfaceMember, IDLS
               identifier == "ChromeOnly" or
               identifier == "UnsafeInPrerendering" or
               identifier == "Pref" or
               identifier == "Deprecated" or
               identifier == "Func" or
               identifier == "AvailableIn" or
               identifier == "CheckPermissions" or
               identifier == "BinaryName" or
-              identifier == "MethodIdentityTestable"):
+              identifier == "MethodIdentityTestable" or
+              identifier == "StaticClassOverride"):
             # Known attributes that we don't need to do anything with here
             pass
         else:
             raise WebIDLError("Unknown extended attribute %s on method" % identifier,
                               [attr.location])
         IDLInterfaceMember.handleExtendedAttribute(self, attr)
 
     def returnsPromise(self):