diff --git a/js/src/jit-test/tests/basic/cross-global-for-in.js b/js/src/jit-test/tests/basic/cross-global-for-in.js new file mode 100644 index 000000000000..3fd772052557 --- /dev/null +++ b/js/src/jit-test/tests/basic/cross-global-for-in.js @@ -0,0 +1,11 @@ +var global = newGlobal(); + +var arrayIter = (new global.Array())[global.Symbol.iterator](); +var ArrayIteratorPrototype = Object.getPrototypeOf(arrayIter); +var arrayIterProtoBase = Object.getPrototypeOf(ArrayIteratorPrototype); +var IteratorPrototype = arrayIterProtoBase; +delete IteratorPrototype.next; + +var obj = global.eval('({a: 1})') +for (var x in obj) {} +assertEq(x, "a"); diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 643007b40c00..b9e833762c62 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -477,6 +477,8 @@ Compare(T* a, T* b, size_t c) return true; } +static bool iterator_next(JSContext* cx, unsigned argc, Value* vp); + static inline PropertyIteratorObject* NewPropertyIteratorObject(JSContext* cx, unsigned flags) { @@ -500,13 +502,35 @@ NewPropertyIteratorObject(JSContext* cx, unsigned flags) GetInitialHeap(GenericObject, clasp), shape, group); if (!obj) return nullptr; + PropertyIteratorObject* res = &obj->as(); MOZ_ASSERT(res->numFixedSlots() == JSObject::ITER_CLASS_NFIXED_SLOTS); return res; } - return NewBuiltinClassInstance(cx); + Rooted res(cx, NewBuiltinClassInstance(cx)); + if (!res) + return nullptr; + + if (flags == 0) { + // Redefine next as an own property. This ensure that deleting the + // next method on the prototype doesn't break cross-global for .. in. + // We don't have to do this for JSITER_ENUMERATE because that object always + // takes an optimized path. + RootedFunction next(cx, NewFunctionWithProto(cx, NullPtr(), iterator_next, 0, + JSFunction::NATIVE_FUN, NullPtr(), + HandlePropertyName(cx->names().next), + NullPtr())); + if (!next) + return nullptr; + + RootedValue value(cx, ObjectValue(*next)); + if (!DefineProperty(cx, res, cx->names().next, value)) + return nullptr; + } + + return res; } NativeIterator*