Backed out changeset 9c6dc3897c17 (bug 898136) for breaking SeaMonkey
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Thu, 01 Aug 2013 07:30:06 +0900
changeset 153116 c84673c64f39d97049186ed2a7ee6809e09cec36
parent 153115 023d2f835ca0006cd86e9b9bd2c31da6eb173732
child 153117 d7d29572f9df1e01d1f324740a368984bace8923
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs898136
milestone25.0a1
backs out9c6dc3897c17585bb1b73fefd986302f66c94443
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
Backed out changeset 9c6dc3897c17 (bug 898136) for breaking SeaMonkey
dom/base/nsDOMClassInfo.cpp
dom/interfaces/base/moz.build
dom/interfaces/base/nsIDOMGlobalObjectConstructor.idl
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -246,16 +246,17 @@ using mozilla::dom::workers::ResolveWork
 #include "BluetoothDevice.h"
 #endif
 
 #include "DOMCameraManager.h"
 #include "DOMCameraControl.h"
 #include "DOMCameraCapabilities.h"
 #include "nsIOpenWindowEventDetail.h"
 #include "nsIAsyncScrollEventDetail.h"
+#include "nsIDOMGlobalObjectConstructor.h"
 #include "nsIDOMCanvasRenderingContext2D.h"
 #include "LockedFile.h"
 #include "nsDebug.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/Likely.h"
 
 #ifdef MOZ_TIME_MANAGER
@@ -2671,32 +2672,86 @@ BaseStubConstructor(nsIWeakReference* aW
     native = do_CreateInstance(*name_struct->mData->mConstructorCID, &rv);
   }
   if (NS_FAILED(rv)) {
     NS_ERROR("Failed to create the object");
     return rv;
   }
 
   nsCOMPtr<nsIJSNativeInitializer> initializer(do_QueryInterface(native));
-  if (initializer) {
+  nsCOMPtr<nsIDOMGlobalObjectConstructor> constructor(do_QueryInterface(native));
+  if (initializer || constructor) {
     // Initialize object using the current inner window, but only if
     // the caller can access it.
     nsCOMPtr<nsPIDOMWindow> owner = do_QueryReferent(aWeakOwner);
     nsPIDOMWindow* outerWindow = owner ? owner->GetOuterWindow() : nullptr;
     nsPIDOMWindow* currentInner =
       outerWindow ? outerWindow->GetCurrentInnerWindow() : nullptr;
     if (!currentInner ||
         (owner != currentInner &&
          !nsContentUtils::CanCallerAccess(currentInner))) {
       return NS_ERROR_DOM_SECURITY_ERR;
     }
 
-    rv = initializer->Initialize(currentInner, cx, obj, args);
-    if (NS_FAILED(rv)) {
-      return rv;
+    if (initializer) {
+      rv = initializer->Initialize(currentInner, cx, obj, args);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+    } else {
+      nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(native);
+
+      JS::Rooted<JSObject*> thisObject(cx, wrappedJS->GetJSObject());
+      if (!thisObject) {
+        return NS_ERROR_UNEXPECTED;
+      }
+
+      nsCxPusher pusher;
+      pusher.Push(cx);
+
+      JSAutoCompartment ac(cx, thisObject);
+
+      JS::Rooted<JS::Value> funval(cx);
+      if (!JS_GetProperty(cx, thisObject, "constructor", &funval) ||
+          !funval.isObject()) {
+        return NS_ERROR_UNEXPECTED;
+      }
+
+      // Check if the object is even callable.
+      NS_ENSURE_STATE(JS_ObjectIsCallable(cx, &funval.toObject()));
+      {
+        // wrap parameters in the target compartment
+        // we also pass in the calling window as the first argument
+        unsigned argc = args.length() + 1;
+        nsAutoArrayPtr<JS::Value> argv(new JS::Value[argc]);
+        JS::AutoArrayRooter rooter(cx, 0, argv);
+
+        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+        nsCOMPtr<nsIDOMWindow> currentWin(do_GetInterface(currentInner));
+        rv = WrapNative(cx, obj, currentWin, &NS_GET_IID(nsIDOMWindow),
+                        true, &argv[0], getter_AddRefs(holder));
+        if (!JS_WrapValue(cx, &argv[0]))
+          return NS_ERROR_FAILURE;
+        rooter.changeLength(1);
+
+        for (size_t i = 1; i < argc; ++i) {
+          argv[i] = args[i - 1];
+          if (!JS_WrapValue(cx, &argv[i]))
+            return NS_ERROR_FAILURE;
+          rooter.changeLength(i + 1);
+        }
+
+        JS::Rooted<JS::Value> frval(cx);
+        bool ret = JS_CallFunctionValue(cx, thisObject, funval, argc, argv,
+                                        frval.address());
+
+        if (!ret) {
+          return NS_ERROR_FAILURE;
+        }
+      }
     }
   }
 
   return WrapNative(cx, obj, native, true, args.rval().address());
 }
 
 static nsresult
 DefineInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj, const nsIID *aIID)
--- a/dom/interfaces/base/moz.build
+++ b/dom/interfaces/base/moz.build
@@ -11,16 +11,17 @@ XPIDL_SOURCES += [
     'nsIContentPrefService.idl',
     'nsIContentPrefService2.idl',
     'nsIContentURIGrouper.idl',
     'nsIDOMCRMFObject.idl',
     'nsIDOMChromeWindow.idl',
     'nsIDOMClientRect.idl',
     'nsIDOMClientRectList.idl',
     'nsIDOMConstructor.idl',
+    'nsIDOMGlobalObjectConstructor.idl',
     'nsIDOMGlobalPropertyInitializer.idl',
     'nsIDOMHistory.idl',
     'nsIDOMJSWindow.idl',
     'nsIDOMLocation.idl',
     'nsIDOMMediaQueryList.idl',
     'nsIDOMModalContentWindow.idl',
     'nsIDOMNavigator.idl',
     'nsIDOMPkcs11.idl',
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/base/nsIDOMGlobalObjectConstructor.idl
@@ -0,0 +1,19 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "domstubs.idl"
+
+[scriptable, uuid(cb439c73-0129-4289-a349-c5216e6b912a)]
+interface nsIDOMGlobalObjectConstructor : nsISupports
+{
+  /*
+   * JS use only
+   *
+   * The constructor() method will be called with any parameters passed
+   * to the object constructor.
+   * If the JS implementation returns a value, it will be ignored.
+   */
+  void constructor();
+};