Bug 855136 - Don't require call/construct args to NewProxyObject (r=luke)
authorBill McCloskey <wmccloskey@mozilla.com>
Tue, 26 Mar 2013 17:51:55 -0700
changeset 126581 3d7ab7be4d31ddd6c107668a4a4cc0f260e1af67
parent 126580 ba144296a12883b03880c2a25d2aa95b0b432c22
child 126582 b2818d4dccfe5d47ceffcaea6e06f3da4444aba2
push id24488
push userryanvm@gmail.com
push dateFri, 29 Mar 2013 00:54:52 +0000
treeherdermozilla-central@8aeabe064932 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs855136
milestone22.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 855136 - Don't require call/construct args to NewProxyObject (r=luke)
js/src/jsproxy.cpp
js/src/jsproxy.h
js/src/jswrapper.cpp
js/src/vm/ScopeObject.cpp
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -3208,29 +3208,26 @@ JS_FRIEND_DATA(Class) js::FunctionProxyC
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         NULL,                /* thisObject      */
     }
 };
 
 static JSObject *
 NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv_, TaggedProto proto_,
-                   JSObject *parent_, JSObject *call_, JSObject *construct_)
+               JSObject *parent_, ProxyCallable callable)
 {
     RootedValue priv(cx, priv_);
     Rooted<TaggedProto> proto(cx, proto_);
-    RootedObject parent(cx, parent_), call(cx, call_), construct(cx, construct_);
+    RootedObject parent(cx, parent_);
 
     JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
     JS_ASSERT_IF(parent, cx->compartment == parent->compartment());
-    JS_ASSERT_IF(construct, cx->compartment == construct->compartment());
-    JS_ASSERT_IF(call && cx->compartment != call->compartment(), priv.get() == ObjectValue(*call));
-    bool fun = call || construct;
     Class *clasp;
-    if (fun)
+    if (callable)
         clasp = &FunctionProxyClass;
     else
         clasp = handler->isOuterWindow() ? &OuterWindowProxyClass : &ObjectProxyClass;
 
     /*
      * Eagerly mark properties unknown for proxies, so we don't try to track
      * their properties and so that we don't need to walk the compartment if
      * their prototype changes later.
@@ -3245,35 +3242,49 @@ NewProxyObject(JSContext *cx, BaseProxyH
     gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
     if (handler->finalizeInBackground(priv))
         allocKind = GetBackgroundAllocKind(allocKind);
     RootedObject obj(cx, NewObjectWithGivenProto(cx, clasp, proto, parent, allocKind, newKind));
     if (!obj)
         return NULL;
     obj->initSlot(JSSLOT_PROXY_HANDLER, PrivateValue(handler));
     obj->initCrossCompartmentSlot(JSSLOT_PROXY_PRIVATE, priv);
-    if (fun) {
-        obj->initCrossCompartmentSlot(JSSLOT_PROXY_CALL, call ? ObjectValue(*call) : UndefinedValue());
-        if (construct) {
-            obj->initSlot(JSSLOT_PROXY_CONSTRUCT, ObjectValue(*construct));
-        }
-    }
 
     /* Don't track types of properties of proxies. */
     if (newKind != SingletonObject)
         MarkTypeObjectUnknownProperties(cx, obj->type());
 
     return obj;
 }
 
 JS_FRIEND_API(JSObject *)
 js::NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv_, JSObject *proto_,
