Bug 1413867 - Remove StopIteration object. r=evilpie
authorJan de Mooij <jdemooij@mozilla.com>
Sun, 05 Nov 2017 19:01:04 +0100
changeset 443500 73a48b92351a1c615108c36324c4900cb8ad41a6
parent 443499 c73851d5851b51f8d3cb262242e363a0962ba892
child 443512 179dae92e4d794e7f45ad080ff01908c80691f31
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersevilpie
bugs1413867
milestone58.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 1413867 - Remove StopIteration object. r=evilpie
dom/tests/mochitest/general/test_interfaces.js
dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
dom/workers/test/test_worker_interfaces.js
js/ipc/JavaScriptTypes.ipdlh
js/ipc/WrapperAnswer.cpp
js/ipc/WrapperOwner.cpp
js/src/jit-test/tests/basic/bug547911-1.js
js/src/jit-test/tests/basic/bug547911-2.js
js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js
js/src/jit-test/tests/collections/Map-forEach.js
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscompartment.cpp
js/src/jsiter.cpp
js/src/jsiter.h
js/src/jsprototypes.h
js/src/vm/GlobalObject.cpp
js/src/vm/StopIterationObject.h
toolkit/components/promiseworker/PromiseWorker.jsm
toolkit/components/promiseworker/worker/PromiseWorker.js
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -58,17 +58,16 @@ var ecmaGlobals =
     "RangeError",
     {name: "ReadableStream", disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
     "ReferenceError",
     "Reflect",
     "RegExp",
     "Set",
     "SharedArrayBuffer",
     {name: "SIMD", nightly: true},
-    "StopIteration",
     "String",
     "Symbol",
     "SyntaxError",
     {name: "TypedObject", nightly: true},
     "TypeError",
     "Uint16Array",
     "Uint32Array",
     "Uint8Array",
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
+++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
@@ -53,17 +53,16 @@ var ecmaGlobals =
     "RangeError",
     {name: "ReadableStream", optional: true},
     "ReferenceError",
     "Reflect",
     "RegExp",
     "Set",
     "SharedArrayBuffer",
     {name: "SIMD", nightly: true},
-    "StopIteration",
     "String",
     "Symbol",
     "SyntaxError",
     {name: "TypedObject", nightly: true},
     "TypeError",
     "Uint16Array",
     "Uint32Array",
     "Uint8Array",
--- a/dom/workers/test/test_worker_interfaces.js
+++ b/dom/workers/test/test_worker_interfaces.js
@@ -53,17 +53,16 @@ var ecmaGlobals =
     "RangeError",
     {name: "ReadableStream", optional: true},
     "ReferenceError",
     "Reflect",
     "RegExp",
     "Set",
     "SharedArrayBuffer",
     {name: "SIMD", nightly: true},
-    "StopIteration",
     "String",
     "Symbol",
     "SyntaxError",
     {name: "TypedObject", nightly: true},
     "TypeError",
     "Uint16Array",
     "Uint32Array",
     "Uint8Array",
--- a/js/ipc/JavaScriptTypes.ipdlh
+++ b/js/ipc/JavaScriptTypes.ipdlh
@@ -90,20 +90,16 @@ union JSIDVariant
     nsString;
     int32_t;
 };
 
 struct ReturnSuccess
 {
 };
 
-struct ReturnStopIteration
-{
-};
-
 struct ReturnDeadCPOW
 {
 };
 
 struct ReturnException
 {
     JSVariant exn;
 };
