diff --git a/dom/tests/mochitest/general/test_interfaces.js b/dom/tests/mochitest/general/test_interfaces.js index 60db6bb804a9..00b6d62e1445 100644 --- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -63,7 +63,6 @@ var ecmaGlobals = "Set", "SharedArrayBuffer", {name: "SIMD", nightly: true}, - "StopIteration", "String", "Symbol", "SyntaxError", diff --git a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js index 13dff9aa2db4..c8ee47277554 100644 --- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js +++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js @@ -58,7 +58,6 @@ var ecmaGlobals = "Set", "SharedArrayBuffer", {name: "SIMD", nightly: true}, - "StopIteration", "String", "Symbol", "SyntaxError", diff --git a/dom/workers/test/test_worker_interfaces.js b/dom/workers/test/test_worker_interfaces.js index 706a66fc102e..0959ca78e819 100644 --- a/dom/workers/test/test_worker_interfaces.js +++ b/dom/workers/test/test_worker_interfaces.js @@ -58,7 +58,6 @@ var ecmaGlobals = "Set", "SharedArrayBuffer", {name: "SIMD", nightly: true}, - "StopIteration", "String", "Symbol", "SyntaxError", diff --git a/js/ipc/JavaScriptTypes.ipdlh b/js/ipc/JavaScriptTypes.ipdlh index 5129fc304f99..bf5794f3baa9 100644 --- a/js/ipc/JavaScriptTypes.ipdlh +++ b/js/ipc/JavaScriptTypes.ipdlh @@ -95,10 +95,6 @@ struct ReturnSuccess { }; -struct ReturnStopIteration -{ -}; - struct ReturnDeadCPOW { }; @@ -116,7 +112,6 @@ struct ReturnObjectOpResult union ReturnStatus { ReturnSuccess; - ReturnStopIteration; ReturnDeadCPOW; ReturnException; ReturnObjectOpResult; diff --git a/js/ipc/WrapperAnswer.cpp b/js/ipc/WrapperAnswer.cpp index 3ad8c5a8e8a7..ad389a423899 100644 --- a/js/ipc/WrapperAnswer.cpp +++ b/js/ipc/WrapperAnswer.cpp @@ -62,11 +62,6 @@ WrapperAnswer::fail(AutoJSAPI& jsapi, ReturnStatus* rs) 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()); diff --git a/js/ipc/WrapperOwner.cpp b/js/ipc/WrapperOwner.cpp index 51f06ab72ce6..c0cf85aea5d6 100644 --- a/js/ipc/WrapperOwner.cpp +++ b/js/ipc/WrapperOwner.cpp @@ -1076,9 +1076,6 @@ 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; diff --git a/js/src/jit-test/tests/basic/bug547911-1.js b/js/src/jit-test/tests/basic/bug547911-1.js index 310f6378974b..74c8d812e077 100644 --- 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); } diff --git a/js/src/jit-test/tests/basic/bug547911-2.js b/js/src/jit-test/tests/basic/bug547911-2.js index 49281eab8b61..a41780345840 100644 --- 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); } diff --git a/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js b/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js index 33646da6c49c..6be257683872 100644 --- a/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js +++ b/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js @@ -1,4 +1,4 @@ -var arr = [StopIteration, StopIteration, StopIteration, StopIteration, {}]; +var arr = [Math, Math, Math, Math, {}]; var obj = {}; var x; var result = 'no error'; diff --git a/js/src/jit-test/tests/collections/Map-forEach.js b/js/src/jit-test/tests/collections/Map-forEach.js index 77ad8970aa7c..6db15f4c312c 100644 --- a/js/src/jit-test/tests/collections/Map-forEach.js +++ b/js/src/jit-test/tests/collections/Map-forEach.js @@ -49,11 +49,10 @@ 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."); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index baa80aab1c1a..d233150a1c12 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -82,7 +82,6 @@ #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" @@ -7122,19 +7121,6 @@ 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(); -} - extern MOZ_NEVER_INLINE JS_PUBLIC_API(void) JS_AbortIfWrongThread(JSContext* cx) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 6bf8bf2a2d7a..323396025b7a 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -6200,15 +6200,6 @@ JS_ErrorFromException(JSContext* cx, JS::HandleObject obj); 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 diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 1b282fdeb7af..0f70077af6eb 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -24,7 +24,6 @@ #include "js/RootingAPI.h" #include "proxy/DeadObjectProxy.h" #include "vm/Debugger.h" -#include "vm/StopIterationObject.h" #include "vm/WrapperObject.h" #include "jsatominlines.h" @@ -395,17 +394,6 @@ JSCompartment::getNonWrapperObjectForCurrentCompartment(JSContext* cx, MutableHa return true; } - // Translate StopIteration singleton. - if (obj->is()) { - // 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. diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index d33a5480acd1..9c811973096d 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -31,7 +31,6 @@ #include "vm/GlobalObject.h" #include "vm/Interpreter.h" #include "vm/Shape.h" -#include "vm/StopIterationObject.h" #include "vm/TypedArrayObject.h" #include "jsscriptinlines.h" @@ -537,8 +536,6 @@ js::GetPropertyKeys(JSContext* cx, HandleObject obj, unsigned flags, AutoIdVecto props); } -static bool property_iterator_next(JSContext* cx, unsigned argc, Value* vp); - static inline PropertyIteratorObject* NewPropertyIteratorObject(JSContext* cx, unsigned flags) { @@ -569,26 +566,7 @@ NewPropertyIteratorObject(JSContext* cx, unsigned flags) return res; } - 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, 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(cx); } NativeIterator* @@ -1055,28 +1033,13 @@ JSCompartment::getOrCreateIterResultTemplateObject(JSContext* cx) 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; } @@ -1105,36 +1068,6 @@ js::IsPropertyIterator(HandleValue v) return v.isObject() && v.toObject().is(); } -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()->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(cx, args); -} - size_t PropertyIteratorObject::sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf) const { @@ -1489,72 +1422,32 @@ bool js::IteratorMore(JSContext* cx, HandleObject iterobj, MutableHandleValue rval) { // Fast path for native iterators. - if (iterobj->is()) { + if (MOZ_LIKELY(iterobj->is())) { NativeIterator* ni = iterobj->as().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)) - 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()) - 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; + MOZ_ASSERT(IsWrapper(iterobj)); + + RootedObject obj(cx, CheckedUnwrap(iterobj)); + if (!obj) + return false; + + MOZ_RELEASE_ASSERT(obj->is()); + { + AutoCompartment ac(cx, obj); + NativeIterator* ni = obj->as().getNativeIterator(); + if (!NativeIteratorNext(cx, ni, rval)) + return false; + } + 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 @@ -1621,23 +1514,3 @@ GlobalObject::initStringIteratorProto(JSContext* cx, Handle globa global->setReservedSlot(STRING_ITERATOR_PROTO, ObjectValue(*proto)); return true; } - -JSObject* -js::InitStopIterationClass(JSContext* cx, HandleObject obj) -{ - Handle global = obj.as(); - 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(); -} diff --git a/js/src/jsiter.h b/js/src/jsiter.h index d2e7560a79f5..a6e4c11f8355 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -204,9 +204,6 @@ SuppressDeletedElement(JSContext* cx, HandleObject obj, uint32_t index); 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. @@ -217,9 +214,6 @@ 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 */ diff --git a/js/src/jsprototypes.h b/js/src/jsprototypes.h index 7833589ae60c..1043530c02e1 100644 --- a/js/src/jsprototypes.h +++ b/js/src/jsprototypes.h @@ -85,7 +85,6 @@ 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)) \ diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 9770ee1096fe..0d27c5492eed 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -37,7 +37,6 @@ #include "vm/PIC.h" #include "vm/RegExpStatics.h" #include "vm/RegExpStaticsObject.h" -#include "vm/StopIterationObject.h" #include "wasm/WasmJS.h" #include "jscompartmentinlines.h" diff --git a/js/src/vm/StopIterationObject.h b/js/src/vm/StopIterationObject.h deleted file mode 100644 index fe366f096f62..000000000000 --- 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 */ diff --git a/toolkit/components/promiseworker/PromiseWorker.jsm b/toolkit/components/promiseworker/PromiseWorker.jsm index 075b1250b18b..364bac286707 100644 --- a/toolkit/components/promiseworker/PromiseWorker.jsm +++ b/toolkit/components/promiseworker/PromiseWorker.jsm @@ -88,9 +88,6 @@ const EXCEPTION_CONSTRUCTORS = { result.stack = error.stack; return result; }, - StopIteration() { - return StopIteration; - } }; /** @@ -124,7 +121,7 @@ this.BasePromiseWorker = function(url) { * } * * By default, this covers EvalError, InternalError, RangeError, - * ReferenceError, SyntaxError, TypeError, URIError, StopIteration. + * ReferenceError, SyntaxError, TypeError, URIError. */ this.ExceptionHandlers = Object.create(EXCEPTION_CONSTRUCTORS); diff --git a/toolkit/components/promiseworker/worker/PromiseWorker.js b/toolkit/components/promiseworker/worker/PromiseWorker.js index 3f927ef53339..787692db3481 100644 --- a/toolkit/components/promiseworker/worker/PromiseWorker.js +++ b/toolkit/components/promiseworker/worker/PromiseWorker.js @@ -169,14 +169,6 @@ AbstractWorker.prototype = { 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