Bug 476447 - Array.prototype getter/setter does not work as usual (r=jorendorff).

This commit is contained in:
Brendan Eich 2009-03-09 11:25:43 -07:00
Родитель 137804716b
Коммит 3b1b70d1c3
3 изменённых файлов: 31 добавлений и 8 удалений

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

@ -63,6 +63,28 @@ extern JSClass js_ArrayClass, js_SlowArrayClass;
#define OBJ_IS_ARRAY(cx,obj) (OBJ_IS_DENSE_ARRAY(cx, obj) || \
OBJ_GET_CLASS(cx, obj) == &js_SlowArrayClass)
/*
* Dense arrays are not native (OBJ_IS_NATIVE(cx, aobj) for a dense array aobj
* results in false, meaning aobj->map does not point to a JSScope).
*
* But Array methods are called via aobj.sort(), e.g., and the interpreter and
* the trace recorder must consult the property cache in order to perform well.
* The cache works only for native objects.
*
* Therefore the interpreter (js_Interpret in JSOP_GETPROP and JSOP_CALLPROP)
* and js_GetPropertyHelper use this inline function to skip up one link in the
* prototype chain when obj is a dense array, in order to find a likely-native
* object (to wit, Array.prototype) in which to probe for cached methods.
*
* Callers of js_GetProtoIfDenseArray must take care to use the original object
* (obj) for the |this| value of a getter, setter, or method call (bug 476447).
*/
static JS_INLINE JSObject *
js_GetProtoIfDenseArray(JSContext *cx, JSObject *obj)
{
return OBJ_IS_DENSE_ARRAY(cx, obj) ? OBJ_GET_PROTO(cx, obj) : obj;
}
extern JSObject *
js_InitArrayClass(JSContext *cx, JSObject *obj);

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

@ -4263,7 +4263,7 @@ js_Interpret(JSContext *cx)
JSObject *aobj;
JSPropCacheEntry *entry;
aobj = OBJ_IS_DENSE_ARRAY(cx, obj) ? OBJ_GET_PROTO(cx, obj) : obj;
aobj = js_GetProtoIfDenseArray(cx, obj);
if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) {
PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom);
if (!atom) {
@ -4291,7 +4291,7 @@ js_Interpret(JSContext *cx)
}
id = ATOM_TO_JSID(atom);
if (entry
? !js_GetPropertyHelper(cx, aobj, id, &rval, &entry)
? !js_GetPropertyHelper(cx, obj, id, &rval, &entry)
: !OBJ_GET_PROPERTY(cx, obj, id, &rval)) {
goto error;
}
@ -4354,7 +4354,7 @@ js_Interpret(JSContext *cx)
goto error;
}
aobj = OBJ_IS_DENSE_ARRAY(cx, obj) ? OBJ_GET_PROTO(cx, obj) : obj;
aobj = js_GetProtoIfDenseArray(cx, obj);
if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) {
PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom);
if (!atom) {
@ -4399,7 +4399,7 @@ js_Interpret(JSContext *cx)
} else
#endif
if (entry
? !js_GetPropertyHelper(cx, aobj, id, &rval, &entry)
? !js_GetPropertyHelper(cx, obj, id, &rval, &entry)
: !OBJ_GET_PROPERTY(cx, obj, id, &rval)) {
goto error;
}

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

@ -4205,9 +4205,9 @@ JSBool
js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
JSPropCacheEntry **entryp)
{
JSObject *aobj, *obj2;
uint32 shape;
int protoIndex;
JSObject *obj2;
JSProperty *prop;
JSScopeProperty *sprop;
@ -4215,8 +4215,9 @@ js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
/* Convert string indices to integers if appropriate. */
CHECK_FOR_STRING_INDEX(id);
shape = OBJ_SHAPE(obj);
protoIndex = js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
aobj = js_GetProtoIfDenseArray(cx, obj);
shape = OBJ_SHAPE(aobj);
protoIndex = js_LookupPropertyWithFlags(cx, aobj, id, cx->resolveFlags,
&obj2, &prop);
if (protoIndex < 0)
return JS_FALSE;
@ -4294,7 +4295,7 @@ js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
if (entryp) {
JS_ASSERT_NOT_ON_TRACE(cx);
js_FillPropertyCache(cx, obj, shape, 0, protoIndex, obj2, sprop, entryp);
js_FillPropertyCache(cx, aobj, shape, 0, protoIndex, obj2, sprop, entryp);
}
JS_UNLOCK_OBJ(cx, obj2);
return JS_TRUE;