@@ -111,17 +107,16 @@ struct ReturnException
 struct ReturnObjectOpResult
 {
     uint32_t code;
 };
 
 union ReturnStatus
 {
     ReturnSuccess;
-    ReturnStopIteration;
     ReturnDeadCPOW;
     ReturnException;
     ReturnObjectOpResult;
 };
 
 union JSParam
 {
     void_t;     /* value is strictly an xpc out param */
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -57,21 +57,16 @@ WrapperAnswer::fail(AutoJSAPI& jsapi, Re
     JSContext* cx = jsapi.cx();
     RootedValue exn(cx);
     if (!jsapi.HasException())
         return true;
 
     if (!jsapi.StealException(&exn))
         return true;
 
-    if (JS_IsStopIteration(exn)) {
-        *rs = ReturnStatus(ReturnStopIteration());
-        return true;
-    }
-
     // If this fails, we still don't want to exit. Just return an invalid
     // exception.
     (void) toVariant(cx, exn, &rs->get_ReturnException().exn());
     return true;
 }
 
 bool
 WrapperAnswer::ok(ReturnStatus* rs)
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -1071,19 +1071,16 @@ WrapperOwner::ipcfail(JSContext* cx)
 }
 
 bool
 WrapperOwner::ok(JSContext* cx, const ReturnStatus& status)
 {
     if (status.type() == ReturnStatus::TReturnSuccess)
         return true;
 
-    if (status.type() == ReturnStatus::TReturnStopIteration)
-        return JS_ThrowStopIteration(cx);
-
     if (status.type() == ReturnStatus::TReturnDeadCPOW) {
         JS_ReportErrorASCII(cx, "operation not possible on dead CPOW");
         return false;
     }
 
     RootedValue exn(cx);
     if (!fromVariant(cx, status.get_ReturnException().exn(), &exn))
         return false;
--- a/js/src/jit-test/tests/basic/bug547911-1.js
+++ b/js/src/jit-test/tests/basic/bug547911-1.js
@@ -1,9 +1,9 @@
 // |jit-test| need-for-each
 
 a = b = c = d = 0;
-this.__defineGetter__("e", function () { throw StopIteration; })
+this.__defineGetter__("e", function () { throw Math; })
 try {
     for each(f in this) {}
 } catch (exc) {
-    assertEq(exc, StopIteration);
+    assertEq(exc, Math);
 }
--- a/js/src/jit-test/tests/basic/bug547911-2.js
+++ b/js/src/jit-test/tests/basic/bug547911-2.js
@@ -1,9 +1,9 @@
 // |jit-test| need-for-each
 
-var obj = {a: 0, b: 0, c: 0, d: 0, get e() { throw StopIteration; }};
+var obj = {a: 0, b: 0, c: 0, d: 0, get e() { throw Math; }};
 try {
     for each (x in obj) {}
     FAIL;
 } catch (exc) {
-    assertEq(exc, StopIteration);
+    assertEq(exc, Math);
 }
--- a/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js
+++ b/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js
@@ -1,9 +1,9 @@
-var arr = [StopIteration, StopIteration, StopIteration, StopIteration, {}];
+var arr = [Math, Math, Math, Math, {}];
 var obj = {};
 var x;
 var result = 'no error';
 try {
     for (var i = 0; i < arr.length; i++)
         x = (obj instanceof arr[i]);  // last iteration throws, triggering deep bail
 } catch (exc) {
     result = exc.constructor.name;
--- a/js/src/jit-test/tests/collections/Map-forEach.js
+++ b/js/src/jit-test/tests/collections/Map-forEach.js
@@ -44,16 +44,15 @@ assertThrowsInstanceOf(function() {
     Map.prototype.forEach.call(s, callback);
 }, TypeError, "Map.prototype.forEach should raise TypeError if not used on a Map");
 
 var fn = 2;
 assertThrowsInstanceOf(function() {
     initialMap.forEach(fn);
 }, TypeError, "Map.prototype.forEach should raise TypeError if callback is not a function");
 
-// testing that Map#forEach uses internal next() function and does not stop when
-// StopIteration exception is thrown
+// testing that Map#forEach uses internal next() function.
 
 var m = new Map([["one", 1]]);
 Object.getPrototypeOf(m[Symbol.iterator]()).next = function () { throw "FAIL"; };
-assertThrowsInstanceOf(function () {
-  m.forEach(function () { throw StopIteration; });
-}, StopIteration, "Map.prototype.forEach should use intrinsic next method.");
+assertThrowsValue(function () {
+  m.forEach(function () { throw Math; });
+}, Math, "Map.prototype.forEach should use intrinsic next method.");
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -77,17 +77,16 @@
 #include "vm/ErrorObject.h"
 #include "vm/HelperThreads.h"
 #include "vm/Interpreter.h"
 #include "vm/RegExpStatics.h"
 #include "vm/Runtime.h"
 #include "vm/SavedStacks.h"
 #include "vm/SelfHosting.h"
 #include "vm/Shape.h"
-#include "vm/StopIterationObject.h"
 #include "vm/String.h"
 #include "vm/StringBuffer.h"
 #include "vm/Symbol.h"
 #include "vm/WrapperObject.h"
 #include "vm/Xdr.h"
 #include "wasm/AsmJS.h"
 #include "wasm/WasmModule.h"
 
@@ -7117,29 +7116,16 @@ JSErrorNotes::begin()
 }
 
 JS_PUBLIC_API(JSErrorNotes::iterator)
 JSErrorNotes::end()
 {
     return iterator(notes_.end());
 }
 
-JS_PUBLIC_API(bool)
-JS_ThrowStopIteration(JSContext* cx)
-{
-    AssertHeapIsIdle();
-    return ThrowStopIteration(cx);
-}
-
-JS_PUBLIC_API(bool)
-JS_IsStopIteration(const Value& v)
-{
-    return v.isObject() && v.toObject().is<StopIterationObject>();
-}
-
 extern MOZ_NEVER_INLINE JS_PUBLIC_API(void)
 JS_AbortIfWrongThread(JSContext* cx)
 {
     if (!CurrentThreadCanAccessRuntime(cx->runtime()))
         MOZ_CRASH();
     if (TlsContext.get() != cx)
         MOZ_CRASH();
 }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -6195,25 +6195,16 @@ JS_ErrorFromException(JSContext* cx, JS:
  * cross-compartment wrapper for one), return the stack for that exception, if
  * any.  Will return null if the given object is not an exception object
  * (including if it's null or a security wrapper that can't be unwrapped) or if
  * the exception has no stack.
  */
 extern JS_PUBLIC_API(JSObject*)
 ExceptionStackOrNull(JS::HandleObject obj);
 
-/*
- * Throws a StopIteration exception on cx.
- */
-extern JS_PUBLIC_API(bool)
-JS_ThrowStopIteration(JSContext* cx);
-
-extern JS_PUBLIC_API(bool)
-JS_IsStopIteration(const JS::Value& v);
-
 /**
  * A JS context always has an "owner thread". The owner thread is set when the
  * context is created (to the current thread) and practically all entry points
  * into the JS engine check that a context (or anything contained in the
  * context: runtime, compartment, object, etc) is only touched by its owner
  * thread. Embeddings may check this invariant outside the JS engine by calling
  * JS_AbortIfWrongThread (which will abort if not on the owner thread, even for
  * non-debug builds).
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -19,17 +19,16 @@
 #include "gc/Policy.h"
 #include "jit/JitCompartment.h"
 #include "jit/JitOptions.h"
 #include "js/Date.h"
 #include "js/Proxy.h"
 #include "js/RootingAPI.h"
 #include "proxy/DeadObjectProxy.h"
 #include "vm/Debugger.h"
-#include "vm/StopIterationObject.h"
 #include "vm/WrapperObject.h"
 
 #include "jsatominlines.h"
 #include "jsfuninlines.h"
 #include "jsgcinlines.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
@@ -390,27 +389,16 @@ JSCompartment::getNonWrapperObjectForCur
     // particular wrapper.
     RootedObject objectPassedToWrap(cx, obj);
     obj.set(UncheckedUnwrap(obj, /* stopAtWindowProxy = */ true));
     if (obj->compartment() == this) {
         MOZ_ASSERT(!IsWindow(obj));
         return true;
     }
 
