зеркало из https://github.com/mozilla/gecko-dev.git
Bug 836301 - Hoist some assertions, remove a bunch of no-op trap overrides, and add assertions that we've entered our policy. r=mrbkap
This commit is contained in:
Родитель
59d3c6c36d
Коммит
0c9994db1d
|
@ -2157,8 +2157,9 @@ ia64*-hpux*)
|
|||
# that behavior) that it's better to turn it off.
|
||||
# MSVC warning C4819 warns some UTF-8 characters (e.g. copyright sign)
|
||||
# on non-Western system locales even if it is in a comment.
|
||||
# khuey says we can safely ignore MSVC warning C4251
|
||||
CFLAGS="$CFLAGS -wd4819"
|
||||
CXXFLAGS="$CXXFLAGS -wd4345 -wd4351 -wd4482 -wd4800 -wd4819"
|
||||
CXXFLAGS="$CXXFLAGS -wd4251 -wd4345 -wd4351 -wd4482 -wd4800 -wd4819"
|
||||
# make 'foo == bar;' error out
|
||||
CFLAGS="$CFLAGS -we4553"
|
||||
CXXFLAGS="$CXXFLAGS -we4553"
|
||||
|
|
|
@ -1684,7 +1684,8 @@ ia64*-hpux*)
|
|||
CFLAGS="$CFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
|
||||
CXXFLAGS="$CXXFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
|
||||
# MSVC warning C4244 is ubiquitous, useless, and annoying.
|
||||
CXXFLAGS="$CXXFLAGS -wd4244"
|
||||
# khuey says we can safely ignore MSVC warning C4251
|
||||
CXXFLAGS="$CXXFLAGS -wd4244 -wd4251"
|
||||
# make 'foo == bar;' error out
|
||||
CFLAGS="$CFLAGS -we4553"
|
||||
CXXFLAGS="$CXXFLAGS -we4553"
|
||||
|
|
|
@ -881,6 +881,9 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
|||
ionReturnOverride_(MagicValue(JS_ARG_POISON)),
|
||||
useHelperThreads_(useHelperThreads),
|
||||
requestedHelperThreadCount(-1),
|
||||
#ifdef DEBUG
|
||||
enteredPolicy(NULL),
|
||||
#endif
|
||||
rngNonce(0)
|
||||
{
|
||||
/* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
|
||||
|
|
|
@ -569,7 +569,7 @@ struct MallocProvider
|
|||
namespace gc {
|
||||
class MarkingValidator;
|
||||
} // namespace gc
|
||||
|
||||
class AutoEnterPolicy;
|
||||
} // namespace js
|
||||
|
||||
struct JSRuntime : js::RuntimeFriendFields,
|
||||
|
@ -1301,7 +1301,11 @@ struct JSRuntime : js::RuntimeFriendFields,
|
|||
return 0;
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
public:
|
||||
js::AutoEnterPolicy *enteredPolicy;
|
||||
|
||||
#endif
|
||||
private:
|
||||
/*
|
||||
* Used to ensure that compartments created at the same time get different
|
||||
|
|
|
@ -1416,6 +1416,13 @@ class JS_FRIEND_API(AutoCTypesActivityCallback) {
|
|||
}
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
extern JS_FRIEND_API(void)
|
||||
assertEnteredPolicy(JSContext *cx, JSObject *obj, jsid id);
|
||||
#else
|
||||
inline JS_FRIEND_API(void) assertEnteredPolicy(JSContext *cx, JSObject *obj, jsid id) {};
|
||||
#endif
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsfriendapi_h___ */
|
||||
|
|
|
@ -63,6 +63,38 @@ js::AutoEnterPolicy::reportError(JSContext *cx, jsid id)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
js::AutoEnterPolicy::recordEnter(JSContext *cx, JSObject *proxy, jsid id)
|
||||
{
|
||||
if (allowed()) {
|
||||
context = cx;
|
||||
enteredProxy.construct(cx, proxy);
|
||||
enteredId.construct(cx, id);
|
||||
prev = cx->runtime->enteredPolicy;
|
||||
cx->runtime->enteredPolicy = this;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js::AutoEnterPolicy::recordLeave()
|
||||
{
|
||||
if (!enteredProxy.empty()) {
|
||||
JS_ASSERT(context->runtime->enteredPolicy == this);
|
||||
context->runtime->enteredPolicy = prev;
|
||||
}
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id)
|
||||
{
|
||||
MOZ_ASSERT(proxy->isProxy());
|
||||
MOZ_ASSERT(cx->runtime->enteredPolicy);
|
||||
MOZ_ASSERT(cx->runtime->enteredPolicy->enteredProxy.ref().get() == proxy);
|
||||
MOZ_ASSERT(cx->runtime->enteredPolicy->enteredId.ref().get() == id);
|
||||
}
|
||||
#endif
|
||||
|
||||
BaseProxyHandler::BaseProxyHandler(void *family)
|
||||
: mFamily(family),
|
||||
mHasPrototype(false),
|
||||
|
@ -85,6 +117,7 @@ BaseProxyHandler::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act,
|
|||
bool
|
||||
BaseProxyHandler::has(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy_, id_);
|
||||
RootedObject proxy(cx, proxy_);
|
||||
RootedId id(cx, id_);
|
||||
AutoPropertyDescriptorRooter desc(cx);
|
||||
|
@ -97,6 +130,7 @@ BaseProxyHandler::has(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
|
|||
bool
|
||||
BaseProxyHandler::hasOwn(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy_, id_);
|
||||
RootedObject proxy(cx, proxy_);
|
||||
RootedId id(cx, id_);
|
||||
AutoPropertyDescriptorRooter desc(cx);
|
||||
|
@ -109,6 +143,7 @@ BaseProxyHandler::hasOwn(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
|
|||
bool
|
||||
BaseProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver_, jsid id_, Value *vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id_);
|
||||
RootedObject receiver(cx, receiver_);
|
||||
RootedId id(cx, id_);
|
||||
|
||||
|
@ -150,6 +185,7 @@ BaseProxyHandler::getElementIfPresent(JSContext *cx, JSObject *proxy_, JSObject
|
|||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
|
||||
if (!has(cx, proxy, id, present))
|
||||
return false;
|
||||
|
@ -166,6 +202,7 @@ bool
|
|||
BaseProxyHandler::set(JSContext *cx, JSObject *proxy_, JSObject *receiver_, jsid id_, bool strict,
|
||||
Value *vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy_, id_);
|
||||
RootedObject proxy(cx, proxy_), receiver(cx, receiver_);
|
||||
RootedId id(cx, id_);
|
||||
|
||||
|
@ -242,6 +279,7 @@ BaseProxyHandler::set(JSContext *cx, JSObject *proxy_, JSObject *receiver_, jsid
|
|||
bool
|
||||
BaseProxyHandler::keys(JSContext *cx, JSObject *proxyArg, AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxyArg, JSID_VOID);
|
||||
JS_ASSERT(props.length() == 0);
|
||||
|
||||
RootedObject proxy(cx, proxyArg);
|
||||
|
@ -255,6 +293,7 @@ BaseProxyHandler::keys(JSContext *cx, JSObject *proxyArg, AutoIdVector &props)
|
|||
for (size_t j = 0, len = props.length(); j < len; j++) {
|
||||
JS_ASSERT(i <= j);
|
||||
jsid id = props[j];
|
||||
AutoWaivePolicy policy(cx, proxy, id);
|
||||
if (!getOwnPropertyDescriptor(cx, proxy, id, &desc, 0))
|
||||
return false;
|
||||
if (desc.obj && (desc.attrs & JSPROP_ENUMERATE))
|
||||
|
@ -270,6 +309,7 @@ BaseProxyHandler::keys(JSContext *cx, JSObject *proxyArg, AutoIdVector &props)
|
|||
bool
|
||||
BaseProxyHandler::iterate(JSContext *cx, JSObject *proxy_, unsigned flags, Value *vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy_, JSID_VOID);
|
||||
RootedObject proxy(cx, proxy_);
|
||||
|
||||
AutoIdVector props(cx);
|
||||
|
@ -291,6 +331,7 @@ bool
|
|||
BaseProxyHandler::call(JSContext *cx, JSObject *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());
|
||||
|
@ -303,6 +344,7 @@ bool
|
|||
BaseProxyHandler::construct(JSContext *cx, JSObject *proxy_, unsigned argc,
|
||||
Value *argv, Value *rval)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy_, JSID_VOID);
|
||||
RootedObject proxy(cx, proxy_);
|
||||
RootedValue fval(cx, GetConstruct(proxy_));
|
||||
if (fval.isUndefined())
|
||||
|
@ -321,6 +363,7 @@ BaseProxyHandler::obj_toString(JSContext *cx, JSObject *proxy)
|
|||
JSString *
|
||||
BaseProxyHandler::fun_toString(JSContext *cx, JSObject *proxy, unsigned indent)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
Value fval = GetCall(proxy);
|
||||
if (IsFunctionProxy(proxy) &&
|
||||
(fval.isPrimitive() || !fval.toObject().isFunction())) {
|
||||
|
@ -366,6 +409,7 @@ BaseProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl im
|
|||
bool
|
||||
BaseProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
RootedValue val(cx, ObjectValue(*proxy.get()));
|
||||
js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
|
||||
JSDVG_SEARCH_STACK, val, NullPtr());
|
||||
|
@ -402,6 +446,8 @@ bool
|
|||
DirectProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy,
|
||||
jsid id, PropertyDescriptor *desc, unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
return JS_GetPropertyDescriptorById(cx, target, id, 0, desc);
|
||||
}
|
||||
|
@ -426,6 +472,7 @@ bool
|
|||
DirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy,
|
||||
jsid id, PropertyDescriptor *desc, unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
return GetOwnPropertyDescriptor(cx, target, id, 0, desc);
|
||||
}
|
||||
|
@ -434,6 +481,7 @@ bool
|
|||
DirectProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id_,
|
||||
PropertyDescriptor *desc)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id_);
|
||||
RootedObject obj(cx, GetProxyTargetObject(proxy));
|
||||
Rooted<jsid> id(cx, id_);
|
||||
Rooted<Value> v(cx, desc->value);
|
||||
|
@ -445,6 +493,7 @@ bool
|
|||
DirectProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
return GetPropertyNames(cx, target, JSITER_OWNONLY | JSITER_HIDDEN, &props);
|
||||
}
|
||||
|
@ -453,6 +502,7 @@ bool
|
|||
DirectProxyHandler::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
{
|
||||
RootedValue v(cx);
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
if (!JS_DeletePropertyById2(cx, target, id, v.address()))
|
||||
return false;
|
||||
|
@ -467,6 +517,8 @@ bool
|
|||
DirectProxyHandler::enumerate(JSContext *cx, JSObject *proxy,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
return GetPropertyNames(cx, target, 0, &props);
|
||||
}
|
||||
|
@ -488,6 +540,7 @@ bool
|
|||
DirectProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v,
|
||||
bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
JSBool b;
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
if (!JS_HasInstance(cx, target, v, &b))
|
||||
|
@ -508,6 +561,7 @@ DirectProxyHandler::objectClassIs(JSObject *proxy, ESClassValue classValue,
|
|||
JSString *
|
||||
DirectProxyHandler::obj_toString(JSContext *cx, JSObject *proxy)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
return obj_toStringHelper(cx, GetProxyTargetObject(proxy));
|
||||
}
|
||||
|
||||
|
@ -515,6 +569,7 @@ JSString *
|
|||
DirectProxyHandler::fun_toString(JSContext *cx, JSObject *proxy,
|
||||
unsigned indent)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
return fun_toStringHelper(cx, target, indent);
|
||||
}
|
||||
|
@ -550,6 +605,8 @@ DirectProxyHandler::DirectProxyHandler(void *family)
|
|||
bool
|
||||
DirectProxyHandler::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
JSBool found;
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
if (!JS_HasPropertyById(cx, target, id, &found))
|
||||
|
@ -561,6 +618,7 @@ DirectProxyHandler::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
|||
bool
|
||||
DirectProxyHandler::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
AutoPropertyDescriptorRooter desc(cx);
|
||||
if (!JS_GetPropertyDescriptorById(cx, target, id, 0, &desc))
|
||||
|
@ -573,6 +631,7 @@ bool
|
|||
DirectProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver_,
|
||||
jsid id_, Value *vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id_);
|
||||
RootedObject receiver(cx, receiver_);
|
||||
RootedId id(cx, id_);
|
||||
RootedValue value(cx);
|
||||
|
@ -588,6 +647,7 @@ bool
|
|||
DirectProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiverArg,
|
||||
jsid id_, bool strict, Value *vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id_);
|
||||
RootedId id(cx, id_);
|
||||
Rooted<JSObject*> receiver(cx, receiverArg);
|
||||
RootedValue value(cx, *vp);
|
||||
|
@ -602,6 +662,7 @@ DirectProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiverArg,
|
|||
bool
|
||||
DirectProxyHandler::keys(JSContext *cx, JSObject *proxy, AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
return GetPropertyNames(cx, GetProxyTargetObject(proxy), JSITER_OWNONLY, &props);
|
||||
}
|
||||
|
||||
|
@ -609,6 +670,8 @@ bool
|
|||
DirectProxyHandler::iterate(JSContext *cx, JSObject *proxy, unsigned flags,
|
||||
Value *vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
Rooted<JSObject*> target(cx, GetProxyTargetObject(proxy));
|
||||
RootedValue value(cx);
|
||||
if (!GetIterator(cx, target, flags, &value))
|
||||
|
|
|
@ -349,22 +349,66 @@ class JS_FRIEND_API(AutoEnterPolicy)
|
|||
typedef BaseProxyHandler::Action Action;
|
||||
AutoEnterPolicy(JSContext *cx, BaseProxyHandler *handler,
|
||||
JSObject *wrapper, jsid id, Action act, bool mayThrow)
|
||||
#ifdef DEBUG
|
||||
: context(NULL)
|
||||
#endif
|
||||
{
|
||||
allow = handler->hasPolicy() ? handler->enter(cx, wrapper, id, act, &rv)
|
||||
: true;
|
||||
recordEnter(cx, wrapper, id);
|
||||
if (!allow && !rv && mayThrow)
|
||||
reportError(cx, id);
|
||||
}
|
||||
|
||||
virtual ~AutoEnterPolicy() { recordLeave(); }
|
||||
inline bool allowed() { return allow; }
|
||||
inline bool returnValue() { JS_ASSERT(!allowed()); return rv; }
|
||||
|
||||
protected:
|
||||
// no-op constructor for subclass
|
||||
AutoEnterPolicy()
|
||||
#ifdef DEBUG
|
||||
: context(NULL)
|
||||
#endif
|
||||
{};
|
||||
void reportError(JSContext *cx, jsid id);
|
||||
bool allow;
|
||||
bool rv;
|
||||
|
||||
#ifdef DEBUG
|
||||
JSContext *context;
|
||||
mozilla::Maybe<RootedObject> enteredProxy;
|
||||
mozilla::Maybe<RootedId> enteredId;
|
||||
// NB: We explicitly don't track the entered action here, because sometimes
|
||||
// SET traps do an implicit GET during their implementation, leading to
|
||||
// spurious assertions.
|
||||
AutoEnterPolicy *prev;
|
||||
void recordEnter(JSContext *cx, JSObject *proxy, jsid id);
|
||||
void recordLeave();
|
||||
|
||||
friend JS_FRIEND_API(void) assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id);
|
||||
#else
|
||||
inline void recordEnter(JSContext *cx, JSObject *proxy, jsid id) {}
|
||||
inline void recordLeave() {}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
class JS_FRIEND_API(AutoWaivePolicy) : public AutoEnterPolicy {
|
||||
public:
|
||||
AutoWaivePolicy(JSContext *cx, JSObject *proxy, jsid id)
|
||||
{
|
||||
allow = true;
|
||||
recordEnter(cx, proxy, id);
|
||||
}
|
||||
};
|
||||
#else
|
||||
class JS_FRIEND_API(AutoWaivePolicy) {
|
||||
public: AutoWaivePolicy(JSContext *cx, JSObject *proxy, jsid id) {};
|
||||
};
|
||||
#endif
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
|
|
|
@ -126,54 +126,6 @@ Wrapper::~Wrapper()
|
|||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapperArg,
|
||||
jsid id, PropertyDescriptor *desc, unsigned flags)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called when there's a prototype.
|
||||
return DirectProxyHandler::getPropertyDescriptor(cx, wrapper, id, desc, flags);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapperArg,
|
||||
jsid id, PropertyDescriptor *desc, unsigned flags)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::getOwnPropertyDescriptor(cx, wrapper, id, desc, flags);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::defineProperty(JSContext *cx, JSObject *wrapperArg, jsid id,
|
||||
PropertyDescriptor *desc)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::defineProperty(cx, wrapper, id, desc);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::getOwnPropertyNames(JSContext *cx, JSObject *wrapperArg,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::getOwnPropertyNames(cx, wrapper, props);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::delete_(JSContext *cx, JSObject *wrapperArg, jsid id, bool *bp)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::delete_(cx, wrapper, id, bp);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::enumerate(JSContext *cx, JSObject *wrapperArg, AutoIdVector &props)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called when there's a prototype.
|
||||
return DirectProxyHandler::enumerate(cx, wrapper, props);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ordinarily, the convert trap would require unwrapping. However, the default
|
||||
* implementation of convert, JS_ConvertStub, obtains a default value by calling
|
||||
|
@ -208,95 +160,6 @@ Wrapper::defaultValue(JSContext *cx, JSObject *wrapperArg, JSType hint, Value *v
|
|||
return DirectProxyHandler::defaultValue(cx, wrapper, hint, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::has(JSContext *cx, JSObject *wrapperArg, jsid id, bool *bp)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called when there's a prototype.
|
||||
return DirectProxyHandler::has(cx, wrapper, id, bp);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::hasOwn(JSContext *cx, JSObject *wrapperArg, jsid id, bool *bp)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::hasOwn(cx, wrapper, id, bp);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::get(JSContext *cx, JSObject *wrapperArg, JSObject *receiver, jsid id, Value *vp)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::get(cx, wrapper, receiver, id, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::set(JSContext *cx, JSObject *wrapperArg, JSObject *receiver, jsid id, bool strict,
|
||||
Value *vp)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::set(cx, wrapper, receiver, id, strict, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::keys(JSContext *cx, JSObject *wrapperArg, AutoIdVector &props)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::keys(cx, wrapper, props);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::iterate(JSContext *cx, JSObject *wrapperArg, unsigned flags, Value *vp)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called when there's a prototype.
|
||||
return DirectProxyHandler::iterate(cx, wrapper, flags, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::call(JSContext *cx, JSObject *wrapperArg, unsigned argc, Value *vp)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::call(cx, wrapper, argc, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::construct(JSContext *cx, JSObject *wrapperArg, unsigned argc, Value *argv, Value *vp)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
return DirectProxyHandler::construct(cx, wrapper, argc, argv, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args)
|
||||
{
|
||||
RootedObject wrapper(cx, &args.thisv().toObject());
|
||||
// Note - we don't enter a policy here because our security architecture guards
|
||||
// against nativeCall by overriding the trap itself in the right circumstances.
|
||||
return DirectProxyHandler::nativeCall(cx, test, impl, args);
|
||||
}
|
||||
|
||||
bool
|
||||
Wrapper::hasInstance(JSContext *cx, HandleObject wrapper, MutableHandleValue v, bool *bp)
|
||||
{
|
||||
return DirectProxyHandler::hasInstance(cx, wrapper, v, bp);
|
||||
}
|
||||
|
||||
JSString *
|
||||
Wrapper::obj_toString(JSContext *cx, JSObject *wrapperArg)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapperArg);
|
||||
JSString *str = DirectProxyHandler::obj_toString(cx, wrapper);
|
||||
return str;
|
||||
}
|
||||
|
||||
JSString *
|
||||
Wrapper::fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent)
|
||||
{
|
||||
JSString *str = DirectProxyHandler::fun_toString(cx, wrapper, indent);
|
||||
return str;
|
||||
}
|
||||
|
||||
Wrapper Wrapper::singleton((unsigned)0);
|
||||
Wrapper Wrapper::singletonWithPrototype((unsigned)0, true);
|
||||
|
||||
|
|
|
@ -66,38 +66,6 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
|
|||
virtual ~Wrapper();
|
||||
|
||||
/* ES5 Harmony fundamental wrapper traps. */
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper,
|
||||
jsid id, PropertyDescriptor *desc,
|
||||
unsigned flags) MOZ_OVERRIDE;
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper,
|
||||
jsid id, PropertyDescriptor *desc,
|
||||
unsigned flags) MOZ_OVERRIDE;
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper,
|
||||
AutoIdVector &props) MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, JSObject *wrapper,
|
||||
AutoIdVector &props) MOZ_OVERRIDE;
|
||||
|
||||
/* ES5 Harmony derived wrapper traps. */
|
||||
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, bool strict,
|
||||
Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, JSObject *wrapper, unsigned flags, Value *vp) MOZ_OVERRIDE;
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual bool call(JSContext *cx, JSObject *wrapper, unsigned argc, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *rval) MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
|
||||
CallArgs args) MOZ_OVERRIDE;
|
||||
virtual bool hasInstance(JSContext *cx, HandleObject wrapper, MutableHandleValue v, bool *bp) MOZ_OVERRIDE;
|
||||
virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE;
|
||||
virtual bool defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint,
|
||||
Value *vp) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ namespace xpc {
|
|||
// their prototype, we have to instrument the traps to do this manually.
|
||||
ChromeObjectWrapper ChromeObjectWrapper::singleton;
|
||||
|
||||
using js::assertEnteredPolicy;
|
||||
|
||||
static bool
|
||||
AllowedByBase(JSContext *cx, JSObject *wrapper, jsid id, js::Wrapper::Action act)
|
||||
{
|
||||
|
@ -58,6 +60,7 @@ ChromeObjectWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapper,
|
|||
jsid id, js::PropertyDescriptor *desc,
|
||||
unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
// First, try a lookup on the base wrapper if permitted.
|
||||
desc->obj = NULL;
|
||||
if (AllowedByBase(cx, wrapper, id, Wrapper::GET) &&
|
||||
|
@ -87,6 +90,7 @@ ChromeObjectWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapper,
|
|||
bool
|
||||
ChromeObjectWrapper::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
// Try the lookup on the base wrapper if permitted.
|
||||
if (AllowedByBase(cx, wrapper, id, js::Wrapper::GET) &&
|
||||
!ChromeObjectWrapperBase::has(cx, wrapper, id, bp))
|
||||
|
@ -114,6 +118,7 @@ bool
|
|||
ChromeObjectWrapper::get(JSContext *cx, JSObject *wrapper, JSObject *receiver,
|
||||
jsid id, js::Value *vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
vp->setUndefined();
|
||||
JSPropertyDescriptor desc;
|
||||
// Only call through to the get trap on the underlying object if we're
|
||||
|
@ -155,7 +160,13 @@ ChromeObjectWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id,
|
|||
// COWs fail silently for GETs, and that also happens to be the only case
|
||||
// where we might want to redirect the lookup to the home prototype chain.
|
||||
*bp = (act == Wrapper::GET);
|
||||
return *bp && PropIsFromStandardPrototype(cx, wrapper, id);
|
||||
if (!*bp || id == JSID_VOID)
|
||||
return false;
|
||||
|
||||
// Note that PropIsFromStandardPrototype needs to invoke getPropertyDescriptor
|
||||
// before we've fully entered the policy. Waive our policy.
|
||||
js::AutoWaivePolicy policy(cx, wrapper, id);
|
||||
return PropIsFromStandardPrototype(cx, wrapper, id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ bool
|
|||
FilteringWrapper<Base, Policy>::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
js::PropertyDescriptor *desc, unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
if (!Base::getPropertyDescriptor(cx, wrapper, id, desc, flags))
|
||||
return false;
|
||||
return FilterSetter<Policy>(cx, wrapper, id, desc);
|
||||
|
@ -74,6 +75,7 @@ FilteringWrapper<Base, Policy>::getOwnPropertyDescriptor(JSContext *cx, JSObject
|
|||
js::PropertyDescriptor *desc,
|
||||
unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
if (!Base::getOwnPropertyDescriptor(cx, wrapper, id, desc, flags))
|
||||
return false;
|
||||
return FilterSetter<Policy>(cx, wrapper, id, desc);
|
||||
|
@ -83,6 +85,7 @@ template <typename Base, typename Policy>
|
|||
bool
|
||||
FilteringWrapper<Base, Policy>::getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
return Base::getOwnPropertyNames(cx, wrapper, props) &&
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
|
@ -91,6 +94,7 @@ template <typename Base, typename Policy>
|
|||
bool
|
||||
FilteringWrapper<Base, Policy>::enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
return Base::enumerate(cx, wrapper, props) &&
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
|
@ -99,6 +103,7 @@ template <typename Base, typename Policy>
|
|||
bool
|
||||
FilteringWrapper<Base, Policy>::keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
return Base::keys(cx, wrapper, props) &&
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
|
@ -107,6 +112,7 @@ template <typename Base, typename Policy>
|
|||
bool
|
||||
FilteringWrapper<Base, Policy>::iterate(JSContext *cx, JSObject *wrapper, unsigned flags, Value *vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
// We refuse to trigger the iterator hook across chrome wrappers because
|
||||
// we don't know how to censor custom iterator objects. Instead we trigger
|
||||
// the default proxy iterate trap, which will ask enumerate() for the list
|
||||
|
|
|
@ -1410,6 +1410,7 @@ bool
|
|||
XrayWrapper<Base, Traits>::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
js::PropertyDescriptor *desc, unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
JSObject *holder = Traits::singleton.ensureHolder(cx, wrapper);
|
||||
if (Traits::isResolving(cx, holder, id)) {
|
||||
desc->obj = NULL;
|
||||
|
@ -1528,6 +1529,7 @@ bool
|
|||
XrayWrapper<Base, Traits>::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
PropertyDescriptor *desc, unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
JSObject *holder = Traits::singleton.ensureHolder(cx, wrapper);
|
||||
if (Traits::isResolving(cx, holder, id)) {
|
||||
desc->obj = NULL;
|
||||
|
@ -1574,6 +1576,7 @@ bool
|
|||
XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
js::PropertyDescriptor *desc)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
// Redirect access straight to the wrapper if we should be transparent.
|
||||
if (XrayUtils::IsTransparent(cx, wrapper, id)) {
|
||||
JSObject *obj = Traits::getTargetObject(wrapper);
|
||||
|
@ -1626,6 +1629,7 @@ bool
|
|||
XrayWrapper<Base, Traits>::getOwnPropertyNames(JSContext *cx, JSObject *wrapper,
|
||||
JS::AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
return enumerate(cx, wrapper, JSITER_OWNONLY | JSITER_HIDDEN, props);
|
||||
}
|
||||
|
||||
|
@ -1633,6 +1637,7 @@ template <typename Base, typename Traits>
|
|||
bool
|
||||
XrayWrapper<Base, Traits>::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
// Redirect access straight to the wrapper if we should be transparent.
|
||||
if (XrayUtils::IsTransparent(cx, wrapper, id)) {
|
||||
JSObject *obj = Traits::getTargetObject(wrapper);
|
||||
|
@ -1669,6 +1674,7 @@ bool
|
|||
XrayWrapper<Base, Traits>::enumerate(JSContext *cx, JSObject *wrapper, unsigned flags,
|
||||
JS::AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
// Redirect access straight to the wrapper if we should be transparent.
|
||||
if (XrayUtils::IsTransparent(cx, wrapper, JSID_VOID)) {
|
||||
JSObject *obj = Traits::getTargetObject(wrapper);
|
||||
|
@ -1762,6 +1768,7 @@ template <typename Base, typename Traits>
|
|||
bool
|
||||
XrayWrapper<Base, Traits>::call(JSContext *cx, JSObject *wrapper, unsigned argc, js::Value *vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
return Traits::call(cx, wrapper, argc, vp);
|
||||
}
|
||||
|
||||
|
@ -1770,6 +1777,7 @@ bool
|
|||
XrayWrapper<Base, Traits>::construct(JSContext *cx, JSObject *wrapper, unsigned argc,
|
||||
js::Value *argv, js::Value *rval)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
return Traits::construct(cx, wrapper, argc, argv, rval);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче