Bug 924720 - Part 5: Allow callers of NewProxyObject() to specify a Proxy JSClass. (r=jwalden)

This commit is contained in:
Eric Faust 2014-01-29 17:20:16 -08:00
parent b81801afd3
commit fc6584c144
8 changed files with 38 additions and 29 deletions

View File

@ -574,7 +574,7 @@ JavaScriptParent::unwrap(JSContext *cx, ObjectId objId)
RootedValue v(cx, UndefinedValue());
ProxyOptions options;
options.setCallable(callable);
options.selectDefaultClass(callable);
obj = NewProxyObject(cx,
&CPOWProxyHandler::singleton,
v,

View File

@ -3179,7 +3179,7 @@ proxy(JSContext *cx, unsigned argc, jsval *vp)
return false;
RootedValue priv(cx, ObjectValue(*target));
ProxyOptions options;
options.setCallable(target->isCallable());
options.selectDefaultClass(target->isCallable());
ProxyObject *proxy =
ProxyObject::New(cx, &ScriptedDirectProxyHandler::singleton,
priv, TaggedProto(TaggedProto::LazyProto), cx->global(),
@ -3264,7 +3264,7 @@ proxy_createFunction(JSContext *cx, unsigned argc, Value *vp)
RootedValue priv(cx, ObjectValue(*handler));
ProxyOptions options;
options.setCallable(true);
options.selectDefaultClass(true);
JSObject *proxy =
ProxyObject::New(cx, &ScriptedIndirectProxyHandler::singleton,
priv, TaggedProto(proto), parent, options);

View File

@ -418,25 +418,32 @@ SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
class MOZ_STACK_CLASS ProxyOptions {
public:
ProxyOptions() : callable_(false),
singleton_(false)
ProxyOptions() : singleton_(false),
clasp_(UncallableProxyClassPtr)
{}
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;
}
const Class *clasp() const {
return clasp_;
}
ProxyOptions &setClass(const Class *claspArg) {
clasp_ = claspArg;
return *this;
}
ProxyOptions &selectDefaultClass(bool callable) {
const Class *classp = callable? CallableProxyClassPtr :
UncallableProxyClassPtr;
return setClass(classp);
}
private:
bool callable_;
bool singleton_;
const Class *clasp_;
};
JS_FRIEND_API(JSObject *)

View File

@ -47,7 +47,7 @@ Wrapper::New(JSContext *cx, JSObject *obj, JSObject *parent, Wrapper *handler)
RootedValue priv(cx, ObjectValue(*obj));
ProxyOptions options;
options.setCallable(obj->isCallable());
options.selectDefaultClass(obj->isCallable());
return NewProxyObject(cx, handler, priv, TaggedProto::LazyProto, parent, options);
}
@ -868,14 +868,6 @@ DeadObjectProxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandle
DeadObjectProxy DeadObjectProxy::singleton;
const char DeadObjectProxy::sDeadObjectFamily = 0;
JSObject *
js::NewDeadProxyObject(JSContext *cx, JSObject *parent,
const ProxyOptions &options)
{
return NewProxyObject(cx, &DeadObjectProxy::singleton, JS::NullHandleValue,
nullptr, parent, options);
}
bool
js::IsDeadProxyObject(JSObject *obj)
{

View File

@ -3788,7 +3788,7 @@ WrapperWithProto::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *p
RootedValue priv(cx, ObjectValue(*obj));
ProxyOptions options;
options.setCallable(obj->isCallable());
options.selectDefaultClass(obj->isCallable());
return NewProxyObject(cx, handler, priv, proto, parent, options);
}

View File

@ -20,14 +20,11 @@ ProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, Tag
Rooted<TaggedProto> proto(cx, proto_);
RootedObject parent(cx, parent_);
const Class *clasp = options.clasp();
JS_ASSERT(isValidProxyClass(clasp));
JS_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment());
JS_ASSERT_IF(parent, cx->compartment() == parent->compartment());
const Class *clasp;
if (handler->isOuterWindow())
clasp = &OuterWindowProxyObject::class_;
else
clasp = options.callable() ? &ProxyObject::callableClass_
: &ProxyObject::uncallableClass_;
/*
* Eagerly mark properties unknown for proxies, so we don't try to track

View File

@ -77,6 +77,19 @@ class ProxyObject : public JSObject
return &getReservedSlotRef(n);
}
static bool isValidProxyClass(const Class *clasp) {
// Since we can take classes from the outside, make sure that they
// are "sane". They have to quack enough like proxies for us to belive
// they should be treated as such.
// proxy_Trace is just a trivial wrapper around ProxyObject::trace for
// friend api exposure.
return clasp->isProxy() &&
(clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS) &&
clasp->trace == proxy_Trace &&
JSCLASS_RESERVED_SLOTS(clasp) >= PROXY_MINIMUM_SLOTS;
}
public:
static unsigned grayLinkSlot(JSObject *obj);

View File

@ -789,7 +789,7 @@ WrapCallable(JSContext *cx, JSObject *callable, JSObject *sandboxProtoProxy)
RootedValue priv(cx, ObjectValue(*callable));
js::ProxyOptions options;
options.setCallable(true);
options.selectDefaultClass(true);
return js::NewProxyObject(cx, &xpc::sandboxCallableProxyHandler,
priv, nullptr,
sandboxProtoProxy, options);