bug 580128 - Rewrite XrayWrapper so the wrapped object is in the wrapped object slot and the holder goes in an extra slot. r=gal

This commit is contained in:
Blake Kaplan 2010-09-20 14:48:01 -07:00
Родитель 805a2aaafb
Коммит 70935f7b8c
12 изменённых файлов: 264 добавлений и 148 удалений

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

@ -954,6 +954,8 @@ struct JSObject : js::gc::Cell {
inline js::JSProxyHandler *getProxyHandler() const;
inline const js::Value &getProxyPrivate() const;
inline void setProxyPrivate(const js::Value &priv);
inline const js::Value &getProxyExtra() const;
inline void setProxyExtra(const js::Value &extra);
/*
* With object-specific getters and setters.

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

@ -905,6 +905,7 @@ proxy_TraceObject(JSTracer *trc, JSObject *obj)
obj->getProxyHandler()->trace(trc, obj);
MarkValue(trc, obj->getProxyPrivate(), "private");
MarkValue(trc, obj->getProxyExtra(), "extra");
if (obj->isFunctionProxy()) {
MarkValue(trc, GetCall(obj), "call");
MarkValue(trc, GetConstruct(obj), "construct");
@ -921,7 +922,7 @@ proxy_Finalize(JSContext *cx, JSObject *obj)
JS_FRIEND_API(Class) ObjectProxyClass = {
"Proxy",
Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(2),
Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(3),
PropertyStub, /* addProperty */
PropertyStub, /* delProperty */
PropertyStub, /* getProperty */
@ -957,7 +958,7 @@ JS_FRIEND_API(Class) ObjectProxyClass = {
JS_FRIEND_API(Class) OuterWindowProxyClass = {
"Proxy",
Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(2),
Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(3),
PropertyStub, /* addProperty */
PropertyStub, /* delProperty */
PropertyStub, /* getProperty */
@ -1025,7 +1026,7 @@ proxy_TypeOf_fun(JSContext *cx, JSObject *obj)
JS_FRIEND_API(Class) FunctionProxyClass = {
"Proxy",
Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(4),
Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(5),
PropertyStub, /* addProperty */
PropertyStub, /* delProperty */
PropertyStub, /* getProperty */

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

@ -49,7 +49,7 @@
namespace js {
/* Base class for all C++ proxy handlers. */
class JSProxyHandler {
class JS_FRIEND_API(JSProxyHandler) {
void *mFamily;
public:
explicit JSProxyHandler(void *family);
@ -68,21 +68,21 @@ class JSProxyHandler {
virtual bool fix(JSContext *cx, JSObject *proxy, Value *vp) = 0;
/* ES5 Harmony derived proxy traps. */
virtual JS_FRIEND_API(bool) has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, js::Value *vp);
virtual JS_FRIEND_API(bool) set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, js::Value *vp);
virtual JS_FRIEND_API(bool) enumerateOwn(JSContext *cx, JSObject *proxy, js::AutoIdVector &props);
virtual JS_FRIEND_API(bool) iterate(JSContext *cx, JSObject *proxy, uintN flags, js::Value *vp);
virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, js::Value *vp);
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, js::Value *vp);
virtual bool enumerateOwn(JSContext *cx, JSObject *proxy, js::AutoIdVector &props);
virtual bool iterate(JSContext *cx, JSObject *proxy, uintN flags, js::Value *vp);
/* Spidermonkey extensions. */
virtual JS_FRIEND_API(bool) call(JSContext *cx, JSObject *proxy, uintN argc, js::Value *vp);
virtual JS_FRIEND_API(bool) construct(JSContext *cx, JSObject *proxy,
virtual bool call(JSContext *cx, JSObject *proxy, uintN argc, js::Value *vp);
virtual bool construct(JSContext *cx, JSObject *proxy,
uintN argc, js::Value *argv, js::Value *rval);
virtual JS_FRIEND_API(JSString *) obj_toString(JSContext *cx, JSObject *proxy);
virtual JS_FRIEND_API(JSString *) fun_toString(JSContext *cx, JSObject *proxy, uintN indent);
virtual JS_FRIEND_API(void) finalize(JSContext *cx, JSObject *proxy);
virtual JS_FRIEND_API(void) trace(JSTracer *trc, JSObject *proxy);
virtual JSString *obj_toString(JSContext *cx, JSObject *proxy);
virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, uintN indent);
virtual void finalize(JSContext *cx, JSObject *proxy);
virtual void trace(JSTracer *trc, JSObject *proxy);
virtual bool isOuterWindow() {
return false;
@ -129,6 +129,7 @@ class JSProxy {
/* Shared between object and function proxies. */
const uint32 JSSLOT_PROXY_HANDLER = JSSLOT_PRIVATE + 0;
const uint32 JSSLOT_PROXY_PRIVATE = JSSLOT_PRIVATE + 1;
const uint32 JSSLOT_PROXY_EXTRA = JSSLOT_PRIVATE + 2;
/* Function proxies only. */
const uint32 JSSLOT_PROXY_CALL = JSSLOT_PRIVATE + 2;
const uint32 JSSLOT_PROXY_CONSTRUCT = JSSLOT_PRIVATE + 3;
@ -180,6 +181,20 @@ JSObject::setProxyPrivate(const js::Value &priv)
setSlot(js::JSSLOT_PROXY_PRIVATE, priv);
}
inline const js::Value &
JSObject::getProxyExtra() const
{
JS_ASSERT(isProxy());
return getSlot(js::JSSLOT_PROXY_EXTRA);
}
inline void
JSObject::setProxyExtra(const js::Value &extra)
{
JS_ASSERT(isProxy());
setSlot(js::JSSLOT_PROXY_EXTRA, extra);
}
namespace js {
JS_FRIEND_API(JSObject *)

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

@ -57,7 +57,13 @@
using namespace js;
using namespace js::gc;
static int sWrapperFamily = 0;
static int sWrapperFamily;
void *
JSWrapper::getWrapperFamily()
{
return &sWrapperFamily;
}
bool
JSObject::isWrapper() const
@ -346,6 +352,10 @@ AutoCompartment::leave()
/* Cross compartment wrappers. */
JSCrossCompartmentWrapper::JSCrossCompartmentWrapper(void *family) : JSWrapper(0)
{
}
JSCrossCompartmentWrapper::JSCrossCompartmentWrapper(uintN flags) : JSWrapper(flags)
{
}
@ -624,4 +634,4 @@ JSCrossCompartmentWrapper::fun_toString(JSContext *cx, JSObject *wrapper, uintN
return str;
}
JSCrossCompartmentWrapper JSCrossCompartmentWrapper::singleton(0);
JSCrossCompartmentWrapper JSCrossCompartmentWrapper::singleton(0u);

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

@ -105,10 +105,17 @@ class JSWrapper : public js::JSProxyHandler {
static inline JSObject *wrappedObject(JSObject *wrapper) {
return wrapper->getProxyPrivate().toObjectOrNull();
}
static JS_FRIEND_API(void *) getWrapperFamily();
};
/* Base class for all cross compartment wrapper handlers. */
class JS_FRIEND_API(JSCrossCompartmentWrapper) : public JSWrapper {
protected:
// XXX Hack to let Xray wrappers derive from either cross compartment
// wrappers or JSProxyHandlers.
JSCrossCompartmentWrapper(void *family);
public:
JSCrossCompartmentWrapper(uintN flags);

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

@ -68,13 +68,7 @@ Unwrap(JSContext *cx, JSObject *wrapper)
// XXX Security check!
}
JSObject *wrappedObj = wrapper->unwrap();
if (wrappedObj->getJSClass() == &xpc::HolderClass) {
typedef xpc::XrayWrapper<JSCrossCompartmentWrapper> Xray;
wrappedObj = Xray::unwrapHolder(cx, wrappedObj);
}
return wrappedObj;
return wrapper->unwrap();
}
js::Class *clasp = wrapper->getClass();
@ -264,13 +258,7 @@ JSObject *
UnsafeUnwrapSecurityWrapper(JSContext *cx, JSObject *obj)
{
if (obj->isProxy()) {
JSObject *wrappedObj = obj->unwrap();
if (wrappedObj->getJSClass() == &xpc::HolderClass) {
typedef xpc::XrayWrapper<JSCrossCompartmentWrapper> Xray;
wrappedObj = Xray::unwrapHolder(cx, wrappedObj);
}
return wrappedObj;
return obj->unwrap();
}
if (IsSecurityWrapper(obj)) {

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

@ -50,6 +50,7 @@
#include "jstl.h"
#include "nsINode.h"
#include "xpcquickstubs.h"
#include "jsproxy.h"
/***************************************************************************/

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

@ -176,10 +176,9 @@ AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapper, jsid
const char *name;
js::Class *clasp = obj->getClass();
NS_ASSERTION(Jsvalify(clasp) != &HolderClass, "shouldn't have a holder here");
if (clasp->ext.innerObject)
name = "Window";
else if (Jsvalify(clasp) == &HolderClass)
name = XrayWrapper<JSCrossCompartmentWrapper>::unwrapHolder(cx, obj)->getClass()->name;
else
name = clasp->name;

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

@ -150,7 +150,8 @@ FilteringWrapper<Base, Policy>::enter(JSContext *cx, JSObject *wrapper, jsid id,
#define SOW FilteringWrapper<JSCrossCompartmentWrapper, OnlyIfSubjectIsSystem>
#define COW FilteringWrapper<JSCrossCompartmentWrapper, ExposedPropertiesOnly>
#define XOW FilteringWrapper<XrayWrapper<CrossOriginWrapper>, CrossOriginAccessiblePropertiesOnly>
#define XOW FilteringWrapper<XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray>, \
CrossOriginAccessiblePropertiesOnly>
#define NNXOW FilteringWrapper<JSCrossCompartmentWrapper, CrossOriginAccessiblePropertiesOnly>
template<> SOW SOW::singleton(0);

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

@ -38,6 +38,7 @@
* ***** END LICENSE BLOCK ***** */
#include "jsobj.h"
#include "jsvalue.h"
#include "WrapperFactory.h"
#include "CrossOriginWrapper.h"
@ -70,6 +71,7 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
{
NS_ASSERTION(!obj->isWrapper() || obj->getClass()->ext.innerObject,
"wrapped object passed to rewrap");
NS_ASSERTION(JS_GET_CLASS(cx, obj) != &HolderClass, "trying to wrap a holder");
if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
return nsnull;
@ -78,19 +80,9 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
if (!obj)
return nsnull;
// Ugly hack to avoid wrapping holder objects instead of the actual
// underlying wrapped native JS object.
if (JS_GET_CLASS(cx, obj) == &HolderClass) {
obj = XrayWrapper<JSCrossCompartmentWrapper>::unwrapHolder(cx, obj);
OBJ_TO_OUTER_OBJECT(cx, obj);
if (!JS_WrapObject(cx, &obj))
return nsnull;
return obj;
}
JSCompartment *origin = obj->getCompartment(cx);
JSCompartment *target = cx->compartment;
JSObject *xrayHolder = nsnull;
JSWrapper *wrapper;
if (AccessCheck::isChrome(target)) {
@ -104,10 +96,11 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
// Native objects must be wrapped into an X-ray wrapper.
if (!obj->getGlobal()->isSystem() &&
(IS_WN_WRAPPER(obj) || obj->getClass()->ext.innerObject)) {
typedef XrayWrapper<JSCrossCompartmentWrapper> Xray;
typedef XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray> Xray;
wrapper = &Xray::singleton;
obj = Xray::createHolder(cx, parent, obj);
xrayHolder = Xray::createHolder(cx, obj, parent);
if (!xrayHolder)
return nsnull;
} else {
wrapper = &JSCrossCompartmentWrapper::singleton;
}
@ -136,13 +129,20 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
wrapper = &FilteringWrapper<JSCrossCompartmentWrapper,
CrossOriginAccessiblePropertiesOnly>::singleton;
} else {
typedef XrayWrapper<CrossOriginWrapper> Xray;
typedef XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray> Xray;
wrapper = &FilteringWrapper<Xray,
CrossOriginAccessiblePropertiesOnly>::singleton;
obj = Xray::createHolder(cx, parent, obj);
xrayHolder = Xray::createHolder(cx, obj, parent);
if (!xrayHolder)
return nsnull;
}
}
return JSWrapper::New(cx, obj, wrappedProto, NULL, wrapper);
JSObject *wrapperObj = JSWrapper::New(cx, obj, wrappedProto, NULL, wrapper);
if (!wrapperObj || !xrayHolder)
return wrapperObj;
wrapperObj->setProxyExtra(js::ObjectValue(*xrayHolder));
return wrapperObj;
}
}

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

@ -72,16 +72,6 @@ JSClass HolderClass = {
NULL, NULL, NULL, NULL
};
template <typename Base>
XrayWrapper<Base>::XrayWrapper(uintN flags) : Base(flags)
{
}
template <typename Base>
XrayWrapper<Base>::~XrayWrapper()
{
}
static XPCWrappedNative *
GetWrappedNative(JSObject *obj)
{
@ -104,21 +94,8 @@ GetWrappedNativeObjectFromHolder(JSContext *cx, JSObject *holder)
static JSBool
holder_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
if (obj->isWrapper()) {
#ifdef DEBUG
{
typedef FilteringWrapper<XrayWrapper<CrossOriginWrapper>,
CrossOriginAccessiblePropertiesOnly>
FilteringXRay;
JSProxyHandler *handler = obj->getProxyHandler();
NS_ASSERTION(handler == &XrayWrapper<JSCrossCompartmentWrapper>::singleton ||
handler == &XrayWrapper<CrossOriginWrapper>::singleton ||
handler == &FilteringXRay::singleton,
"bad object");
}
#endif
obj = obj->unwrap();
}
if (obj->isWrapper())
obj = &obj->getProxyExtra().toObject();
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, obj);
XPCWrappedNative *wn = GetWrappedNative(wnObject);
@ -154,7 +131,8 @@ holder_set(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
}
static bool
ResolveNativeProperty(JSContext *cx, JSObject *holder, jsid id, bool set, JSPropertyDescriptor *desc)
ResolveNativeProperty(JSContext *cx, JSObject *holder, jsid id, bool set,
JSPropertyDescriptor *desc)
{
desc->obj = NULL;
@ -208,6 +186,7 @@ ResolveNativeProperty(JSContext *cx, JSObject *holder, jsid id, bool set, JSProp
desc->shortid = NULL;
desc->value = JSVAL_VOID;
jsval fval = JSVAL_VOID;
if (member->IsConstant()) {
if (!member->GetConstantValue(ccx, iface, &desc->value)) {
JS_ReportError(cx, "Failed to convert constant native property to JS value");
@ -215,17 +194,14 @@ ResolveNativeProperty(JSContext *cx, JSObject *holder, jsid id, bool set, JSProp
}
} else if (member->IsAttribute()) {
// This is a getter/setter. Clone a function for it.
jsval fval;
if (!member->NewFunctionObject(ccx, iface, wnObject, &fval)) {
JS_ReportError(cx, "Failed to clone function object for native getter/setter");
return false;
}
desc->getter = CastAsJSPropertyOp(JSVAL_TO_OBJECT(fval));
desc->attrs |= JSPROP_GETTER;
if (member->IsWritableAttribute()) {
desc->setter = desc->getter;;
if (member->IsWritableAttribute())
desc->attrs |= JSPROP_SETTER;
}
// Make the property shared on the holder so no slot is allocated
// for it. This avoids keeping garbage alive through that slot.
@ -244,6 +220,18 @@ ResolveNativeProperty(JSContext *cx, JSObject *holder, jsid id, bool set, JSProp
desc->getter = desc->setter = JS_PropertyStub;
}
JSAutoEnterCompartment ac;
if (!ac.enter(cx, holder))
return false;
if (!JS_WrapValue(cx, &desc->value) || !JS_WrapValue(cx, &fval))
return false;
if (desc->attrs & JSPROP_GETTER)
desc->getter = CastAsJSPropertyOp(JSVAL_TO_OBJECT(fval));
if (desc->attrs & JSPROP_SETTER)
desc->setter = desc->getter;
// Define the property.
return JS_DefinePropertyById(cx, holder, id, desc->value,
desc->getter, desc->setter, desc->attrs);
@ -268,26 +256,13 @@ holder_enumerate(JSContext *cx, JSObject *holder)
return true;
}
struct NativePropertiesOnly : public Policy {
static bool check(JSContext *cx, JSObject *obj, jsid id, bool set, Permission &perm);
};
extern JSCrossCompartmentWrapper XrayWrapperWaivedWrapper;
static JSBool
wrappedJSObject_getter(JSContext *cx, JSObject *holder, jsid id, jsval *vp)
{
if (holder->isWrapper()) {
#ifdef DEBUG
{
JSProxyHandler *handler = holder->getProxyHandler();
NS_ASSERTION(handler == &XrayWrapper<JSCrossCompartmentWrapper>::singleton ||
handler == &XrayWrapper<CrossOriginWrapper>::singleton,
"bad object");
}
#endif
holder = holder->unwrap();
}
if (holder->isWrapper())
holder = &holder->getProxyExtra().toObject();
// If the caller intentionally waives the X-ray wrapper we usually
// apply for wrapped natives, use a special wrapper to make sure the
@ -306,26 +281,20 @@ wrappedJSObject_getter(JSContext *cx, JSObject *holder, jsid id, jsval *vp)
return true;
}
template <typename Base>
bool
XrayWrapper<Base>::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
js::Value *vp)
template <typename Base, typename Policy>
XrayWrapper<Base, Policy>::XrayWrapper(int flags) : Base(JSWrapper::getWrapperFamily())
{
return JSProxyHandler::get(cx, wrapper, receiver, id, vp);
}
template <typename Base>
bool
XrayWrapper<Base>::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
js::Value *vp)
template <typename Base, typename Policy>
XrayWrapper<Base, Policy>::~XrayWrapper()
{
return JSProxyHandler::set(cx, wrapper, receiver, id, vp);
}
template <typename Base>
template <typename Base, typename Policy>
bool
XrayWrapper<Base>::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
bool set, PropertyDescriptor *desc_in)
XrayWrapper<Base, Policy>::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
bool set, PropertyDescriptor *desc_in)
{
JSPropertyDescriptor *desc = Jsvalify(desc_in);
@ -338,43 +307,123 @@ XrayWrapper<Base>::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid
desc->value = JSVAL_VOID;
return true;
}
if (!Base::getPropertyDescriptor(cx, wrapper, id, set, desc_in)) {
void *priv;
if (!Policy::enter(cx, wrapper, &id, set ? JSWrapper::SET : JSWrapper::GET, &priv))
return false;
}
if (desc->obj)
return true;
return ResolveNativeProperty(cx, Base::wrappedObject(wrapper), id, false, desc);
JSObject *holder = &wrapper->getProxyExtra().toObject();
bool ok = ResolveNativeProperty(cx, holder, id, false, desc);
// TODO expandos
Policy::leave(cx, wrapper, priv);
return ok;
}
template <typename Base>
template <typename Base, typename Policy>
bool
XrayWrapper<Base>::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
bool set, PropertyDescriptor *desc)
XrayWrapper<Base, Policy>::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
bool set, PropertyDescriptor *desc)
{
return getPropertyDescriptor(cx, wrapper, id, set, desc);
}
template <typename Base>
template <typename Base, typename Policy>
bool
XrayWrapper<Base>::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
XrayWrapper<Base, Policy>::defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
js::PropertyDescriptor *desc)
{
// Use the default implementation, which forwards to getPropertyDescriptor.
// XXX When am I called? Implement me!
return true;
}
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::getOwnPropertyNames(JSContext *cx, JSObject *wrapper,
js::AutoIdVector &props)
{
// XXX implement me.
return true;
}
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
{
// XXX implement me.
return true;
}
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::enumerate(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props)
{
// XXX implement me.
return true;
}
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::fix(JSContext *cx, JSObject *proxy, js::Value *vp)
{
vp->setUndefined();
return true;
}
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
js::Value *vp)
{
// Skip our Base if it isn't already JSProxyHandler.
return JSProxyHandler::get(cx, wrapper, receiver, id, vp);
}
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
js::Value *vp)
{
// Skip our Base if it isn't already JSProxyHandler.
return JSProxyHandler::set(cx, wrapper, receiver, id, vp);
}
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
{
// Skip our Base if it isn't already JSProxyHandler.
return JSProxyHandler::has(cx, wrapper, id, bp);
}
template <typename Base>
template <typename Base, typename Policy>
bool
XrayWrapper<Base>::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
XrayWrapper<Base, Policy>::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
{
// Use the default implementation, which forwards to getOwnPropertyDescriptor.
// Skip our Base if it isn't already JSProxyHandler.
return JSProxyHandler::hasOwn(cx, wrapper, id, bp);
}
template <typename Base>
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::enumerateOwn(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props)
{
// Skip our Base if it isn't already JSProxyHandler.
return JSProxyHandler::enumerateOwn(cx, wrapper, props);
}
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::iterate(JSContext *cx, JSObject *wrapper, uintN flags, js::Value *vp)
{
// Skip our Base if it isn't already JSProxyHandler.
return JSProxyHandler::iterate(cx, wrapper, flags, vp);
}
template <typename Base, typename Policy>
JSObject *
XrayWrapper<Base>::createHolder(JSContext *cx,
JSObject *parent,
JSObject *wrappedNative)
XrayWrapper<Base, Policy>::createHolder(JSContext *cx, JSObject *wrappedNative, JSObject *parent)
{
JSObject *holder = JS_NewObjectWithGivenProto(cx, &HolderClass, nsnull, parent);
if (!holder)
@ -384,21 +433,33 @@ XrayWrapper<Base>::createHolder(JSContext *cx,
return holder;
}
template <typename Base>
JSObject *
XrayWrapper<Base>::unwrapHolder(JSContext *cx, JSObject *holder)
bool
CrossCompartmentXray::enter(JSContext *cx, JSObject *wrapper, jsid *idp,
JSWrapper::Action act, void **priv)
{
NS_ASSERTION(holder->getJSClass() == &HolderClass, "bad holder");
return GetWrappedNativeObjectFromHolder(cx, holder);
JSObject *target = wrapper->unwrap();
JSCrossCompartmentCall *call = JS_EnterCrossCompartmentCall(cx, target);
if (!call)
return false;
*priv = call;
// XXX wrap id
return true;
}
#define SJOW XrayWrapper<JSCrossCompartmentWrapper>
#define XOSJOW XrayWrapper<CrossOriginWrapper>
void
CrossCompartmentXray::leave(JSContext *cx, JSObject *wrapper, void *priv)
{
JS_LeaveCrossCompartmentCall(static_cast<JSCrossCompartmentCall *>(priv));
}
template <> SJOW SJOW::singleton(0);
template <> XOSJOW XOSJOW::singleton(0);
#define XPCNW XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray>
#define SCNW XrayWrapper<JSProxyHandler, SameCompartmentXray>
template class SJOW;
template class XOSJOW;
template <> XPCNW XPCNW::singleton(0);
template <> SCNW SCNW::singleton(0);
template class XPCNW;
template class SCNW;
}

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

@ -42,32 +42,63 @@
// Xray wrappers re-resolve the original native properties on the native
// object and always directly access to those properties.
// Because they work so differently from the rest of the wrapper hierarchy,
// we pull them out of the JSWrapper inheritance hierarchy and create a
// little world around them.
namespace xpc {
extern JSClass HolderClass;
template <typename Base>
// NB: Base *must* derive from JSProxyHandler
template <typename Base, typename Policy>
class XrayWrapper : public Base {
public:
XrayWrapper(uintN flags);
XrayWrapper(int flags);
virtual ~XrayWrapper();
virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
js::Value *vp);
virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
js::Value *vp);
/* Fundamental proxy traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
bool set, js::PropertyDescriptor *desc);
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
bool set, js::PropertyDescriptor *desc);
virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
js::PropertyDescriptor *desc);
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper,
js::AutoIdVector &props);
virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual bool enumerate(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
virtual bool fix(JSContext *cx, JSObject *proxy, js::Value *vp);
/* Derived proxy traps. */
virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
js::Value *vp);
virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
js::Value *vp);
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual bool enumerateOwn(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
virtual bool iterate(JSContext *cx, JSObject *wrapper, uintN flags, js::Value *vp);
static JSObject *createHolder(JSContext *cx, JSObject *parent, JSObject *wrappedNative);
static JSObject *unwrapHolder(JSContext *cx, JSObject *holder);
static JSObject *createHolder(JSContext *cx, JSObject *wrappedNative, JSObject *parent);
static XrayWrapper singleton;
};
class CrossCompartmentXray {
public:
static bool enter(JSContext *cx, JSObject *wrapper, jsid *idp,
JSWrapper::Action act, void **priv);
static void leave(JSContext *cx, JSObject *wrapper, void *priv);
};
class SameCompartmentXray {
public:
static bool enter(JSContext *, JSObject *, jsid *, JSWrapper::Action, void **) {
return true;
}
static void leave(JSContext *cx, JSObject *wrapper, void *priv) {
}
};
}