Bug 921454 - Refactor proxy creation to use an options object. r=jonco

This commit is contained in:
Bobby Holley 2013-10-04 13:29:35 +02:00
parent e049188b70
commit f8062f062d
9 changed files with 51 additions and 24 deletions

View File

@ -211,11 +211,12 @@ WindowNamedPropertiesHandler::Install(JSContext* aCx,
// chain, it needs a singleton type to avoid polluting type information
// for properties on the window.
JS::Rooted<JSObject*> gsp(aCx);
js::ProxyOptions options;
options.setSingleton(true);
gsp = js::NewProxyObject(aCx, WindowNamedPropertiesHandler::getInstance(),
JS::NullHandleValue, protoProto,
js::GetGlobalForObjectCrossCompartment(aProto),
js::ProxyNotCallable,
/* singleton = */ true);
options);
if (!gsp) {
return;
}

View File

@ -572,12 +572,14 @@ JavaScriptParent::unwrap(JSContext *cx, ObjectId objId)
RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
RootedValue v(cx, UndefinedValue());
ProxyOptions options;
options.setCallable(callable);
obj = NewProxyObject(cx,
&CPOWProxyHandler::singleton,
v,
nullptr,
global,
callable ? ProxyIsCallable : ProxyNotCallable);
options);
if (!obj)
return nullptr;

View File

@ -3143,10 +3143,10 @@ const Class* const js::OuterWindowProxyClassPtr = &OuterWindowProxyObject::class
JS_FRIEND_API(JSObject *)
js::NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, JSObject *proto_,
JSObject *parent_, ProxyCallable callable, bool singleton)
JSObject *parent_, const ProxyOptions &options)
{
return ProxyObject::New(cx, handler, priv, TaggedProto(proto_), parent_,
callable, singleton);
options);
}
void
@ -3186,11 +3186,12 @@ proxy(JSContext *cx, unsigned argc, jsval *vp)
if (!JSObject::getProto(cx, target, &proto))
return false;
RootedValue priv(cx, ObjectValue(*target));
ProxyOptions options;
options.setCallable(target->isCallable());
ProxyObject *proxy =
ProxyObject::New(cx, &ScriptedDirectProxyHandler::singleton,
priv, TaggedProto(proto), cx->global(),
target->isCallable() ? ProxyIsCallable
: ProxyNotCallable);
options);
if (!proxy)
return false;
proxy->setExtra(0, ObjectOrNullValue(handler));
@ -3269,9 +3270,11 @@ proxy_createFunction(JSContext *cx, unsigned argc, Value *vp)
ccHolder->setReservedSlot(1, ObjectValue(*construct));
RootedValue priv(cx, ObjectValue(*handler));
ProxyOptions options;
options.setCallable(true);
JSObject *proxy =
ProxyObject::New(cx, &ScriptedIndirectProxyHandler::singleton,
priv, TaggedProto(proto), parent, ProxyIsCallable);
priv, TaggedProto(proto), parent, options);
if (!proxy)
return false;
proxy->as<ProxyObject>().setExtra(0, ObjectValue(*ccHolder));

View File

@ -350,15 +350,32 @@ SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
SetReservedSlot(obj, PROXY_EXTRA_SLOT + n, extra);
}
enum ProxyCallable {
ProxyNotCallable = false,
ProxyIsCallable = true
class MOZ_STACK_CLASS ProxyOptions {
public:
ProxyOptions() : callable_(false),
singleton_(false)
{}
bool callable() const { return callable_; }
ProxyOptions &setCallable(bool flag) {
callable_ = flag;
return *this;
}
bool singleton() const { return singleton_; }
ProxyOptions &setSingleton(bool flag) {
singleton_ = flag;
return *this;
}
private:
bool callable_;
bool singleton_;
};
JS_FRIEND_API(JSObject *)
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv,
JSObject *proto, JSObject *parent,
ProxyCallable callable = ProxyNotCallable, bool singleton = false);
JSObject *proto, JSObject *parent, const ProxyOptions &options = ProxyOptions());
JSObject *
RenewProxyObject(JSContext *cx, JSObject *obj, BaseProxyHandler *handler, Value priv);

View File

@ -47,8 +47,9 @@ Wrapper::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, Wr
AutoMarkInDeadZone amd(cx->zone());
RootedValue priv(cx, ObjectValue(*obj));
return NewProxyObject(cx, handler, priv, proto, parent,
obj->isCallable() ? ProxyIsCallable : ProxyNotCallable);
ProxyOptions options;
options.setCallable(obj->isCallable());
return NewProxyObject(cx, handler, priv, proto, parent, options);
}
JSObject *
@ -839,7 +840,7 @@ JSObject *
js::NewDeadProxyObject(JSContext *cx, JSObject *parent)
{
return NewProxyObject(cx, &DeadObjectProxy::singleton, JS::NullHandleValue,
NULL, parent, ProxyNotCallable);
NULL, parent);
}
bool

View File

@ -15,7 +15,7 @@ using namespace js;
/* static */ ProxyObject *
ProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, TaggedProto proto_,
JSObject *parent_, ProxyCallable callable, bool singleton)
JSObject *parent_, const ProxyOptions &options)
{
Rooted<TaggedProto> proto(cx, proto_);
RootedObject parent(cx, parent_);
@ -26,22 +26,22 @@ ProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, Tag
if (handler->isOuterWindow())
clasp = &OuterWindowProxyObject::class_;
else
clasp = callable ? &ProxyObject::callableClass_
: &ProxyObject::uncallableClass_;
clasp = options.callable() ? &ProxyObject::callableClass_
: &ProxyObject::uncallableClass_;
/*
* 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.
*/
if (proto.isObject() && !singleton) {
if (proto.isObject() && !options.singleton()) {
RootedObject protoObj(cx, proto.toObject());
if (!JSObject::setNewTypeUnknown(cx, clasp, protoObj))
return NULL;
}
NewObjectKind newKind =
(clasp == &OuterWindowProxyObject::class_ || singleton) ? SingletonObject : GenericObject;
(clasp == &OuterWindowProxyObject::class_ || options.singleton()) ? SingletonObject : GenericObject;
gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
if (handler->finalizeInBackground(priv))
allocKind = GetBackgroundAllocKind(allocKind);

View File

@ -24,7 +24,8 @@ class ProxyObject : public JSObject
public:
static ProxyObject *New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv,
TaggedProto proto_, JSObject *parent_, ProxyCallable callable, bool singleton = false);
TaggedProto proto_, JSObject *parent_,
const ProxyOptions &options);
const Value &private_() {
return GetReservedSlot(this, PRIVATE_SLOT);

View File

@ -1508,7 +1508,7 @@ DebugScopeObject::create(JSContext *cx, ScopeObject &scope, HandleObject enclosi
JS_ASSERT(scope.compartment() == cx->compartment());
RootedValue priv(cx, ObjectValue(scope));
JSObject *obj = NewProxyObject(cx, &DebugScopeProxy::singleton, priv,
nullptr /* proto */, &scope.global(), ProxyNotCallable);
nullptr /* proto */, &scope.global());
if (!obj)
return nullptr;

View File

@ -719,9 +719,11 @@ WrapCallable(JSContext *cx, JSObject *callable, JSObject *sandboxProtoProxy)
&xpc::sandboxProxyHandler);
RootedValue priv(cx, ObjectValue(*callable));
js::ProxyOptions options;
options.setCallable(true);
return js::NewProxyObject(cx, &xpc::sandboxCallableProxyHandler,
priv, nullptr,
sandboxProtoProxy, js::ProxyIsCallable);
sandboxProtoProxy, options);
}
template<typename Op>