Get basic this-unwrapping going
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 30 Jan 2012 10:15:45 -0500
changeset 85183 06eeb17df2d844ce56b59360e2f875fed3a4a92f
parent 85182 a3c8ecffb634389001f33a721891680ea53455a4
child 85184 376ae400530fad30ca8e1c2ae45c7d34fd2391be
push id79
push userbzbarsky@mozilla.com
push dateMon, 30 Jan 2012 15:16:03 +0000
milestone12.0a1
Get basic this-unwrapping going
dom/bindings/BindingGen.py
dom/bindings/Bindings.conf
dom/bindings/Codegen.py
dom/bindings/Makefile.in
--- a/dom/bindings/BindingGen.py
+++ b/dom/bindings/BindingGen.py
@@ -45,22 +45,29 @@ def generate_binding_cpp(config, outputp
 
     filename = outputprefix + ".cpp"
     print "Generating binding implementation: %s" % (filename)
     f = open(filename, 'w')
 
     parentIncludeTemplate = """#include "%sBinding.h"
 """
 
+    implIncludeTemplate = """#include "%s"
+"""
+
     includes = ""
-    for domClass in config.dom_classes.values():
+    domClasses = config.dom_classes.values()
+    domClasses.sort()
+    for domClass in domClasses:
         parentInterface = domClass.interface.parent
         if parentInterface:
             parentFileName = os.path.split(parentInterface.filename())[1].replace(".webidl", "");
             includes += parentIncludeTemplate % parentFileName
+        for implementation in domClass.implementations:
+            includes += implIncludeTemplate % implementation.declarationFile
 
     prologue = autogenerated_comment + """
 %s
 #include "%s.h"
 
 """ % (includes, outputprefix)
 
     epilogue = """"""
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1,62 +1,70 @@
 dom_classes = [
     {
         'name': 'XMLHttpRequest',
         'implementations': [
             {
                 'nativeClass' : 'nsXMLHttpRequest'
             },
             {
-                'nativeClass' : 'mozilla::dom::workers::XMLHttpRequestPrivate',
+                'nativeClass' : 'mozilla::dom::workers::xhr::XMLHttpRequestPrivate',
                 'workers': True
             }
         ]
     },
     {
         'name': 'EventTarget',
         'implementations': [
             {
                 'nativeClass': 'nsDOMEventTargetHelper'
             },
             {
-                'nativeClass': 'mozilla::dom::workers::EventTargetPrivate',
+	    # NO SUCH CLASS YET
+#                'nativeClass': 'mozilla::dom::workers::EventTargetPrivate',
+                'nativeClass': 'nsDOMEventTargetHelper',
                 'workers': True
             }
         ]
     },
     {
         'name': 'Event',
         'implementations': [
             {
-                'nativeClass': 'nsDOMEventTarget'
+                'nativeClass': 'nsDOMEvent'
             },
             {
-                'nativeClass': 'mozilla::dom::workers::Event',
+	    # NO SUCH CLASS YET
+#                'nativeClass': 'mozilla::dom::workers::Event',
+                'nativeClass': 'nsDOMEvent',
                 'workers': True
             }
         ]
     },
     {
         'name': 'EventListener',
         'implementations': [
             {
                 'nativeClass': 'nsIDOMEventListener'
             },
             {
-                'nativeClass': 'mozilla::dom::workers::EventListener',
+	    # NO SUCH CLASS YET
+#                'nativeClass': 'mozilla::dom::workers::EventListener',
+                'nativeClass': 'nsIDOMEventListener',
                 'workers': True
             }
         ]
     },
     {
         'name': 'XMLHttpRequestEventTarget',
         'implementations': [
             {
-                'nativeClass': 'nsXMLHttpRequestEventTarget'
+                'nativeClass': 'nsXMLHttpRequest'
             },
             {
-                'nativeClass': 'XMLHttpRequestEventTargetPrivate',
+	    # NO SUCH CLASS YET
+#                'nativeClass': 'XMLHttpRequestEventTargetPrivate',
+                'nativeClass': 'nsXMLHttpRequest',
                 'workers': True
             }
         ]
     },
 ]
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1,14 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # Common codegen classes.
 
+import re
+
 autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n"
 
 class CGThing():
     """
     Abstract base case for things that spit out code.
     """
     def __init__(self):
         pass # Nothing for now
@@ -26,17 +28,17 @@ class CGImplThing(CGThing):
     def __init__(self, implementation):
         CGThing.__init__(self)
         self.implementation = implementation
 
 class CGDOMJSClass(CGImplThing):
     def __init__(self, implementation):
         CGImplThing.__init__(self, implementation)
     def declare(self):
-        return "extern DOMJSClass Class;\n\n"
+        return "  extern DOMJSClass Class;\n"
     def define(self):
         prototypeChainString = ', '.join(['id::' + proto \
                                           for proto in self.implementation.prototypeChain])
         return """DOMJSClass Class = {
   { "%s",
     JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1),
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
@@ -114,31 +116,44 @@ class CGAbstractMethod(CGImplThing):
         if self.inline:
             decorators.append('inline')
         if self.static:
             decorators.append('static')
         decorators.append(self.returnType)
         return ' '.join(decorators)
     def declare(self):
         if self.inline:
-            return self._define()
-        return "%s %s(%s);\n" % (self._decorators(), self.name, self._argstring())
+            # Make sure to indent our definition properly
+            return self._define().replace("\n", "\n  ")
+        return "\n  %s %s(%s);\n" % (self._decorators(), self.name, self._argstring())
     def _define(self):
         return self.definition_prologue() + self.definition_body() + self.definition_epilogue()
     def define(self):
         return "" if self.inline else self._define()
     def definition_prologue(self):
         maybeNewline = " " if self.inline else "\n"
-        return "%s%s%s(%s)\n{" % (self._decorators(), maybeNewline,
-                                  self.name, self._argstring())
+        return "\n%s%s%s(%s)\n{" % (self._decorators(), maybeNewline,
+                                    self.name, self._argstring())
     def definition_epilogue(self):
         return "\n}\n"
     def definition_body(self):
         assert(False) # Override me!
 
+class CGAbstractStaticMethod(CGAbstractMethod):
+    """
+    Abstract base class for codegen of implementation-only (no
+    declaration) static methods.
+    """
+    def __init__(self, implementation, name, returnType, args):
+        CGAbstractMethod.__init__(self, implementation, name, returnType, args,
+                                  inline=False, static=True)
+    def declare(self):
+        # We only have implementation
+        return ""
+
 class MethodDefiner:
     def __init__(self, implementation):
         self.implementation = implementation
     def __str__(self):
         methods = [m for m in self.implementation.domClass.interface.members if m.isMethod()]
         if len(methods) == 0:
             return ""
 
@@ -246,67 +261,91 @@ class CGGetProtoObjectMethod(CGAbstractM
   JSObject *ourProto = protoArray[id::%s];
   if (!ourProto) {
     ourProto = protoArray[id::%s] = CreateProtoObject(aCx, aGlobal);
   }
 
   /* ourProto might _still_ be null, but that's OK */
   return ourProto;""" % (self.implementation.name, self.implementation.name)
 
-class CGNativeMethod(CGAbstractMethod):
+class CGAbstractBindingMethod(CGAbstractStaticMethod):
+    def __init__(self, implementation, name, returnType, args):
+        CGAbstractStaticMethod.__init__(self, implementation, name,
+                                        returnType, args)
+    def definition_body(self):
+        return (self.unwrap_this() + self.unwrap_args() +
+                self.generate_call() + self.wrap_return_value())
+
+    def unwrap_this(self):
+        return """
+  %s *self;
+  if (!UnwrapThis(cx, obj, %s, %s, &self))
+    return false;
+""" % (self.implementation.nativeClass, "id::" + self.implementation.name,
+       "depth::" + self.implementation.name)
+
+    def unwrap_args(self):
+        # NEED TO ADD SOME IMPL HERE
+        return """// XXXbz ARGUMENT UNWRAPPING CODE HERE.  Maybe this should be in subclasses of CGAbstractBindingMethod!
+"""
+
+    def generate_call(self):
+        # NEED TO ADD SOME IMPL HERE
+        return """// XXXbz CALL GENERATION HERE
+"""
+
+    def wrap_return_value(self):
+        # NEED TO ADD SOME IMPL HERE
+        return """// XXXbz RETURN VALUE WRAPPING, IF ANY, HERE
+  return false;"""
+
+
+class CGNativeMethod(CGAbstractBindingMethod):
     def __init__(self, implementation, method):
         self.method = method
         args = [Argument('JSContext*', 'cx'), Argument('uintN', 'argc'),
                 Argument('JS::Value*', 'vp')]
-        CGAbstractMethod.__init__(self, implementation, method.identifier.name,
-                                  'JSBool', args)
-    def declare(self):
-        # We only have an implementation
-        return ""
-    def definition_body(self):
-        # NEED TO ADD SOME IMPL HERE
-        return """
-  return false;"""
+        CGAbstractBindingMethod.__init__(self, implementation,
+                                         method.identifier.name,
+                                         'JSBool', args)
+    def unwrap_this(self):
+         return """
+  JSObject *obj = JS_THIS_OBJECT(cx, vp);
+  if (!obj)
+    return false;""" + CGAbstractBindingMethod.unwrap_this(self)
 
-class CGNativeGetter(CGAbstractMethod):
+class CGNativeGetter(CGAbstractBindingMethod):
     def __init__(self, implementation, attr):
         self.attr = attr
         args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'obj'),
                 Argument('jsid', 'id'), Argument('JS::Value*', 'vp')]
