diff --git a/mozilla/js/src/jsinterp.c b/mozilla/js/src/jsinterp.c index f8f9120c4bd..02e6c8ebef3 100644 --- a/mozilla/js/src/jsinterp.c +++ b/mozilla/js/src/jsinterp.c @@ -2679,6 +2679,8 @@ interrupt: (iterobj == obj) ? NULL : &fid, &rval); if (!ok) { + uintN protoFlags; + /* Nothing more to iterate in obj, or some other exception? */ if (!cx->throwing || !VALUE_IS_STOP_ITERATION(cx, cx->exception)) { @@ -2705,14 +2707,23 @@ interrupt: goto end_forinloop; } + /* + * Clear JSITER_FOREACH now that we are up the prototype chain + * from the original object. We can't expect to get the same + * value from a prototype as we would if we started the get at + * the original object, so we must do our own getting, further + * below when testing 'if (flags & JSITER_FOREACH)'. + */ + protoFlags = flags & ~JSITER_FOREACH; + if (flags & JSITER_COMPAT) { - ok = js_NewNativeIterator(cx, obj, flags, vp); + ok = js_NewNativeIterator(cx, obj, protoFlags, vp); if (!ok) goto out; iterobj = JSVAL_TO_OBJECT(*vp); } else { iterobj = js_ValueToIterator(cx, OBJECT_TO_JSVAL(obj), - flags); + protoFlags); if (!iterobj) { JS_ASSERT(!ok); goto out; @@ -2770,6 +2781,18 @@ interrupt: if (flags & JSITER_FOREACH) { /* Clear the local foreach flag set by our prefix bytecode. */ flags = 0; + + /* + * If enumerating up the prototype chain, we suppressed the + * JSITER_FOREACH flag when we created the iterator, because + * the iterator can't get the value for fid without starting + * from origobj. So we must OBJ_GET_PROPERTY here. + */ + if (origobj != obj) { + ok = OBJ_GET_PROPERTY(cx, origobj, fid, &rval); + if (!ok) + goto out; + } } else if (iterobj == obj) { /* Iterators return arbitrary values, not string ids. */ JS_ASSERT(fid == JSVAL_NULL);