-    // Translate StopIteration singleton.
-    if (obj->is<StopIterationObject>()) {
-        // StopIteration isn't a constructor, but it's stored in GlobalObject
-        // as one, out of laziness. Hence the GetBuiltinConstructor call here.
-        RootedObject stopIteration(cx);
-        if (!GetBuiltinConstructor(cx, JSProto_StopIteration, &stopIteration))
-            return false;
-        obj.set(stopIteration);
-        return true;
-    }
-
     // Invoke the prewrap callback. The prewrap callback is responsible for
     // doing similar reification as above, but can account for any additional
     // embedder requirements.
     //
     // We're a bit worried about infinite recursion here, so we do a check -
     // see bug 809295.
     auto preWrap = cx->runtime()->wrapObjectCallbacks->preWrap;
     if (!CheckSystemRecursionLimit(cx))
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -26,17 +26,16 @@
 
 #include "ds/Sort.h"
 #include "gc/Marking.h"
 #include "js/Proxy.h"
 #include "vm/GeneratorObject.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/Shape.h"
-#include "vm/StopIterationObject.h"
 #include "vm/TypedArrayObject.h"
 
 #include "jsscriptinlines.h"
 
 #include "vm/NativeObject-inl.h"
 #include "vm/ReceiverGuard-inl.h"
 #include "vm/Stack-inl.h"
 #include "vm/String-inl.h"