-        CGAbstractMethod.__init__(self, implementation,
-                                  'get_'+attr.identifier.name, 'JSBool', args)
-    def declare(self):
-        # We only have an implementation
-        return ""
-    def definition_body(self):
-        # NEED TO ADD SOME IMPL HERE
-        return """
-  return false;"""
+        CGAbstractBindingMethod.__init__(self, implementation,
+                                         'get_'+attr.identifier.name,
+                                         'JSBool', args)
 
-class CGNativeSetter(CGAbstractMethod):
+class CGNativeSetter(CGAbstractBindingMethod):
     def __init__(self, implementation, attr):
         self.attr = attr
         args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'obj'),
                 Argument('jsid', 'id'), Argument('JSBool', 'strict'),
                 Argument('JS::Value*', 'vp')]
-        CGAbstractMethod.__init__(self, implementation,
-                                  'set_'+attr.identifier.name, 'JSBool', args)
-    def declare(self):
-        # We only have an implementation
-        return ""
-    def definition_body(self):
-        # NEED TO ADD SOME IMPL HERE
-        return """
-  return false;"""
+        CGAbstractBindingMethod.__init__(self, implementation,
+                                         'set_'+attr.identifier.name,
+                                         'JSBool', args)
 
 class DOMClassImplementation(CGThing):
     def __init__(self, domClass, implConf):
         CGThing.__init__(self)
         self.domClass = domClass
         self.nativeClass = implConf['nativeClass']
