Bug 827486, part 6 - generate headers and code for JS implemented WebIDL classes. r=bz
authorAndrew McCreight <amccreight@mozilla.com>
Mon, 18 Mar 2013 16:05:51 -0700
changeset 131758 8212a0b3bbe7078a40b9608a8836ad11e488d60e
parent 131757 7fe1bc48dd10ad01e57831ad4502a549c07fc8f4
child 131759 d047a7ed2871760f789b0d083a93641ead2b5cb5
push idunknown
push userunknown
push dateunknown
reviewersbz
bugs827486
milestone22.0a1
Bug 827486, part 6 - generate headers and code for JS implemented WebIDL classes. r=bz
dom/bindings/Codegen.py
dom/bindings/Configuration.py
dom/bindings/parser/WebIDL.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5,17 +5,17 @@
 # Common codegen classes.
 
 import operator
 import os
 import re
 import string
 
 from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType
-from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback
+from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, Descriptor
 
 AUTOGENERATED_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
 ADDPROPERTY_HOOK_NAME = '_addProperty'
 FINALIZE_HOOK_NAME = '_finalize'
 TRACE_HOOK_NAME = '_trace'
 CONSTRUCT_HOOK_NAME = '_constructor'
 LEGACYCALLER_HOOK_NAME = '_legacycaller'
@@ -471,18 +471,19 @@ def callForEachType(descriptors, diction
         for t in getTypesFromCallback(callback):
             func(t)
 
 class CGHeaders(CGWrapper):
     """
     Generates the appropriate include statements.
     """
     def __init__(self, descriptors, dictionaries, callbacks,
-                 callbackDescriptors, declareIncludes, defineIncludes, child,
-                 config=None):
+                 callbackDescriptors,
+                 declareIncludes, defineIncludes, child,
+                 config=None, anyJSImplemented=False):
         """
         Builds a set of includes to cover |descriptors|.
 
         Also includes the files in |declareIncludes| in the header
         file and the files in |defineIncludes| in the .cpp.
         """
 
         # Determine the filenames for which we need headers.
@@ -581,17 +582,17 @@ class CGHeaders(CGWrapper):
             bindingHeaders.add(self.getDeclarationFilename(c.interface))
 
         if len(callbacks) != 0:
             # We need CallbackFunction to serve as our parent class
             declareIncludes.add("mozilla/dom/CallbackFunction.h")
             # And we need BindingUtils.h so we can wrap "this" objects
             declareIncludes.add("mozilla/dom/BindingUtils.h")
 
-        if len(callbackDescriptors) != 0:
+        if len(callbackDescriptors) != 0 or anyJSImplemented:
             # We need CallbackInterface to serve as our parent class
             declareIncludes.add("mozilla/dom/CallbackInterface.h")
             # And we need BindingUtils.h so we can wrap "this" objects
             declareIncludes.add("mozilla/dom/BindingUtils.h")
 
         # Let the machinery do its thing.
         def _includeString(includes):
             return ''.join(['#include "%s"\n' % i for i in includes]) + '\n'
@@ -7070,17 +7071,18 @@ class CGBindingRoot(CGThing):
         workerDictionaries = config.getDictionaries(webIDLFile=webIDLFile,
                                                     workers=True)
         mainCallbacks = config.getCallbacks(webIDLFile=webIDLFile,
                                             workers=False)
         workerCallbacks = config.getCallbacks(webIDLFile=webIDLFile,
                                               workers=True)
         callbackDescriptors = config.getDescriptors(webIDLFile=webIDLFile,
                                                     isCallback=True)
-
+        jsImplemented = config.getDescriptors(webIDLFile=webIDLFile,
+                                              isJSImplemented=True)
         forwardDeclares = [CGClassForwardDeclare('XPCWrappedNativeScope')]
 
         descriptorsForForwardDeclaration = list(descriptors)
         ifaces = []
         workerIfaces = []
         def getInterfacesFromDictionary(d):
             return [ type.unroll().inner
                      for type in getTypesFromDictionary(d)
@@ -7224,16 +7226,21 @@ class CGBindingRoot(CGThing):
                         for c in mainCallbacks)
 
         # Do codegen for all the descriptors
         cgthings.extend([CGDescriptor(x) for x in descriptors])
 
         # Do codegen for all the callback interfaces
         cgthings.extend([CGCallbackInterface(x) for x in callbackDescriptors])
 