@@ -532,18 +531,16 @@ Snapshot(JSContext* cx, HandleObject pob
 JS_FRIEND_API(bool)
 js::GetPropertyKeys(JSContext* cx, HandleObject obj, unsigned flags, AutoIdVector* props)
 {
     return Snapshot(cx, obj,
                     flags & (JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS | JSITER_SYMBOLSONLY),
                     props);
 }
 
-static bool property_iterator_next(JSContext* cx, unsigned argc, Value* vp);
-
 static inline PropertyIteratorObject*
 NewPropertyIteratorObject(JSContext* cx, unsigned flags)
 {
     if (flags & JSITER_ENUMERATE) {
         RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &PropertyIteratorObject::class_,
                                                                  TaggedProto(nullptr)));
         if (!group)
             return nullptr;
@@ -564,36 +561,17 @@ NewPropertyIteratorObject(JSContext* cx,
         // CodeGenerator::visitIteratorStartO assumes the iterator object is not
         // inside the nursery when deciding whether a barrier is necessary.
         MOZ_ASSERT(!js::gc::IsInsideNursery(res));
 
         MOZ_ASSERT(res->numFixedSlots() == JSObject::ITER_CLASS_NFIXED_SLOTS);
         return res;
     }
 
-    Rooted<PropertyIteratorObject*> res(cx, NewBuiltinClassInstance<PropertyIteratorObject>(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, NewNativeFunction(cx, property_iterator_next, 0,
-                                                  HandlePropertyName(cx->names().next)));
-        if (!next)
-            return nullptr;
-
-        RootedValue value(cx, ObjectValue(*next));
-        if (!DefineDataProperty(cx, res, cx->names().next, value))
-            return nullptr;
-    }
-
-    return res;
+    return NewBuiltinClassInstance<PropertyIteratorObject>(cx);
 }
 
 NativeIterator*
 NativeIterator::allocateIterator(JSContext* cx, uint32_t numGuards, uint32_t plength)
 {
     JS_STATIC_ASSERT(sizeof(ReceiverGuard) == 2 * sizeof(void*));
 
     size_t extraLength = plength + numGuards * 2;
@@ -1050,38 +1028,23 @@ JSCompartment::getOrCreateIterResultTemp
     MOZ_ASSERT(shape->slot() == JSCompartment::IterResultObjectDoneSlot &&
                shape->propidRef() == NameToId(cx->names().done));
 
     iterResultTemplate_.set(templateObject);
 
     return iterResultTemplate_;
 }
 
-bool
-js::ThrowStopIteration(JSContext* cx)
-{
-    MOZ_ASSERT(!JS_IsExceptionPending(cx));
-
-    // StopIteration isn't a constructor, but it's stored in GlobalObject
-    // as one, out of laziness. Hence the GetBuiltinConstructor call here.
-    RootedObject ctor(cx);
-    if (GetBuiltinConstructor(cx, JSProto_StopIteration, &ctor))
-        cx->setPendingException(ObjectValue(*ctor));
-    return false;
-}
-
 /*** Iterator objects ****************************************************************************/
 
 MOZ_ALWAYS_INLINE bool
