Bug 556830 part 2. Fill the propcache even if we start the lookup on a Call whose parent is the global the property is on. r=jorendorff
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4612,42 +4612,48 @@ js_FindIdentifierBase(JSContext *cx, JSO
JSObject *obj = scopeChain;
/*
* Loop over cacheable objects on the scope chain until we find a
* property. We also stop when we reach the global object skipping any
* farther checks or lookups. For details see the JSOP_BINDNAME case of
* js_Interpret.
+ *
+ * The test order here matters because js_IsCacheableNonGlobalScope
+ * must not be passed a global object (i.e. one with null parent).
*/
- for (int scopeIndex = 0; js_IsCacheableNonGlobalScope(obj); scopeIndex++) {
+ for (int scopeIndex = 0;
+ !obj->getParent() || js_IsCacheableNonGlobalScope(obj);
+ scopeIndex++) {
JSObject *pobj;
JSProperty *prop;
int protoIndex = js_LookupPropertyWithFlags(cx, obj, id,
cx->resolveFlags,
&pobj, &prop);
if (protoIndex < 0)
return NULL;
if (prop) {
JS_ASSERT(pobj->isNative());
- JS_ASSERT(pobj->getClass() == obj->getClass());
+ JS_ASSERT(!obj->getParent() ||
+ pobj->getClass() == obj->getClass());
#ifdef DEBUG
PropertyCacheEntry *entry =
#endif
JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, protoIndex, pobj,
(JSScopeProperty *) prop);
JS_ASSERT(entry);
JS_UNLOCK_OBJ(cx, pobj);
return obj;
}
- /* Call and other cacheable objects always have a parent. */
- obj = obj->getParent();
- if (!obj->getParent())
+ JSObject *parent = obj->getParent();
+ if (!parent)
return obj;
+ obj = parent;
}
/* Loop until we find a property or reach the global object. */
do {
JSObject *pobj;
JSProperty *prop;
if (!obj->lookupProperty(cx, id, &pobj, &prop))
return NULL;