зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
805a2aaafb
Коммит
70935f7b8c
|
@ -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) {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче