Bug 1225396 part 2 - Fix ES6 iterator prototype chains. r=jorendorff
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 09 Dec 2015 22:54:44 -0500
changeset 310178 0eb91b63bf26dd32861376a017f77bad372854d3
parent 310177 a87be824cc8f8a0962e51908c3199330affd91cd
child 310179 de72e2291ae84ca9798ce7e27976f4b839780a9a
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1225396
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1225396 part 2 - Fix ES6 iterator prototype chains. r=jorendorff
js/public/Class.h
js/src/builtin/Array.js
js/src/builtin/MapObject.cpp
js/src/builtin/String.js
js/src/jit-test/tests/collections/iterator-1.js
js/src/jit-test/tests/collections/iterator-proto-1.js
js/src/jit-test/tests/collections/iterator-proto-surfaces.js
js/src/jit-test/tests/for-of/array-iterator-surfaces-2.js
js/src/jit-test/tests/for-of/string-iterator-surfaces.js
js/src/jsapi.cpp
js/src/jsiter.cpp
js/src/vm/GlobalObject.h
js/src/vm/SelfHosting.cpp
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -714,17 +714,17 @@ struct JSClass {
 // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
 // previously allowed, but is now an ES5 violation and thus unsupported.
 //
 // JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
 // the beginning of every global object's slots for use by the
 // application.
 #define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
 #define JSCLASS_GLOBAL_SLOT_COUNT                                             \
-    (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 35)
+    (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 36)
 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                                    \
     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
 #define JSCLASS_GLOBAL_FLAGS                                                  \
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
 
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -680,19 +680,16 @@ function CreateArrayIteratorAt(obj, kind
     UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_INDEX, n);
     UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_ITEM_KIND, kind);
     return iterator;
 }
 function CreateArrayIterator(obj, kind) {
     return CreateArrayIteratorAt(obj, kind, 0);
 }
 
-function ArrayIteratorIdentity() {
-    return this;
-}
 
 function ArrayIteratorNext() {
     if (!IsObject(this) || !IsArrayIterator(this)) {
         return callFunction(CallArrayIteratorMethodIfWrapped, this,
                             "ArrayIteratorNext");
     }
 
     var a = UnsafeGetObjectFromReservedSlot(this, ITERATOR_SLOT_TARGET);
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -113,17 +113,16 @@ const Class MapIteratorObject::class_ = 
     nullptr, /* setProperty */
     nullptr, /* enumerate */
     nullptr, /* resolve */
     nullptr, /* mayResolve */
     MapIteratorObject::finalize
 };
 
 const JSFunctionSpec MapIteratorObject::methods[] = {
-    JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0),
     JS_SELF_HOSTED_FN("next", "MapIteratorNext", 0, 0),
     JS_FS_END
 };
 
 static inline ValueMap::Range*
 MapIteratorObjectRange(NativeObject* obj)
 {
     MOZ_ASSERT(obj->is<MapIteratorObject>());
@@ -136,24 +135,22 @@ MapIteratorObject::kind() const
     int32_t i = getSlot(KindSlot).toInt32();
     MOZ_ASSERT(i == MapObject::Keys || i == MapObject::Values || i == MapObject::Entries);
     return MapObject::IteratorKind(i);
 }
 
 bool
 GlobalObject::initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
 {
-    Rooted<JSObject*> base(cx, GlobalObject::getOrCreateLegacyIteratorPrototype(cx, global));
+    Rooted<JSObject*> base(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
     if (!base)
         return false;
-    Rooted<MapIteratorObject*> proto(cx,
-        NewObjectWithGivenProto<MapIteratorObject>(cx, base));
+    RootedPlainObject proto(cx, NewObjectWithGivenProto<PlainObject>(cx, base));
     if (!proto)
         return false;
-    proto->setSlot(MapIteratorObject::RangeSlot, PrivateValue(nullptr));
     if (!JS_DefineFunctions(cx, proto, MapIteratorObject::methods))
         return false;
     global->setReservedSlot(MAP_ITERATOR_PROTO, ObjectValue(*proto));
     return true;
 }
 
 MapIteratorObject*
 MapIteratorObject::create(JSContext* cx, HandleObject mapobj, ValueMap* data,
@@ -839,17 +836,16 @@ const Class SetIteratorObject::class_ = 
     nullptr, /* setProperty */
     nullptr, /* enumerate */
     nullptr, /* resolve */
     nullptr, /* mayResolve */
     SetIteratorObject::finalize
 };
 
 const JSFunctionSpec SetIteratorObject::methods[] = {
-    JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0),
     JS_FN("next", next, 0, 0),
     JS_FS_END
 };
 
 inline ValueSet::Range*
 SetIteratorObject::range()
 {
     return static_cast<ValueSet::Range*>(getSlot(RangeSlot).toPrivate());
@@ -861,24 +857,22 @@ SetIteratorObject::kind() const
     int32_t i = getSlot(KindSlot).toInt32();
     MOZ_ASSERT(i == SetObject::Values || i == SetObject::Entries);
     return SetObject::IteratorKind(i);
 }
 
 bool
 GlobalObject::initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
 {
-    Rooted<JSObject*> base(cx, GlobalObject::getOrCreateLegacyIteratorPrototype(cx, global));
+    Rooted<JSObject*> base(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
     if (!base)
         return false;
-    Rooted<SetIteratorObject*> proto(cx,
-        NewObjectWithGivenProto<SetIteratorObject>(cx, base));
+    RootedPlainObject proto(cx, NewObjectWithGivenProto<PlainObject>(cx, base));
     if (!proto)
         return false;
-    proto->setSlot(SetIteratorObject::RangeSlot, PrivateValue(nullptr));
     if (!JS_DefineFunctions(cx, proto, SetIteratorObject::methods))
         return false;
     global->setReservedSlot(SET_ITERATOR_PROTO, ObjectValue(*proto));
     return true;
 }
 
 SetIteratorObject*
 SetIteratorObject::create(JSContext* cx, HandleObject setobj, ValueSet* data,
--- a/js/src/builtin/String.js
+++ b/js/src/builtin/String.js
@@ -194,20 +194,16 @@ function String_iterator() {
     RequireObjectCoercible(this);
     var S = ToString(this);
     var iterator = NewStringIterator();
     UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_TARGET, S);
     UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_INDEX, 0);
     return iterator;
 }
 
