Implement callback type support in codegen
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 13 Feb 2012 15:44:55 -0500
changeset 86816 cfb376b59c08e8db24acc29992d48bc95d44cc2c
parent 86815 f7e3e684436983ccf55144582f6e9ff2d9d0ac59
child 86817 54ad6268014c39a07498c2e99b85ac43369b568e
push id119
push userbzbarsky@mozilla.com
push dateMon, 13 Feb 2012 20:53:28 +0000
milestone13.0a1
Implement callback type support in codegen
dom/bindings/Codegen.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -595,16 +595,32 @@ def getArgumentConversionTemplate(type, 
             "    bool ok;\n"
             "    $name = (%(enumtype)s) FindEnumStringIndex(cx, ${argVal}, %(values)s, &ok);\n"
             "    if (!ok) {\n"
             "      return false;\n"
             "    }\n"
             "  }" % { "enumtype" : enum + "::value",
                       "values" : enum + "::strings" })
 
+    if (isinstance(type, IDLCallbackType) or
+        (isinstance(type, IDLWrapperType) and
+         isinstance(type.inner, IDLCallbackType))):
+        # XXXbz we're going to assume that callback types are always
+        # nullable and always have [TreatNonCallableAsNull] for now.
+        return (
+            "  JSObject *${name};\n"
+            "  if (${argVal}.isObject() && JS_ObjectIsCallable(cx, &${argVal}.toObject())) {\n"
+            "    ${name} = &${argVal}.toObject();\n"
+            "  } else {\n"
+            "    ${name} = NULL;\n"
+            "  }\n")
+
+    if isinstance(type, IDLNullableType) and isinstance(type.inner, IDLCallbackType):
+        raise TypeError("nullable callback")
+
     if not type.isPrimitive():
         return """
   // XXXbz Need conversion for argument type '%s'""" % type
 
     tag = type.tag()
     replacements = dict()
     if type.nullable():
         replacements["declareArg"] = (
@@ -759,24 +775,34 @@ def getWrapTemplateForTypeImpl(type, res
             return """
   return xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr});""" % result
 
     if type.isEnum():
         if type.nullable():
             raise TypeError("We don't support nullable enumerated return types "
                             "yet")
         return """
-  MOZ_ASSERT(uint32_t(result) < ArrayLength(%(strings)s));
-  JSString* result_str = JS_NewStringCopyZ(cx, %(strings)s[uint32_t(result)]);
+  MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s));
+  JSString* result_str = JS_NewStringCopyZ(cx, %(strings)s[uint32_t(%(result)s)]);
   if (!result_str) {
     return false;
   }
   ${jsvalRef} = JS::StringValue(result_str);
-  return true;""" % { "strings" : type.inner.identifier.name + "::strings" }
-    
+  return true;""" % { "result" : result,
+                      "strings" : type.inner.identifier.name + "::strings" }
+
+    if (isinstance(type, IDLCallbackType) or
+        (isinstance(type, IDLWrapperType) and
+         isinstance(type.inner, IDLCallbackType))):
+        # XXXbz we're going to assume that callback types are always
+        # nullable and always have [TreatNonCallableAsNull] for now.
+        return """
+  ${jsvalRef} = JS::ObjectOrNullValue(%s);
+""" % result
+
     if not type.isPrimitive():
         return """
   // XXXbz need to learn to wrap %s
   return false;""" % type
 
     if type.nullable():
         return """
   if (%s.IsNull()) {
@@ -897,16 +923,22 @@ class PerSignatureCall():
             else:
                 resultDeclaration = "  %s result = 0;\n" % builtinNames[self.returnType.tag()]
         elif self.returnType.isString():
             resultDeclaration = "  nsString result;\n"
         elif self.returnType.isEnum():
             if self.returnType.nullable():
                 raise TypeError("We don't support nullable enum return values")
             resultDeclaration = "  %s result;\n" % (self.returnType.inner.identifier.name + "::value")
+        elif (isinstance(self.returnType, IDLCallbackType) or
+              (isinstance(self.returnType, IDLWrapperType) and
+               isinstance(self.returnType.inner, IDLCallbackType))):
+            # XXXbz we're going to assume that callback types are always
+            # nullable for now.
+            resultDeclaration = "  JSObject* result = NULL;\n"
         else:
             resultDeclaration = "  // XXX need to declare |result| for type %s.\n" % self.returnType
 
         if self.returnType is None or self.returnType.isVoid():
             resultAssignment = ""
         else:
             resultAssignment = "result = "