Bug 855136 - Don't use call/construct slots for direct proxies (r=luke)

This commit is contained in:
Bill McCloskey 2013-03-26 17:53:00 -07:00
Родитель 8b5998ff20
Коммит 297984ced3
6 изменённых файлов: 83 добавлений и 57 удалений

Просмотреть файл

@ -485,12 +485,6 @@ JSCompartment::markCrossCompartmentWrappers(JSTracer *trc)
Value referent = GetProxyPrivate(wrapper);
MarkValueRoot(trc, &referent, "cross-compartment wrapper");
JS_ASSERT(referent == GetProxyPrivate(wrapper));
if (IsFunctionProxy(wrapper)) {
Value call = GetProxyCall(wrapper);
MarkValueRoot(trc, &call, "cross-compartment wrapper");
JS_ASSERT(call == GetProxyCall(wrapper));
}
}
}
}

Просмотреть файл

@ -3260,11 +3260,6 @@ JSCompartment::findOutgoingEdges(ComponentFinder<JS::Zone> &finder)
if (w->isGCMarking())
finder.addEdgeTo(w);
}
#ifdef DEBUG
JSObject *wrapper = &e.front().value.toObject();
JS_ASSERT_IF(IsFunctionProxy(wrapper), &GetProxyCall(wrapper).toObject() == other);
#endif
}
Debugger::findCompartmentEdges(zone(), finder);

Просмотреть файл

@ -327,24 +327,16 @@ bool
BaseProxyHandler::call(JSContext *cx, HandleObject proxy, unsigned argc,
Value *vp)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
AutoValueRooter rval(cx);
RootedValue call(cx, GetCall(proxy));
JSBool ok = Invoke(cx, vp[1], call, argc, JS_ARGV(cx, vp), rval.addr());
if (ok)
JS_SET_RVAL(cx, vp, rval.value());
return ok;
JS_NOT_REACHED("callable proxies should implement call trap");
return false;
}
bool
BaseProxyHandler::construct(JSContext *cx, HandleObject proxy, unsigned argc,
Value *argv, MutableHandleValue rval)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedValue fval(cx, GetConstruct(proxy));
if (fval.isUndefined())
fval = GetCall(proxy);
return InvokeConstructor(cx, fval, argc, argv, rval.address());
JS_NOT_REACHED("callable proxies should implement construct trap");
return false;
}
JSString *
@ -358,19 +350,8 @@ BaseProxyHandler::obj_toString(JSContext *cx, HandleObject proxy)
JSString *
BaseProxyHandler::fun_toString(JSContext *cx, HandleObject proxy, unsigned indent)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
Value fval = GetCall(proxy);
if (IsFunctionProxy(proxy) &&
(fval.isPrimitive() || !fval.toObject().isFunction())) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_PROTO,
js_Function_str, js_toString_str,
"object");
return NULL;
}
RootedObject obj(cx, &fval.toObject());
return fun_toStringHelper(cx, obj, indent);
JS_NOT_REACHED("callable proxies should implement fun_toString trap");
return false;
}
bool
@ -511,6 +492,28 @@ DirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy,
return GetPropertyNames(cx, target, 0, &props);
}
bool
DirectProxyHandler::call(JSContext *cx, HandleObject proxy, unsigned argc,
Value *vp)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
AutoValueRooter rval(cx);
RootedValue target(cx, GetProxyPrivate(proxy));
JSBool ok = Invoke(cx, vp[1], target, argc, JS_ARGV(cx, vp), rval.addr());
if (ok)
JS_SET_RVAL(cx, vp, rval.value());
return ok;
}
bool
DirectProxyHandler::construct(JSContext *cx, HandleObject proxy, unsigned argc,
Value *argv, MutableHandleValue rval)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedValue target(cx, GetProxyPrivate(proxy));
return InvokeConstructor(cx, target, argc, argv, rval.address());
}
bool
DirectProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args)
@ -812,8 +815,12 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler {
MutableHandleValue vp) MOZ_OVERRIDE;
/* Spidermonkey extensions. */
virtual bool call(JSContext *cx, HandleObject proxy, unsigned argc, Value *vp) MOZ_OVERRIDE;
virtual bool construct(JSContext *cx, HandleObject proxy, unsigned argc,
Value *argv, MutableHandleValue rval) MOZ_OVERRIDE;
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args) MOZ_OVERRIDE;
virtual JSString *fun_toString(JSContext *cx, HandleObject proxy, unsigned indent) MOZ_OVERRIDE;
virtual bool defaultValue(JSContext *cx, HandleObject obj, JSType hint,
MutableHandleValue vp) MOZ_OVERRIDE;
@ -1011,6 +1018,30 @@ ScriptedIndirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigne
ReturnedValueMustNotBePrimitive(cx, proxy, cx->names().iterate, vp);
}
bool
ScriptedIndirectProxyHandler::call(JSContext *cx, HandleObject proxy, unsigned argc,
Value *vp)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
AutoValueRooter rval(cx);
RootedValue call(cx, GetCall(proxy));
JSBool ok = Invoke(cx, vp[1], call, argc, JS_ARGV(cx, vp), rval.addr());
if (ok)
JS_SET_RVAL(cx, vp, rval.value());
return ok;
}
bool
ScriptedIndirectProxyHandler::construct(JSContext *cx, HandleObject proxy, unsigned argc,
Value *argv, MutableHandleValue rval)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedValue fval(cx, GetConstruct(proxy));
if (fval.isUndefined())
fval = GetCall(proxy);
return InvokeConstructor(cx, fval, argc, argv, rval.address());
}
bool
ScriptedIndirectProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args)
@ -1018,6 +1049,23 @@ ScriptedIndirectProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, N
return BaseProxyHandler::nativeCall(cx, test, impl, args);
}
JSString *
ScriptedIndirectProxyHandler::fun_toString(JSContext *cx, HandleObject proxy, unsigned indent)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
Value fval = GetCall(proxy);
if (IsFunctionProxy(proxy) &&
(fval.isPrimitive() || !fval.toObject().isFunction())) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_PROTO,
js_Function_str, js_toString_str,
"object");
return NULL;
}
RootedObject obj(cx, &fval.toObject());
return fun_toStringHelper(cx, obj, indent);
}
bool
ScriptedIndirectProxyHandler::defaultValue(JSContext *cx, HandleObject proxy, JSType hint,
MutableHandleValue vp)
@ -3262,9 +3310,9 @@ js::NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv_,
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)
static JSObject *
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv_, JSObject *proto_,
JSObject *parent_, JSObject *call, JSObject *construct)
{
JS_ASSERT_IF(construct, cx->compartment == construct->compartment());
JS_ASSERT_IF(call && cx->compartment != call->compartment(), priv_ == ObjectValue(*call));

Просмотреть файл

@ -191,6 +191,9 @@ public:
/* Spidermonkey extensions. */
virtual bool isExtensible(JSObject *proxy) MOZ_OVERRIDE;
virtual bool call(JSContext *cx, HandleObject proxy, unsigned argc, Value *vp) MOZ_OVERRIDE;
virtual bool construct(JSContext *cx, HandleObject proxy, unsigned argc,
Value *argv, MutableHandleValue rval) MOZ_OVERRIDE;
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args) MOZ_OVERRIDE;
virtual bool hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v,
@ -316,13 +319,6 @@ GetProxyTargetObject(RawObject obj)
return GetProxyPrivate(obj).toObjectOrNull();
}
inline const Value &
GetProxyCall(RawObject obj)
{
JS_ASSERT(IsFunctionProxy(obj));
return GetReservedSlot(obj, JSSLOT_PROXY_CALL);
}
inline const Value &
GetProxyExtra(RawObject obj, size_t n)
{
@ -354,10 +350,6 @@ JS_FRIEND_API(JSObject *)
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
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);