+        # Do codegen for JS implemented classes
+        for x in jsImplemented:
+            cgthings.append(CGCallbackInterface(x))
+            cgthings.append(CGJSImplClass(x))
+
         # And make sure we have the right number of newlines at the end
         curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
 
         # Wrap all of that in our namespaces.
         curr = CGNamespace.build(['mozilla', 'dom'],
                                  CGWrapper(curr, pre="\n"))
 
         curr = CGList([forwardDeclares,
@@ -7262,17 +7269,18 @@ class CGBindingRoot(CGThing):
                           'WorkerPrivate.h',
                           'nsContentUtils.h',
                           'mozilla/Preferences.h',
                           # Have to include nsDOMQS.h to get fast arg unwrapping
                           # for old-binding things with castability.
                           'nsDOMQS.h'
                           ],
                          curr,
-                         config)
+                         config,
+                         anyJSImplemented = len(jsImplemented) != 0)
 
         # Add include guards.
         curr = CGIncludeGuard(prefix, curr)
 
         # Add the auto-generated comment.
         curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
 
         # Store the final result.
@@ -8054,16 +8062,18 @@ class CGJSImplClass(CGBindingImplClass):
 class CGCallback(CGClass):
     def __init__(self, idlObject, descriptorProvider, baseName, methods,
                  getters=[], setters=[]):
         self.baseName = baseName
         self._deps = idlObject.getDeps()
         name = idlObject.identifier.name
         if descriptorProvider.workers:
             name += "Workers"
+        if isinstance(descriptorProvider, Descriptor) and descriptorProvider.interface.isJSImplemented():
+            name = jsImplName(name)
         # For our public methods that needThisHandling we want most of the
         # same args and the same return type as what CallbackMember
         # generates.  So we want to take advantage of all its
         # CGNativeMember infrastructure, but that infrastructure can't deal
         # with templates and most especially template arguments.  So just
         # cheat and have CallbackMember compute all those things for us.
         realMethods = []
         for method in methods:
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -108,16 +108,18 @@ class Configuration:
                 getter = lambda x: (not x.interface.isExternal() and
                                     x.interface.hasInterfacePrototypeObject())
             elif key == 'hasInterfaceOrInterfacePrototypeObject':
                 getter = lambda x: x.hasInterfaceOrInterfacePrototypeObject()
             elif key == 'isCallback':
                 getter = lambda x: x.interface.isCallback()
             elif key == 'isExternal':
                 getter = lambda x: x.interface.isExternal()
+            elif key == 'isJSImplemented':
+                getter = lambda x: x.interface.isJSImplemented()
             else:
                 getter = lambda x: getattr(x, key)
             curr = filter(lambda x: getter(x) == val, curr)
         return curr
     def getEnums(self, webIDLFile):
         return filter(lambda e: e.filename() == webIDLFile, self.enums)
 
     @staticmethod
@@ -208,17 +210,17 @@ class Descriptor(DescriptorProvider):
             else:
                 nativeTypeDefault = "mozilla::dom::" + ifaceName
 
         self.nativeType = desc.get('nativeType', nativeTypeDefault)
 
         # Do something sane for JSObject
         if self.nativeType == "JSObject":
             headerDefault = "jsapi.h"
-        elif self.interface.isCallback():
+        elif self.interface.isCallback() or self.interface.isJSImplemented():
             # A copy of CGHeaders.getDeclarationFilename; we can't
             # import it here, sadly.
             # Use our local version of the header, not the exported one, so that
             # test bindings, which don't export, will work correctly.
             basename = os.path.basename(self.interface.filename())
             headerDefault = basename.replace('.webidl', 'Binding.h')
         else:
             if self.workers:
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -774,17 +774,17 @@ class IDLInterface(IDLObjectWithScope):
 
     def setCallback(self, value):
         self._callback = value
 
     def isCallback(self):
         return self._callback
 
     def isSingleOperationInterface(self):
-        assert self.isCallback()
+        assert self.isCallback() or self.isJSImplemented()
         return (
             # Not inheriting from another interface
             not self.parent and
             # No consequential interfaces
             len(self.getConsequentialInterfaces()) == 0 and
             # No attributes of any kinds
             not any(m.isAttr() for m in self.members) and
             # There is at least one regular operation, and all regular