-NativeIteratorNext(JSContext* cx, NativeIterator* ni, MutableHandleValue rval, bool* done)
+NativeIteratorNext(JSContext* cx, NativeIterator* ni, MutableHandleValue rval)
 {
-    *done = false;
-
     if (ni->props_cursor >= ni->props_end) {
-        *done = true;
+        rval.setMagic(JS_NO_ITER_VALUE);
         return true;
     }
 
     if (MOZ_LIKELY(ni->isKeyIter())) {
         rval.setString(*ni->current());
         ni->incCursor();
         return true;
     }
@@ -1100,46 +1063,16 @@ NativeIteratorNext(JSContext* cx, Native
 }
 
 bool
 js::IsPropertyIterator(HandleValue v)
 {
     return v.isObject() && v.toObject().is<PropertyIteratorObject>();
 }
 
-MOZ_ALWAYS_INLINE bool
-property_iterator_next_impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(IsPropertyIterator(args.thisv()));
-
-    RootedObject thisObj(cx, &args.thisv().toObject());
-
-    NativeIterator* ni = thisObj.as<PropertyIteratorObject>()->getNativeIterator();
-    RootedValue value(cx);
-    bool done;
-    if (!NativeIteratorNext(cx, ni, &value, &done))
-         return false;
-
-    // Use old iterator protocol for compatibility reasons.
-    if (done) {
-        ThrowStopIteration(cx);
-        return false;
-    }
-
-    args.rval().set(value);
-    return true;
-}
-
-static bool
-property_iterator_next(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<IsPropertyIterator, property_iterator_next_impl>(cx, args);
-}
-
 size_t
 PropertyIteratorObject::sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf) const
 {
     return mallocSizeOf(getPrivate());
 }
 
 void
 PropertyIteratorObject::trace(JSTracer* trc, JSObject* obj)
@@ -1484,82 +1417,42 @@ js::SuppressDeletedElement(JSContext* cx
         return false;
     return SuppressDeletedPropertyHelper(cx, obj, SingleStringPredicate(str));
 }
 
 bool
 js::IteratorMore(JSContext* cx, HandleObject iterobj, MutableHandleValue rval)
 {
     // Fast path for native iterators.
-    if (iterobj->is<PropertyIteratorObject>()) {
+    if (MOZ_LIKELY(iterobj->is<PropertyIteratorObject>())) {
         NativeIterator* ni = iterobj->as<PropertyIteratorObject>().getNativeIterator();
-        bool done;
-        if (!NativeIteratorNext(cx, ni, rval, &done))
-            return false;
-
-        if (done)
-            rval.setMagic(JS_NO_ITER_VALUE);
-        return true;
+        return NativeIteratorNext(cx, ni, rval);
     }
 
-    // We're reentering below and can call anything.
-    if (!CheckRecursionLimit(cx))
+    if (JS_IsDeadWrapper(iterobj)) {
+        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
         return false;
+    }
 
-    // Call the iterator object's .next method.
-    if (!GetProperty(cx, iterobj, iterobj, cx->names().next, rval))
+    MOZ_ASSERT(IsWrapper(iterobj));
+
+    RootedObject obj(cx, CheckedUnwrap(iterobj));
+    if (!obj)
         return false;
 
-    // Call the .next method.  Fall through to the error-handling cases in the
-    // unlikely event that either one of the fallible operations performed
-    // during the call process fails.
-    FixedInvokeArgs<0> args(cx);
-    RootedValue iterval(cx, ObjectValue(*iterobj));
-    if (!js::Call(cx, rval, iterval, args, rval)) {
-        // Check for StopIteration.
-        if (!cx->isExceptionPending())
+    MOZ_RELEASE_ASSERT(obj->is<PropertyIteratorObject>());
+    {
+        AutoCompartment ac(cx, obj);
+        NativeIterator* ni = obj->as<PropertyIteratorObject>().getNativeIterator();
+        if (!NativeIteratorNext(cx, ni, rval))
             return false;
-        RootedValue exception(cx);
-        if (!cx->getPendingException(&exception))
-            return false;
-        if (!JS_IsStopIteration(exception))
-            return false;
-
-        cx->clearPendingException();
-        rval.setMagic(JS_NO_ITER_VALUE);
     }
-
-    return true;
+    return cx->compartment()->wrap(cx, rval);
 }
 
-static bool
-stopiter_hasInstance(JSContext* cx, HandleObject obj, MutableHandleValue v, bool* bp)
-{
-    *bp = JS_IsStopIteration(v);
-    return true;
-}
-
-static const ClassOps StopIterationObjectClassOps = {
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* enumerate */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* mayResolve */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    stopiter_hasInstance
-};
-
-const Class StopIterationObject::class_ = {
-    "StopIteration",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration),
-    &StopIterationObjectClassOps
-};
-
 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)
 {
@@ -1616,28 +1509,8 @@ GlobalObject::initStringIteratorProto(JS
         !DefineToStringTag(cx, proto, cx->names().StringIterator))
     {
         return false;
     }
 
     global->setReservedSlot(STRING_ITERATOR_PROTO, ObjectValue(*proto));
     return true;
 }
