From 5caab0148cac327fa969ba30736a286697363ef0 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sat, 24 Apr 2021 17:56:16 +0200 Subject: [PATCH] LibJS: Add TemporaryClearException helper class This is very similar to AK::TemporaryChange (and in fact replaces one use of it), but since we can't directly set VM's m_exception from outside of the VM, we need something more sophisticated. Sometimes we need to temporarily remove the stored exception for some other operation to succeed (e.g. anything that uses call(), as well as get_without_side_effects()) and later restore it - the boilerplate code required for this is annoying enough to justify a helper. --- .../LibJS/Runtime/TemporaryClearException.h | 34 +++++++++++++++++++ Userland/Libraries/LibJS/Runtime/VM.cpp | 4 +-- 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 Userland/Libraries/LibJS/Runtime/TemporaryClearException.h diff --git a/Userland/Libraries/LibJS/Runtime/TemporaryClearException.h b/Userland/Libraries/LibJS/Runtime/TemporaryClearException.h new file mode 100644 index 0000000000..a10d34afc6 --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/TemporaryClearException.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, Linus Groh + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace JS { + +class TemporaryClearException { +public: + explicit TemporaryClearException(VM& vm) + : m_vm(vm) + , m_previous_exception(vm.exception()) + { + m_vm.clear_exception(); + } + + ~TemporaryClearException() + { + if (m_previous_exception) + m_vm.set_exception(*m_previous_exception); + } + +private: + VM& m_vm; + Exception* m_previous_exception; +}; + +} diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index b7fc15c781..c1a38a6def 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -18,6 +17,7 @@ #include #include #include +#include #include namespace JS { @@ -376,7 +376,7 @@ void VM::run_queued_promise_jobs() dbgln_if(PROMISE_DEBUG, "Running queued promise jobs"); // Temporarily get rid of the exception, if any - job functions must be called // either way, and that can't happen if we already have an exception stored. - TemporaryChange change(m_exception, static_cast(nullptr)); + TemporaryClearException clear_exception(*this); while (!m_promise_jobs.is_empty()) { auto* job = m_promise_jobs.take_first(); dbgln_if(PROMISE_DEBUG, "Calling promise job function @ {}", job);