Bug 822470 part 1. Factor out the code that callback functions and callback interfaces will be able to share into a CallbackObject class. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 28 Jan 2013 08:34:29 -0500
changeset 130730 39d1a2977442128be6835b875dc79202488a2aae
parent 130729 436d46763d623091f3baf412847d39f9e526e1b2
child 130731 d03fc64bbe76e7865cbb5578ac2a5153717a5ef5
push id317
push userbbajaj@mozilla.com
push dateTue, 07 May 2013 01:20:33 +0000
treeherdermozilla-release@159a10910249 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs822470
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 822470 part 1. Factor out the code that callback functions and callback interfaces will be able to share into a CallbackObject class. r=peterv
dom/bindings/CallbackFunction.cpp
dom/bindings/CallbackFunction.h
dom/bindings/CallbackObject.cpp
dom/bindings/CallbackObject.h
dom/bindings/Codegen.py
dom/bindings/Makefile.in
--- a/dom/bindings/CallbackFunction.h
+++ b/dom/bindings/CallbackFunction.h
@@ -9,154 +9,55 @@
  *
  * This class implements common functionality like lifetime
  * management, initialization with the callable, and setup of the call
  * environment.  Subclasses corresponding to particular callback
  * function types should provide a Call() method that actually does
  * the call.
  */
 
-#pragma once
+#ifndef mozilla_dom_CallbackFunction_h
+#define mozilla_dom_CallbackFunction_h
 
-#include "nsISupports.h"
-#include "nsISupportsImpl.h"
-#include "nsCycleCollectionParticipant.h"
-#include "jsapi.h"
-#include "jswrapper.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/Util.h"
-#include "nsContentUtils.h"
-#include "nsWrapperCache.h"
-#include "nsJSEnvironment.h"
-#include "xpcpublic.h"
-#include "nsLayoutStatics.h"
+#include "mozilla/dom/CallbackObject.h"
 
 namespace mozilla {
 namespace dom {
 
-class CallbackFunction : public nsISupports
+class CallbackFunction : public CallbackObject
 {
 public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallbackFunction)
-
   /**
    * Create a CallbackFunction.  aCallable is the callable we're wrapping.
    * aOwner is the object that will be receiving this CallbackFunction as a
    * method argument, if any.  We need this so we can store our callable in the
    * same compartment as our owner.  If *aInited is set to false, an exception
    * has been thrown.
    */
   CallbackFunction(JSContext* cx, JSObject* aOwner, JSObject* aCallable,
                    bool* aInited)
-    : mCallable(nullptr)
+    : CallbackObject(cx, aOwner, aCallable, aInited)
   {
     MOZ_ASSERT(JS_ObjectIsCallable(cx, aCallable));
-    // If aOwner is not null, enter the compartment of aOwner's
-    // underlying object.
-    if (aOwner) {
-      aOwner = js::UnwrapObject(aOwner);
-      JSAutoCompartment ac(cx, aOwner);
-      if (!JS_WrapObject(cx, &aCallable)) {
-        *aInited = false;
-        return;
-      }
-    }
-
-    // Set mCallable before we hold, on the off chance that a GC could somehow
-    // happen in there... (which would be pretty odd, granted).
-    mCallable = aCallable;
-    // Make sure we'll be able to drop as needed
-    nsLayoutStatics::AddRef();
-    NS_HOLD_JS_OBJECTS(this, CallbackFunction);
-    *aInited = true;
-  }
-
-  virtual ~CallbackFunction()
-  {
-    DropCallback();
   }
 
   JSObject* Callable() const
   {
-    xpc_UnmarkGrayObject(mCallable);
-    return mCallable;
+    return Callback();
   }
 
   bool HasGrayCallable() const
   {
     // Play it safe in case this gets called after unlink.
-    return mCallable && xpc_IsGrayGCThing(mCallable);
+    return mCallback && xpc_IsGrayGCThing(mCallback);
   }
 
 protected:
   explicit CallbackFunction(CallbackFunction* aCallbackFunction)
-    : mCallable(aCallbackFunction->mCallable)
-  {
-    // Set mCallable before we hold, on the off chance that a GC could somehow
-    // happen in there... (which would be pretty odd, granted).
-    // Make sure we'll be able to drop as needed
-    nsLayoutStatics::AddRef();
-    NS_HOLD_JS_OBJECTS(this, CallbackFunction);
-  }
-
-  void DropCallback()
-  {
-    if (mCallable) {
-      mCallable = nullptr;
-      NS_DROP_JS_OBJECTS(this, CallbackFunction);
-      nsLayoutStatics::Release();
-    }
-  }
-
-  JSObject* mCallable;
-
-  class NS_STACK_CLASS CallSetup
+    : CallbackObject(aCallbackFunction)
   {
-    /**
-     * A class that performs whatever setup we need to safely make a
-     * call while this class is on the stack, After the constructor
-     * returns, the call is safe to make if GetContext() returns
-     * non-null.
-     */
-  public:
-    CallSetup(JSObject* const aCallable);
-    ~CallSetup();
-
-    JSContext* GetContext() const
-    {
-      return mCx;
-    }
-
-  private:
-    // We better not get copy-constructed
-    CallSetup(const CallSetup&) MOZ_DELETE;
-
-    // Members which can go away whenever
-    JSContext* mCx;
-    nsCOMPtr<nsIScriptContext> mCtx;
-
-    // And now members whose construction/destruction order we need to control.
-
-    // Put our nsAutoMicrotask first, so it gets destroyed after everything else
-    // is gone
-    nsAutoMicroTask mMt;
-
-    // Can't construct an XPCAutoRequest until we have a JSContext, so
-    // this needs to be a Maybe.
-    Maybe<XPCAutoRequest> mAr;
-
-    // Can't construct a TerminationFuncHolder without an nsJSContext.  But we
-    // generally want its destructor to come after the destructor of mCxPusher.
-    Maybe<nsJSContext::TerminationFuncHolder> mTerminationFuncHolder;
-
-    nsCxPusher mCxPusher;
-
-    // Can't construct a JSAutoCompartment without a JSContext either.  Also,
-    // Put mAc after mCxPusher so that we exit the compartment before we pop the
-    // JSContext.  Though in practice we'll often manually order those two
-    // things.
-    Maybe<JSAutoCompartment> mAc;
-  };
+  }
 };
 
 } // namespace dom
 } // namespace mozilla
