summaryrefslogtreecommitdiff
path: root/gjs/context.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gjs/context.cpp')
-rw-r--r--gjs/context.cpp60
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