-                   JSObject *parent_, JSObject *call_, JSObject *construct_)
+                   JSObject *parent_, ProxyCallable callable)
+{
+    return NewProxyObject(cx, handler, priv_, TaggedProto(proto_), parent_, callable);
+}
+
+JS_FRIEND_API(JSObject *)
+js::NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv_, JSObject *proto_,
+                   JSObject *parent_, JSObject *call, JSObject *construct)
 {
-    return NewProxyObject(cx, handler, priv_, TaggedProto(proto_), parent_, call_, construct_);
+    JS_ASSERT_IF(construct, cx->compartment == construct->compartment());
+    JS_ASSERT_IF(call && cx->compartment != call->compartment(), priv_ == ObjectValue(*call));
+
+    JSObject *proxy = NewProxyObject(cx, handler, priv_, TaggedProto(proto_), parent_,
+                                     call || construct ? ProxyIsCallable : ProxyNotCallable);
+    if (!proxy)
+        return NULL;
+
+    if (call)
+        proxy->initCrossCompartmentSlot(JSSLOT_PROXY_CALL, ObjectValue(*call));
+    if (construct)
+        proxy->initCrossCompartmentSlot(JSSLOT_PROXY_CONSTRUCT, ObjectValue(*construct));
+
+    return proxy;
 }
 
 JSObject *
 js::RenewProxyObject(JSContext *cx, JSObject *obj,
                      BaseProxyHandler *handler, Value priv)
 {
     JS_ASSERT_IF(IsCrossCompartmentWrapper(obj), IsDeadProxyObject(obj));
     JS_ASSERT(obj->getParent() == cx->global());
@@ -3392,17 +3403,18 @@ proxy_createFunction(JSContext *cx, unsi
     JSObject *construct = NULL;
     if (argc > 2) {
         construct = ValueToCallable(cx, vp[4], argc - 3);
         if (!construct)
             return false;
     }
 
     JSObject *proxy = NewProxyObject(cx, &ScriptedIndirectProxyHandler::singleton,
-                                     ObjectValue(*handler), proto, parent, call, construct);
+                                     ObjectValue(*handler), proto, parent,
+                                     call, construct);
     if (!proxy)
         return false;
 
     vp->setObject(*proxy);
     return true;
 }
 
 static JSFunctionSpec static_methods[] = {
--- a/js/src/jsproxy.h
+++ b/js/src/jsproxy.h
@@ -340,20 +340,28 @@ SetProxyHandler(RawObject obj, BaseProxy
 inline void
 SetProxyExtra(RawObject obj, size_t n, const Value &extra)
 {
     JS_ASSERT(IsProxy(obj));
     JS_ASSERT(n <= 1);
     SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra);
 }
 
+enum ProxyCallable {
+    ProxyNotCallable = false,
+    ProxyIsCallable = true
+};
+
 JS_FRIEND_API(JSObject *)
 NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
-               JSObject *proto, JSObject *parent,
-               JSObject *call = NULL, JSObject *construct = NULL);
+               JSObject *proto, JSObject *parent, ProxyCallable callable = ProxyNotCallable);
+
+JS_FRIEND_API(JSObject *)
+NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
+               JSObject *proto, JSObject *parent, JSObject *call, JSObject *construct);
 
 JSObject *
 RenewProxyObject(JSContext *cx, JSObject *obj, BaseProxyHandler *handler, Value priv);
 
 class JS_FRIEND_API(AutoEnterPolicy)
 {
   public:
     typedef BaseProxyHandler::Action Action;
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -812,17 +812,17 @@ DeadObjectProxy::getPrototypeOf(JSContex
 
 DeadObjectProxy DeadObjectProxy::singleton;
 int DeadObjectProxy::sDeadObjectFamily;
 
 JSObject *
 js::NewDeadProxyObject(JSContext *cx, JSObject *parent)
 {
     return NewProxyObject(cx, &DeadObjectProxy::singleton, NullValue(),
-                          NULL, parent, NULL, NULL);
+                          NULL, parent, ProxyNotCallable);
 }
 
 bool
 js::IsDeadProxyObject(RawObject obj)
 {
     return IsProxy(obj) && GetProxyHandler(obj) == &DeadObjectProxy::singleton;
 }
 
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -1471,18 +1471,17 @@ class DebugScopeProxy : public BaseProxy
 int DebugScopeProxy::family = 0;
 DebugScopeProxy DebugScopeProxy::singleton;
 
 /* static */ DebugScopeObject *
 DebugScopeObject::create(JSContext *cx, ScopeObject &scope, HandleObject enclosing)
 {
     JS_ASSERT(scope.compartment() == cx->compartment);
     JSObject *obj = NewProxyObject(cx, &DebugScopeProxy::singleton, ObjectValue(scope),
-                                   NULL /* proto */, &scope.global(),
-                                   NULL /* call */, NULL /* construct */);
+                                   NULL /* proto */, &scope.global(), ProxyNotCallable);
     if (!obj)
         return NULL;
 
     JS_ASSERT(!enclosing->isScope());
     SetProxyExtra(obj, ENCLOSING_EXTRA, ObjectValue(*enclosing));
     SetProxyExtra(obj, SNAPSHOT_EXTRA, NullValue());
 
     return &obj->asDebugScope();