Просмотреть файл

@ -46,7 +46,7 @@ Wrapper::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
AutoMarkInDeadZone amd(cx->zone());
return NewProxyObject(cx, handler, ObjectValue(*obj), proto, parent,
obj->isCallable() ? obj : NULL, NULL);
obj->isCallable() ? ProxyIsCallable : ProxyNotCallable);
}
JSObject *

Просмотреть файл

@ -3057,8 +3057,7 @@ bool
xpc::SandboxCallableProxyHandler::call(JSContext *cx, JS::Handle<JSObject*> proxy,
unsigned argc, Value *vp)
{
// We forward the call to our underlying callable. The callable to forward
// to can be gotten via GetProxyCall.
// We forward the call to our underlying callable.
// The parent of our proxy is the SandboxProxyHandler proxy
JSObject *sandboxProxy = JS_GetParent(proxy);
@ -3106,7 +3105,7 @@ xpc::SandboxCallableProxyHandler::call(JSContext *cx, JS::Handle<JSObject*> prox
thisVal = ObjectValue(*js::GetProxyTargetObject(sandboxProxy));
}
return JS::Call(cx, thisVal, js::GetProxyCall(proxy), argc,
return JS::Call(cx, thisVal, js::GetProxyPrivate(proxy), argc,
JS_ARGV(cx, vp), vp);
}
@ -3125,11 +3124,9 @@ WrapCallable(JSContext *cx, JSObject *callable, JSObject *sandboxProtoProxy)
js::GetProxyHandler(sandboxProtoProxy) ==
&xpc::sandboxProxyHandler);
// We need to pass the given callable in as the "call" and
// "construct" so we get a function proxy.
return js::NewProxyObject(cx, &xpc::sandboxCallableProxyHandler,
ObjectValue(*callable), nullptr,
sandboxProtoProxy, callable, callable);
sandboxProtoProxy, js::ProxyIsCallable);
}
template<typename Op>