diff options
Diffstat (limited to 'gjs/context.cpp')
| -rw-r--r-- | gjs/context.cpp | 60 |
1 files changed, 22 insertions, 38 deletions
diff --git a/gjs/context.cpp b/gjs/context.cpp index d8992a58..d58de59e 100644 --- a/gjs/context.cpp +++ b/gjs/context.cpp @@ -81,6 +81,7 @@ #include "gjs/objectbox.h" #include "gjs/profiler-private.h" #include "gjs/profiler.h" +#include "gjs/promise.h" #include "gjs/text-encoding.h" #include "modules/modules.h" #include "util/log.h" @@ -320,9 +321,11 @@ gjs_context_class_init(GjsContextClass *klass) char *priv_typelib_dir = g_build_filename (PKGLIBDIR, "girepository-1.0", NULL); #endif g_irepository_prepend_search_path(priv_typelib_dir); - g_free (priv_typelib_dir); + g_free(priv_typelib_dir); } + gjs_register_native_module("_promiseNative", + gjs_define_native_promise_stuff); gjs_register_native_module("_byteArrayNative", gjs_define_byte_array_stuff); gjs_register_native_module("_encodingNative", gjs_define_text_encoding_stuff); @@ -404,6 +407,8 @@ void GjsContextPrivate::unregister_notifier(DestroyNotify notify_func, void GjsContextPrivate::dispose(void) { if (m_cx) { + stop_draining_job_queue(); + gjs_debug(GJS_DEBUG_CONTEXT, "Notifying reference holders of GjsContext dispose"); @@ -531,8 +536,8 @@ GjsContextPrivate::GjsContextPrivate(JSContext* cx, GjsContext* public_context) : m_public_context(public_context), m_cx(cx), m_owner_thread(std::this_thread::get_id()), + m_promise_queue_task(this), m_environment_preparer(cx) { - JS_SetGCCallback( cx, [](JSContext*, JSGCStatus status, JS::GCReason reason, void* data) { @@ -653,6 +658,8 @@ GjsContextPrivate::GjsContextPrivate(JSContext* cx, GjsContext* public_context) cx, "resource:///org/gnome/gjs/modules/esm/_bootstrap/default.js", "ESM bootstrap"); } + + start_draining_job_queue(); } void GjsContextPrivate::set_args(std::vector<std::string>&& args) { @@ -894,32 +901,15 @@ bool GjsContextPrivate::should_exit(uint8_t* exit_code_p) const { } void GjsContextPrivate::start_draining_job_queue(void) { - if (!m_idle_drain_handler) { - gjs_debug(GJS_DEBUG_CONTEXT, "Starting promise job queue handler"); - m_idle_drain_handler = g_idle_add_full( - G_PRIORITY_DEFAULT, drain_job_queue_idle_handler, this, nullptr); - } + gjs_debug(GJS_DEBUG_CONTEXT, "Starting promise job queue task"); + m_promise_queue_task.start(); } void GjsContextPrivate::stop_draining_job_queue(void) { m_draining_job_queue = false; - if (m_idle_drain_handler) { - gjs_debug(GJS_DEBUG_CONTEXT, "Stopping promise job queue handler"); - g_source_remove(m_idle_drain_handler); - m_idle_drain_handler = 0; - } -} -gboolean GjsContextPrivate::drain_job_queue_idle_handler(void* data) { - gjs_debug(GJS_DEBUG_CONTEXT, "Promise job queue handler"); - auto* gjs = static_cast<GjsContextPrivate*>(data); - gjs->runJobs(gjs->context()); - /* Uncatchable exceptions are swallowed here - no way to get a handle on - * the main loop to exit it from this idle handler */ - gjs_debug(GJS_DEBUG_CONTEXT, "Promise job queue handler finished"); - g_assert(gjs->empty() && gjs->m_idle_drain_handler == 0 && - "GjsContextPrivate::runJobs() should have emptied queue"); - return G_SOURCE_REMOVE; + gjs_debug(GJS_DEBUG_CONTEXT, "Stopping promise job queue task"); + m_promise_queue_task.stop(); } JSObject* GjsContextPrivate::getIncumbentGlobal(JSContext* cx) { @@ -942,18 +932,13 @@ bool GjsContextPrivate::enqueuePromiseJob(JSContext* cx [[maybe_unused]], gjs_debug_object(job).c_str(), gjs_debug_object(promise).c_str(), gjs_debug_object(allocation_site).c_str()); - if (m_idle_drain_handler) - g_assert(!empty()); - else - g_assert(empty()); - if (!m_job_queue.append(job)) { JS_ReportOutOfMemory(m_cx); return false; } JS::JobQueueMayNotBeEmpty(m_cx); - start_draining_job_queue(); + m_promise_queue_task.start(); return true; } @@ -1031,8 +1016,8 @@ bool GjsContextPrivate::run_jobs_fallible(void) { } } + m_draining_job_queue = false; m_job_queue.clear(); - stop_draining_job_queue(); JS::JobQueueIsEmpty(m_cx); return retval; } @@ -1041,14 +1026,12 @@ class GjsContextPrivate::SavedQueue : public JS::JobQueue::SavedJobQueue { private: GjsContextPrivate* m_gjs; JS::PersistentRooted<JobQueueStorage> m_queue; - bool m_idle_was_pending : 1; bool m_was_draining : 1; public: explicit SavedQueue(GjsContextPrivate* gjs) : m_gjs(gjs), m_queue(gjs->m_cx, std::move(gjs->m_job_queue)), - m_idle_was_pending(gjs->m_idle_drain_handler != 0), m_was_draining(gjs->m_draining_job_queue) { gjs_debug(GJS_DEBUG_CONTEXT, "Pausing job queue"); gjs->stop_draining_job_queue(); @@ -1058,8 +1041,7 @@ class GjsContextPrivate::SavedQueue : public JS::JobQueue::SavedJobQueue { gjs_debug(GJS_DEBUG_CONTEXT, "Unpausing job queue"); m_gjs->m_job_queue = std::move(m_queue.get()); m_gjs->m_draining_job_queue = m_was_draining; - if (m_idle_was_pending) - m_gjs->start_draining_job_queue(); + m_gjs->start_draining_job_queue(); } }; @@ -1285,13 +1267,17 @@ bool GjsContextPrivate::eval(const char* script, ssize_t script_len, } if (exit_status_p) { + uint8_t code; if (retval.isInt32()) { int code = retval.toInt32(); gjs_debug(GJS_DEBUG_CONTEXT, "Script returned integer code %d", code); *exit_status_p = code; + } else if (should_exit(&code)) { + *exit_status_p = code; } else { - /* Assume success if no integer was returned */ + /* Assume success if no integer was returned and should exit isn't + * set */ *exit_status_p = 0; } } @@ -1325,9 +1311,7 @@ bool GjsContextPrivate::eval_module(const char* identifier, return false; } - bool ok = true; - if (!JS::ModuleEvaluate(m_cx, obj)) - ok = false; + bool ok = JS::ModuleEvaluate(m_cx, obj); /* The promise job queue should be drained even on error, to finish * outstanding async tasks before the context is torn down. Drain after |
