Bug 698495 part 2. Add an optional getElementIfPresent ObjectOps hook. r=waldo

This commit is contained in:
Boris Zbarsky 2011-11-04 12:19:00 -04:00
parent ebefbb96db
commit a11f9b8298
10 changed files with 58 additions and 1 deletions

View File

@ -1296,6 +1296,8 @@ Class js::ArrayClass = {
array_getGeneric,
array_getProperty,
array_getElement,
NULL, /* getElementIfPresent, because this is hard for now for
slow arrays */
array_getSpecial,
array_setGeneric,
array_setProperty,

View File

@ -208,6 +208,8 @@ typedef JSBool
typedef JSBool
(* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp);
typedef JSBool
(* ElementIfPresentOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp, bool* present);
typedef JSBool
(* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
typedef JSBool
(* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
@ -313,6 +315,7 @@ struct ObjectOps
GenericIdOp getGeneric;
PropertyIdOp getProperty;
ElementIdOp getElement;
ElementIfPresentOp getElementIfPresent; /* can be null */
SpecialIdOp getSpecial;
StrictGenericIdOp setGeneric;
StrictPropertyIdOp setProperty;
@ -341,7 +344,7 @@ struct ObjectOps
#define JS_NULL_OBJECT_OPS \
{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL}
NULL,NULL,NULL,NULL,NULL,NULL}
struct Class
{

View File

@ -3457,6 +3457,7 @@ Class js::WithClass = {
with_GetGeneric,
with_GetProperty,
with_GetElement,
NULL, /* getElementIfPresent */
with_GetSpecial,
with_SetGeneric,
with_SetProperty,

View File

@ -1258,6 +1258,10 @@ inline JSBool
JSObject::getElementIfPresent(JSContext *cx, JSObject *receiver, uint32 index, js::Value *vp,
bool *present)
{
js::ElementIfPresentOp op = getOps()->getElementIfPresent;
if (op)
return op(cx, this, receiver, index, vp, present);
/* For now, do the index-to-id conversion just once, then use
* lookupGeneric/getGeneric. Once lookupElement and getElement stop both
* doing index-to-id conversions, we can use those here.

View File

@ -139,6 +139,24 @@ ProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, V
return CallJSPropertyOp(cx, desc.getter, receiver, id, vp);
}
bool
ProxyHandler::getElementIfPresent(JSContext *cx, JSObject *proxy, JSObject *receiver, uint32 index, Value *vp, bool *present)
{
jsid id;
if (!IndexToId(cx, index, &id))
return false;
if (!has(cx, proxy, id, present))
return false;
if (!*present) {
Debug_SetValueRangeToCrashOnTouch(vp, 1);
return true;
}
return get(cx, proxy, receiver, id, vp);
}
bool
ProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
Value *vp)
@ -809,6 +827,15 @@ Proxy::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *v
return GetProxyHandler(proxy)->get(cx, proxy, receiver, id, vp);
}
bool
Proxy::getElementIfPresent(JSContext *cx, JSObject *proxy, JSObject *receiver, uint32 index,
Value *vp, bool *present)
{
JS_CHECK_RECURSION(cx, return false);
AutoPendingProxyOperation pending(cx, proxy);
return GetProxyHandler(proxy)->getElementIfPresent(cx, proxy, receiver, index, vp, present);
}
bool
Proxy::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict, Value *vp)
{
@ -1017,6 +1044,13 @@ proxy_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index,
return proxy_GetGeneric(cx, obj, receiver, id, vp);
}
static JSBool
proxy_GetElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index,
Value *vp, bool *present)
{
return Proxy::getElementIfPresent(cx, obj, receiver, index, vp, present);
}
static JSBool
proxy_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
{
@ -1251,6 +1285,7 @@ JS_FRIEND_DATA(Class) js::ObjectProxyClass = {
proxy_GetGeneric,
proxy_GetProperty,
proxy_GetElement,
proxy_GetElementIfPresent,
proxy_GetSpecial,
proxy_SetGeneric,
proxy_SetProperty,
@ -1312,6 +1347,7 @@ JS_FRIEND_DATA(Class) js::OuterWindowProxyClass = {
proxy_GetGeneric,
proxy_GetProperty,
proxy_GetElement,
proxy_GetElementIfPresent,
proxy_GetSpecial,
proxy_SetGeneric,
proxy_SetProperty,
@ -1385,6 +1421,7 @@ JS_FRIEND_DATA(Class) js::FunctionProxyClass = {
proxy_GetGeneric,
proxy_GetProperty,
proxy_GetElement,
proxy_GetElementIfPresent,
proxy_GetSpecial,
proxy_SetGeneric,
proxy_SetProperty,

View File

@ -88,6 +88,8 @@ class JS_FRIEND_API(ProxyHandler) {
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
virtual void finalize(JSContext *cx, JSObject *proxy);
virtual void trace(JSTracer *trc, JSObject *proxy);
virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver,
uint32 index, Value *vp, bool *present);
virtual bool isOuterWindow() {
return false;
@ -120,6 +122,8 @@ class Proxy {
static bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
static bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
static bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp);
static bool getElementIfPresent(JSContext *cx, JSObject *proxy, JSObject *receiver,
uint32 index, Value *vp, bool *present);
static bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
Value *vp);
static bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props);

View File

@ -2105,6 +2105,7 @@ Class js::ArrayBufferClass = {
ArrayBuffer::obj_getGeneric,
ArrayBuffer::obj_getProperty,
ArrayBuffer::obj_getElement,
NULL, /* getElementIfPresent */
ArrayBuffer::obj_getSpecial,
ArrayBuffer::obj_setGeneric,
ArrayBuffer::obj_setProperty,
@ -2217,6 +2218,7 @@ JSFunctionSpec _typedArray::jsfuncs[] = { \
_typedArray::obj_getGeneric, \
_typedArray::obj_getProperty, \
_typedArray::obj_getElement, \
NULL, /* getElementIfPresent */ \
_typedArray::obj_getSpecial, \
_typedArray::obj_setGeneric, \
_typedArray::obj_setProperty, \

View File

@ -5361,6 +5361,7 @@ JS_FRIEND_DATA(Class) js::XMLClass = {
xml_getGeneric,
xml_getProperty,
xml_getElement,
NULL, /* getElementIfPresent */
xml_getSpecial,
xml_setGeneric,
xml_setProperty,

View File

@ -866,6 +866,7 @@ js::Class XPC_WN_NoHelper_JSClass = {
nsnull, // getGeneric
nsnull, // getProperty
nsnull, // getElement
nsnull, // getElementIfPresent
nsnull, // getSpecial
nsnull, // setGeneric
nsnull, // setProperty

View File

@ -1407,6 +1407,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj);
nsnull, /* getGeneric */ \
nsnull, /* getProperty */ \
nsnull, /* getElement */ \
nsnull, /* getElementIfPresent */ \
nsnull, /* getSpecial */ \
nsnull, /* setGeneric */ \
nsnull, /* setProperty */ \
@ -1444,6 +1445,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj);
nsnull, /* getGeneric */ \
nsnull, /* getProperty */ \
nsnull, /* getElement */ \
nsnull, /* getElementIfPresent */ \
nsnull, /* getSpecial */ \
nsnull, /* setGeneric */ \
nsnull, /* setProperty */ \