merge mozilla-inbound to mozilla-central. r=merge a=merge

This commit is contained in:
Sebastian Hengst 2017-11-06 00:14:30 +02:00
Родитель fedf233426 2681f26832
Коммит 9c98389a1c
22 изменённых файлов: 228 добавлений и 318 удалений

Просмотреть файл

@ -443,9 +443,9 @@ public:
mPrincipalInfo(aPrincipalInfo),
mOpenMode(aOpenMode),
mWriteParams(aWriteParams),
mOperationMayProceed(true),
mState(eInitial),
mResult(JS::AsmJSCache_InternalError),
mDeleteReceived(false),
mActorDestroyed(false),
mOpened(false)
{
@ -486,6 +486,22 @@ private:
MOZ_ASSERT(!IsOnOwningThread());
}
bool
IsActorDestroyed() const
{
AssertIsOnOwningThread();
return mActorDestroyed;
}
// May be called on any thread, but you should call IsActorDestroyed() if
// you know you're on the background thread because it is slightly faster.
bool
OperationMayProceed() const
{
return mOperationMayProceed;
}
// This method is called on the owning thread when the JS engine is finished
// reading/writing the cache entry.
void
@ -493,12 +509,18 @@ private:
{
AssertIsOnOwningThread();
MOZ_ASSERT(mState == eOpened);
MOZ_ASSERT(mResult == JS::AsmJSCache_Success);
mState = eFinished;
MOZ_ASSERT(mOpened);
mOpened = false;
FinishOnOwningThread();
if (!mActorDestroyed) {
Unused << Send__delete__(this, mResult);
}
}
// This method is called upon any failure that prevents the eventual opening
@ -508,6 +530,7 @@ private:
{
AssertIsOnOwningThread();
MOZ_ASSERT(mState != eFinished);
MOZ_ASSERT(mResult != JS::AsmJSCache_Success);
mState = eFinished;
@ -515,7 +538,7 @@ private:
FinishOnOwningThread();
if (!mDeleteReceived && !mActorDestroyed) {
if (!mActorDestroyed) {
Unused << Send__delete__(this, mResult);
}
}
@ -557,16 +580,18 @@ private:
{
AssertIsOnOwningThread();
// If shutdown just started, the QuotaManager may have been deleted.
QuotaManager* qm = QuotaManager::Get();
if (!qm) {
FailOnNonOwningThread();
if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) ||
IsActorDestroyed()) {
Fail();
return;
}
QuotaManager* qm = QuotaManager::Get();
MOZ_ASSERT(qm);
nsresult rv = qm->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
FailOnNonOwningThread();
Fail();
return;
}
}
@ -579,62 +604,96 @@ private:
DirectoryLockFailed() override;
// IPDL methods.
mozilla::ipc::IPCResult
Recv__delete__(const JS::AsmJSCacheResult& aResult) override
{
AssertIsOnOwningThread();
MOZ_ASSERT(mState != eFinished);
MOZ_ASSERT(!mDeleteReceived);
mDeleteReceived = true;
if (mOpened) {
Close();
} else {
Fail();
}
MOZ_ASSERT(mState == eFinished);
return IPC_OK();
}
void
ActorDestroy(ActorDestroyReason why) override
{
AssertIsOnOwningThread();
MOZ_ASSERT(!mActorDestroyed);
MOZ_ASSERT(mOperationMayProceed);
mActorDestroyed = true;
mOperationMayProceed = false;
// Assume ActorDestroy can happen at any time, so probe the current state to
// determine what needs to happen.
if (mState == eFinished) {
return;
}
// Assume ActorDestroy can happen at any time, so we can't probe the
// current state since mState can be modified on any thread (only one
// thread at a time based on the state machine).
// However we can use mOpened which is only touched on the owning thread.
// If mOpened is true, we can also modify mState since we are guaranteed
// that there are no pending runnables which would probe mState to decide
// what code needs to run (there shouldn't be any running runnables on
// other threads either).
if (mOpened) {
Close();
} else {
Fail();
MOZ_ASSERT(mState == eFinished);
}
MOZ_ASSERT(mState == eFinished);
// We don't have to call Fail() if mOpened is not true since it means that
// either nothing has been initialized yet, so nothing to cleanup or there
// are pending runnables that will detect that the actor has been destroyed
// and call Fail().
}
mozilla::ipc::IPCResult
RecvSelectCacheFileToRead(const uint32_t& aModuleIndex) override
RecvSelectCacheFileToRead(const OpenMetadataForReadResponse& aResponse)
override
{
AssertIsOnOwningThread();
MOZ_ASSERT(mState == eWaitingToOpenCacheFileForRead);
MOZ_ASSERT(mOpenMode == eOpenForRead);
MOZ_ASSERT(!mOpened);
// A cache entry has been selected to open.
if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread())) {
Fail();
return IPC_OK();
}
mModuleIndex = aModuleIndex;
mState = eReadyToOpenCacheFileForRead;
DispatchToIOThread();
switch (aResponse.type()) {
case OpenMetadataForReadResponse::TAsmJSCacheResult: {
MOZ_ASSERT(aResponse.get_AsmJSCacheResult() != JS::AsmJSCache_Success);
mResult = aResponse.get_AsmJSCacheResult();
// This ParentRunnable can only be held alive by the IPDL. Fail()
// clears that last reference. So we need to add a self reference here.
RefPtr<ParentRunnable> kungFuDeathGrip = this;
Fail();
break;
}
case OpenMetadataForReadResponse::Tuint32_t:
// A cache entry has been selected to open.
mModuleIndex = aResponse.get_uint32_t();
mState = eReadyToOpenCacheFileForRead;
DispatchToIOThread();
break;
default:
MOZ_CRASH("Should never get here!");
}
return IPC_OK();
}
mozilla::ipc::IPCResult
RecvClose() override
{
AssertIsOnOwningThread();
MOZ_ASSERT(mState == eOpened);
// This ParentRunnable can only be held alive by the IPDL. Close() clears
// that last reference. So we need to add a self reference here.
RefPtr<ParentRunnable> kungFuDeathGrip = this;
Close();
MOZ_ASSERT(mState == eFinished);
return IPC_OK();
}
@ -655,6 +714,8 @@ private:
nsCOMPtr<nsIFile> mMetadataFile;
Metadata mMetadata;
Atomic<bool> mOperationMayProceed;
// State initialized during eWaitingToOpenCacheFileForRead
unsigned mModuleIndex;
@ -675,7 +736,6 @@ private:
State mState;
JS::AsmJSCacheResult mResult;
bool mDeleteReceived;
bool mActorDestroyed;
bool mOpened;
};
@ -916,6 +976,12 @@ ParentRunnable::Run()
case eInitial: {
MOZ_ASSERT(NS_IsMainThread());
if (NS_WARN_IF(Client::IsShuttingDownOnNonBackgroundThread()) ||
!OperationMayProceed()) {
FailOnNonOwningThread();
return NS_OK;
}
rv = InitOnMainThread();
if (NS_FAILED(rv)) {
FailOnNonOwningThread();
@ -931,7 +997,8 @@ ParentRunnable::Run()
case eWaitingToFinishInit: {
AssertIsOnOwningThread();
if (QuotaManager::IsShuttingDown()) {
if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) ||
IsActorDestroyed()) {
Fail();
return NS_OK;
}
@ -950,6 +1017,12 @@ ParentRunnable::Run()
case eWaitingToOpenDirectory: {
AssertIsOnOwningThread();
if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) ||
IsActorDestroyed()) {
Fail();
return NS_OK;
}
if (NS_WARN_IF(!QuotaManager::Get())) {
Fail();
return NS_OK;
@ -962,6 +1035,12 @@ ParentRunnable::Run()
case eReadyToReadMetadata: {
AssertIsOnIOThread();
if (NS_WARN_IF(Client::IsShuttingDownOnNonBackgroundThread()) ||
!OperationMayProceed()) {
FailOnNonOwningThread();
return NS_OK;
}
rv = ReadMetadata();
if (NS_FAILED(rv)) {
FailOnNonOwningThread();
@ -990,6 +1069,12 @@ ParentRunnable::Run()
AssertIsOnOwningThread();
MOZ_ASSERT(mOpenMode == eOpenForRead);
if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) ||
IsActorDestroyed()) {
Fail();
return NS_OK;
}
mState = eWaitingToOpenCacheFileForRead;
// Metadata is now open.
@ -1005,6 +1090,12 @@ ParentRunnable::Run()
AssertIsOnIOThread();
MOZ_ASSERT(mOpenMode == eOpenForRead);
if (NS_WARN_IF(Client::IsShuttingDownOnNonBackgroundThread()) ||
!OperationMayProceed()) {
FailOnNonOwningThread();
return NS_OK;
}
rv = OpenCacheFileForRead();
if (NS_FAILED(rv)) {
FailOnNonOwningThread();
@ -1019,11 +1110,13 @@ ParentRunnable::Run()
case eSendingCacheFile: {
AssertIsOnOwningThread();
mState = eOpened;
if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) ||
IsActorDestroyed()) {
Fail();
return NS_OK;
}
// The entry is now open.
MOZ_ASSERT(!mOpened);
mOpened = true;
mState = eOpened;
FileDescriptor::PlatformHandleType handle =
FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mFileDesc));
@ -1032,6 +1125,12 @@ ParentRunnable::Run()
return NS_OK;
}
// The entry is now open.
MOZ_ASSERT(!mOpened);
mOpened = true;
mResult = JS::AsmJSCache_Success;
return NS_OK;
}
@ -1291,15 +1390,16 @@ private:
MOZ_ASSERT(mState == eOpening);
uint32_t moduleIndex;
if (!FindHashMatch(aMetadata, mReadParams, &moduleIndex)) {
Fail(JS::AsmJSCache_InternalError);
Send__delete__(this, JS::AsmJSCache_InternalError);
return IPC_OK();
bool ok;
if (FindHashMatch(aMetadata, mReadParams, &moduleIndex)) {
ok = SendSelectCacheFileToRead(moduleIndex);
} else {
ok = SendSelectCacheFileToRead(JS::AsmJSCache_InternalError);
}
if (!SendSelectCacheFileToRead(moduleIndex)) {
if (!ok) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
@ -1327,9 +1427,20 @@ private:
Recv__delete__(const JS::AsmJSCacheResult& aResult) override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mState == eOpening);
MOZ_ASSERT(mState == eOpening || mState == eFinishing);
MOZ_ASSERT_IF(mState == eOpening, aResult != JS::AsmJSCache_Success);
MOZ_ASSERT_IF(mState == eFinishing, aResult == JS::AsmJSCache_Success);
Fail(aResult);
if (mState == eOpening) {
Fail(aResult);
} else {
// Match the AddRef in BlockUntilOpen(). The IPDL still holds an
// outstanding ref which will keep 'this' alive until ActorDestroy()
// is executed.
Release();
mState = eFinished;
}
return IPC_OK();
}
@ -1392,10 +1503,10 @@ private:
const OpenMode mOpenMode;
enum State {
eInitial, // Just created, waiting to be dispatched to the main thread
eBackgroundChildPending, // Waiting for the background child to be created
eOpening, // Waiting for the parent process to respond
eOpened, // Parent process opened the entry and sent it back
eClosing, // Waiting to be dispatched to the main thread to Send__delete__
eFinishing, // Waiting for the parent process to close
eFinished // Terminal state
};
State mState;
@ -1455,28 +1566,31 @@ ChildRunnable::Run()
// Per FileDescriptorHolder::Finish()'s comment, call before
// releasing the directory lock (which happens in the parent upon receipt
// of the Send__delete__ message).
// of the Close message).
FileDescriptorHolder::Finish();
MOZ_ASSERT(mOpened);
mOpened = false;
// Match the AddRef in BlockUntilOpen(). The main thread event loop still
// holds an outstanding ref which will keep 'this' alive until returning to
// the event loop.
Release();
if (mActorDestroyed) {
// Match the AddRef in BlockUntilOpen(). The main thread event loop
// still holds an outstanding ref which will keep 'this' alive until
// returning to the event loop.
Release();
if (!mActorDestroyed) {
Unused << Send__delete__(this, JS::AsmJSCache_Success);
mState = eFinished;
} else {
Unused << SendClose();
mState = eFinishing;
}
mState = eFinished;
return NS_OK;
}
case eBackgroundChildPending:
case eOpening:
case eOpened:
case eFinishing:
case eFinished: {
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Shouldn't Run() in this state");
}

