diff options
author | Evan Welsh <contact@evanwelsh.com> | 2022-05-08 15:06:06 -0700 |
---|---|---|
committer | Evan Welsh <contact@evanwelsh.com> | 2022-05-08 15:06:06 -0700 |
commit | a06e890b8d06f019b49e5db29387df42547e8e6b (patch) | |
tree | 2d68c36342302a9bd4bfef535d5c00daf5f8da04 /gi/repo.cpp | |
parent | 6ab6db38fe5a45979167d2b6f0cadd06a772798f (diff) | |
download | gjs-ewlsh/replace-internal-imports.tar.gz |
modules: Use ESM as the primary module systemewlsh/replace-internal-imports
Diffstat (limited to 'gi/repo.cpp')
-rw-r--r-- | gi/repo.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/gi/repo.cpp b/gi/repo.cpp index 9f5d4e1f..6059b720 100644 --- a/gi/repo.cpp +++ b/gi/repo.cpp @@ -50,6 +50,8 @@ #include "util/log.h" GJS_JSAPI_RETURN_CONVENTION +static bool load_override_module(JSContext*, const char* ns_name); +GJS_JSAPI_RETURN_CONVENTION static bool lookup_override_function(JSContext *, JS::HandleId, JS::MutableHandleValue); @@ -128,6 +130,9 @@ static bool resolve_namespace_object(JSContext* context, GJS_MODULE_PROP_FLAGS)) return false; + if (!load_override_module(context, ns_name.get())) + return false; + JS::RootedValue override(context); if (!lookup_override_function(context, ns_id, &override)) return false; @@ -515,6 +520,125 @@ out: return retval; } +static bool add_promise_reactions(JSContext* cx, JS::HandleValue promise, + JSNative resolve, JSNative reject, + const std::string& debug_tag) { + g_assert(promise.isObject() && "got weird value from JS::ModuleEvaluate"); + JS::RootedObject promise_object(cx, &promise.toObject()); + + std::string resolved_tag = debug_tag + " async resolved"; + std::string rejected_tag = debug_tag + " async rejected"; + + JS::RootedFunction on_rejected( + cx, + js::NewFunctionWithReserved(cx, reject, 1, 0, resolved_tag.c_str())); + if (!on_rejected) + return false; + JS::RootedFunction on_resolved( + cx, + js::NewFunctionWithReserved(cx, resolve, 1, 0, rejected_tag.c_str())); + if (!on_resolved) + return false; + + JS::RootedObject resolved(cx, JS_GetFunctionObject(on_resolved)); + JS::RootedObject rejected(cx, JS_GetFunctionObject(on_rejected)); + + return JS::AddPromiseReactions(cx, promise_object, resolved, rejected); +} + +static bool on_context_module_resolved(JSContext* cx, unsigned argc, + JS::Value* vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + args.rval().setUndefined(); + + GjsContextPrivate::from_cx(cx)->main_loop_release(); + + return true; +} + +static bool load_override_module_(JSContext* cx, const char* uri, + const char* debug_identifier) { + JS::RootedObject loader(cx, gjs_module_load(cx, uri, uri, true)); + + if (!loader) { + return false; + } + + if (!JS::ModuleInstantiate(cx, loader)) { + gjs_log_exception(cx); + return false; + } + + JS::RootedValue evaluation_promise(cx); + if (!JS::ModuleEvaluate(cx, loader, &evaluation_promise)) { + gjs_log_exception(cx); + return false; + } + + GjsContextPrivate::from_cx(cx)->main_loop_hold(); + bool ok = add_promise_reactions( + cx, evaluation_promise, on_context_module_resolved, + [](JSContext* cx, unsigned argc, JS::Value* vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + JS::HandleValue error = args.get(0); + + GjsContextPrivate* gjs_cx = GjsContextPrivate::from_cx(cx); + gjs_cx->report_unhandled_exception(); + + gjs_log_exception_full(cx, error, nullptr, G_LOG_LEVEL_CRITICAL); + + gjs_cx->main_loop_release(); + + args.rval().setUndefined(); + + return false; + }, + "overrides"); + + if (!ok) { + gjs_log_exception(cx); + return false; + } + + return true; +} + +GJS_JSAPI_RETURN_CONVENTION +static bool load_override_module(JSContext* cx, const char* ns_name) { + JS::AutoSaveExceptionState saved_exc(cx); + + JS::RootedObject global(cx, gjs_get_import_global(cx)); + JS::RootedValue importer( + cx, gjs_get_global_slot(global, GjsGlobalSlot::IMPORTS)); + g_assert(importer.isObject()); + + JS::RootedObject overridespkg(cx), module(cx); + JS::RootedObject importer_obj(cx, &importer.toObject()); + const GjsAtoms& atoms = GjsContextPrivate::atoms(cx); + + GjsAutoChar uri = g_strdup_printf( + "resource:///org/gnome/gjs/modules/overrides/%s.js", ns_name); + if (!load_override_module_(cx, uri, ns_name)) { + JS::RootedValue exc(cx); + JS_GetPendingException(cx, &exc); + + /* If the exception was an ImportError (i.e., module not found) then + * we simply didn't have an override, don't throw an exception */ + if (error_has_name(cx, exc, + JS_AtomizeAndPinString(cx, "ImportError"))) { + saved_exc.restore(); + return true; + } + goto fail; + } + + return true; + +fail: + saved_exc.drop(); + return false; +} + GJS_JSAPI_RETURN_CONVENTION static bool lookup_override_function(JSContext *cx, |