mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 924720 - Part 5: Allow callers of NewProxyObject() to specify a Proxy JSClass. (r=jwalden)
This commit is contained in:
parent
b81801afd3
commit
fc6584c144
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 *)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user