Просмотреть файл

@ -11,6 +11,12 @@ namespace mozilla {
namespace dom {
namespace asmjscache {
union OpenMetadataForReadResponse
{
AsmJSCacheResult;
uint32_t;
};
protocol PAsmJSCacheEntry
{
manager PBackground;
@ -21,14 +27,24 @@ protocol PAsmJSCacheEntry
child:
async OnOpenMetadataForRead(Metadata metadata);
parent:
async SelectCacheFileToRead(uint32_t moduleIndex);
async SelectCacheFileToRead(OpenMetadataForReadResponse response);
child:
// Once the cache file has been opened, the child is notified and sent an
// open file descriptor.
async OnOpenCacheFile(int64_t fileSize, FileDescriptor fileDesc);
both:
parent:
// When the child process is done with the cache entry, the parent process
// is notified (via Close).
async Close();
child:
// When there's an error during the opening phase, the child process is
// notified (via __delete__) and sent an error result.
// When the parent process receives the Close message, it closes the cache
// entry on the parent side and the child is notified (via __delete__).
// The protocol is destroyed in both cases.
async __delete__(AsmJSCacheResult result);
};

Просмотреть файл

@ -63,7 +63,6 @@ var ecmaGlobals =
"Set",
"SharedArrayBuffer",
{name: "SIMD", nightly: true},
"StopIteration",
"String",
"Symbol",
"SyntaxError",

Просмотреть файл

@ -58,7 +58,6 @@ var ecmaGlobals =
"Set",
"SharedArrayBuffer",
{name: "SIMD", nightly: true},
"StopIteration",
"String",
"Symbol",
"SyntaxError",

Просмотреть файл

@ -58,7 +58,6 @@ var ecmaGlobals =
"Set",
"SharedArrayBuffer",
{name: "SIMD", nightly: true},
"StopIteration",
"String",
"Symbol",
"SyntaxError",

Просмотреть файл

@ -95,10 +95,6 @@ struct ReturnSuccess
{
};
struct ReturnStopIteration
{
};
struct ReturnDeadCPOW
{
};
@ -116,7 +112,6 @@ struct ReturnObjectOpResult
union ReturnStatus
{
ReturnSuccess;
ReturnStopIteration;
ReturnDeadCPOW;
ReturnException;
ReturnObjectOpResult;

Просмотреть файл

@ -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());

Просмотреть файл

@ -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;

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -1,4 +1,4 @@
var arr = [StopIteration, StopIteration, StopIteration, StopIteration, {}];
var arr = [Math, Math, Math, Math, {}];
var obj = {};
var x;
var result = 'no error';

Просмотреть файл

@ -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.");

Просмотреть файл

@ -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<StopIterationObject>();
}
extern MOZ_NEVER_INLINE JS_PUBLIC_API(void)
JS_AbortIfWrongThread(JSContext* cx)
{

Просмотреть файл

@ -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

Просмотреть файл

@ -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<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.

Просмотреть файл

@ -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<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*
@ -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<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
{
@ -1489,72 +1422,32 @@ 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))
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<PropertyIteratorObject>());
{
AutoCompartment ac(cx, obj);
NativeIterator* ni = obj->as<PropertyIteratorObject>().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<GlobalObject*> globa
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();
}

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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)) \

Просмотреть файл

@ -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"

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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);

Просмотреть файл

@ -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