-
-JSObject*
-js::InitStopIterationClass(JSContext* cx, HandleObject obj)
-{
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-    if (!global->getPrototype(JSProto_StopIteration).isObject()) {
-        RootedObject proto(cx, GlobalObject::createBlankPrototype(cx, global,
-                                                                  &StopIterationObject::class_));
-        if (!proto || !FreezeObject(cx, proto))
-            return nullptr;
-
-        // This should use a non-JSProtoKey'd slot, but this is easier for now.
-        if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_StopIteration, proto, proto))
-            return nullptr;
-
-        global->setConstructor(JSProto_StopIteration, ObjectValue(*proto));
-    }
-
-    return &global->getPrototype(JSProto_StopIteration).toObject();
-}
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -199,29 +199,23 @@ SuppressDeletedElement(JSContext* cx, Ha
 
 /*
  * IteratorMore() returns the next iteration value. If no value is available,
  * MagicValue(JS_NO_ITER_VALUE) is returned.
  */
 extern bool
 IteratorMore(JSContext* cx, HandleObject iterobj, MutableHandleValue rval);
 
-extern bool
-ThrowStopIteration(JSContext* cx);
-
 /*
  * Create an object of the form { value: VALUE, done: DONE }.
  * ES 2017 draft 7.4.7.
  */
 extern JSObject*
 CreateIterResultObject(JSContext* cx, HandleValue value, bool done);
 
 bool
 IsPropertyIterator(HandleValue v);
 
-extern JSObject*
-InitStopIterationClass(JSContext* cx, HandleObject obj);
-
 enum class IteratorKind { Sync, Async };
 
 } /* namespace js */
 
 #endif /* jsiter_h */
--- a/js/src/jsprototypes.h
+++ b/js/src/jsprototypes.h
@@ -80,17 +80,16 @@
     real(SyntaxError,           InitViaClassSpec,       ERROR_CLASP(JSEXN_SYNTAXERR)) \
     real(TypeError,             InitViaClassSpec,       ERROR_CLASP(JSEXN_TYPEERR)) \
     real(URIError,              InitViaClassSpec,       ERROR_CLASP(JSEXN_URIERR)) \
     real(DebuggeeWouldRun,      InitViaClassSpec,       ERROR_CLASP(JSEXN_DEBUGGEEWOULDRUN)) \
     real(CompileError,          InitViaClassSpec,       ERROR_CLASP(JSEXN_WASMCOMPILEERROR)) \
     real(LinkError,             InitViaClassSpec,       ERROR_CLASP(JSEXN_WASMLINKERROR)) \
     real(RuntimeError,          InitViaClassSpec,       ERROR_CLASP(JSEXN_WASMRUNTIMEERROR)) \
     imaginary(Iterator,         dummy,                  dummy) \
