Bug 780542. Make construction via a function proxy with an object in the constructor slot actually construct instead of just calling. a=lsblakk r=ejpbruel
☠☠ backed out by aa331c131a65 ☠ ☠
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 08 Aug 2012 11:41:46 -0400
changeset 100503 ad7dd2476dfe73a840887a955fe58727fc16f084
parent 100502 7488058a7c3f9798454b5587dc7732b2203506e9
child 100504 fe13653f05ecfa5efc271dd9c1d75a65bfdcd68f
push id1275
push userejpbruel@mozilla.com
push dateTue, 14 Aug 2012 18:11:26 +0000
treeherdermozilla-beta@ad7dd2476dfe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsblakk, ejpbruel
bugs780542
milestone15.0
Bug 780542. Make construction via a function proxy with an object in the constructor slot actually construct instead of just calling. a=lsblakk r=ejpbruel
js/src/jit-test/tests/basic/testProxyConstructors.js
js/src/jsproxy.cpp
js/xpconnect/tests/chrome/test_bug771429.xul
--- a/js/src/jit-test/tests/basic/testProxyConstructors.js
+++ b/js/src/jit-test/tests/basic/testProxyConstructors.js
@@ -1,17 +1,29 @@
 // |jit-test| error: ExitCleanly
 
 // proxies can return primitives
 assertEq(new (Proxy.createFunction({}, function(){}, function(){})), undefined);
 x = Proxy.createFunction((function () {}), Uint16Array, wrap)
 new(wrap(x))
+assertEq((new (Proxy.createFunction({},
+                                    function(){ this.x = 1 },
+                                    function(){ this.x = 2 }))).x, 2);
+try {
+    x = Proxy.createFunction((function () {}), Uint16Array, wrap)
+    new(wrap(x))
+    throw "Should not be reached"
+}
+catch (e) {
+    assertEq(String(e.message).indexOf('is not a constructor') === -1, false);
+}
 // proxies can return the callee
 var x = Proxy.createFunction({}, function (q) { return q; });
 assertEq(new x(x), x);
 try {
     var x = (Proxy.createFunction({}, "".indexOf));
     new x;
+    throw "Should not be reached"
 }
 catch (e) {
     assertEq(e.message, 'new x is not a constructor');
 }
 throw "ExitCleanly"
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -448,18 +448,18 @@ IndirectProxyHandler::call(JSContext *cx
 
 bool
 IndirectProxyHandler::construct(JSContext *cx, JSObject *proxy, unsigned argc,
                                 Value *argv, Value *rval)
 {
     JS_ASSERT(OperationInProgress(cx, proxy));
     Value fval = GetConstruct(proxy);
     if (fval.isUndefined())
-        return InvokeConstructor(cx, GetCall(proxy), argc, argv, rval);
-    return Invoke(cx, UndefinedValue(), fval, argc, argv, rval);
+        fval = GetCall(proxy);
+    return InvokeConstructor(cx, fval, argc, argv, rval);
 }
 
 bool
 IndirectProxyHandler::nativeCall(JSContext *cx, JSObject *proxy, Class *clasp,
                                  Native native, CallArgs args)
 {
     return CallJSNative(cx, native, args);
 }
--- a/js/xpconnect/tests/chrome/test_bug771429.xul
+++ b/js/xpconnect/tests/chrome/test_bug771429.xul
@@ -15,29 +15,32 @@ https://bugzilla.mozilla.org/show_bug.cg
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
       /** Test for Bug 771429 **/
       function f() {}
       function g() { return this; }
+      function ctor() { this.x = 1; }
       f.x = 2;
       f.g = g;
       var Cu = Components.utils;
       var s = new Cu.Sandbox(window, { sandboxPrototype: window } );
       try {
         is(Cu.evalInSandbox('f.x', s), 2,
            "Should have gotten the right thing back");
         is(Cu.evalInSandbox('f.g()', s), f,
            "Should have the right function object");
         is(Cu.evalInSandbox('var x = { z: 7 }; g.call(x).z', s), 7,
            "Should not rebind calls that are already bound");
         // And test what happens when we use the normal Function.prototype.call
         // on g instead of whatever our proxies happen to return.
         is(Cu.evalInSandbox('var x = { z: 7 }; Function.prototype.call.call(g, x).z', s), 7,
            "Should not rebind calls that are already bound");
+        is(Cu.evalInSandbox('new ctor();', s).x, 1,
+           "Should get a properly constructed object out of the sandbox");
       } catch (e) {
         ok(false, "Should not get an exception: " + e);
       }
   ]]>
   </script>
 </window>