+        if "declarationFile" in implConf:
+            self.declarationFile = implConf["declarationFile"]
+        else:
+            # Just use the native class, minus the namespaces
+            self.declarationFile = self.nativeClass.split("::")[-1] + ".h"
         self.workers = implConf.get('workers', False)
         def make_name(name):
             return name + "_workers" if self.workers else name
         self.name = make_name(domClass.name)
         self.nativeIsISupports = not self.workers
 
         # Build the prototype chain.
         self.prototypeChain = []
@@ -363,10 +402,11 @@ class Configuration:
         self.dom_classes = dict()
         for classConf in self.configFile['dom_classes']:
             name = classConf['name']
             if name not in parseData:
                 continue
             self.dom_classes[name] = DOMClass(classConf, parseData[name])
 
         classCollection = [cls for cls in self.dom_classes.values()]
+        classCollection.sort();
         self.cgRoot = CGNamespace.build(['mozilla', 'dom', 'bindings', 'prototypes'],
                                         CGWrapper(CGList(classCollection), pre="\n"))
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -28,17 +28,23 @@ EXPORTS_NAMESPACES = $(binding_include_p
 
 EXPORTS_$(binding_include_path) = \
   DOMJSClass.h \
   PrototypeList.h \
   Utils.h \
   $(binding_header_files) \
   $(NULL)
 
-LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src
+LOCAL_INCLUDES += \
+  -I$(topsrcdir)/js/xpconnect/src \
+  -I$(topsrcdir)/content/base/src \
+  -I$(topsrcdir)/content/events/src \
+  -I$(topsrcdir)/dom/workers \
+  -I$(topsrcdir)/dom/base \
+  $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 bindinggen_dependencies := \
   BindingGen.py \
   Bindings.conf \
   Codegen.py \
   ParserResults.pkl \