diff --git a/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp b/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp index 16b58cf817af..e5077a5a452d 100644 --- a/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp +++ b/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2021 Apple Inc. All rights reserved. + * Copyright (C) 2013-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,6 +38,7 @@ #include #include #include +#include namespace WebCore { using namespace JSC; @@ -56,6 +57,14 @@ void DeferredPromise::callFunction(JSGlobalObject& lexicalGlobalObject, ResolveM if (shouldIgnoreRequestToFulfill()) return; + JSC::VM& vm = lexicalGlobalObject.vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + auto handleExceptionIfNeeded = makeScopeExit([&] { + if (UNLIKELY(scope.exception())) + handleUncaughtException(scope, *jsCast(&lexicalGlobalObject)); + }); + if (activeDOMObjectsAreSuspended()) { JSC::Strong strongResolution(lexicalGlobalObject.vm(), resolution); ASSERT(scriptExecutionContext()->eventLoop().isSuspended()); @@ -100,7 +109,14 @@ void DeferredPromise::whenSettled(Function&& callback) return; } - DOMPromise::whenPromiseIsSettled(globalObject(), deferred(), WTFMove(callback)); + { + auto* globalObject = this->globalObject(); + auto& vm = globalObject->vm(); + JSC::JSLockHolder locker(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + DOMPromise::whenPromiseIsSettled(globalObject, deferred(), WTFMove(callback)); + DEFERRED_PROMISE_HANDLE_AND_RETURN_IF_EXCEPTION(scope, globalObject); + } } void DeferredPromise::reject(RejectAsHandled rejectAsHandled) @@ -144,10 +160,10 @@ void DeferredPromise::reject(Exception exception, RejectAsHandled rejectAsHandle EXCEPTION_ASSERT(scope.exception()); auto error = scope.exception()->value(); bool isTerminating = handleTerminationExceptionIfNeeded(scope, lexicalGlobalObject); - scope.clearException(); - - if (!isTerminating) + if (!isTerminating) { + scope.clearException(); reject(error, rejectAsHandled); + } return; } @@ -179,10 +195,10 @@ void DeferredPromise::reject(ExceptionCode ec, const String& message, RejectAsHa EXCEPTION_ASSERT(scope.exception()); auto error = scope.exception()->value(); bool isTerminating = handleTerminationExceptionIfNeeded(scope, lexicalGlobalObject); - scope.clearException(); - - if (!isTerminating) + if (!isTerminating) { + scope.clearException(); reject(error, rejectAsHandled); + } return; } @@ -214,6 +230,8 @@ void rejectPromiseWithExceptionIfAny(JSC::JSGlobalObject& lexicalGlobalObject, J UNUSED_PARAM(lexicalGlobalObject); if (LIKELY(!catchScope.exception())) return; + if (catchScope.vm().hasPendingTerminationException()) + return; JSValue error = catchScope.exception()->value(); catchScope.clearException(); @@ -284,6 +302,7 @@ bool DeferredPromise::handleTerminationExceptionIfNeeded(CatchScope& scope, JSDO bool terminatorCausedException = vm.isTerminationException(exception); if (terminatorCausedException || (scriptController && scriptController->isTerminatingExecution())) { scriptController->forbidExecution(); + m_needsAbort = true; return true; } } diff --git a/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h b/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h index 611ee88d676c..fa2d961d1f0a 100644 --- a/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h +++ b/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2021 Apple Inc. All rights reserved. + * Copyright (C) 2013-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,14 @@ namespace WebCore { class JSLocalDOMWindow; enum class RejectAsHandled : bool { No, Yes }; +#define DEFERRED_PROMISE_HANDLE_AND_RETURN_IF_EXCEPTION(scope, globalObject) do { \ + if (UNLIKELY(scope.exception())) { \ + handleUncaughtException(scope, *jsCast(globalObject)); \ + return; \ + } \ + } while (false) + + class DeferredPromise : public DOMGuarded { public: enum class Mode { @@ -66,8 +74,13 @@ class DeferredPromise : public DOMGuarded { ASSERT(deferred()); ASSERT(globalObject()); JSC::JSGlobalObject* lexicalGlobalObject = globalObject(); - JSC::JSLockHolder locker(lexicalGlobalObject); - resolve(*lexicalGlobalObject, toJS(*lexicalGlobalObject, *globalObject(), std::forward(value))); + auto& vm = lexicalGlobalObject->vm(); + JSC::JSLockHolder locker(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + auto jsValue = toJS(*lexicalGlobalObject, *globalObject(), std::forward(value)); + DEFERRED_PROMISE_HANDLE_AND_RETURN_IF_EXCEPTION(scope, lexicalGlobalObject); + resolve(*lexicalGlobalObject, jsValue); + DEFERRED_PROMISE_HANDLE_AND_RETURN_IF_EXCEPTION(scope, lexicalGlobalObject); } void resolveWithJSValue(JSC::JSValue resolution) @@ -103,8 +116,12 @@ class DeferredPromise : public DOMGuarded { ASSERT(deferred()); ASSERT(globalObject()); JSC::JSGlobalObject* lexicalGlobalObject = globalObject(); - JSC::JSLockHolder locker(lexicalGlobalObject); - resolve(*lexicalGlobalObject, toJSNewlyCreated(*lexicalGlobalObject, *globalObject(), std::forward(value))); + auto& vm = lexicalGlobalObject->vm(); + JSC::JSLockHolder locker(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + auto jsValue = toJSNewlyCreated(*lexicalGlobalObject, *globalObject(), std::forward(value)); + DEFERRED_PROMISE_HANDLE_AND_RETURN_IF_EXCEPTION(scope, lexicalGlobalObject); + resolve(*lexicalGlobalObject, jsValue); } template @@ -116,8 +133,12 @@ class DeferredPromise : public DOMGuarded { ASSERT(deferred()); ASSERT(globalObject()); auto* lexicalGlobalObject = globalObject(); - JSC::JSLockHolder locker(lexicalGlobalObject); - resolve(*lexicalGlobalObject, toJSNewlyCreated(*lexicalGlobalObject, *globalObject(), createValue(*globalObject()->scriptExecutionContext()))); + auto& vm = lexicalGlobalObject->vm(); + JSC::JSLockHolder locker(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + auto jsValue = toJSNewlyCreated(*lexicalGlobalObject, *globalObject(), createValue(*globalObject()->scriptExecutionContext())); + DEFERRED_PROMISE_HANDLE_AND_RETURN_IF_EXCEPTION(scope, lexicalGlobalObject); + resolve(*lexicalGlobalObject, jsValue); } template @@ -129,8 +150,12 @@ class DeferredPromise : public DOMGuarded { ASSERT(deferred()); ASSERT(globalObject()); JSC::JSGlobalObject* lexicalGlobalObject = globalObject(); - JSC::JSLockHolder locker(lexicalGlobalObject); - reject(*lexicalGlobalObject, toJS(*lexicalGlobalObject, *globalObject(), std::forward(value)), rejectAsHandled); + auto& vm = lexicalGlobalObject->vm(); + JSC::JSLockHolder locker(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + auto jsValue = toJS(*lexicalGlobalObject, *globalObject(), std::forward(value)); + DEFERRED_PROMISE_HANDLE_AND_RETURN_IF_EXCEPTION(scope, lexicalGlobalObject); + reject(*lexicalGlobalObject, jsValue, rejectAsHandled); } void reject(RejectAsHandled = RejectAsHandled::No); @@ -148,12 +173,12 @@ class DeferredPromise : public DOMGuarded { ASSERT(deferred()); ASSERT(globalObject()); auto* lexicalGlobalObject = globalObject(); - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = lexicalGlobalObject->vm(); JSC::JSLockHolder locker(vm); auto scope = DECLARE_CATCH_SCOPE(vm); - resolve(*lexicalGlobalObject, callback(*globalObject())); - if (UNLIKELY(scope.exception())) - handleUncaughtException(scope, *lexicalGlobalObject); + auto jsValue = callback(*globalObject()); + DEFERRED_PROMISE_HANDLE_AND_RETURN_IF_EXCEPTION(scope, lexicalGlobalObject); + resolve(*lexicalGlobalObject, jsValue); } template @@ -168,14 +193,15 @@ class DeferredPromise : public DOMGuarded { JSC::VM& vm = lexicalGlobalObject->vm(); JSC::JSLockHolder locker(vm); auto scope = DECLARE_CATCH_SCOPE(vm); - reject(*lexicalGlobalObject, callback(*globalObject()), rejectAsHandled); - if (UNLIKELY(scope.exception())) - handleUncaughtException(scope, *lexicalGlobalObject); + auto jsValue = callback(*globalObject()); + DEFERRED_PROMISE_HANDLE_AND_RETURN_IF_EXCEPTION(scope, lexicalGlobalObject); + reject(*lexicalGlobalObject, jsValue, rejectAsHandled); } JSC::JSValue promise() const; void whenSettled(Function&&); + bool needsAbort() const { return m_needsAbort; } private: DeferredPromise(JSDOMGlobalObject& globalObject, JSC::JSPromise& deferred, Mode mode) @@ -198,9 +224,10 @@ class DeferredPromise : public DOMGuarded { } bool handleTerminationExceptionIfNeeded(JSC::CatchScope&, JSDOMGlobalObject& lexicalGlobalObject); - void handleUncaughtException(JSC::CatchScope&, JSDOMGlobalObject& lexicalGlobalObject); + WEBCORE_EXPORT void handleUncaughtException(JSC::CatchScope&, JSDOMGlobalObject& lexicalGlobalObject); Mode m_mode; + bool m_needsAbort { false }; }; class DOMPromiseDeferredBase { diff --git a/Source/WebCore/bindings/js/JSMicrotaskCallback.h b/Source/WebCore/bindings/js/JSMicrotaskCallback.h index b57b2ca2f11f..caeb0357f1ad 100644 --- a/Source/WebCore/bindings/js/JSMicrotaskCallback.h +++ b/Source/WebCore/bindings/js/JSMicrotaskCallback.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2018 Yusuke Suzuki . - * Copyright (C) 2021 Apple Inc. All rights reserved. + * Copyright (C) 2021-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,9 +43,7 @@ class JSMicrotaskCallback : public RefCounted { auto protectedThis { Ref { *this } }; JSC::VM& vm = m_globalObject->vm(); JSC::JSLockHolder lock(vm); - auto scope = DECLARE_CATCH_SCOPE(vm); JSExecState::runTask(m_globalObject.get(), m_task); - scope.assertNoExceptionExceptTermination(); } private: diff --git a/Source/WebCore/dom/BroadcastChannel.cpp b/Source/WebCore/dom/BroadcastChannel.cpp index f24492f2a205..a66e853099da 100644 --- a/Source/WebCore/dom/BroadcastChannel.cpp +++ b/Source/WebCore/dom/BroadcastChannel.cpp @@ -248,7 +248,15 @@ void BroadcastChannel::dispatchMessage(Ref&& message) if (!globalObject) return; + auto& vm = globalObject->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); auto event = MessageEvent::create(*globalObject, WTFMove(message), scriptExecutionContext()->securityOrigin()->toString()); + if (UNLIKELY(scope.exception())) { + // Currently, we assume that the only way we can get here is if we have a termination. + RELEASE_ASSERT(vm.hasPendingTerminationException()); + return; + } + dispatchEvent(event.event); }); } diff --git a/Source/WebCore/dom/MessagePort.cpp b/Source/WebCore/dom/MessagePort.cpp index be82b8a91c5f..1e82521acf7e 100644 --- a/Source/WebCore/dom/MessagePort.cpp +++ b/Source/WebCore/dom/MessagePort.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2023 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -278,6 +278,9 @@ void MessagePort::dispatchMessages() return; ASSERT(context->isContextThread()); + auto* globalObject = context->globalObject(); + auto& vm = globalObject->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); bool contextIsWorker = is(*context); for (auto& message : messages) { @@ -286,7 +289,12 @@ void MessagePort::dispatchMessages() return; auto ports = MessagePort::entanglePorts(*context, WTFMove(message.transferredPorts)); - auto event = MessageEvent::create(*context->globalObject(), message.message.releaseNonNull(), { }, { }, { }, WTFMove(ports)); + auto event = MessageEvent::create(*globalObject, message.message.releaseNonNull(), { }, { }, { }, WTFMove(ports)); + if (UNLIKELY(scope.exception())) { + // Currently, we assume that the only way we can get here is if we have a termination. + RELEASE_ASSERT(vm.hasPendingTerminationException()); + return; + } // Per specification, each MessagePort object has a task source called the port message queue. queueTaskKeepingObjectAlive(*this, TaskSource::PostedMessageQueue, [this, event = WTFMove(event)] { diff --git a/Source/WebCore/dom/Microtasks.cpp b/Source/WebCore/dom/Microtasks.cpp index c6b2f97892dd..ec4e8a77977f 100644 --- a/Source/WebCore/dom/Microtasks.cpp +++ b/Source/WebCore/dom/Microtasks.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2014 Yoav Weiss (yoav@yoav.ws) * Copyright (C) 2015 Akamai Technologies Inc. All rights reserved. + * Copyright (C) 2023 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -52,10 +53,12 @@ void MicrotaskQueue::performMicrotaskCheckpoint() return; SetForScope change(m_performingMicrotaskCheckpoint, true); - JSC::JSLockHolder locker(vm()); + VM& vm = this->vm(); + JSC::JSLockHolder locker(vm); + auto catchScope = DECLARE_CATCH_SCOPE(vm); Vector> toKeep; - while (!m_microtaskQueue.isEmpty()) { + while (!m_microtaskQueue.isEmpty() && !vm.executionForbidden()) { Vector> queue = WTFMove(m_microtaskQueue); for (auto& task : queue) { auto* group = task->group(); @@ -63,32 +66,45 @@ void MicrotaskQueue::performMicrotaskCheckpoint() continue; if (group->isSuspended()) toKeep.append(WTFMove(task)); - else + else { task->execute(); + if (UNLIKELY(!catchScope.clearExceptionExceptTermination())) + break; // Encountered termination. + } } } - vm().finalizeSynchronousJSExecution(); + vm.finalizeSynchronousJSExecution(); m_microtaskQueue = WTFMove(toKeep); - auto checkpointTasks = std::exchange(m_checkpointTasks, { }); - for (auto& checkpointTask : checkpointTasks) { - auto* group = checkpointTask->group(); - if (!group || group->isStoppedPermanently()) - continue; + if (!vm.executionForbidden()) { + auto checkpointTasks = std::exchange(m_checkpointTasks, { }); + for (auto& checkpointTask : checkpointTasks) { + auto* group = checkpointTask->group(); + if (!group || group->isStoppedPermanently()) + continue; - if (group->isSuspended()) { - m_checkpointTasks.append(WTFMove(checkpointTask)); - continue; - } + if (group->isSuspended()) { + m_checkpointTasks.append(WTFMove(checkpointTask)); + continue; + } - checkpointTask->execute(); + checkpointTask->execute(); + if (UNLIKELY(!catchScope.clearExceptionExceptTermination())) + break; // Encountered termination. + } } // https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint (step 4). - m_eventLoop->forEachAssociatedContext([](auto& context) { + auto* vmPtr = &vm; + m_eventLoop->forEachAssociatedContext([vmPtr](auto& context) { + auto& vm = *vmPtr; + if (UNLIKELY(vm.executionForbidden())) + return; + auto catchScope = DECLARE_CATCH_SCOPE(vm); if (auto* tracker = context.rejectedPromiseTracker()) tracker->processQueueSoon(); + catchScope.clearExceptionExceptTermination(); }); // FIXME: We should cleanup Indexed Database transactions as per: diff --git a/Source/WebCore/page/LocalDOMWindow.cpp b/Source/WebCore/page/LocalDOMWindow.cpp index 936cdbdd5014..bfc9b017bfb9 100644 --- a/Source/WebCore/page/LocalDOMWindow.cpp +++ b/Source/WebCore/page/LocalDOMWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2021 Apple Inc. All rights reserved. + * Copyright (C) 2006-2023 Apple Inc. All rights reserved. * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without @@ -933,11 +933,20 @@ void LocalDOMWindow::processPostMessage(JSC::JSGlobalObject& lexicalGlobalObject if (!globalObject) return; + auto& vm = globalObject->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + UserGestureIndicator userGestureIndicator(userGestureToForward); InspectorInstrumentation::willDispatchPostMessage(frame, postMessageIdentifier); auto ports = MessagePort::entanglePorts(*document(), WTFMove(message.transferredPorts)); auto event = MessageEvent::create(*globalObject, message.message.releaseNonNull(), sourceOrigin, { }, incumbentWindowProxy ? std::make_optional(MessageEventSource(WTFMove(incumbentWindowProxy))) : std::nullopt, WTFMove(ports)); + if (UNLIKELY(scope.exception())) { + // Currently, we assume that the only way we can get here is if we have a termination. + RELEASE_ASSERT(vm.hasPendingTerminationException()); + return; + } + dispatchEvent(event.event); InspectorInstrumentation::didDispatchPostMessage(frame, postMessageIdentifier); diff --git a/Source/WebCore/workers/WorkerMessagingProxy.cpp b/Source/WebCore/workers/WorkerMessagingProxy.cpp index 7a21f18f03fe..b379634bdda7 100644 --- a/Source/WebCore/workers/WorkerMessagingProxy.cpp +++ b/Source/WebCore/workers/WorkerMessagingProxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2023 Apple Inc. All Rights Reserved. * Copyright (C) 2009-2022 Google Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -190,8 +190,15 @@ void WorkerMessagingProxy::postMessageToWorkerObject(MessageWithMessagePorts&& m if (!globalObject) return; + auto& vm = globalObject->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); UserGestureIndicator userGestureIndicator(userGestureForwarder ? userGestureForwarder->userGestureToForward() : nullptr); auto event = MessageEvent::create(*globalObject, message.message.releaseNonNull(), { }, { }, { }, WTFMove(ports)); + if (UNLIKELY(scope.exception())) { + // Currently, we assume that the only way we can get here is if we have a termination. + RELEASE_ASSERT(vm.hasPendingTerminationException()); + return; + } worker->dispatchEvent(event.event); }); }); @@ -223,6 +230,9 @@ void WorkerMessagingProxy::postMessageToWorkerGlobalScope(MessageWithMessagePort if (!globalObject) return; + auto& vm = globalObject->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + // Setting m_userGestureForwarder here, before dispatching the MessageEvent, will allow all calls to // worker.postMessage() made during the handling of that MessageEvent to inherit the UserGestureToken // held by the forwarder; see postMessageToWorkerObject() above. @@ -230,6 +240,11 @@ void WorkerMessagingProxy::postMessageToWorkerGlobalScope(MessageWithMessagePort auto ports = MessagePort::entanglePorts(scriptContext, WTFMove(message.transferredPorts)); auto event = MessageEvent::create(*globalObject, message.message.releaseNonNull(), { }, { }, std::nullopt, WTFMove(ports)); + if (UNLIKELY(scope.exception())) { + // Currently, we assume that the only way we can get here is if we have a termination. + RELEASE_ASSERT(vm.hasPendingTerminationException()); + return; + } context.dispatchEvent(event.event); // Because WorkerUserGestureForwarder is defined as DestructionThread::Main, releasing this Ref diff --git a/Source/WebCore/workers/WorkerRunLoop.cpp b/Source/WebCore/workers/WorkerRunLoop.cpp index a23b709c361e..9fd45aa24e74 100644 --- a/Source/WebCore/workers/WorkerRunLoop.cpp +++ b/Source/WebCore/workers/WorkerRunLoop.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2016-2021 Apple Inc. All rights reserved. + * Copyright (C) 2016-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -32,6 +32,8 @@ #include "config.h" #include "WorkerRunLoop.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObject.h" #include "ScriptExecutionContext.h" #include "SharedTimer.h" #include "ThreadGlobalData.h" @@ -40,6 +42,7 @@ #include "WorkerOrWorkletGlobalScope.h" #include "WorkerOrWorkletScriptController.h" #include "WorkerThread.h" +#include #include #if USE(GLIB) @@ -274,8 +277,21 @@ void WorkerRunLoop::postDebuggerTask(ScriptExecutionContext::Task&& task) void WorkerDedicatedRunLoop::Task::performTask(WorkerOrWorkletGlobalScope* context) { - if ((!context->isClosing() && context->script() && !context->script()->isTerminatingExecution()) || m_task.isCleanupTask()) + if (m_task.isCleanupTask()) m_task.performTask(*context); + else if (!context->isClosing() && context->script() && !context->script()->isTerminatingExecution()) { + JSC::VM& vm = context->script()->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + m_task.performTask(*context); + if (UNLIKELY(context->script() && scope.exception())) { + if (vm.hasPendingTerminationException()) { + context->script()->forbidExecution(); + return; + } + Locker locker(vm.apiLock()); + reportException(context->script()->globalScopeWrapper(), scope.exception()); + } + } } WorkerDedicatedRunLoop::Task::Task(ScriptExecutionContext::Task&& task, const String& mode) diff --git a/Source/WebCore/workers/service/ServiceWorkerContainer.cpp b/Source/WebCore/workers/service/ServiceWorkerContainer.cpp index bf7740066e6a..2aed68b853d8 100644 --- a/Source/WebCore/workers/service/ServiceWorkerContainer.cpp +++ b/Source/WebCore/workers/service/ServiceWorkerContainer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Apple Inc. All rights reserved. + * Copyright (C) 2017-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -443,6 +443,8 @@ void ServiceWorkerContainer::jobResolvedWithRegistration(ServiceWorkerJob& job, notifyRegistrationIsSettled(iterator->value); m_ongoingSettledRegistrations.remove(iterator); }); + if (UNLIKELY(promise->needsAbort())) + return; } promise->resolve>(WTFMove(registration)); @@ -452,13 +454,25 @@ void ServiceWorkerContainer::jobResolvedWithRegistration(ServiceWorkerJob& job, void ServiceWorkerContainer::postMessage(MessageWithMessagePorts&& message, ServiceWorkerData&& sourceData, String&& sourceOrigin) { auto& context = *scriptExecutionContext(); + if (UNLIKELY(context.isJSExecutionForbidden())) + return; + auto* globalObject = context.globalObject(); if (!globalObject) return; + auto& vm = globalObject->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + MessageEventSource source = RefPtr { ServiceWorker::getOrCreate(context, WTFMove(sourceData)) }; auto messageEvent = MessageEvent::create(*globalObject, message.message.releaseNonNull(), sourceOrigin, { }, WTFMove(source), MessagePort::entanglePorts(context, WTFMove(message.transferredPorts))); + if (UNLIKELY(scope.exception())) { + // Currently, we assume that the only way we can get here is if we have a termination. + RELEASE_ASSERT(vm.hasPendingTerminationException()); + return; + } + if (m_shouldDeferMessageEvents) m_deferredMessageEvents.append(WTFMove(messageEvent)); else {