mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Implement iterate trap for proxy handlers (568413, r=brendan).
This commit is contained in:
parent
e85c97aafb
commit
22db0647cc
@ -3900,7 +3900,7 @@ JS_Enumerate(JSContext *cx, JSObject *obj)
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
JSIdArray *ida;
|
||||
if (!EnumerateOwnProperties(cx, obj, &ida))
|
||||
if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &ida))
|
||||
return false;
|
||||
for (size_t n = 0; n < size_t(ida->length); ++n)
|
||||
JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
|
||||
|
@ -191,11 +191,12 @@ const char *const js_common_atom_names[] = {
|
||||
"delete", /* deleteAtom */
|
||||
"getOwnPropertyNames", /* getOwnPropertyNames */
|
||||
"enumerate", /* enumerateAtom */
|
||||
"fix",
|
||||
"fix", /* fixAtom */
|
||||
|
||||
"has", /* hasAtom */
|
||||
"hasOwn", /* hasOwnAtom */
|
||||
"enumerateOwn" /* enumerateOwnAtom */
|
||||
"enumerateOwn", /* enumerateOwnAtom */
|
||||
"iterate" /* iterateAtom */
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) * sizeof(JSAtom *) ==
|
||||
|
@ -308,6 +308,7 @@ struct JSAtomState {
|
||||
JSAtom *hasAtom;
|
||||
JSAtom *hasOwnAtom;
|
||||
JSAtom *enumerateOwnAtom;
|
||||
JSAtom *iterateAtom;
|
||||
|
||||
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
|
||||
struct {
|
||||
|
@ -233,15 +233,15 @@ EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uint
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
MakeNativeIterator(JSContext *cx, uintN flags, uint32 *sarray, uint32 slength, uint32 key,
|
||||
jsval *parray, uint32 plength, NativeIterator **nip)
|
||||
NativeIterator *
|
||||
NativeIterator::allocate(JSContext *cx, uintN flags, uint32 *sarray, uint32 slength, uint32 key,
|
||||
jsval *parray, uint32 plength)
|
||||
{
|
||||
NativeIterator *ni = (NativeIterator *)
|
||||
cx->malloc(sizeof(NativeIterator) + plength * sizeof(jsval) + slength * sizeof(uint32));
|
||||
if (!ni) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
ni->props_array = ni->props_cursor = (jsval *) (ni + 1);
|
||||
ni->props_end = ni->props_array + plength;
|
||||
@ -253,19 +253,15 @@ MakeNativeIterator(JSContext *cx, uintN flags, uint32 *sarray, uint32 slength, u
|
||||
ni->flags = flags;
|
||||
if (slength)
|
||||
memcpy(ni->shapes_array, sarray, slength * sizeof(uint32));
|
||||
|
||||
*nip = ni;
|
||||
|
||||
return true;
|
||||
return ni;
|
||||
}
|
||||
|
||||
static bool
|
||||
InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, uint32 slength,
|
||||
uint32 key, NativeIterator **nip)
|
||||
static NativeIterator *
|
||||
Snapshot(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, uint32 slength, uint32 key)
|
||||
{
|
||||
HashSet<jsid> ht(cx);
|
||||
if (!(flags & JSITER_OWNONLY) && !ht.init(32))
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
AutoValueVector props(cx);
|
||||
|
||||
@ -276,45 +272,45 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui
|
||||
pobj->map->ops->enumerate == js_Enumerate &&
|
||||
!(clasp->flags & JSCLASS_NEW_ENUMERATE)) {
|
||||
if (!clasp->enumerate(cx, pobj))
|
||||
return false;
|
||||
return NULL;
|
||||
if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props))
|
||||
return false;
|
||||
return NULL;
|
||||
} else if (pobj->isDenseArray()) {
|
||||
if (!EnumerateDenseArrayProperties(cx, obj, pobj, flags, ht, props))
|
||||
return false;
|
||||
return NULL;
|
||||
} else {
|
||||
if (pobj->isProxy()) {
|
||||
JSIdArray *ida;
|
||||
if (flags & JSITER_OWNONLY) {
|
||||
if (!JSProxy::enumerateOwn(cx, pobj, &ida))
|
||||
return false;
|
||||
return NULL;
|
||||
} else {
|
||||
if (!JSProxy::enumerate(cx, pobj, &ida))
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
AutoIdArray idar(cx, ida);
|
||||
for (size_t n = 0; n < size_t(ida->length); ++n) {
|
||||
if (!Enumerate(cx, obj, pobj, ida->vector[n], true, flags, ht, props))
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
/* Proxy objects enumerate the prototype on their own, so we are done here. */
|
||||
break;
|
||||
}
|
||||
jsval state;
|
||||
if (!pobj->enumerate(cx, JSENUMERATE_INIT, &state, NULL))
|
||||
return false;
|
||||
return NULL;
|
||||
if (state == JSVAL_NATIVE_ENUMERATE_COOKIE) {
|
||||
if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props))
|
||||
return false;
|
||||
return NULL;
|
||||
} else {
|
||||
while (true) {
|
||||
jsid id;
|
||||
if (!pobj->enumerate(cx, JSENUMERATE_NEXT, &state, &id))
|
||||
return false;
|
||||
return NULL;
|
||||
if (state == JSVAL_NULL)
|
||||
break;
|
||||
if (!Enumerate(cx, obj, pobj, id, true, flags, ht, props))
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -325,7 +321,7 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui
|
||||
pobj = pobj->getProto();
|
||||
}
|
||||
|
||||
return MakeNativeIterator(cx, flags, sarray, slength, key, props.begin(), props.length(), nip);
|
||||
return NativeIterator::allocate(cx, flags, sarray, slength, key, props.begin(), props.length());
|
||||
}
|
||||
|
||||
bool
|
||||
@ -335,7 +331,7 @@ NativeIteratorToJSIdArray(JSContext *cx, NativeIterator *ni, JSIdArray **idap)
|
||||
JS_ASSERT(sizeof(NativeIterator) > sizeof(JSIdArray));
|
||||
JS_ASSERT(ni->props_array == (jsid *) (ni + 1));
|
||||
size_t length = size_t(ni->props_end - ni->props_array);
|
||||
JSIdArray *ida = (JSIdArray *) (uintptr_t(ni->props_array) - (sizeof(JSIdArray) - sizeof(jsid)));
|
||||
JSIdArray *ida = (JSIdArray *) uintptr_t(ni->props_array) - (sizeof(JSIdArray) - sizeof(jsid));
|
||||
ida->self = ni;
|
||||
ida->length = length;
|
||||
JS_ASSERT(&ida->vector[0] == &ni->props_array[0]);
|
||||
@ -344,28 +340,10 @@ NativeIteratorToJSIdArray(JSContext *cx, NativeIterator *ni, JSIdArray **idap)
|
||||
}
|
||||
|
||||
bool
|
||||
EnumerateOwnProperties(JSContext *cx, JSObject *obj, JSIdArray **idap)
|
||||
GetPropertyNames(JSContext *cx, JSObject *obj, uintN flags, JSIdArray **idap)
|
||||
{
|
||||
NativeIterator *ni;
|
||||
if (!InitNativeIterator(cx, obj, JSITER_OWNONLY, NULL, 0, true, &ni))
|
||||
return false;
|
||||
return NativeIteratorToJSIdArray(cx, ni, idap);
|
||||
}
|
||||
|
||||
bool
|
||||
EnumerateAllProperties(JSContext *cx, JSObject *obj, JSIdArray **idap)
|
||||
{
|
||||
NativeIterator *ni;
|
||||
if (!InitNativeIterator(cx, obj, 0, NULL, 0, true, &ni))
|
||||
return false;
|
||||
return NativeIteratorToJSIdArray(cx, ni, idap);
|
||||
}
|
||||
|
||||
bool
|
||||
GetOwnProperties(JSContext *cx, JSObject *obj, JSIdArray **idap)
|
||||
{
|
||||
NativeIterator *ni;
|
||||
if (!InitNativeIterator(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, NULL, 0, true, &ni))
|
||||
NativeIterator *ni = Snapshot(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN), NULL, 0, true);
|
||||
if (!ni)
|
||||
return false;
|
||||
return NativeIteratorToJSIdArray(cx, ni, idap);
|
||||
}
|
||||
@ -413,16 +391,40 @@ Compare(T *a, T *b, size_t c)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static JSObject *
|
||||
NewIteratorObject(JSContext *cx, uintN flags)
|
||||
{
|
||||
return !(flags & JSITER_ENUMERATE)
|
||||
? NewObject(cx, &js_IteratorClass.base, NULL, NULL)
|
||||
: NewObjectWithGivenProto(cx, &js_IteratorClass.base, NULL, NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
JSIdArrayToIterator(JSContext *cx, uintN flags, JSIdArray *ida, jsval *vp)
|
||||
{
|
||||
JSObject *iterobj = NewIteratorObject(cx, flags);
|
||||
if (!iterobj)
|
||||
return false;
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(iterobj);
|
||||
|
||||
NativeIterator *ni = NativeIterator::allocate(cx, flags, NULL, 0, 0,
|
||||
ida->vector, ida->length);
|
||||
if (!ni)
|
||||
return false;
|
||||
|
||||
iterobj->setNativeIterator(ni);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GetIterator(JSContext *cx, JSObject *obj, uintN flags, jsval *vp)
|
||||
{
|
||||
uint32 hash;
|
||||
JSObject **hp;
|
||||
NativeIterator *ni;
|
||||
Vector<uint32, 8> shapes(cx);
|
||||
uint32 key = 0;
|
||||
|
||||
bool escaping = !(flags & JSITER_ENUMERATE);
|
||||
bool keysOnly = (flags == JSITER_ENUMERATE);
|
||||
|
||||
if (obj) {
|
||||
@ -452,7 +454,7 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, jsval *vp)
|
||||
hp = &JS_THREAD_DATA(cx)->cachedNativeIterators[hash];
|
||||
JSObject *iterobj = *hp;
|
||||
if (iterobj) {
|
||||
ni = iterobj->getNativeIterator();
|
||||
NativeIterator *ni = iterobj->getNativeIterator();
|
||||
if (ni->shapes_key == key &&
|
||||
ni->shapes_length == shapes.length() &&
|
||||
Compare(ni->shapes_array, shapes.begin(), ni->shapes_length)) {
|
||||
@ -464,27 +466,26 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, jsval *vp)
|
||||
}
|
||||
|
||||
miss:
|
||||
if (!obj->isProxy()) {
|
||||
if (!GetCustomIterator(cx, obj, flags, vp))
|
||||
return false;
|
||||
if (*vp != JSVAL_VOID)
|
||||
return true;
|
||||
}
|
||||
if (obj->isProxy())
|
||||
return JSProxy::iterate(cx, obj, flags, vp);
|
||||
if (!GetCustomIterator(cx, obj, flags, vp))
|
||||
return false;
|
||||
if (*vp != JSVAL_VOID)
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *iterobj = escaping
|
||||
? NewObject(cx, &js_IteratorClass.base, NULL, NULL)
|
||||
: NewObjectWithGivenProto(cx, &js_IteratorClass.base, NULL, NULL);
|
||||
JSObject *iterobj = NewIteratorObject(cx, flags);
|
||||
if (!iterobj)
|
||||
return false;
|
||||
|
||||
/* Store in *vp to protect it from GC (callers must root vp). */
|
||||
*vp = OBJECT_TO_JSVAL(iterobj);
|
||||
|
||||
if (!InitNativeIterator(cx, obj, flags, shapes.begin(), shapes.length(), key, &ni))
|
||||
NativeIterator *ni = Snapshot(cx, obj, flags, shapes.begin(), shapes.length(), key);
|
||||
if (!ni)
|
||||
return false;
|
||||
iterobj->setNativeIterator(ni);
|
||||
|
||||
iterobj->setNativeIterator(ni);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -629,7 +630,7 @@ js_CloseIterator(JSContext *cx, jsval v)
|
||||
/* Cache the iterator object if possible. */
|
||||
NativeIterator *ni = obj->getNativeIterator();
|
||||
if (ni->shapes_length) {
|
||||
uint32 hash = ni->shapes_key % JS_ARRAY_LENGTH(JS_THREAD_DATA(cx)->cachedNativeIterators);
|
||||
uint32 hash = ni->shapes_key % NATIVE_ITER_CACHE_SIZE;
|
||||
JSObject **hp = &JS_THREAD_DATA(cx)->cachedNativeIterators[hash];
|
||||
ni->props_cursor = ni->props_array;
|
||||
ni->next = *hp;
|
||||
|
@ -70,6 +70,10 @@ struct NativeIterator {
|
||||
uintN flags;
|
||||
JSObject *next;
|
||||
|
||||
static NativeIterator *allocate(JSContext *cx, uintN flags,
|
||||
uint32 *sarray, uint32 slength, uint32 key,
|
||||
jsval *parray, uint32 plength);
|
||||
|
||||
void mark(JSTracer *trc);
|
||||
};
|
||||
|
||||
@ -81,13 +85,13 @@ struct NativeIterator {
|
||||
static const jsval JSVAL_NATIVE_ENUMERATE_COOKIE = SPECIAL_TO_JSVAL(0x220576);
|
||||
|
||||
bool
|
||||
EnumerateOwnProperties(JSContext *cx, JSObject *obj, JSIdArray **idap);
|
||||
GetPropertyNames(JSContext *cx, JSObject *obj, uintN flags, JSIdArray **idap);
|
||||
|
||||
bool
|
||||
EnumerateAllProperties(JSContext *cx, JSObject *obj, JSIdArray **idap);
|
||||
GetIterator(JSContext *cx, JSObject *obj, uintN flags, jsval *vp);
|
||||
|
||||
bool
|
||||
GetOwnProperties(JSContext *cx, JSObject *obj, JSIdArray **idap);
|
||||
JSIdArrayToIterator(JSContext *cx, uintN flags, JSIdArray *ida, jsval *vp);
|
||||
|
||||
/*
|
||||
* Convert the value stored in *vp to its iteration object. The flags should
|
||||
|
@ -170,6 +170,16 @@ JSProxyHandler::enumerateOwn(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxyHandler::iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp)
|
||||
{
|
||||
JSIdArray *ida;
|
||||
if (!enumerate(cx, proxy, &ida))
|
||||
return false;
|
||||
AutoIdArray idar(cx, ida);
|
||||
return JSIdArrayToIterator(cx, flags, ida, vp);
|
||||
}
|
||||
|
||||
void
|
||||
JSProxyHandler::finalize(JSContext *cx, JSObject *proxy)
|
||||
{
|
||||
@ -189,20 +199,23 @@ JSNoopProxyHandler::~JSNoopProxyHandler()
|
||||
}
|
||||
|
||||
bool
|
||||
JSNoopProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||
JSNoopProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc)
|
||||
{
|
||||
JSObject *wobj = wrappedObject(proxy);
|
||||
return JS_GetPropertyDescriptorById(cx, wobj, id, JSRESOLVE_QUALIFIED, desc);
|
||||
}
|
||||
|
||||
bool
|
||||
JSNoopProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||
JSNoopProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc)
|
||||
{
|
||||
return JS_GetPropertyDescriptorById(cx, wrappedObject(proxy), id, JSRESOLVE_QUALIFIED, desc);
|
||||
}
|
||||
|
||||
bool
|
||||
JSNoopProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||
JSNoopProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc)
|
||||
{
|
||||
return JS_DefinePropertyById(cx, wrappedObject(proxy), id, desc->value,
|
||||
desc->getter, desc->setter, desc->attrs);
|
||||
@ -211,7 +224,7 @@ JSNoopProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPr
|
||||
bool
|
||||
JSNoopProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
{
|
||||
return GetOwnProperties(cx, wrappedObject(proxy), idap);
|
||||
return GetPropertyNames(cx, wrappedObject(proxy), JSITER_OWNONLY | JSITER_HIDDEN, idap);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -227,7 +240,7 @@ JSNoopProxyHandler::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
bool
|
||||
JSNoopProxyHandler::enumerate(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
{
|
||||
return EnumerateAllProperties(cx, wrappedObject(proxy), idap);
|
||||
return GetPropertyNames(cx, wrappedObject(proxy), 0, idap);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -273,7 +286,13 @@ JSNoopProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid
|
||||
bool
|
||||
JSNoopProxyHandler::enumerateOwn(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
{
|
||||
return EnumerateOwnProperties(cx, wrappedObject(proxy), idap);
|
||||
return GetPropertyNames(cx, wrappedObject(proxy), JSITER_OWNONLY, idap);
|
||||
}
|
||||
|
||||
bool
|
||||
JSNoopProxyHandler::iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp)
|
||||
{
|
||||
return GetIterator(cx, wrappedObject(proxy), flags, vp);
|
||||
}
|
||||
|
||||
void
|
||||
@ -290,7 +309,7 @@ JSNoopProxyHandler::trace(JSTracer *trc, JSObject *proxy)
|
||||
JS_CALL_OBJECT_TRACER(trc, mWrappedObject, "wrappedObject");
|
||||
}
|
||||
|
||||
void *
|
||||
const void *
|
||||
JSNoopProxyHandler::family()
|
||||
{
|
||||
return &singleton;
|
||||
@ -301,17 +320,7 @@ JSNoopProxyHandler JSNoopProxyHandler::singleton(NULL);
|
||||
static bool
|
||||
GetTrap(JSContext *cx, JSObject *handler, JSAtom *atom, jsval *fvalp)
|
||||
{
|
||||
if (!handler->getProperty(cx, ATOM_TO_JSID(atom), fvalp)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNDEFINED_PROP,
|
||||
JS_GetStringBytes(JSVAL_TO_STRING(ID_TO_VALUE(atom))));
|
||||
return false;
|
||||
}
|
||||
if (!js_IsCallable(*fvalp)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_FUNCTION,
|
||||
JS_GetStringBytes(JSVAL_TO_STRING(ID_TO_VALUE(atom))));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return handler->getProperty(cx, ATOM_TO_JSID(atom), fvalp);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -325,39 +334,65 @@ TryHandlerTrap(JSContext *cx, JSObject *proxy, bool ok = true)
|
||||
}
|
||||
|
||||
static bool
|
||||
Trap(JSContext *cx, JSObject *handler, JSAtom *atom, uintN argc, jsval* argv, jsval *rval)
|
||||
FundamentalTrap(JSContext *cx, JSObject *handler, JSAtom *atom, jsval *fvalp)
|
||||
{
|
||||
if (!GetTrap(cx, handler, atom, fvalp))
|
||||
return false;
|
||||
|
||||
if (!js_IsCallable(*fvalp)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_FUNCTION,
|
||||
js_AtomToPrintableString(cx, atom));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DerivedTrap(JSContext *cx, JSObject *handler, JSAtom *atom, jsval *fvalp)
|
||||
{
|
||||
JS_ASSERT(atom == ATOM(has) ||
|
||||
atom == ATOM(hasOwn) ||
|
||||
atom == ATOM(get) ||
|
||||
atom == ATOM(set) ||
|
||||
atom == ATOM(enumerateOwn) ||
|
||||
atom == ATOM(iterate));
|
||||
|
||||
return GetTrap(cx, handler, atom, fvalp);
|
||||
}
|
||||
|
||||
static bool
|
||||
Trap(JSContext *cx, JSObject *handler, jsval fval, uintN argc, jsval* argv, jsval *rval)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
||||
jsval fval;
|
||||
if (!GetTrap(cx, handler, atom, &fval))
|
||||
return false;
|
||||
return js_InternalCall(cx, handler, fval, argc, argv, rval);
|
||||
}
|
||||
|
||||
static bool
|
||||
Trap1(JSContext *cx, JSObject *handler, JSAtom *atom, jsid id, jsval *rval)
|
||||
Trap1(JSContext *cx, JSObject *handler, jsval fval, jsid id, jsval *rval)
|
||||
{
|
||||
JSString *str = js_ValueToString(cx, ID_TO_VALUE(id));
|
||||
if (!str)
|
||||
return false;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return Trap(cx, handler, atom, 1, rval, rval);
|
||||
return Trap(cx, handler, fval, 1, rval, rval);
|
||||
}
|
||||
|
||||
static bool
|
||||
Trap2(JSContext *cx, JSObject *handler, JSAtom *atom, jsid id, jsval v, jsval *rval)
|
||||
Trap2(JSContext *cx, JSObject *handler, jsval fval, jsid id, jsval v, jsval *rval)
|
||||
{
|
||||
JSString *str = js_ValueToString(cx, ID_TO_VALUE(id));
|
||||
if (!str)
|
||||
return false;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
jsval argv[2] = { *rval, v };
|
||||
return Trap(cx, handler, atom, 2, argv, rval);
|
||||
return Trap(cx, handler, fval, 2, argv, rval);
|
||||
}
|
||||
|
||||
static bool
|
||||
ParsePropertyDescriptorObject(JSContext *cx, JSObject *obj, jsid id, jsval v, JSPropertyDescriptor *desc)
|
||||
ParsePropertyDescriptorObject(JSContext *cx, JSObject *obj, jsid id, jsval v,
|
||||
JSPropertyDescriptor *desc)
|
||||
{
|
||||
AutoDescriptorArray descs(cx);
|
||||
PropertyDescriptor *d = descs.append();
|
||||
@ -386,80 +421,18 @@ MakePropertyDescriptorObject(JSContext *cx, jsid id, JSPropertyDescriptor *desc,
|
||||
return js_NewPropertyDescriptorObject(cx, id, attrs, getter, setter, desc->value, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||
static bool
|
||||
ValueToBool(JSContext *cx, jsval v, bool *bp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter tvr(cx);
|
||||
return TryHandlerTrap(cx, proxy, Trap1(cx, JSVAL_TO_OBJECT(handler), ATOM(getPropertyDescriptor), id, tvr.addr())) &&
|
||||
ParsePropertyDescriptorObject(cx, proxy, id, tvr.value(), desc);
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->getPropertyDescriptor(cx, proxy, id, desc));
|
||||
JSBool b;
|
||||
if (!JS_ValueToBoolean(cx, v, &b))
|
||||
return false;
|
||||
*bp = !!b;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, jsval *vp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
return TryHandlerTrap(cx, proxy, Trap1(cx, JSVAL_TO_OBJECT(handler), ATOM(getPropertyDescriptor), id, vp));
|
||||
}
|
||||
AutoDescriptor desc(cx);
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->getPropertyDescriptor(cx, proxy, id, &desc)) &&
|
||||
MakePropertyDescriptorObject(cx, id, &desc, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter tvr(cx);
|
||||
return TryHandlerTrap(cx, proxy, Trap1(cx, JSVAL_TO_OBJECT(handler), ATOM(getOwnPropertyDescriptor), id, tvr.addr())) &&
|
||||
ParsePropertyDescriptorObject(cx, proxy, id, tvr.value(), desc);
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->getOwnPropertyDescriptor(cx, proxy, id, desc));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, jsval *vp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return TryHandlerTrap(cx, proxy, Trap1(cx, JSVAL_TO_OBJECT(handler), ATOM(getOwnPropertyDescriptor), id, vp));
|
||||
AutoDescriptor desc(cx);
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->getOwnPropertyDescriptor(cx, proxy, id, &desc)) &&
|
||||
MakePropertyDescriptorObject(cx, id, &desc, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter tvr(cx);
|
||||
return MakePropertyDescriptorObject(cx, id, desc, tvr.addr()) &&
|
||||
TryHandlerTrap(cx, proxy, Trap2(cx, JSVAL_TO_OBJECT(handler), ATOM(defineProperty), id, tvr.value(), tvr.addr()));
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->defineProperty(cx, proxy, id, desc));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::defineProperty(JSContext *cx, JSObject *proxy, jsid id, jsval v)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter tvr(cx);
|
||||
return TryHandlerTrap(cx, proxy, Trap2(cx, JSVAL_TO_OBJECT(handler), ATOM(defineProperty), id, v, tvr.addr()));
|
||||
}
|
||||
AutoDescriptor desc(cx);
|
||||
return ParsePropertyDescriptorObject(cx, proxy, id, v, &desc) &&
|
||||
TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->defineProperty(cx, proxy, id, &desc));
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayToJSIDArray(JSContext *cx, jsval array, JSIdArray **idap)
|
||||
ArrayToJSIdArray(JSContext *cx, jsval array, JSIdArray **idap)
|
||||
{
|
||||
if (JSVAL_IS_PRIMITIVE(array))
|
||||
return (*idap = NewIdArray(cx, 0)) != NULL;
|
||||
@ -488,48 +461,298 @@ ArrayToJSIDArray(JSContext *cx, jsval array, JSIdArray **idap)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Derived class for all scripted proxy handlers. */
|
||||
class JSScriptedProxyHandler : public JSProxyHandler {
|
||||
public:
|
||||
JSScriptedProxyHandler();
|
||||
virtual ~JSScriptedProxyHandler();
|
||||
|
||||
/* ES5 Harmony fundamental proxy traps. */
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc);
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc);
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc);
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, JSIdArray **idap);
|
||||
virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
virtual bool enumerate(JSContext *cx, JSObject *proxy, JSIdArray **idap);
|
||||
virtual bool fix(JSContext *cx, JSObject *proxy, jsval *vp);
|
||||
|
||||
/* ES5 Harmony derived proxy traps. */
|
||||
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, jsval *vp);
|
||||
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
|
||||
virtual bool enumerateOwn(JSContext *cx, JSObject *proxy, JSIdArray **idap);
|
||||
virtual bool iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual const void *family();
|
||||
|
||||
static JSScriptedProxyHandler singleton;
|
||||
};
|
||||
|
||||
JSScriptedProxyHandler::JSScriptedProxyHandler()
|
||||
{
|
||||
}
|
||||
|
||||
JSScriptedProxyHandler::~JSScriptedProxyHandler()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
return FundamentalTrap(cx, handler, ATOM(getPropertyDescriptor), tvr.addr()) &&
|
||||
TryHandlerTrap(cx, proxy, Trap1(cx, handler, tvr.value(), id, tvr.addr())) &&
|
||||
ParsePropertyDescriptorObject(cx, proxy, id, tvr.value(), desc);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
return FundamentalTrap(cx, handler, ATOM(getOwnPropertyDescriptor), tvr.addr()) &&
|
||||
TryHandlerTrap(cx, proxy, Trap1(cx, handler, tvr.value(), id, tvr.addr())) &&
|
||||
ParsePropertyDescriptorObject(cx, proxy, id, tvr.value(), desc);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
AutoValueRooter fval(cx);
|
||||
return FundamentalTrap(cx, handler, ATOM(defineProperty), fval.addr()) &&
|
||||
MakePropertyDescriptorObject(cx, id, desc, tvr.addr()) &&
|
||||
TryHandlerTrap(cx, proxy, Trap2(cx, handler, fval.value(), id, tvr.value(), tvr.addr()));
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
return FundamentalTrap(cx, handler, ATOM(getOwnPropertyNames), tvr.addr()) &&
|
||||
TryHandlerTrap(cx, proxy, Trap(cx, handler, tvr.value(), 0, NULL, tvr.addr())) &&
|
||||
ArrayToJSIdArray(cx, tvr.value(), idap);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
return FundamentalTrap(cx, handler, ATOM(delete), tvr.addr()) &&
|
||||
TryHandlerTrap(cx, proxy, Trap1(cx, handler, tvr.value(), id, tvr.addr())) &&
|
||||
ValueToBool(cx, tvr.value(), bp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::enumerate(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
return FundamentalTrap(cx, handler, ATOM(enumerate), tvr.addr()) &&
|
||||
TryHandlerTrap(cx, proxy, Trap(cx, handler, tvr.value(), 0, NULL, tvr.addr())) &&
|
||||
ArrayToJSIdArray(cx, tvr.value(), idap);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::fix(JSContext *cx, JSObject *proxy, jsval *vp)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
return FundamentalTrap(cx, handler, ATOM(fix), vp) &&
|
||||
Trap(cx, handler, *vp, 0, NULL, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!DerivedTrap(cx, handler, ATOM(has), tvr.addr()))
|
||||
return false;
|
||||
if (!js_IsCallable(tvr.value()))
|
||||
return JSProxyHandler::has(cx, proxy, id, bp);
|
||||
return TryHandlerTrap(cx, proxy, Trap1(cx, handler, tvr.value(), id, tvr.addr())) &&
|
||||
ValueToBool(cx, tvr.value(), bp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!DerivedTrap(cx, handler, ATOM(hasOwn), tvr.addr()))
|
||||
return false;
|
||||
if (!js_IsCallable(tvr.value()))
|
||||
return JSProxyHandler::hasOwn(cx, proxy, id, bp);
|
||||
return TryHandlerTrap(cx, proxy, Trap1(cx, handler, tvr.value(), id, tvr.addr())) &&
|
||||
ValueToBool(cx, tvr.value(), bp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
JSString *str = js_ValueToString(cx, ID_TO_VALUE(id));
|
||||
if (!str)
|
||||
return false;
|
||||
AutoValueRooter tvr(cx, STRING_TO_JSVAL(str));
|
||||
jsval argv[] = { OBJECT_TO_JSVAL(receiver), tvr.value() };
|
||||
AutoValueRooter fval(cx);
|
||||
if (!DerivedTrap(cx, handler, ATOM(get), fval.addr()))
|
||||
return false;
|
||||
if (!js_IsCallable(fval.value()))
|
||||
return JSProxyHandler::get(cx, proxy, receiver, id, vp);
|
||||
return TryHandlerTrap(cx, proxy, Trap(cx, handler, fval.value(), 2, argv, vp));
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
JSString *str = js_ValueToString(cx, ID_TO_VALUE(id));
|
||||
if (!str)
|
||||
return false;
|
||||
AutoValueRooter tvr(cx, STRING_TO_JSVAL(str));
|
||||
jsval argv[] = { OBJECT_TO_JSVAL(receiver), tvr.value(), *vp };
|
||||
AutoValueRooter fval(cx);
|
||||
if (!DerivedTrap(cx, handler, ATOM(set), fval.addr()))
|
||||
return false;
|
||||
if (!js_IsCallable(fval.value()))
|
||||
return JSProxyHandler::set(cx, proxy, receiver, id, vp);
|
||||
return TryHandlerTrap(cx, proxy, Trap(cx, handler, fval.value(), 3, argv, tvr.addr()));
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::enumerateOwn(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!DerivedTrap(cx, handler, ATOM(enumerateOwn), tvr.addr()))
|
||||
return false;
|
||||
if (!js_IsCallable(tvr.value()))
|
||||
return JSProxyHandler::enumerateOwn(cx, proxy, idap);
|
||||
return TryHandlerTrap(cx, proxy, Trap(cx, handler, tvr.value(), 0, NULL, tvr.addr())) &&
|
||||
ArrayToJSIdArray(cx, tvr.value(), idap);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScriptedProxyHandler::iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp)
|
||||
{
|
||||
JSObject *handler = JSVAL_TO_OBJECT(proxy->getProxyHandler());
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!DerivedTrap(cx, handler, ATOM(iterate), tvr.addr()))
|
||||
return false;
|
||||
if (!js_IsCallable(tvr.value()))
|
||||
return JSProxyHandler::iterate(cx, proxy, flags, vp);
|
||||
return TryHandlerTrap(cx, proxy, Trap(cx, handler, tvr.value(), 0, NULL, vp));
|
||||
}
|
||||
|
||||
const void *
|
||||
JSScriptedProxyHandler::family()
|
||||
{
|
||||
return &singleton;
|
||||
}
|
||||
|
||||
JSScriptedProxyHandler JSScriptedProxyHandler::singleton;
|
||||
|
||||
static JSProxyHandler *
|
||||
JSVAL_TO_HANDLER(jsval handler)
|
||||
{
|
||||
return (JSProxyHandler *) JSVAL_TO_PRIVATE(handler);
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.getPropertyDescriptor(cx, proxy, id, desc);
|
||||
return TryHandlerTrap(cx, proxy,
|
||||
JSVAL_TO_HANDLER(handler)->getPropertyDescriptor(cx, proxy, id, desc));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, jsval *vp)
|
||||
{
|
||||
AutoDescriptor desc(cx);
|
||||
return JSProxy::getPropertyDescriptor(cx, proxy, id, &desc) &&
|
||||
MakePropertyDescriptorObject(cx, id, &desc, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.getOwnPropertyDescriptor(cx, proxy, id, desc);
|
||||
return TryHandlerTrap(cx, proxy,
|
||||
JSVAL_TO_HANDLER(handler)->getOwnPropertyDescriptor(cx, proxy, id, desc));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, jsval *vp)
|
||||
{
|
||||
AutoDescriptor desc(cx);
|
||||
return JSProxy::getOwnPropertyDescriptor(cx, proxy, id, &desc) &&
|
||||
MakePropertyDescriptorObject(cx, id, &desc, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.defineProperty(cx, proxy, id, desc);
|
||||
return TryHandlerTrap(cx, proxy,
|
||||
JSVAL_TO_HANDLER(handler)->defineProperty(cx, proxy, id, desc));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::defineProperty(JSContext *cx, JSObject *proxy, jsid id, jsval v)
|
||||
{
|
||||
AutoDescriptor desc(cx);
|
||||
return ParsePropertyDescriptorObject(cx, proxy, id, v, &desc) &&
|
||||
JSProxy::defineProperty(cx, proxy, id, &desc);
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::getOwnPropertyNames(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!TryHandlerTrap(cx, proxy, Trap(cx, JSVAL_TO_OBJECT(handler), ATOM(getOwnPropertyNames),
|
||||
0, NULL, tvr.addr())))
|
||||
return false;
|
||||
return ArrayToJSIDArray(cx, tvr.value(), idap);
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->getOwnPropertyNames(cx, proxy, idap));
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.getOwnPropertyNames(cx, proxy, idap);
|
||||
return TryHandlerTrap(cx, proxy,
|
||||
JSVAL_TO_HANDLER(handler)->getOwnPropertyNames(cx, proxy, idap));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!TryHandlerTrap(cx, proxy, Trap1(cx, JSVAL_TO_OBJECT(handler), ATOM(delete), id, tvr.addr())))
|
||||
return false;
|
||||
JSBool deleted;
|
||||
if (!JS_ValueToBoolean(cx, tvr.value(), &deleted))
|
||||
return false;
|
||||
*bp = !!deleted;
|
||||
return true;
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->delete_(cx, proxy, id, bp));
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.delete_(cx, proxy, id, bp);
|
||||
return TryHandlerTrap(cx, proxy, JSVAL_TO_HANDLER(handler)->delete_(cx, proxy, id, bp));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::enumerate(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!TryHandlerTrap(cx, proxy, Trap(cx, JSVAL_TO_OBJECT(handler), ATOM(enumerate), 0, NULL, tvr.addr())))
|
||||
return false;
|
||||
return ArrayToJSIDArray(cx, tvr.value(), idap);
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->enumerate(cx, proxy, idap));
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.enumerate(cx, proxy, idap);
|
||||
return TryHandlerTrap(cx, proxy, JSVAL_TO_HANDLER(handler)->enumerate(cx, proxy, idap));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -537,85 +760,62 @@ JSProxy::fix(JSContext *cx, JSObject *proxy, jsval *vp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return Trap(cx, JSVAL_TO_OBJECT(handler), ATOM(fix), 0, NULL, vp);
|
||||
return ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->fix(cx, proxy, vp);
|
||||
return JSScriptedProxyHandler::singleton.fix(cx, proxy, vp);
|
||||
return JSVAL_TO_HANDLER(handler)->fix(cx, proxy, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!TryHandlerTrap(cx, proxy, Trap1(cx, JSVAL_TO_OBJECT(handler), ATOM(has), id, tvr.addr())))
|
||||
return false;
|
||||
JSBool has;
|
||||
if (!JS_ValueToBoolean(cx, tvr.value(), &has))
|
||||
return false;
|
||||
*bp = !!has;
|
||||
return true;
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->has(cx, proxy, id, bp));
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.has(cx, proxy, id, bp);
|
||||
return TryHandlerTrap(cx, proxy, JSVAL_TO_HANDLER(handler)->has(cx, proxy, id, bp));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!TryHandlerTrap(cx, proxy, Trap1(cx, JSVAL_TO_OBJECT(handler), ATOM(hasOwn), id, tvr.addr())))
|
||||
return false;
|
||||
JSBool has;
|
||||
if (!JS_ValueToBoolean(cx, tvr.value(), &has))
|
||||
return false;
|
||||
*bp = !!has;
|
||||
return true;
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->hasOwn(cx, proxy, id, bp));
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.hasOwn(cx, proxy, id, bp);
|
||||
return TryHandlerTrap(cx, proxy, JSVAL_TO_HANDLER(handler)->hasOwn(cx, proxy, id, bp));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
JSString *str = js_ValueToString(cx, ID_TO_VALUE(id));
|
||||
if (!str)
|
||||
return false;
|
||||
AutoValueRooter tvr(cx, STRING_TO_JSVAL(str));
|
||||
jsval argv[] = { OBJECT_TO_JSVAL(receiver), tvr.value() };
|
||||
return TryHandlerTrap(cx, proxy, Trap(cx, JSVAL_TO_OBJECT(handler), ATOM(get), 2, argv, vp));
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->get(cx, proxy, receiver, id, vp));
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.get(cx, proxy, receiver, id, vp);
|
||||
return TryHandlerTrap(cx, proxy, JSVAL_TO_HANDLER(handler)->get(cx, proxy, receiver, id, vp));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
JSString *str = js_ValueToString(cx, ID_TO_VALUE(id));
|
||||
if (!str)
|
||||
return false;
|
||||
AutoValueRooter tvr(cx, STRING_TO_JSVAL(str));
|
||||
jsval argv[] = { OBJECT_TO_JSVAL(receiver), tvr.value(), *vp };
|
||||
return TryHandlerTrap(cx, proxy, Trap(cx, JSVAL_TO_OBJECT(handler), ATOM(set), 3, argv, tvr.addr()));
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->set(cx, proxy, receiver, id, vp));
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.set(cx, proxy, receiver, id, vp);
|
||||
return TryHandlerTrap(cx, proxy, JSVAL_TO_HANDLER(handler)->set(cx, proxy, receiver, id, vp));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::enumerateOwn(JSContext *cx, JSObject *proxy, JSIdArray **idap)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler)) {
|
||||
AutoValueRooter rval(cx);
|
||||
if (!TryHandlerTrap(cx, proxy, Trap(cx, JSVAL_TO_OBJECT(handler), ATOM(enumerateOwn), 0, NULL, rval.addr())))
|
||||
return false;
|
||||
return ArrayToJSIDArray(cx, rval.value(), idap);
|
||||
}
|
||||
return TryHandlerTrap(cx, proxy, ((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->enumerateOwn(cx, proxy, idap));
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.enumerateOwn(cx, proxy, idap);
|
||||
return TryHandlerTrap(cx, proxy, JSVAL_TO_HANDLER(handler)->enumerateOwn(cx, proxy, idap));
|
||||
}
|
||||
|
||||
bool
|
||||
JSProxy::iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp)
|
||||
{
|
||||
jsval handler = proxy->getProxyHandler();
|
||||
if (JSVAL_IS_OBJECT(handler))
|
||||
return JSScriptedProxyHandler::singleton.iterate(cx, proxy, flags, vp);
|
||||
return TryHandlerTrap(cx, proxy, JSVAL_TO_HANDLER(handler)->iterate(cx, proxy, flags, vp));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
@ -743,7 +943,7 @@ proxy_TraceObject(JSTracer *trc, JSObject *obj)
|
||||
if (!JSVAL_IS_PRIMITIVE(handler))
|
||||
JS_CALL_OBJECT_TRACER(trc, JSVAL_TO_OBJECT(handler), "handler");
|
||||
else
|
||||
((JSProxyHandler *) JSVAL_TO_PRIVATE(handler))->trace(trc, obj);
|
||||
JSVAL_TO_HANDLER(handler)->trace(trc, obj);
|
||||
if (obj->isFunctionProxy()) {
|
||||
JS_CALL_VALUE_TRACER(trc, obj->fslots[JSSLOT_PROXY_CALL], "call");
|
||||
JS_CALL_VALUE_TRACER(trc, obj->fslots[JSSLOT_PROXY_CONSTRUCT], "construct");
|
||||
@ -788,9 +988,8 @@ obj_proxy_getObjectOps(JSContext *cx, JSClass *clasp)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSClass) ObjectProxyClass = {
|
||||
"ObjectProxy",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(3) |
|
||||
JSCLASS_NEW_ENUMERATE,
|
||||
"Proxy",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(3),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
|
||||
obj_proxy_getObjectOps, NULL, NULL, NULL,
|
||||
@ -812,11 +1011,17 @@ proxy_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rv
|
||||
JS_ASSERT(proxy->isProxy());
|
||||
jsval fval = proxy->fslots[JSSLOT_PROXY_CONSTRUCT];
|
||||
if (fval == JSVAL_VOID) {
|
||||
/* We don't have an explicit constructor trap so allocate a new object and use the call trap. */
|
||||
/*
|
||||
* We don't have an explicit constructor trap so allocate a new
|
||||
* object and use the call trap.
|
||||
*/
|
||||
fval = proxy->fslots[JSSLOT_PROXY_CALL];
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(fval));
|
||||
|
||||
/* proxy is the constructor, so get proxy.prototype as the proto of the new object. */
|
||||
/*
|
||||
* proxy is the constructor, so get proxy.prototype as the proto
|
||||
* of the new object.
|
||||
*/
|
||||
if (!JSProxy::get(cx, proxy, obj, ATOM_TO_JSID(ATOM(classPrototype)), rval))
|
||||
return false;
|
||||
JSObject *proto = !JSVAL_IS_PRIMITIVE(*rval) ? JSVAL_TO_OBJECT(*rval) : NULL;
|
||||
@ -867,9 +1072,8 @@ fun_proxy_getObjectOps(JSContext *cx, JSClass *clasp)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSClass) FunctionProxyClass = {
|
||||
"FunctionProxy",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(3) |
|
||||
JSCLASS_NEW_ENUMERATE,
|
||||
"Proxy",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(3),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
|
||||
fun_proxy_getObjectOps, NULL, NULL, NULL,
|
||||
@ -916,7 +1120,7 @@ proxy_create(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc < 1) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
|
||||
"Proxy.create", "0", "s");
|
||||
"create", "0", "s");
|
||||
return false;
|
||||
}
|
||||
JSObject *handler;
|
||||
@ -945,7 +1149,7 @@ proxy_createFunction(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc < 2) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
|
||||
"Proxy.createFunction", "1", "");
|
||||
"createFunction", "1", "");
|
||||
return false;
|
||||
}
|
||||
JSObject *handler;
|
||||
@ -967,7 +1171,8 @@ proxy_createFunction(JSContext *cx, uintN argc, jsval *vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject *proxy = NewFunctionProxy(cx, OBJECT_TO_JSVAL(handler), proto, parent, call, construct);
|
||||
JSObject *proxy = NewFunctionProxy(cx, OBJECT_TO_JSVAL(handler), proto, parent,
|
||||
call, construct);
|
||||
if (!proxy)
|
||||
return false;
|
||||
|
||||
@ -982,7 +1187,7 @@ proxy_isTrapping(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc < 1) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
|
||||
"Proxy.isTrapping", "0", "s");
|
||||
"isTrapping", "0", "s");
|
||||
return false;
|
||||
}
|
||||
JSObject *obj;
|
||||
@ -997,7 +1202,7 @@ proxy_fix(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc < 1) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
|
||||
"Proxy.fix", "0", "s");
|
||||
"fix", "0", "s");
|
||||
return false;
|
||||
}
|
||||
JSObject *obj;
|
||||
@ -1071,9 +1276,8 @@ callable_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval
|
||||
}
|
||||
|
||||
JSClass CallableObjectClass = {
|
||||
"CallableObject",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(2) |
|
||||
JSCLASS_NEW_ENUMERATE,
|
||||
"Function",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(2),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
|
||||
NULL, NULL, callable_Call, callable_Construct,
|
||||
|
@ -53,9 +53,12 @@ class JSProxyHandler {
|
||||
virtual ~JSProxyHandler();
|
||||
|
||||
/* ES5 Harmony fundamental proxy traps. */
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc) = 0;
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc) = 0;
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc) = 0;
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc) = 0;
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc) = 0;
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc) = 0;
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, JSIdArray **idap) = 0;
|
||||
virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) = 0;
|
||||
virtual bool enumerate(JSContext *cx, JSObject *proxy, JSIdArray **idap) = 0;
|
||||
@ -67,11 +70,12 @@ class JSProxyHandler {
|
||||
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
|
||||
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
|
||||
virtual bool enumerateOwn(JSContext *cx, JSObject *proxy, JSIdArray **idap);
|
||||
virtual bool iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual void finalize(JSContext *cx, JSObject *proxy);
|
||||
virtual void trace(JSTracer *trc, JSObject *proxy);
|
||||
virtual void *family() = 0;
|
||||
virtual const void *family() = 0;
|
||||
};
|
||||
|
||||
/* No-op wrapper handler base class. */
|
||||
@ -85,10 +89,14 @@ class JSNoopProxyHandler {
|
||||
JS_FRIEND_API(virtual ~JSNoopProxyHandler());
|
||||
|
||||
/* ES5 Harmony fundamental proxy traps. */
|
||||
virtual JS_FRIEND_API(bool) getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc);
|
||||
virtual JS_FRIEND_API(bool) getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc);
|
||||
virtual JS_FRIEND_API(bool) defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc);
|
||||
virtual JS_FRIEND_API(bool) getOwnPropertyNames(JSContext *cx, JSObject *proxy, JSIdArray **idap);
|
||||
virtual JS_FRIEND_API(bool) getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc);
|
||||
virtual JS_FRIEND_API(bool) getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc);
|
||||
virtual JS_FRIEND_API(bool) defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc);
|
||||
virtual JS_FRIEND_API(bool) getOwnPropertyNames(JSContext *cx, JSObject *proxy,
|
||||
JSIdArray **idap);
|
||||
virtual JS_FRIEND_API(bool) delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
virtual JS_FRIEND_API(bool) enumerate(JSContext *cx, JSObject *proxy, JSIdArray **idap);
|
||||
virtual JS_FRIEND_API(bool) fix(JSContext *cx, JSObject *proxy, jsval *vp);
|
||||
@ -96,19 +104,23 @@ class JSNoopProxyHandler {
|
||||
/* 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, jsval *vp);
|
||||
virtual JS_FRIEND_API(bool) set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
|
||||
virtual JS_FRIEND_API(bool) get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id,
|
||||
jsval *vp);
|
||||
virtual JS_FRIEND_API(bool) set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id,
|
||||
jsval *vp);
|
||||
virtual JS_FRIEND_API(bool) enumerateOwn(JSContext *cx, JSObject *proxy, JSIdArray **idap);
|
||||
virtual JS_FRIEND_API(bool) iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual JS_FRIEND_API(void) finalize(JSContext *cx, JSObject *proxy);
|
||||
virtual JS_FRIEND_API(void) trace(JSTracer *trc, JSObject *proxy);
|
||||
virtual JS_FRIEND_API(void) *family();
|
||||
virtual JS_FRIEND_API(const void *) family();
|
||||
|
||||
static JSNoopProxyHandler singleton;
|
||||
|
||||
template <class T>
|
||||
static JSObject *wrap(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, JSString *className);
|
||||
static JSObject *wrap(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
|
||||
JSString *className);
|
||||
|
||||
inline JSObject *wrappedObject(JSObject *proxy) {
|
||||
return mWrappedObject ? mWrappedObject : JSVAL_TO_OBJECT(proxy->getProxyPrivate());
|
||||
@ -119,9 +131,11 @@ class JSNoopProxyHandler {
|
||||
class JSProxy {
|
||||
public:
|
||||
/* ES5 Harmony fundamental proxy traps. */
|
||||
static bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc);
|
||||
static bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc);
|
||||
static bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, jsval *vp);
|
||||
static bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc);
|
||||
static bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
JSPropertyDescriptor *desc);
|
||||
static bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, jsval *vp);
|
||||
static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc);
|
||||
static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, jsval v);
|
||||
@ -136,6 +150,7 @@ class JSProxy {
|
||||
static bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
|
||||
static bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
|
||||
static bool enumerateOwn(JSContext *cx, JSObject *proxy, JSIdArray **idap);
|
||||
static bool iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
|
||||
};
|
||||
|
||||
/* Shared between object and function proxies. */
|
||||
@ -197,10 +212,12 @@ JSObject::setProxyPrivate(jsval priv)
|
||||
namespace js {
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
NewObjectProxy(JSContext *cx, jsval handler, JSObject *proto, JSObject *parent, JSString *className);
|
||||
NewObjectProxy(JSContext *cx, jsval handler, JSObject *proto, JSObject *parent,
|
||||
JSString *className);
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
NewFunctionProxy(JSContext *cx, jsval handler, JSObject *proto, JSObject *parent, JSObject *call, JSObject *construct);
|
||||
NewFunctionProxy(JSContext *cx, jsval handler, JSObject *proto, JSObject *parent,
|
||||
JSObject *call, JSObject *construct);
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
GetProxyObjectClass(JSContext *cx, JSObject *proxy, const char **namep);
|
||||
@ -210,18 +227,21 @@ FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp);
|
||||
|
||||
template <class T>
|
||||
JSObject *
|
||||
JSNoopProxyHandler::wrap(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, JSString *className)
|
||||
JSNoopProxyHandler::wrap(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
|
||||
JSString *className)
|
||||
{
|
||||
if (obj->isCallable()) {
|
||||
JSNoopProxyHandler *handler = new T(obj);
|
||||
if (!handler)
|
||||
return NULL;
|
||||
JSObject *wrapper = NewFunctionProxy(cx, PRIVATE_TO_JSVAL(handler), proto, parent, obj, NULL);
|
||||
JSObject *wrapper = NewFunctionProxy(cx, PRIVATE_TO_JSVAL(handler), proto, parent,
|
||||
obj, NULL);
|
||||
if (!wrapper)
|
||||
delete handler;
|
||||
return wrapper;
|
||||
}
|
||||
JSObject *wrapper = NewObjectProxy(cx, PRIVATE_TO_JSVAL(&T::singleton), proto, parent, className);
|
||||
JSObject *wrapper = NewObjectProxy(cx, PRIVATE_TO_JSVAL(&T::singleton), proto, parent,
|
||||
className);
|
||||
if (wrapper)
|
||||
wrapper->setProxyPrivate(OBJECT_TO_JSVAL(obj));
|
||||
return wrapper;
|
||||
|
@ -69,6 +69,7 @@
|
||||
#define INT_TO_JSID(i) ((jsid)INT_TO_JSVAL(i))
|
||||
#define INT_JSVAL_TO_JSID(v) ((jsid)(v))
|
||||
#define INT_JSID_TO_JSVAL(id) ((jsval)(id))
|
||||
#define INT_FITS_IN_JSID(i) INT_FITS_IN_JSVAL(i)
|
||||
|
||||
#define JSID_IS_OBJECT(id) JSVAL_IS_OBJECT((jsval)(id))
|
||||
#define JSID_TO_OBJECT(id) JSVAL_TO_OBJECT((jsval)(id))
|
||||
|
Loading…
Reference in New Issue
Block a user