-function StringIteratorIdentity() {
-    return this;
-}
-
 function StringIteratorNext() {
     if (!IsObject(this) || !IsStringIterator(this)) {
         return callFunction(CallStringIteratorMethodIfWrapped, this,
                             "StringIteratorNext");
     }
 
     var S = UnsafeGetStringFromReservedSlot(this, ITERATOR_SLOT_TARGET);
     // We know that JSString::MAX_LENGTH <= INT32_MAX (and assert this in
--- a/js/src/jit-test/tests/collections/iterator-1.js
+++ b/js/src/jit-test/tests/collections/iterator-1.js
@@ -1,14 +1,14 @@
-// collection.iterator() returns an Iterator object.
+// collection.iterator() returns an iterator object.
 
 load(libdir + "iteration.js");
 
 function test(obj, name) {
     var iter = obj[Symbol.iterator]();
     assertEq(typeof iter, "object");
-    assertEq(iter instanceof Iterator, true);
+    assertEq(iter instanceof Iterator, false); // Not a legacy Iterator.
     assertEq(iter.toString(), "[object " + obj.constructor.name + " Iterator]");
 }
 
 test([]);
 test(new Map);
 test(new Set);
--- a/js/src/jit-test/tests/collections/iterator-proto-1.js
+++ b/js/src/jit-test/tests/collections/iterator-proto-1.js
@@ -1,15 +1,18 @@
 // All iterators of the same collection type share their immediate prototype.
-// Those prototype objects in turn inherit directly from Iterator.prototype.
+// Those prototype objects in turn inherit directly from %IteratorPrototype%.
 
 load(libdir + "iteration.js");
 
+// Get %IteratorPrototype%.
+var iterProto = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
+
 function test(obj0, obj1) {
     var iter0 = obj0[Symbol.iterator](), iter1 = obj1[Symbol.iterator]();
     var proto = Object.getPrototypeOf(iter0);
     assertEq(Object.getPrototypeOf(iter1), proto);
-    assertEq(Object.getPrototypeOf(proto), Iterator.prototype);
+    assertEq(Object.getPrototypeOf(proto), iterProto);
 }
 
 test([], [1]);
 test(new Map(), new Map([[1, 1]]));
 test(new Set(), new Set([1]));
--- a/js/src/jit-test/tests/collections/iterator-proto-surfaces.js
+++ b/js/src/jit-test/tests/collections/iterator-proto-surfaces.js
@@ -1,24 +1,43 @@
 // Iterator prototype surfaces.
 
 load(libdir + "asserts.js");
 load(libdir + "iteration.js");
 
+var iterProto = null;
+
 function test(constructor) {
-    var proto = Object.getPrototypeOf(new constructor()[Symbol.iterator]());
-    var names = Object.getOwnPropertyNames(proto);
+    var iter = new constructor()[Symbol.iterator]();
+    assertDeepEq(Reflect.ownKeys(iter), []);
+
+    // Iterator prototypes only have a .next property.
+    // At least until we support @@toStringTag.
+    var proto1 = Object.getPrototypeOf(iter);
+
+    var names = Reflect.ownKeys(proto1);
     names.sort();
-    assertDeepEq(names, ['next']);
-    assertEq(proto.hasOwnProperty(Symbol.iterator), true);
+    assertDeepEq(Reflect.ownKeys(proto1), ['next']);
 
-    var desc = Object.getOwnPropertyDescriptor(proto, 'next');
+    var desc = Object.getOwnPropertyDescriptor(proto1, 'next');
     assertEq(desc.configurable, true);
     assertEq(desc.enumerable, false);
     assertEq(desc.writable, true);
 
-    assertEq(proto[Symbol.iterator](), proto);
-    assertIteratorDone(proto, undefined);
+    // %IteratorPrototype%
+    var proto2 = Object.getPrototypeOf(proto1);
+    assertEq(Object.getPrototypeOf(proto2), Object.prototype);
+    assertEq(Object.prototype.toString.call(proto2), "[object Object]");
+
+    assertDeepEq(Reflect.ownKeys(proto2), [Symbol.iterator]);
+    assertEq(proto2[Symbol.iterator](), proto2);
+
+    // Check there's a single %IteratorPrototype% object.
+    if (iterProto === null)
+	iterProto = proto2;
+    else
+	assertEq(iterProto, proto2);
 }
 
-//test(Array);
+test(Array);
+test(String);
 test(Map);
 test(Set);
--- a/js/src/jit-test/tests/for-of/array-iterator-surfaces-2.js
+++ b/js/src/jit-test/tests/for-of/array-iterator-surfaces-2.js
@@ -1,18 +1,18 @@
 // Superficial tests for iterators created by Array.prototype.iterator
 
 load(libdir + "iteration.js");
 
 var proto = Object.getPrototypeOf([][Symbol.iterator]());
-assertEq(Object.getPrototypeOf(proto), Iterator.prototype);
+var iterProto = Object.getPrototypeOf(proto);
 proto = Object.getPrototypeOf([].keys());
-assertEq(Object.getPrototypeOf(proto), Iterator.prototype);
+assertEq(Object.getPrototypeOf(proto), iterProto);
 proto = Object.getPrototypeOf([].entries());
-assertEq(Object.getPrototypeOf(proto), Iterator.prototype);
+assertEq(Object.getPrototypeOf(proto), iterProto);
 
 function check(it) {
     assertEq(typeof it, 'object');
     assertEq(Object.getPrototypeOf(it), proto);
     assertEq(Object.getOwnPropertyNames(it).length, 0);
     assertEq(it[Symbol.iterator](), it);
 
     // for-in enumerates the iterator's properties.
--- a/js/src/jit-test/tests/for-of/string-iterator-surfaces.js
+++ b/js/src/jit-test/tests/for-of/string-iterator-surfaces.js
@@ -48,25 +48,23 @@ function assertBuiltinFunction(o, name, 
 
 // String.prototype[@@iterator] is a built-in function
 assertBuiltinFunction(String.prototype, Symbol.iterator, 0);
 
 // Test StringIterator.prototype surface
 var iter = ""[Symbol.iterator]();
 var iterProto = Object.getPrototypeOf(iter);
 
-// StringIterator.prototype inherits from Object.prototype
-assertEq(Object.getPrototypeOf(iterProto), Object.prototype);
+// StringIterator.prototype inherits from %IteratorPrototype%. Check it's the
+// same object as %ArrayIteratorPrototype%'s proto.
+assertEq(Object.getPrototypeOf(iterProto),
+         Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
 
 // Own properties for StringIterator.prototype: "next"
 arraysEqual(Object.getOwnPropertyNames(iterProto).sort(), ["next"]);
-assertEq(iterProto.hasOwnProperty(Symbol.iterator), true);
-
-// StringIterator.prototype[@@iterator] is a built-in function
-assertBuiltinFunction(iterProto, Symbol.iterator, 0);
 
 // StringIterator.prototype.next is a built-in function
 assertBuiltinFunction(iterProto, "next", 0);
 
 // StringIterator.prototype[@@iterator] is generic and returns |this|
 for (var v of [void 0, null, true, false, "", 0, 1, {}, [], iter, iterProto]) {
     assertEq(iterProto[Symbol.iterator].call(v), v);
 }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1220,17 +1220,17 @@ JS_GetErrorPrototype(JSContext* cx)
     return GlobalObject::getOrCreateCustomErrorPrototype(cx, global, JSEXN_ERR);
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_GetIteratorPrototype(JSContext* cx)
 {
     CHECK_REQUEST(cx);
     Rooted<GlobalObject*> global(cx, cx->global());
-    return GlobalObject::getOrCreateLegacyIteratorPrototype(cx, global);
+    return GlobalObject::getOrCreateIteratorPrototype(cx, global);
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_GetGlobalForObject(JSContext* cx, JSObject* obj)
 {
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, obj);
     return &obj->global();
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1104,17 +1104,16 @@ enum {
 };
 
 const Class ArrayIteratorObject::class_ = {
     "Array Iterator",
     JSCLASS_HAS_RESERVED_SLOTS(ArrayIteratorSlotCount)
 };
 
 static const JSFunctionSpec array_iterator_methods[] = {
-    JS_SELF_HOSTED_SYM_FN(iterator, "ArrayIteratorIdentity", 0, 0),
     JS_SELF_HOSTED_FN("next", "ArrayIteratorNext", 0, 0),
     JS_FS_END
 };
 
 static const Class StringIteratorPrototypeClass = {
     "String Iterator",
     0
 };
@@ -1126,17 +1125,16 @@ enum {
 };
 
 const Class StringIteratorObject::class_ = {
     "String Iterator",
     JSCLASS_HAS_RESERVED_SLOTS(StringIteratorSlotCount)
 };
 
 static const JSFunctionSpec string_iterator_methods[] = {
-    JS_SELF_HOSTED_SYM_FN(iterator, "StringIteratorIdentity", 0, 0),
     JS_SELF_HOSTED_FN("next", "StringIteratorNext", 0, 0),
     JS_FS_END
 };
 
 enum {
     ListIteratorSlotIteratedObject,
     ListIteratorSlotNextIndex,
     ListIteratorSlotNextMethod,
@@ -1457,23 +1455,42 @@ const Class StopIterationObject::class_ 
     nullptr, /* enumerate */
     nullptr, /* resolve */
     nullptr, /* mayResolve */
     nullptr, /* finalize */
     nullptr, /* call */
     stopiter_hasInstance
 };
 
+static const JSFunctionSpec iterator_proto_methods[] = {
+    JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0),
+    JS_FS_END
+};
+
+/* static */ bool
+GlobalObject::initIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
+{
+    if (global->getReservedSlot(ITERATOR_PROTO).isObject())
+        return true;
+
+    RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
+    if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, iterator_proto_methods))
+        return false;
+
+    global->setReservedSlot(ITERATOR_PROTO, ObjectValue(*proto));
+    return true;
+}
+
 /* static */ bool
 GlobalObject::initArrayIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
 {
     if (global->getReservedSlot(ARRAY_ITERATOR_PROTO).isObject())
         return true;
 
-    RootedObject iteratorProto(cx, GlobalObject::getOrCreateLegacyIteratorPrototype(cx, global));
+    RootedObject iteratorProto(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
     if (!iteratorProto)
         return false;
 
     const Class* cls = &ArrayIteratorPrototypeClass;
     RootedObject proto(cx, global->createBlankPrototypeInheriting(cx, cls, iteratorProto));
     if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, array_iterator_methods))
         return false;
 
@@ -1482,18 +1499,22 @@ GlobalObject::initArrayIteratorProto(JSC
 }
 
 /* static */ bool
 GlobalObject::initStringIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
 {
     if (global->getReservedSlot(STRING_ITERATOR_PROTO).isObject())
         return true;
 
+    RootedObject iteratorProto(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
+    if (!iteratorProto)
+        return false;
+
     const Class* cls = &StringIteratorPrototypeClass;
-    RootedObject proto(cx, global->createBlankPrototype(cx, cls));
+    RootedObject proto(cx, global->createBlankPrototypeInheriting(cx, cls, iteratorProto));
     if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, string_iterator_methods))
         return false;
 
     global->setReservedSlot(STRING_ITERATOR_PROTO, ObjectValue(*proto));
     return true;
 }
 
 JSObject*
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -91,16 +91,17 @@ class GlobalObject : public NativeObject
         FROM_BUFFER_UINT32,
         FROM_BUFFER_INT32,
         FROM_BUFFER_FLOAT32,
         FROM_BUFFER_FLOAT64,
         FROM_BUFFER_UINT8CLAMPED,
 
         /* One-off properties stored after slots for built-ins. */
         LEXICAL_SCOPE,
+        ITERATOR_PROTO,
         ARRAY_ITERATOR_PROTO,
         STRING_ITERATOR_PROTO,
         LEGACY_GENERATOR_OBJECT_PROTO,
         STAR_GENERATOR_OBJECT_PROTO,
         STAR_GENERATOR_FUNCTION_PROTO,
         STAR_GENERATOR_FUNCTION,
         MAP_ITERATOR_PROTO,
         SET_ITERATOR_PROTO,
@@ -504,23 +505,19 @@ class GlobalObject : public NativeObject
             return &v.toObject();
         RootedGlobalObject self(cx, this);
         if (!init(cx, self))
             return nullptr;
         return &self->getSlot(slot).toObject();
     }
 
   public:
-    static NativeObject* getOrCreateLegacyIteratorPrototype(JSContext* cx,
-                                                            Handle<GlobalObject*> global)
+    static NativeObject* getOrCreateIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global)
     {
-        if (!ensureConstructor(cx, global, JSProto_Iterator))
-            return nullptr;
-        size_t slot = APPLICATION_SLOTS + JSProto_LIMIT + JSProto_Iterator;
-        return &global->getSlot(slot).toObject().as<NativeObject>();
+        return MaybeNativeObject(global->getOrCreateObject(cx, ITERATOR_PROTO, initIteratorProto));
     }
 
     static NativeObject* getOrCreateArrayIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global)
     {
         return MaybeNativeObject(global->getOrCreateObject(cx, ARRAY_ITERATOR_PROTO, initArrayIteratorProto));
     }
 
     static NativeObject* getOrCreateStringIteratorPrototype(JSContext* cx,
@@ -673,16 +670,17 @@ class GlobalObject : public NativeObject
 
     static bool getOrCreateEval(JSContext* cx, Handle<GlobalObject*> global,
                                 MutableHandleObject eval);
 
     // Infallibly test whether the given value is the eval function for this global.
     bool valueIsEval(Value val);
 
     // Implemented in jsiter.cpp.
+    static bool initIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
     static bool initArrayIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
     static bool initStringIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
 
     // Implemented in vm/GeneratorObject.cpp.
     static bool initLegacyGeneratorProto(JSContext* cx, Handle<GlobalObject*> global);
     static bool initStarGenerators(JSContext* cx, Handle<GlobalObject*> global);
 
     // Implemented in builtin/MapObject.cpp.
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -443,17 +443,17 @@ intrinsic_IsPackedArray(JSContext* cx, u
 }
 
 static bool
 intrinsic_GetIteratorPrototype(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 0);
 
-    JSObject* obj = GlobalObject::getOrCreateLegacyIteratorPrototype(cx, cx->global());
+    JSObject* obj = GlobalObject::getOrCreateIteratorPrototype(cx, cx->global());
     if (!obj)
         return false;
 
     args.rval().setObject(*obj);
     return true;
 }
 
 static bool
@@ -508,17 +508,17 @@ intrinsic_NewStringIterator(JSContext* c
 }
 
 static bool
 intrinsic_NewListIterator(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 0);
 
-    RootedObject proto(cx, GlobalObject::getOrCreateLegacyIteratorPrototype(cx, cx->global()));
+    RootedObject proto(cx, GlobalObject::getOrCreateIteratorPrototype(cx, cx->global()));
     if (!proto)
         return false;
 
     RootedObject iterator(cx);
     iterator = NewObjectWithGivenProto(cx, &ListIteratorObject::class_, proto);
     if (!iterator)
         return false;