-    real(StopIteration,         InitStopIterationClass, OCLASP(StopIteration)) \
     real(ArrayBuffer,           InitViaClassSpec,       OCLASP(ArrayBuffer)) \
     real(Int8Array,             InitViaClassSpec,       TYPED_ARRAY_CLASP(Int8)) \
     real(Uint8Array,            InitViaClassSpec,       TYPED_ARRAY_CLASP(Uint8)) \
     real(Int16Array,            InitViaClassSpec,       TYPED_ARRAY_CLASP(Int16)) \
     real(Uint16Array,           InitViaClassSpec,       TYPED_ARRAY_CLASP(Uint16)) \
     real(Int32Array,            InitViaClassSpec,       TYPED_ARRAY_CLASP(Int32)) \
     real(Uint32Array,           InitViaClassSpec,       TYPED_ARRAY_CLASP(Uint32)) \
     real(Float32Array,          InitViaClassSpec,       TYPED_ARRAY_CLASP(Float32)) \
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -32,17 +32,16 @@
 #include "builtin/WeakMapObject.h"
 #include "builtin/WeakSetObject.h"
 #include "vm/Debugger.h"
 #include "vm/EnvironmentObject.h"
 #include "vm/HelperThreads.h"
 #include "vm/PIC.h"
 #include "vm/RegExpStatics.h"
 #include "vm/RegExpStaticsObject.h"
-#include "vm/StopIterationObject.h"
 #include "wasm/WasmJS.h"
 
 #include "jscompartmentinlines.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 #include "vm/NativeObject-inl.h"
 
deleted file mode 100644
--- a/js/src/vm/StopIterationObject.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef vm_StopIterationObject_h
-#define vm_StopIterationObject_h
-
-#include "jsobj.h"
-
-namespace js {
-
-class StopIterationObject : public JSObject
-{
-  public:
-    static const Class class_;
-};
-
-} // namespace js
-
-#endif /* vm_StopIterationObject_h */
--- a/toolkit/components/promiseworker/PromiseWorker.jsm
+++ b/toolkit/components/promiseworker/PromiseWorker.jsm
@@ -83,19 +83,16 @@ const EXCEPTION_CONSTRUCTORS = {
     result.stack = error.stack;
     return result;
   },
   URIError(error) {
     let result = new URIError(error.message, error.fileName, error.lineNumber);
     result.stack = error.stack;
     return result;
   },
-  StopIteration() {
-    return StopIteration;
-  }
 };
 
 /**
  * An object responsible for dispatching messages to a chrome worker
  * and routing the responses.
  *
  * Instances of this constructor who need logging may provide a method
  * `log: function(...args) { ... }` in charge of printing out (or
@@ -119,17 +116,17 @@ this.BasePromiseWorker = function(url) {
    * A set of methods, with the following
    *
    * ConstructorName: function({message, fileName, lineNumber}) {
    *   // Construct a new instance of ConstructorName based on
    *   // `message`, `fileName`, `lineNumber`
    * }
    *
    * By default, this covers EvalError, InternalError, RangeError,
-   * ReferenceError, SyntaxError, TypeError, URIError, StopIteration.
+   * ReferenceError, SyntaxError, TypeError, URIError.
    */
   this.ExceptionHandlers = Object.create(EXCEPTION_CONSTRUCTORS);
 
   /**
    * The queue of deferred, waiting for the completion of their
    * respective job by the worker.
    *
    * Each item in the list may contain an additional field |closure|,
--- a/toolkit/components/promiseworker/worker/PromiseWorker.js
+++ b/toolkit/components/promiseworker/worker/PromiseWorker.js
@@ -164,24 +164,16 @@ AbstractWorker.prototype = {
       let error = {
         exn: exn.constructor.name,
         message: exn.message,
         fileName: exn.moduleName || exn.fileName,
         lineNumber: exn.lineNumber,
         stack: exn.moduleStack
       };
       this.postMessage({fail: error, id, durationMs});
-    } else if (exn == StopIteration) {
-      // StopIteration is a well-known singleton, and requires a
-      // slightly different treatment.
-      this.log("Sending back StopIteration, id is", id);
-      let error = {
-        exn: "StopIteration"
-      };
-      this.postMessage({fail: error, id, durationMs});
     } else if ("toMsg" in exn) {
       // Extension mechanism for exception [de]serialization. We
       // assume that any exception with a method `toMsg()` knows how
       // to serialize itself. The other side is expected to have
       // registered a deserializer using the `ExceptionHandlers`
       // object.
       this.log("Sending back an error that knows how to serialize itself", exn, "id is", id);
       let msg = exn.toMsg();