+
+#endif // mozilla_dom_CallbackFunction_h
rename from dom/bindings/CallbackFunction.cpp
rename to dom/bindings/CallbackObject.cpp
--- a/dom/bindings/CallbackFunction.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -1,59 +1,61 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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/. */
 
-#include "mozilla/dom/CallbackFunction.h"
+#include "mozilla/dom/CallbackObject.h"
 #include "jsfriendapi.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIXPConnect.h"
 #include "nsIScriptContext.h"
 #include "nsPIDOMWindow.h"
 #include "nsJSUtils.h"
 #include "nsIScriptSecurityManager.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CallbackFunction)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CallbackObject)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(CallbackFunction)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(CallbackFunction)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(CallbackObject)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(CallbackObject)
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackFunction)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackObject)
   tmp->DropCallback();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackFunction)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackFunction)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallable)
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallback)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
-CallbackFunction::CallSetup::CallSetup(JSObject* const aCallable)
+CallbackObject::CallSetup::CallSetup(JSObject* const aCallback)
   : mCx(nullptr)
 {
-  xpc_UnmarkGrayObject(aCallable);
+  xpc_UnmarkGrayObject(aCallback);
 
-  // We need to produce a useful JSContext here.  Ideally one that the callable
+  // We need to produce a useful JSContext here.  Ideally one that the callback
   // is in some sense associated with, so that we can sort of treat it as a
-  // "script entry point".
+  // "script entry point".  Though once we actually have script entry points,
+  // we'll need to do the script entry point bits once we have an actual
+  // callable.
 
-  // First, find the real underlying callable.
-  JSObject* realCallable = js::UnwrapObject(aCallable);
+  // First, find the real underlying callback.
+  JSObject* realCallback = js::UnwrapObject(aCallback);
 
-  // Now get the nsIScriptGlobalObject for this callable.
+  // Now get the nsIScriptGlobalObject for this callback.
   JSContext* cx = nullptr;
   nsIScriptContext* ctx = nullptr;
-  nsIScriptGlobalObject* sgo = nsJSUtils::GetStaticScriptGlobal(realCallable);
+  nsIScriptGlobalObject* sgo = nsJSUtils::GetStaticScriptGlobal(realCallback);
   if (sgo) {
     // Make sure that if this is a window it's the current inner, since the
     // nsIScriptContext and hence JSContext are associated with the outer
     // window.  Which means that if someone holds on to a function from a
     // now-unloaded document we'd have the new document as the script entry
     // point...
     nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(sgo);
     if (win) {
@@ -93,42 +95,42 @@ CallbackFunction::CallSetup::CallSetup(J
   // have an nsIScriptContext.
   // XXXbz Why, if, say CheckFunctionAccess fails?  I know that's how
   // nsJSContext::CallEventHandler works, but is it required?
   // FIXME: Bug 807369.
   mCtx = ctx;
 
   // Check that it's ok to run this callback at all.
   // FIXME: Bug 807371: we want a less silly check here.
-  // Make sure to unwrap aCallable before passing it in, because
+  // Make sure to unwrap aCallback before passing it in, because
   // getting principals from wrappers is silly.
   nsresult rv = nsContentUtils::GetSecurityManager()->
-    CheckFunctionAccess(cx, js::UnwrapObject(aCallable), nullptr);
+    CheckFunctionAccess(cx, js::UnwrapObject(aCallback), nullptr);
 
   // Construct a termination func holder even if we're not planning to
   // run any script.  We need this because we're going to call
   // ScriptEvaluated even if we don't run the script...  See XXX
   // comment above.
   if (ctx) {
     mTerminationFuncHolder.construct(static_cast<nsJSContext*>(ctx));
   }
 
   if (NS_FAILED(rv)) {
     // Security check failed.  We're done here.
     return;
   }
 
-  // Enter the compartment of our callable, so we can actually call it.
-  mAc.construct(cx, aCallable);
+  // Enter the compartment of our callback, so we can actually work with it.
+  mAc.construct(cx, aCallback);
 
   // And now we're ready to go.
   mCx = cx;
 }
 
-CallbackFunction::CallSetup::~CallSetup()
+CallbackObject::CallSetup::~CallSetup()
 {
   // First things first: if we have a JSContext, report any pending
   // errors on it.
   if (mCx) {
     nsJSUtils::ReportPendingException(mCx);
   }
 
   // If we have an mCtx, we need to call ScriptEvaluated() on it.  But we have
copy from dom/bindings/CallbackFunction.h
copy to dom/bindings/CallbackObject.h
--- a/dom/bindings/CallbackFunction.h
+++ b/dom/bindings/CallbackObject.h
@@ -1,25 +1,26 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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/. */
 
 /**
- * A common base class for representing WebIDL callback function types in C++.
+ * A common base class for representing WebIDL callback function and
+ * callback interface types in C++.
  *
  * This class implements common functionality like lifetime
- * management, initialization with the callable, and setup of the call
- * environment.  Subclasses corresponding to particular callback
- * function types should provide a Call() method that actually does
- * the call.
+ * management, initialization with the JS object, and setup of the
+ * call environment.  Subclasses are responsible for providing methods
+ * that do the call into JS as needed.
  */
 
-#pragma once
+#ifndef mozilla_dom_CallbackObject_h
+#define mozilla_dom_CallbackObject_h
 
 #include "nsISupports.h"
 #include "nsISupportsImpl.h"
 #include "nsCycleCollectionParticipant.h"
 #include "jsapi.h"
 #include "jswrapper.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Util.h"
@@ -27,92 +28,85 @@
 #include "nsWrapperCache.h"
 #include "nsJSEnvironment.h"
 #include "xpcpublic.h"
 #include "nsLayoutStatics.h"
 
 namespace mozilla {
 namespace dom {
 
-class CallbackFunction : public nsISupports
+class CallbackObject : public nsISupports
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallbackFunction)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallbackObject)
 
   /**
-   * Create a CallbackFunction.  aCallable is the callable we're wrapping.
-   * aOwner is the object that will be receiving this CallbackFunction as a
-   * method argument, if any.  We need this so we can store our callable in the
+   * Create a CallbackObject.  aCallback is the callback object we're wrapping.
+   * aOwner is the object that will be receiving this CallbackObject as a method
+   * argument, if any.  We need this so we can store our callback object in the
    * same compartment as our owner.  If *aInited is set to false, an exception
    * has been thrown.
    */
-  CallbackFunction(JSContext* cx, JSObject* aOwner, JSObject* aCallable,
-                   bool* aInited)
-    : mCallable(nullptr)
+  CallbackObject(JSContext* cx, JSObject* aOwner, JSObject* aCallback,
+                 bool* aInited)
+    : mCallback(nullptr)
   {
-    MOZ_ASSERT(JS_ObjectIsCallable(cx, aCallable));
     // If aOwner is not null, enter the compartment of aOwner's
     // underlying object.
     if (aOwner) {
       aOwner = js::UnwrapObject(aOwner);
       JSAutoCompartment ac(cx, aOwner);
-      if (!JS_WrapObject(cx, &aCallable)) {
+      if (!JS_WrapObject(cx, &aCallback)) {
         *aInited = false;
         return;
       }
     }
 
-    // Set mCallable before we hold, on the off chance that a GC could somehow
+    // Set mCallback before we hold, on the off chance that a GC could somehow
     // happen in there... (which would be pretty odd, granted).
-    mCallable = aCallable;
+    mCallback = aCallback;
     // Make sure we'll be able to drop as needed
     nsLayoutStatics::AddRef();
-    NS_HOLD_JS_OBJECTS(this, CallbackFunction);
+    NS_HOLD_JS_OBJECTS(this, CallbackObject);
     *aInited = true;
   }
 
-  virtual ~CallbackFunction()
+  virtual ~CallbackObject()
   {
     DropCallback();
   }
 
-  JSObject* Callable() const
+  JSObject* Callback() const
   {
-    xpc_UnmarkGrayObject(mCallable);
-    return mCallable;
-  }
-
-  bool HasGrayCallable() const
-  {
-    // Play it safe in case this gets called after unlink.
-    return mCallable && xpc_IsGrayGCThing(mCallable);
+    xpc_UnmarkGrayObject(mCallback);
+    return mCallback;
   }
 
 protected:
-  explicit CallbackFunction(CallbackFunction* aCallbackFunction)
-    : mCallable(aCallbackFunction->mCallable)
+  explicit CallbackObject(CallbackObject* aCallbackFunction)
+    : mCallback(aCallbackFunction->mCallback)
   {
-    // Set mCallable before we hold, on the off chance that a GC could somehow
+    // Set mCallback before we hold, on the off chance that a GC could somehow
     // happen in there... (which would be pretty odd, granted).
     // Make sure we'll be able to drop as needed
     nsLayoutStatics::AddRef();
-    NS_HOLD_JS_OBJECTS(this, CallbackFunction);
+    NS_HOLD_JS_OBJECTS(this, CallbackObject);
   }
 
   void DropCallback()
   {
-    if (mCallable) {
-      mCallable = nullptr;
-      NS_DROP_JS_OBJECTS(this, CallbackFunction);
+    if (mCallback) {
+      mCallback = nullptr;
+      NS_DROP_JS_OBJECTS(this, CallbackObject);
       nsLayoutStatics::Release();
     }
   }
 
-  JSObject* mCallable;
+  JSObject* mCallback;
 
   class NS_STACK_CLASS CallSetup
   {
     /**
      * A class that performs whatever setup we need to safely make a
      * call while this class is on the stack, After the constructor
      * returns, the call is safe to make if GetContext() returns
      * non-null.
@@ -155,8 +149,10 @@ protected:
     // JSContext.  Though in practice we'll often manually order those two
     // things.
     Maybe<JSAutoCompartment> mAc;
   };
 };
 
 } // namespace dom
 } // namespace mozilla
+
+#endif // mozilla_dom_CallbackObject_h
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -7661,22 +7661,22 @@ class CGCallbackFunction(CGClass):
         if not self.generatable:
             return ""
         return CGClass.declare(self)
 
     def getConstructors(self):
         return [ClassConstructor(
             [Argument("JSContext*", "cx"),
              Argument("JSObject*", "aOwner"),
-             Argument("JSObject*", "aCallable"),
+             Argument("JSObject*", "aCallback"),
              Argument("bool*", "aInited")],
             bodyInHeader=True,
             visibility="public",
             baseConstructors=[
-                "CallbackFunction(cx, aOwner, aCallable, aInited)"
+                "CallbackFunction(cx, aOwner, aCallback, aInited)"
                 ],
             body=""),
             ClassConstructor(
             [Argument("CallbackFunction*", "aOther")],
             bodyInHeader=True,
             visibility="public",
             explicit=True,
             baseConstructors=[
@@ -7695,25 +7695,25 @@ class CGCallbackFunction(CGClass):
         # the private method.
         argnames = [arg.name for arg in args]
         argnamesWithThis = ["s.GetContext()", "thisObjJS"] + argnames
         argnamesWithoutThis = ["s.GetContext()", "nullptr"] + argnames
         # And now insert our template argument.
         argsWithoutThis = list(args)
         args.insert(0, Argument("const T&",  "thisObj"))
 
-        setupCall = ("CallSetup s(mCallable);\n"
+        setupCall = ("CallSetup s(mCallback);\n"
                      "if (!s.GetContext()) {\n"
                      "  aRv.Throw(NS_ERROR_UNEXPECTED);\n"
                      "  return${errorReturn};\n"
                      "}\n")
 
         bodyWithThis = string.Template(
             setupCall+
-            "JSObject* thisObjJS = WrapCallThisObject(s.GetContext(), mCallable, thisObj);\n"
+            "JSObject* thisObjJS = WrapCallThisObject(s.GetContext(), mCallback, thisObj);\n"
             "if (!thisObjJS) {\n"
             "  aRv.Throw(NS_ERROR_FAILURE);\n"
             "  return${errorReturn};\n"
             "}\n"
             "return Call(${callArgs});").substitute({
                 "errorReturn" : callCallback.getDefaultRetval(),
                 "callArgs" : ", ".join(argnamesWithThis)
                 })
@@ -7797,31 +7797,31 @@ class CallCallback(CGNativeMember):
             replacements["argvDecl"] = ""
             replacements["argv"] = "nullptr"
             replacements["argc"] = "0"
 
         return string.Template(
             "JS::Value rval = JSVAL_VOID;\n"
             "${argvDecl}" # Newlines and semicolons are in the value
             "${convertArgs}"
-            "if (!JS_CallFunctionValue(cx, aThisObj, JS::ObjectValue(*mCallable),\n"
+            "if (!JS_CallFunctionValue(cx, aThisObj, JS::ObjectValue(*mCallback),\n"
             "                          ${argc}, ${argv}, &rval)) {\n"
             "  aRv.Throw(NS_ERROR_UNEXPECTED);\n"
             "  return${errorReturn};\n"
             "}\n"
             "${returnResult}").substitute(replacements)
 
     def getResultConversion(self):
         replacements = {
             "val": "rval",
             "valPtr": "&rval",
             "holderName" : "rvalHolder",
             "declName" : "rvalDecl",
             # We actually want to pass in a null scope object here, because
-            # wrapping things into our current compartment (that of mCallable)
+            # wrapping things into our current compartment (that of mCallback)
             # is what we want.
             "obj": "nullptr"
             }
 
         convertType = instantiateJSToNativeConversionTemplate(
             getJSToNativeConversionTemplate(self.retvalType,
                                             self.descriptor,
                                             exceptionCode=self.exceptionCode),
@@ -7876,17 +7876,17 @@ class CallCallback(CGNativeMember):
             arg.type, self.descriptor,
             {
                 'result' : result,
                 'successCode' : "continue;" if arg.variadic else "break;",
                 'jsvalRef' : "argv[%s]" % jsvalIndex,
                 'jsvalPtr' : "&argv[%s]" % jsvalIndex,
                 # XXXbz we don't have anything better to use for 'obj',
                 # really...
-                'obj' : 'mCallable',
+                'obj' : 'mCallback',
                 'isCreator': False,
                 'exceptionCode' : self.exceptionCode
                 })
         if arg.variadic:
             conversion = string.Template(
                 "for (uint32_t idx = 0; idx < ${arg}.Length(); ++idx) {\n" +
                 CGIndenter(CGGeneric(conversion)).define() + "\n"
                 "}\n"
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -41,30 +41,31 @@ globalgen_targets := \
   UnionTypes.cpp \
   UnionConversions.h \
   $(NULL)
 
 CPPSRCS = \
   $(linked_binding_cpp_files) \
   $(filter %.cpp, $(globalgen_targets)) \
   BindingUtils.cpp \
-  CallbackFunction.cpp \
+  CallbackObject.cpp \
   DOMJSProxyHandler.cpp \
   $(NULL)
 
 EXPORTS_NAMESPACES = $(binding_include_path) mozilla
 
 EXPORTS_mozilla = \
   ErrorResult.h \
   $(NULL)
 
 EXPORTS_$(binding_include_path) = \
   BindingDeclarations.h \
   BindingUtils.h \
   CallbackFunction.h \
+  CallbackObject.h \
   DOMJSClass.h \
   DOMJSProxyHandler.h \
   Errors.msg \
   NonRefcountedDOMObject.h \
   Nullable.h \
   PrimitiveConversions.h \
   PrototypeList.h \
   RegisterBindings.h \