[gjs/ewlsh/workers-api: 1/4] modules: Use ESM as the primary module system




commit 1f7c067547dc213db96870427921fdc5c546d6b3
Author: Evan Welsh <contact evanwelsh com>
Date:   Fri Mar 11 20:57:46 2022 -0800

    modules: Use ESM as the primary module system

 .eslintrc.yml                                      |   5 +-
 gi/repo.cpp                                        | 127 +++++++++++++++++-
 gjs/importer.cpp                                   |   1 -
 gjs/module.cpp                                     |  89 +++++--------
 gjs/module.h                                       |   2 +-
 installed-tests/js/testGObject.js                  |   2 +-
 installed-tests/js/testImporter.js                 |  30 -----
 js.gresource.xml                                   |  38 +++---
 modules/{script => }/_bootstrap/.eslintrc.yml      |   0
 modules/{script => }/_bootstrap/coverage.js        |   0
 modules/{script => }/_bootstrap/debugger.js        |   0
 modules/{script => }/_bootstrap/default.js         |   0
 modules/_bootstrap/worker.js                       |   0
 modules/{core/_common.js => common/class.js}       |   6 +-
 modules/core/_cairo.js                             | 128 ------------------
 modules/core/_gettext.js                           |  83 ------------
 modules/{core => deprecated}/.eslintrc.yml         |   6 +-
 modules/{script => deprecated}/_legacy.js          |  68 +++++++++-
 modules/{core/_format.js => deprecated/format.js}  |  46 ++++++-
 modules/deprecated/imports.js                      |  38 ++++++
 .../{core/_signals.js => deprecated/signals.js}    |  12 +-
 modules/esm/_bootstrap/default.js                  |  13 ++
 modules/esm/_bootstrap/imports.js                  |   9 ++
 modules/esm/cairo.js                               | 145 ++++++++++++++++++++-
 modules/esm/gettext.js                             | 101 ++++++++++++--
 modules/internal/loader.js                         |  39 +++---
 modules/{core => }/overrides/.eslintrc.yml         |   7 +-
 modules/{core => }/overrides/GLib.js               |  96 +++++++-------
 modules/{core => }/overrides/GObject.js            |  41 +++---
 modules/{core => }/overrides/Gio.js                |  43 +++---
 modules/{core => }/overrides/Gtk.js                |  18 ++-
 modules/{core => }/overrides/cairo.js              |   7 +-
 modules/script/cairo.js                            |   3 -
 modules/script/format.js                           |  23 +---
 modules/script/gettext.js                          |  18 +--
 modules/script/lang.js                             |   2 -
 modules/script/overrides/__init__.js               |   1 +
 modules/script/signals.js                          |  19 +--
 38 files changed, 731 insertions(+), 535 deletions(-)
---
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 97e728f96..3da99101d 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -69,7 +69,10 @@ rules:
   jsdoc/check-types: error
   jsdoc/implements-on-classes: error
   jsdoc/newline-after-description: error
-  jsdoc/require-jsdoc: error
+  jsdoc/require-jsdoc:
+    - error
+    - publicOnly: true
+      enableFixer: false
   jsdoc/require-param: error
   jsdoc/require-param-description: error
   jsdoc/require-param-name: error
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 9f5d4e1f3..8bcc1ac14 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -49,6 +49,8 @@
 #include "gjs/module.h"
 #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,
@@ -592,7 +716,8 @@ JSObject* gjs_lookup_namespace_object_by_name(JSContext* cx,
                                               JS::HandleId ns_name) {
     JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
 
-    g_assert(gjs_global_get_type(global) == GjsGlobalType::DEFAULT);
+    g_assert(gjs_global_get_type(global) == GjsGlobalType::DEFAULT ||
+             gjs_global_get_type(global) == GjsGlobalType::WORKER);
     return lookup_namespace(cx, global, ns_name);
 }
 
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 273ab1bc2..7e4a1ac46 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -796,7 +796,6 @@ JSFunctionSpec gjs_importer_proto_funcs[] = {
         }
 
         gjs_search_path.push_back("resource:///org/gnome/gjs/modules/script/");
-        gjs_search_path.push_back("resource:///org/gnome/gjs/modules/core/");
 
         /* $XDG_DATA_DIRS /gjs-1.0 */
         system_data_dirs = g_get_system_data_dirs();
diff --git a/gjs/module.cpp b/gjs/module.cpp
index 115444830..dd57df6a3 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -4,7 +4,7 @@
 
 #include <config.h>
 
-#include <stddef.h>     // for size_t
+#include <stddef.h>  // for size_t
 #include <string.h>
 
 #include <string>  // for u16string
@@ -34,7 +34,7 @@
 #include <js/Utility.h>  // for UniqueChars
 #include <js/Value.h>
 #include <js/ValueArray.h>
-#include <jsapi.h>  // for JS_DefinePropertyById, ...
+#include <jsapi.h>        // for JS_DefinePropertyById, ...
 #include <jsfriendapi.h>  // for SetFunctionNativeReserved
 #include <mozilla/Maybe.h>
 
@@ -54,7 +54,7 @@ union Utf8Unit;
 }
 
 class GjsScriptModule {
-    char *m_name;
+    char* m_name;
 
     GjsScriptModule(const char* name) {
         m_name = g_strdup(name);
@@ -84,12 +84,8 @@ class GjsScriptModule {
 
     /* Defines the empty module as a property on the importer */
     GJS_JSAPI_RETURN_CONVENTION
-    bool
-    define_import(JSContext       *cx,
-                  JS::HandleObject module,
-                  JS::HandleObject importer,
-                  JS::HandleId     name) const
-    {
+    bool define_import(JSContext* cx, JS::HandleObject module,
+                       JS::HandleObject importer, JS::HandleId name) const {
         if (!JS_DefinePropertyById(cx, importer, name, module,
                                    GJS_MODULE_PROP_FLAGS & ~JSPROP_PERMANENT)) {
             gjs_debug(GJS_DEBUG_IMPORTER, "Failed to define '%s' in importer",
@@ -141,12 +137,8 @@ class GjsScriptModule {
 
     /* Loads JS code from a file and imports it */
     GJS_JSAPI_RETURN_CONVENTION
-    bool
-    import_file(JSContext       *cx,
-                JS::HandleObject module,
-                GFile           *file)
-    {
-        GError *error = nullptr;
+    bool import_file(JSContext* cx, JS::HandleObject module, GFile* file) {
+        GError* error = nullptr;
         GjsAutoChar script;
         size_t script_len = 0;
 
@@ -163,16 +155,12 @@ class GjsScriptModule {
     /* JSClass operations */
 
     GJS_JSAPI_RETURN_CONVENTION
-    bool
-    resolve_impl(JSContext       *cx,
-                 JS::HandleObject module,
-                 JS::HandleId     id,
-                 bool            *resolved)
-    {
+    bool resolve_impl(JSContext* cx, JS::HandleObject module, JS::HandleId id,
+                      bool* resolved) {
         JS::RootedObject lexical(cx, JS_ExtensibleLexicalEnvironment(module));
         if (!lexical) {
             *resolved = false;
-            return true;  /* nothing imported yet */
+            return true; /* nothing imported yet */
         }
 
         JS::Rooted<mozilla::Maybe<JS::PropertyDescriptor>> maybe_desc(cx);
@@ -187,26 +175,23 @@ class GjsScriptModule {
          * be supported according to ES6. For compatibility with earlier GJS,
          * we treat it as if it were a real property, but warn about it. */
 
-        g_warning("Some code accessed the property '%s' on the module '%s'. "
-                  "That property was defined with 'let' or 'const' inside the "
-                  "module. This was previously supported, but is not correct "
-                  "according to the ES6 standard. Any symbols to be exported "
-                  "from a module must be defined with 'var'. The property "
-                  "access will work as previously for the time being, but "
-                  "please fix your code anyway.",
-                  gjs_debug_id(id).c_str(), m_name);
+        g_warning(
+            "Some code accessed the property '%s' on the module '%s'. "
+            "That property was defined with 'let' or 'const' inside the "
+            "module. This was previously supported, but is not correct "
+            "according to the ES6 standard. Any symbols to be exported "
+            "from a module must be defined with 'var'. The property "
+            "access will work as previously for the time being, but "
+            "please fix your code anyway.",
+            gjs_debug_id(id).c_str(), m_name);
 
         JS::Rooted<JS::PropertyDescriptor> desc(cx, maybe_desc.value());
         return JS_DefinePropertyById(cx, module, id, desc);
     }
 
     GJS_JSAPI_RETURN_CONVENTION
-    static bool
-    resolve(JSContext       *cx,
-            JS::HandleObject module,
-            JS::HandleId     id,
-            bool            *resolved)
-    {
+    static bool resolve(JSContext* cx, JS::HandleObject module, JS::HandleId id,
+                        bool* resolved) {
         return priv(module)->resolve_impl(cx, module, id, resolved);
     }
 
@@ -248,16 +233,10 @@ class GjsScriptModule {
 
     /* Carries out the import operation */
     GJS_JSAPI_RETURN_CONVENTION
-    static JSObject *
-    import(JSContext       *cx,
-           JS::HandleObject importer,
-           JS::HandleId     id,
-           const char      *name,
-           GFile           *file)
-    {
+    static JSObject* import(JSContext* cx, JS::HandleObject importer,
+                            JS::HandleId id, const char* name, GFile* file) {
         JS::RootedObject module(cx, GjsScriptModule::create(cx, name));
-        if (!module ||
-            !priv(module)->define_import(cx, module, importer, id) ||
+        if (!module || !priv(module)->define_import(cx, module, importer, id) ||
             !priv(module)->import_file(cx, module, file))
             return nullptr;
 
@@ -296,13 +275,8 @@ JSObject* gjs_script_module_build_private(JSContext* cx, const char* uri) {
  *
  * Returns: the JS module object, or nullptr on failure.
  */
-JSObject *
-gjs_module_import(JSContext       *cx,
-                  JS::HandleObject importer,
-                  JS::HandleId     id,
-                  const char      *name,
-                  GFile           *file)
-{
+JSObject* gjs_module_import(JSContext* cx, JS::HandleObject importer,
+                            JS::HandleId id, const char* name, GFile* file) {
     return GjsScriptModule::import(cx, importer, id, name, file);
 }
 
@@ -357,9 +331,10 @@ JSObject* gjs_get_module_registry(JSObject* global) {
  * @returns whether an error occurred while resolving the specifier.
  */
 JSObject* gjs_module_load(JSContext* cx, const char* identifier,
-                          const char* file_uri) {
+                          const char* file_uri, bool internal) {
     g_assert((gjs_global_is_type(cx, GjsGlobalType::DEFAULT) ||
-              gjs_global_is_type(cx, GjsGlobalType::INTERNAL)) &&
+              gjs_global_is_type(cx, GjsGlobalType::INTERNAL) ||
+              gjs_global_is_type(cx, GjsGlobalType::WORKER)) &&
              "gjs_module_load can only be called from module-enabled "
              "globals.");
 
@@ -378,9 +353,10 @@ JSObject* gjs_module_load(JSContext* cx, const char* identifier,
     if (!uri)
         return nullptr;
 
-    JS::RootedValueArray<2> args(cx);
+    JS::RootedValueArray<3> args(cx);
     args[0].setString(id);
     args[1].setString(uri);
+    args[2].setBoolean(internal);
 
     gjs_debug(GJS_DEBUG_IMPORTER,
               "Module resolve hook for module '%s' (%s), global %p", identifier,
@@ -504,7 +480,8 @@ bool gjs_populate_module_meta(JSContext* cx, JS::HandleValue private_ref,
 JSObject* gjs_module_resolve(JSContext* cx, JS::HandleValue importingModulePriv,
                              JS::HandleObject module_request) {
     g_assert((gjs_global_is_type(cx, GjsGlobalType::DEFAULT) ||
-              gjs_global_is_type(cx, GjsGlobalType::INTERNAL)) &&
+              gjs_global_is_type(cx, GjsGlobalType::INTERNAL) ||
+              gjs_global_is_type(cx, GjsGlobalType::WORKER)) &&
              "gjs_module_resolve can only be called from module-enabled "
              "globals.");
     g_assert(importingModulePriv.isObject() &&
diff --git a/gjs/module.h b/gjs/module.h
index f6b3a353c..5e2d477d9 100644
--- a/gjs/module.h
+++ b/gjs/module.h
@@ -32,7 +32,7 @@ JSObject* gjs_get_module_registry(JSObject* global);
 
 GJS_JSAPI_RETURN_CONVENTION
 JSObject* gjs_module_load(JSContext* cx, const char* identifier,
-                          const char* uri);
+                          const char* uri, bool internal = false);
 
 GJS_JSAPI_RETURN_CONVENTION
 JSObject* gjs_module_resolve(JSContext* cx,
diff --git a/installed-tests/js/testGObject.js b/installed-tests/js/testGObject.js
index 160f85abd..d88487238 100644
--- a/installed-tests/js/testGObject.js
+++ b/installed-tests/js/testGObject.js
@@ -2,7 +2,7 @@
 // SPDX-FileCopyrightText: 2013 Giovanni Campagna <gcampagna src gnome org>
 // SPDX-FileCopyrightText: 2018 Red Hat, Inc.
 
-// This is where overrides in modules/core/overrides/GObject.js are tested,
+// This is where overrides in modules/overrides/GObject.js are tested,
 // except for the class machinery, interface machinery, and GObject.ParamSpec,
 // which are big enough to get their own files.
 
diff --git a/installed-tests/js/testImporter.js b/installed-tests/js/testImporter.js
index 8380af20c..c91bca95d 100644
--- a/installed-tests/js/testImporter.js
+++ b/installed-tests/js/testImporter.js
@@ -6,36 +6,6 @@ describe('GI importer', function () {
         var GLib = imports.gi.GLib;
         expect(GLib.MAJOR_VERSION).toEqual(2);
     });
-
-    describe('on failure', function () {
-        // For these tests, we provide special overrides files to sabotage the
-        // import, at the path resource:///org/gjs/jsunit/modules/badOverrides.
-        let oldSearchPath;
-        beforeAll(function () {
-            oldSearchPath = imports.overrides.searchPath.slice();
-            imports.overrides.searchPath = ['resource:///org/gjs/jsunit/modules/badOverrides'];
-        });
-
-        afterAll(function () {
-            imports.overrides.searchPath = oldSearchPath;
-        });
-
-        it("throws an exception when the overrides file can't be imported", function () {
-            expect(() => imports.gi.WarnLib).toThrowError(SyntaxError);
-        });
-
-        it('throws an exception when the overrides import throws one', function () {
-            expect(() => imports.gi.GIMarshallingTests).toThrow('💩');
-        });
-
-        it('throws an exception when the overrides _init throws one', function () {
-            expect(() => imports.gi.Regress).toThrow('💩');
-        });
-
-        it("throws an exception when the overrides _init isn't a function", function () {
-            expect(() => imports.gi.Gio).toThrowError(/_init/);
-        });
-    });
 });
 
 // Jasmine v3 often uses duck-typing (checking for a property to determine a type) to pretty print objects.
diff --git a/js.gresource.xml b/js.gresource.xml
index e12dea125..40db4cab5 100644
--- a/js.gresource.xml
+++ b/js.gresource.xml
@@ -3,10 +3,13 @@
 <!-- SPDX-FileCopyrightText: 2014 Red Hat, Inc. -->
 <gresources>
   <gresource prefix="/org/gnome/gjs">
+    <file>modules/common/class.js</file>
+
     <!-- Internal modules -->
     <file>modules/internal/loader.js</file>
 
     <!-- ESM-based modules -->
+    <file>modules/esm/_bootstrap/imports.js</file>
     <file>modules/esm/_bootstrap/default.js</file>
 
     <file>modules/esm/_encoding/encoding.js</file>
@@ -14,27 +17,29 @@
     <file>modules/esm/_encoding/util.js</file>
 
     <file>modules/esm/_timers.js</file>
+    <file>modules/esm/_workers.js</file>
 
     <file>modules/esm/cairo.js</file>
     <file>modules/esm/gettext.js</file>
     <file>modules/esm/console.js</file>
+    <file>modules/esm/events.js</file>
     <file>modules/esm/gi.js</file>
     <file>modules/esm/system.js</file>
 
     <!-- Script-based Modules -->
-    <file>modules/script/_bootstrap/debugger.js</file>
-    <file>modules/script/_bootstrap/default.js</file>
-    <file>modules/script/_bootstrap/coverage.js</file>
+    <file>modules/_bootstrap/debugger.js</file>
+    <file>modules/_bootstrap/default.js</file>
+    <file>modules/_bootstrap/worker.js</file>
+    <file>modules/_bootstrap/coverage.js</file>
 
     <file>modules/script/tweener/equations.js</file>
     <file>modules/script/tweener/tweener.js</file>
     <file>modules/script/tweener/tweenList.js</file>
-
+    <file>modules/script/overrides/__init__.js</file>
     <file>modules/script/byteArray.js</file>
     <file>modules/script/cairo.js</file>
     <file>modules/script/gettext.js</file>
     <file>modules/script/lang.js</file>
-    <file>modules/script/_legacy.js</file>
     <file>modules/script/mainloop.js</file>
     <file>modules/script/jsUnit.js</file>
     <file>modules/script/signals.js</file>
@@ -42,16 +47,15 @@
     <file>modules/script/package.js</file>
 
     <!-- Core Modules -->
-    <file>modules/core/overrides/cairo.js</file>
-    <file>modules/core/overrides/GLib.js</file>
-    <file>modules/core/overrides/Gio.js</file>
-    <file>modules/core/overrides/GObject.js</file>
-    <file>modules/core/overrides/Gtk.js</file>
-
-    <file>modules/core/_cairo.js</file>
-    <file>modules/core/_common.js</file>
-    <file>modules/core/_format.js</file>
-    <file>modules/core/_gettext.js</file>
-    <file>modules/core/_signals.js</file>
+    <file>modules/overrides/cairo.js</file>
+    <file>modules/overrides/GLib.js</file>
+    <file>modules/overrides/Gio.js</file>
+    <file>modules/overrides/GObject.js</file>
+    <file>modules/overrides/Gtk.js</file>
+
+    <file>modules/deprecated/imports.js</file>
+    <file>modules/deprecated/_legacy.js</file>
+    <file>modules/deprecated/format.js</file>
+    <file>modules/deprecated/signals.js</file>
   </gresource>
-</gresources>
+</gresources>
\ No newline at end of file
diff --git a/modules/script/_bootstrap/.eslintrc.yml b/modules/_bootstrap/.eslintrc.yml
similarity index 100%
rename from modules/script/_bootstrap/.eslintrc.yml
rename to modules/_bootstrap/.eslintrc.yml
diff --git a/modules/script/_bootstrap/coverage.js b/modules/_bootstrap/coverage.js
similarity index 100%
rename from modules/script/_bootstrap/coverage.js
rename to modules/_bootstrap/coverage.js
diff --git a/modules/script/_bootstrap/debugger.js b/modules/_bootstrap/debugger.js
similarity index 100%
rename from modules/script/_bootstrap/debugger.js
rename to modules/_bootstrap/debugger.js
diff --git a/modules/script/_bootstrap/default.js b/modules/_bootstrap/default.js
similarity index 100%
rename from modules/script/_bootstrap/default.js
rename to modules/_bootstrap/default.js
diff --git a/modules/_bootstrap/worker.js b/modules/_bootstrap/worker.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/modules/core/_common.js b/modules/common/class.js
similarity index 94%
rename from modules/core/_common.js
rename to modules/common/class.js
index 1a7fe7724..7b514c84d 100644
--- a/modules/core/_common.js
+++ b/modules/common/class.js
@@ -8,9 +8,9 @@
 // This is a helper module in which to put code that is common between the
 // legacy GObject.Class system and the new GObject.registerClass system.
 
-var _registerType = Symbol('GObject register type hook');
+export const _registerType = Symbol('GObject register type hook');
 
-function _generateAccessors(pspec, propdesc, GObject) {
+export function _generateAccessors(pspec, propdesc, GObject) {
     const {name, flags} = pspec;
     const readable = flags & GObject.ParamFlags.READABLE;
     const writable = flags & GObject.ParamFlags.WRITABLE;
@@ -59,7 +59,7 @@ function _generateAccessors(pspec, propdesc, GObject) {
     return propdesc;
 }
 
-function _checkAccessors(proto, pspec, GObject) {
+export function _checkAccessors(proto, pspec, GObject) {
     const {name, flags} = pspec;
     if (flags & GObject.ParamFlags.CONSTRUCT_ONLY)
         return;
diff --git a/modules/core/.eslintrc.yml b/modules/deprecated/.eslintrc.yml
similarity index 57%
rename from modules/core/.eslintrc.yml
rename to modules/deprecated/.eslintrc.yml
index 6c9c0253c..84e48aef0 100644
--- a/modules/core/.eslintrc.yml
+++ b/modules/deprecated/.eslintrc.yml
@@ -1,5 +1,7 @@
 ---
 # SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 # SPDX-FileCopyrightText: 2020 Evan Welsh <contact evanwelsh com>
-rules:
-  jsdoc/require-jsdoc: 'off'
+extends: '../../.eslintrc.yml'
+parserOptions:
+  sourceType: 'module'
+  ecmaVersion: 2022
diff --git a/modules/script/_legacy.js b/modules/deprecated/_legacy.js
similarity index 96%
rename from modules/script/_legacy.js
rename to modules/deprecated/_legacy.js
index 135d25177..429602128 100644
--- a/modules/script/_legacy.js
+++ b/modules/deprecated/_legacy.js
@@ -9,6 +9,14 @@ defineGtkLegacyObjects */
 // Adapted from MooTools
 // https://github.com/mootools/mootools-core
 
+import {_checkAccessors} from '../common/class.js';
+
+const Gi = import.meta.importSync('_gi');
+
+
+/**
+ *
+ */
 function _Base() {
     throw new TypeError('Cannot instantiate abstract class _Base');
 }
@@ -24,6 +32,9 @@ _Base.prototype.toString = function () {
     return `[object ${this.__name__}]`;
 };
 
+/**
+ * @param {...any} args
+ */
 function _parent(...args) {
     if (!this.__caller__)
         throw new TypeError("The method 'parent' cannot be called");
@@ -40,6 +51,10 @@ function _parent(...args) {
     return previous.apply(this, args);
 }
 
+/**
+ * @param required
+ * @param proto
+ */
 function _interfacePresent(required, proto) {
     if (!proto.__interfaces__)
         return false;
@@ -49,6 +64,9 @@ function _interfacePresent(required, proto) {
     return _interfacePresent(required, proto.constructor.__super__.prototype);
 }
 
+/**
+ * @param params
+ */
 function getMetaClass(params) {
     if (params.MetaClass)
         return params.MetaClass;
@@ -59,6 +77,10 @@ function getMetaClass(params) {
     return null;
 }
 
+/**
+ * @param params
+ * @param {...any} otherArgs
+ */
 function Class(params, ...otherArgs) {
     let metaClass = getMetaClass(params);
 
@@ -77,6 +99,9 @@ Class.prototype.wrapFunction = function (name, meth) {
     if (meth._origin)
         meth = meth._origin;
 
+    /**
+     * @param {...any} args
+     */
     function wrapper(...args) {
         let prevCaller = this.__caller__;
         this.__caller__ = wrapper;
@@ -106,6 +131,9 @@ Class.prototype._construct = function (params, ...otherArgs) {
     if (!parent)
         parent = _Base;
 
+    /**
+     * @param {...any} args
+     */
     function newClass(...args) {
         if (params.Abstract && new.target.name === name)
             throw new TypeError(`Cannot instantiate abstract class ${name}`);
@@ -237,6 +265,9 @@ Class.prototype._init = function (params) {
 // such as GObject.Class supply their own meta-interface.
 // This is in order to enable creating GObject interfaces with Lang.Interface,
 // much as you can create GObject classes with Lang.Class.
+/**
+ * @param params
+ */
 function _getMetaInterface(params) {
     if (!params.Requires || params.Requires.length === 0)
         return null;
@@ -274,6 +305,10 @@ function _getMetaInterface(params) {
     return metaInterface;
 }
 
+/**
+ * @param params
+ * @param {...any} otherArgs
+ */
 function Interface(params, ...otherArgs) {
     let metaInterface = _getMetaInterface(params);
     if (metaInterface && metaInterface !== this.constructor)
@@ -411,12 +446,16 @@ Interface.prototype._init = function (params) {
 
 // GObject Lang.Class magic
 
-function defineGObjectLegacyObjects(GObject) {
-    const Gi = imports._gi;
-    const {_checkAccessors} = imports._common;
-
+/**
+ * @param GObject
+ */
+export function defineGObjectLegacyObjects(GObject) {
     // Some common functions between GObject.Class and GObject.Interface
 
+    /**
+     * @param gtype
+     * @param signals
+     */
     function _createSignals(gtype, signals) {
         for (let signalName in signals) {
             let obj = signals[signalName];
@@ -433,6 +472,9 @@ function defineGObjectLegacyObjects(GObject) {
         }
     }
 
+    /**
+     * @param params
+     */
     function _createGTypeName(params) {
         if (params.GTypeName)
             return params.GTypeName;
@@ -440,10 +482,16 @@ function defineGObjectLegacyObjects(GObject) {
             return `Gjs_${params.Name.replace(/[^a-z0-9_+-]/gi, '_')}`;
     }
 
+    /**
+     * @param interfaces
+     */
     function _getGObjectInterfaces(interfaces) {
         return interfaces.filter(iface => iface.hasOwnProperty('$gtype'));
     }
 
+    /**
+     * @param params
+     */
     function _propertiesAsArray(params) {
         let propertiesArray = [];
         if (params.Properties) {
@@ -582,6 +630,9 @@ function defineGObjectLegacyObjects(GObject) {
         },
     });
 
+    /**
+     * @param {...any} args
+     */
     function GObjectInterface(...args) {
         return this._construct(...args);
     }
@@ -646,7 +697,11 @@ function defineGObjectLegacyObjects(GObject) {
     return {GObjectMeta, GObjectInterface};
 }
 
-function defineGtkLegacyObjects(GObject, Gtk) {
+/**
+ * @param GObject
+ * @param Gtk
+ */
+export function defineGtkLegacyObjects(GObject, Gtk) {
     const GtkWidgetClass = new Class({
         Name: 'GtkWidgetClass',
         Extends: GObject.Class,
@@ -715,3 +770,6 @@ function defineGtkLegacyObjects(GObject, Gtk) {
 
     return {GtkWidgetClass};
 }
+
+export {Class, Interface, getMetaClass};
+
diff --git a/modules/core/_format.js b/modules/deprecated/format.js
similarity index 71%
rename from modules/core/_format.js
rename to modules/deprecated/format.js
index eb6f03199..55e652af1 100644
--- a/modules/core/_format.js
+++ b/modules/deprecated/format.js
@@ -3,10 +3,12 @@
 // SPDX-FileCopyrightText: 2012 Red Hat, Inc.
 // SPDX-FileCopyrightText: 2012 Giovanni Campagna <scampa giovanni gmail com>
 
-/* exported vprintf */
-
-const GjsPrivate = imports.gi.GjsPrivate;
+import GjsPrivate from 'gi://GjsPrivate';
 
+/**
+ * @param string
+ * @param args
+ */
 function vprintf(string, args) {
     let i = 0;
     let usePos = false;
@@ -29,11 +31,19 @@ function vprintf(string, args) {
         let fillChar = widthGroup && widthGroup[0] === '0' ? '0' : ' ';
         let width = parseInt(widthGroup, 10) || 0;
 
+        /**
+         * @param s
+         * @param c
+         * @param w
+         */
         function fillWidth(s, c, w) {
             let fill = c.repeat(w);
             return fill.substr(s.length) + s;
         }
 
+        /**
+         *
+         */
         function getArg() {
             return usePos ? args[pos - 1] : args[i++];
         }
@@ -68,3 +78,33 @@ function vprintf(string, args) {
         return fillWidth(s, fillChar, width);
     });
 }
+
+/**
+ * @param fmt
+ * @param {...any} args
+ */
+function printf(fmt, ...args) {
+    print(vprintf(fmt, args));
+}
+
+/**
+ * This function is intended to extend the String object and provide a
+ * String.format API for string formatting.
+ * It has to be set up using String.prototype.format = Format.format;
+ * Usage:
+ * "somestring %s %d".format('hello', 5);
+ * It supports %s, %d, %x and %f.
+ * For %f it also supports precisions like "%.2f".format(1.526).
+ * All specifiers can be prefixed with a minimum field width, e.g.
+ * "%5s".format("foo").
+ * Unless the width is prefixed with '0', the formatted string will be padded
+ * with spaces.
+ *
+ * @this {string}
+ * @param {...any} args
+ */
+function format(...args) {
+    return vprintf(this, args);
+}
+
+export {vprintf, printf, format};
diff --git a/modules/deprecated/imports.js b/modules/deprecated/imports.js
new file mode 100644
index 000000000..02c026d20
--- /dev/null
+++ b/modules/deprecated/imports.js
@@ -0,0 +1,38 @@
+
+import {Class, Interface, getMetaClass} from './_legacy.js';
+import {
+    _connect,
+    _disconnect,
+    _emit,
+    _signalHandlerIsConnected,
+    _disconnectAll,
+    addSignalMethods
+} from './signals.js';
+import {format, vprintf, printf} from './format.js';
+
+if ('imports' in globalThis) {
+    // eslint-disable-next-line no-restricted-properties
+    Object.assign(imports.format, {format, vprintf, printf});
+    Object.assign(imports.lang, {Class, Interface, getMetaClass});
+    Object.assign(imports.signals, {
+        _connect,
+        _disconnect,
+        _emit,
+        _signalHandlerIsConnected,
+        _disconnectAll,
+        addSignalMethods,
+    });
+
+    const Lang = imports.lang;
+
+    const WithSignals = new Lang.Interface({
+        Name: 'WithSignals',
+        connect: _connect,
+        disconnect: _disconnect,
+        emit: _emit,
+        signalHandlerIsConnected: _signalHandlerIsConnected,
+        disconnectAll: _disconnectAll,
+    });
+
+    Object.assign(imports.signals, {WithSignals});
+}
diff --git a/modules/core/_signals.js b/modules/deprecated/signals.js
similarity index 95%
rename from modules/core/_signals.js
rename to modules/deprecated/signals.js
index 25dcfd475..7a9941fe5 100644
--- a/modules/core/_signals.js
+++ b/modules/deprecated/signals.js
@@ -1,8 +1,6 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2008 litl, LLC
 
-/* exported addSignalMethods */
-
 // A couple principals of this simple signal system:
 // 1) should look just like our GObject signal binding
 // 2) memory and safety matter more than speed of connect/disconnect/emit
@@ -58,6 +56,9 @@ function _disconnect(id) {
     throw new Error(`No signal connection ${id} found`);
 }
 
+/**
+ * @param id
+ */
 function _signalHandlerIsConnected(id) {
     if (!('_signalConnections' in this))
         return false;
@@ -141,3 +142,10 @@ function addSignalMethods(proto) {
     // this one is not in GObject, but useful
     _addSignalMethod(proto, 'disconnectAll', _disconnectAll);
 }
+
+export {
+    // Private API, remains exported for backwards compatibility reasons
+    _connect, _disconnect, _emit, _signalHandlerIsConnected, _disconnectAll,
+    // Public API
+    addSignalMethods
+};
diff --git a/modules/esm/_bootstrap/default.js b/modules/esm/_bootstrap/default.js
index ff1f28bfc..e0f54e1cb 100644
--- a/modules/esm/_bootstrap/default.js
+++ b/modules/esm/_bootstrap/default.js
@@ -9,3 +9,16 @@ import '_encoding/encoding';
 import 'console';
 // Bootstrap the Timers API
 import '_timers';
+// Bootstrap the Workers API
+import '_workers';
+
+// Import remaining modules
+import 'gettext';
+
+// Bootstrap the gi module
+import 'gi';
+
+
+
+// globalThis.imports compatibility
+import './imports.js';
diff --git a/modules/esm/_bootstrap/imports.js b/modules/esm/_bootstrap/imports.js
new file mode 100644
index 000000000..d98d2d64d
--- /dev/null
+++ b/modules/esm/_bootstrap/imports.js
@@ -0,0 +1,9 @@
+import gettext from 'gettext';
+import cairo from 'cairo';
+
+import '../../deprecated/imports.js';
+
+if ('imports' in globalThis) {
+    Object.assign(imports.gettext, gettext);
+    Object.assign(imports.cairo, cairo);
+}
diff --git a/modules/esm/cairo.js b/modules/esm/cairo.js
index d6127ff12..1dc013efb 100644
--- a/modules/esm/cairo.js
+++ b/modules/esm/cairo.js
@@ -1,10 +1,145 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+// SPDX-FileCopyrightText: 2010 litl, LLC.
 // SPDX-FileCopyrightText: 2020 Evan Welsh <contact evanwelsh com>
 
+const Antialias = {
+    DEFAULT: 0,
+    NONE: 1,
+    GRAY: 2,
+    SUBPIXEL: 3,
+};
+
+const Content = {
+    COLOR: 0x1000,
+    ALPHA: 0x2000,
+    COLOR_ALPHA: 0x3000,
+};
+
+const Extend = {
+    NONE: 0,
+    REPEAT: 1,
+    REFLECT: 2,
+    PAD: 3,
+};
+
+const FillRule = {
+    WINDING: 0,
+    EVEN_ODD: 1,
+};
+
+const Filter = {
+    FAST: 0,
+    GOOD: 1,
+    BEST: 2,
+    NEAREST: 3,
+    BILINEAR: 4,
+    GAUSSIAN: 5,
+};
+
+const FontSlant = {
+    NORMAL: 0,
+    ITALIC: 1,
+    OBLIQUE: 2,
+};
+
+const FontWeight = {
+    NORMAL: 0,
+    BOLD: 1,
+};
+
+const Format = {
+    ARGB32: 0,
+    RGB24: 1,
+    A8: 2,
+    A1: 3,
+    // The value of 4 is reserved by a deprecated enum value
+    RGB16_565: 5,
+};
+
+const LineCap = {
+    BUTT: 0,
+    ROUND: 1,
+    SQUASH: 2,
+};
+
+const LineJoin = {
+    MITER: 0,
+    ROUND: 1,
+    BEVEL: 2,
+};
+
+const Operator = {
+    CLEAR: 0,
+    SOURCE: 1,
+    OVER: 2,
+    IN: 3,
+    OUT: 4,
+    ATOP: 5,
+    DEST: 6,
+    DEST_OVER: 7,
+    DEST_IN: 8,
+    DEST_OUT: 9,
+    DEST_ATOP: 10,
+    XOR: 11,
+    ADD: 12,
+    SATURATE: 13,
+    MULTIPLY: 14,
+    SCREEN: 15,
+    OVERLAY: 16,
+    DARKEN: 17,
+    LIGHTEN: 18,
+    COLOR_DODGE: 19,
+    COLOR_BURN: 20,
+    HARD_LIGHT: 21,
+    SOFT_LIGHT: 22,
+    DIFFERENCE: 23,
+    EXCLUSION: 24,
+    HSL_HUE: 25,
+    HSL_SATURATION: 26,
+    HSL_COLOR: 27,
+    HSL_LUMINOSITY: 28,
+};
+
+const PatternType = {
+    SOLID: 0,
+    SURFACE: 1,
+    LINEAR: 2,
+    RADIAL: 3,
+};
+
+const SurfaceType = {
+    IMAGE: 0,
+    PDF: 1,
+    PS: 2,
+    XLIB: 3,
+    XCB: 4,
+    GLITZ: 5,
+    QUARTZ: 6,
+    WIN32: 7,
+    BEOS: 8,
+    DIRECTFB: 9,
+    SVG: 10,
+    OS2: 11,
+    WIN32_PRINTING: 12,
+    QUARTZ_IMAGE: 13,
+};
+
 const cairo = import.meta.importSync('cairoNative');
 
-export default Object.assign(
-    {},
-    imports._cairo,
-    cairo
-);
+const exports = Object.assign({}, {
+    Antialias,
+    Content,
+    Extend,
+    FillRule,
+    Filter,
+    FontSlant,
+    FontWeight,
+    Format,
+    LineCap,
+    LineJoin,
+    Operator,
+    PatternType,
+    SurfaceType,
+}, cairo);
+
+export default exports;
diff --git a/modules/esm/gettext.js b/modules/esm/gettext.js
index bcef3863c..5c303a0ca 100644
--- a/modules/esm/gettext.js
+++ b/modules/esm/gettext.js
@@ -1,20 +1,93 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+// SPDX-FileCopyrightText: 2009 Red Hat, Inc.
 // SPDX-FileCopyrightText: 2020 Evan Welsh <contact evanwelsh com>
 
-export let {
-    LocaleCategory,
-    setlocale,
-    textdomain,
-    bindtextdomain,
-    gettext,
-    dgettext,
-    dcgettext,
-    ngettext,
-    dngettext,
-    pgettext,
-    dpgettext,
-    domain,
-} = imports._gettext;
+/* exported bindtextdomain, dcgettext, dgettext, dngettext, domain, dpgettext,
+gettext, LocaleCategory, ngettext, pgettext, setlocale, textdomain */
+
+/**
+ * This module provides a convenience layer for the "gettext" family of functions,
+ * relying on GLib for the actual implementation.
+ *
+ * Usage:
+ *
+ * const Gettext = imports.gettext;
+ *
+ * Gettext.textdomain("myapp");
+ * Gettext.bindtextdomain("myapp", "/usr/share/locale");
+ *
+ * let translated = Gettext.gettext("Hello world!");
+ */
+
+import GLib from 'gi://GLib';
+import GjsPrivate from 'gi://GjsPrivate';
+
+export let LocaleCategory = GjsPrivate.LocaleCategory;
+
+export function setlocale(category, locale) {
+    return GjsPrivate.setlocale(category, locale);
+}
+
+export function textdomain(dom) {
+    return GjsPrivate.textdomain(dom);
+}
+
+export function bindtextdomain(dom, location) {
+    return GjsPrivate.bindtextdomain(dom, location);
+}
+
+export function gettext(msgid) {
+    return GLib.dgettext(null, msgid);
+}
+
+export function dgettext(dom, msgid) {
+    return GLib.dgettext(dom, msgid);
+}
+
+export function dcgettext(dom, msgid, category) {
+    return GLib.dcgettext(dom, msgid, category);
+}
+
+export function ngettext(msgid1, msgid2, n) {
+    return GLib.dngettext(null, msgid1, msgid2, n);
+}
+
+export function dngettext(dom, msgid1, msgid2, n) {
+    return GLib.dngettext(dom, msgid1, msgid2, n);
+}
+
+// FIXME: missing dcngettext ?
+
+export function pgettext(context, msgid) {
+    return GLib.dpgettext2(null, context, msgid);
+}
+
+export function dpgettext(dom, context, msgid) {
+    return GLib.dpgettext2(dom, context, msgid);
+}
+
+/**
+ * Create an object with bindings for gettext, ngettext,
+ * and pgettext bound to a particular translation domain.
+ *
+ * @param {string} domainName Translation domain string
+ * @returns {object} an object with gettext bindings
+ */
+export function domain(domainName) {
+    return {
+        gettext(msgid) {
+            return GLib.dgettext(domainName, msgid);
+        },
+
+        ngettext(msgid1, msgid2, n) {
+            return GLib.dngettext(domainName, msgid1, msgid2, n);
+        },
+
+        pgettext(context, msgid) {
+            return GLib.dpgettext2(domainName, context, msgid);
+        },
+    };
+}
 
 export default {
     LocaleCategory,
diff --git a/modules/internal/loader.js b/modules/internal/loader.js
index 2f3f71d8e..0ce9d0534 100644
--- a/modules/internal/loader.js
+++ b/modules/internal/loader.js
@@ -13,6 +13,7 @@
 /** @typedef {{ load(uri: Uri): [contents: string, internal: boolean]; }} SchemeHandler */
 /** @typedef {{ [key: string]: string | undefined; }} Query */
 /** @typedef {(uri: string, contents: string) => Module} CompileFunc */
+const {print, logError} = loadNative('_print');
 
 /**
  * Thrown when there is an error importing a module.
@@ -154,12 +155,13 @@ class InternalModuleLoader {
 
     /**
      * @param {string} specifier the specifier (e.g. relative path, root package) to resolve
-     * @param {string | null} importingModuleURI the URI of the module
-     *   triggering this resolve
+     * @param {ModulePrivate} importingModulePriv the private object of the module initiating
+     *     the import triggering this resolve
      *
      * @returns {Module | null}
      */
-    resolveModule(specifier, importingModuleURI) {
+    resolveModule(specifier, importingModulePriv) {
+        const importingModuleURI = importingModulePriv.uri;
         const registry = getRegistry(this.global);
 
         // Check if the module has already been loaded
@@ -180,9 +182,14 @@ class InternalModuleLoader {
             if (!result)
                 return null;
 
-            const [text, internal = false] = result;
-
-            const priv = new ModulePrivate(uri.uri, uri.uri, internal);
+            const [text, internal] = result;
+            // print('>>');
+            // print(specifier);
+            // print(importingModulePriv.uri);
+            // print(importingModulePriv.internal);
+            // print(internal);
+            // print('<<');
+            const priv = new ModulePrivate(uri.uri, uri.uri, internal ?? importingModulePriv.internal);
             const compiled = this.compileModule(priv, text);
 
             registry.set(uri.uri, compiled);
@@ -193,15 +200,15 @@ class InternalModuleLoader {
     }
 
     moduleResolveHook(importingModulePriv, specifier) {
-        const resolved = this.resolveModule(specifier, importingModulePriv.uri ?? null);
+        const resolved = this.resolveModule(specifier, importingModulePriv ?? null);
         if (!resolved)
             throw new ImportError(`Module not found: ${specifier}`);
 
         return resolved;
     }
 
-    moduleLoadHook(id, uri) {
-        const priv = new ModulePrivate(id, uri);
+    moduleLoadHook(id, uri, internal) {
+        const priv = new ModulePrivate(id, uri, internal);
 
         const result = this.loadURI(parseURI(uri));
         // result can only be null if `this` is InternalModuleLoader. If `this`
@@ -335,7 +342,7 @@ class ModuleLoader extends InternalModuleLoader {
      * @returns {import("./internalLoader").Module}
      */
     moduleResolveHook(importingModulePriv, specifier) {
-        const module = this.resolveModule(specifier, importingModulePriv.uri);
+        const module = this.resolveModule(specifier, importingModulePriv);
         if (module)
             return module;
 
@@ -348,18 +355,20 @@ class ModuleLoader extends InternalModuleLoader {
         if (!importingModulePriv || !importingModulePriv.uri)
             throw new ImportError('Cannot resolve relative imports from an unknown file.');
 
-        return this.resolveModuleAsync(specifier, importingModulePriv.uri);
+        return this.resolveModuleAsync(specifier, importingModulePriv);
     }
 
     /**
      * Resolves a module import with optional handling for relative imports asynchronously.
      *
      * @param {string} specifier the specifier (e.g. relative path, root package) to resolve
-     * @param {string | null} importingModuleURI the URI of the module
+     * @param {ModulePrivate} importingModulePriv the private object of the module initiating
+     *     the import triggering this resolve
      *   triggering this resolve
      * @returns {import("../types").Module}
      */
-    async resolveModuleAsync(specifier, importingModuleURI) {
+    async resolveModuleAsync(specifier, importingModulePriv) {
+        const importingModuleURI = importingModulePriv.uri;
         const registry = getRegistry(this.global);
 
         // Check if the module has already been loaded
@@ -385,9 +394,9 @@ class ModuleLoader extends InternalModuleLoader {
             if (module)
                 return module;
 
-            const [text, internal = false] = result;
+            const [text, internal] = result;
 
-            const priv = new ModulePrivate(uri.uri, uri.uri, internal);
+            const priv = new ModulePrivate(uri.uri, uri.uri, internal ?? importingModulePriv.internal);
             const compiled = this.compileModule(priv, text);
 
             registry.set(uri.uri, compiled);
diff --git a/modules/core/overrides/.eslintrc.yml b/modules/overrides/.eslintrc.yml
similarity index 63%
rename from modules/core/overrides/.eslintrc.yml
rename to modules/overrides/.eslintrc.yml
index 8a5f8fd93..bd5a206c8 100644
--- a/modules/core/overrides/.eslintrc.yml
+++ b/modules/overrides/.eslintrc.yml
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 # SPDX-FileCopyrightText: 2018 Philip Chimento <philip chimento gmail com>
 rules:
-  no-unused-vars:
-    - error
-    - varsIgnorePattern: ^_init$
+  require-jsdoc: "off"
+parserOptions:
+  sourceType: 'module'
+  ecmaVersion: 2022
\ No newline at end of file
diff --git a/modules/core/overrides/GLib.js b/modules/overrides/GLib.js
similarity index 87%
rename from modules/core/overrides/GLib.js
rename to modules/overrides/GLib.js
index cb8f177e7..da9677879 100644
--- a/modules/core/overrides/GLib.js
+++ b/modules/overrides/GLib.js
@@ -1,9 +1,8 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2011 Giovanni Campagna
 
-const ByteArray = imports.byteArray;
-
-let GLib;
+const gi = import.meta.importSync('gi');
+const {GLib} = gi;
 
 const SIMPLE_TYPES = ['b', 'y', 'n', 'q', 'i', 'u', 'x', 't', 'h', 'd', 's', 'o', 'g'];
 
@@ -101,10 +100,11 @@ function _packVariant(signature, value) {
             // special case for array of bytes
             let bytes;
             if (typeof value === 'string') {
-                let byteArray = ByteArray.fromString(value);
+                let encoder = new TextEncoder();
+                let byteArray = encoder.encode(value);
                 if (byteArray[byteArray.length - 1] !== 0)
                     byteArray = Uint8Array.of(...byteArray, 0);
-                bytes = ByteArray.toGBytes(byteArray);
+                bytes = new GLib.Bytes(byteArray);
             } else {
                 bytes = new GLib.Bytes(value);
             }
@@ -202,7 +202,7 @@ function _unpackVariant(variant, deep, recursive = false) {
     case 'a':
         if (variant.is_of_type(new GLib.VariantType('a{?*}'))) {
             // special case containers
-            let ret = { };
+            let ret = {};
             let nElements = variant.n_children();
             for (let i = 0; i < nElements; i++) {
                 // always unpack the dictionary entry, and always unpack
@@ -246,6 +246,10 @@ function _notIntrospectableError(funcName, replacement) {
     return new Error(`${funcName} is not introspectable. Use ${replacement} instead.`);
 }
 
+/**
+ * @param funcName
+ * @param replacement
+ */
 function _warnNotIntrospectable(funcName, replacement) {
     logError(_notIntrospectableError(funcName, replacement));
 }
@@ -256,16 +260,12 @@ function _escapeCharacterSetChars(char) {
     return char;
 }
 
-function _init() {
-    // this is imports.gi.GLib
-
-    GLib = this;
-
+(function () {
     // For convenience in property min or max values, since GLib.MAXINT64 and
     // friends will log a warning when used
-    this.MAXINT64_BIGINT = 0x7fff_ffff_ffff_ffffn;
-    this.MININT64_BIGINT = -this.MAXINT64_BIGINT - 1n;
-    this.MAXUINT64_BIGINT = 0xffff_ffff_ffff_ffffn;
+    GLib.MAXINT64_BIGINT = 0x7fff_ffff_ffff_ffffn;
+    GLib.MININT64_BIGINT = -GLib.MAXINT64_BIGINT - 1n;
+    GLib.MAXUINT64_BIGINT = 0xffff_ffff_ffff_ffffn;
 
     // small HACK: we add a matches() method to standard Errors so that
     // you can do "if (e.matches(Ns.FooError, Ns.FooError.SOME_CODE))"
@@ -276,15 +276,15 @@ function _init() {
 
     // Guard against domains that aren't valid quarks and would lead
     // to a crash
-    const quarkToString = this.quark_to_string;
-    const realNewLiteral = this.Error.new_literal;
-    this.Error.new_literal = function (domain, code, message) {
+    const quarkToString = GLib.quark_to_string;
+    const realNewLiteral = GLib.Error.new_literal;
+    GLib.Error.new_literal = function (domain, code, message) {
         if (quarkToString(domain) === null)
             throw new TypeError(`Error.new_literal: ${domain} is not a valid domain`);
         return realNewLiteral(domain, code, message);
     };
 
-    this.Variant._new_internal = function (sig, value) {
+    GLib.Variant._new_internal = function (sig, value) {
         let signature = Array.prototype.slice.call(sig);
 
         let variant = _packVariant(signature, value);
@@ -295,32 +295,32 @@ function _init() {
     };
 
     // Deprecate version of new GLib.Variant()
-    this.Variant.new = function (sig, value) {
+    GLib.Variant.new = function (sig, value) {
         return new GLib.Variant(sig, value);
     };
-    this.Variant.prototype.unpack = function () {
+    GLib.Variant.prototype.unpack = function () {
         return _unpackVariant(this, false);
     };
-    this.Variant.prototype.deepUnpack = function () {
+    GLib.Variant.prototype.deepUnpack = function () {
         return _unpackVariant(this, true);
     };
     // backwards compatibility alias
-    this.Variant.prototype.deep_unpack = this.Variant.prototype.deepUnpack;
+    GLib.Variant.prototype.deep_unpack = GLib.Variant.prototype.deepUnpack;
 
     // Note: discards type information, if the variant contains any 'v' types
-    this.Variant.prototype.recursiveUnpack = function () {
+    GLib.Variant.prototype.recursiveUnpack = function () {
         return _unpackVariant(this, true, true);
     };
 
-    this.Variant.prototype.toString = function () {
-        return `[object variant of type "${this.get_type_string()}"]`;
+    GLib.Variant.prototype.toString = function () {
+        return `[object variant of type "${GLib.get_type_string()}"]`;
     };
 
-    this.Bytes.prototype.toArray = function () {
+    GLib.Bytes.prototype.toArray = function () {
         return imports._byteArrayNative.fromGBytes(this);
     };
 
-    this.log_structured =
+    GLib.log_structured =
     /**
      * @param {string} logDomain
      * @param {GLib.LogLevelFlags} logLevel
@@ -356,19 +356,19 @@ function _init() {
     // GjsPrivate depends on GLib so we cannot import it
     // before GLib is fully resolved.
 
-    this.log_set_writer_func_variant = function (...args) {
-        const {log_set_writer_func} = imports.gi.GjsPrivate;
+    GLib.log_set_writer_func_variant = function (...args) {
+        const {log_set_writer_func} = gi.GjsPrivate;
 
         log_set_writer_func(...args);
     };
 
-    this.log_set_writer_default = function (...args) {
-        const {log_set_writer_default} = imports.gi.GjsPrivate;
+    GLib.log_set_writer_default = function (...args) {
+        const {log_set_writer_default} = gi.GjsPrivate;
 
         log_set_writer_default(...args);
     };
 
-    this.log_set_writer_func = function (writer_func) {
+    GLib.log_set_writer_func = function (writer_func) {
         const {log_set_writer_func} = imports.gi.GjsPrivate;
 
         if (typeof writer_func !== 'function') {
@@ -381,7 +381,7 @@ function _init() {
         }
     };
 
-    this.VariantDict.prototype.lookup = function (key, variantType = null, deep = false) {
+    GLib.VariantDict.prototype.lookup = function (key, variantType = null, deep = false) {
         if (typeof variantType === 'string')
             variantType = new GLib.VariantType(variantType);
 
@@ -401,11 +401,11 @@ function _init() {
     // is useless anyway and GLib.ascii_formatd() which is too complicated to
     // implement here.
 
-    this.stpcpy = function () {
+    GLib.stpcpy = function () {
         throw _notIntrospectableError('GLib.stpcpy()', 'the + operator');
     };
 
-    this.strstr_len = function (haystack, len, needle) {
+    GLib.strstr_len = function (haystack, len, needle) {
         _warnNotIntrospectable('GLib.strstr_len()', 'String.indexOf()');
         let searchString = haystack;
         if (len !== -1)
@@ -416,7 +416,7 @@ function _init() {
         return haystack.slice(index);
     };
 
-    this.strrstr = function (haystack, needle) {
+    GLib.strrstr = function (haystack, needle) {
         _warnNotIntrospectable('GLib.strrstr()', 'String.lastIndexOf()');
         const index = haystack.lastIndexOf(needle);
         if (index === -1)
@@ -424,7 +424,7 @@ function _init() {
         return haystack.slice(index);
     };
 
-    this.strrstr_len = function (haystack, len, needle) {
+    GLib.strrstr_len = function (haystack, len, needle) {
         _warnNotIntrospectable('GLib.strrstr_len()', 'String.lastIndexOf()');
         let searchString = haystack;
         if (len !== -1)
@@ -435,52 +435,52 @@ function _init() {
         return haystack.slice(index);
     };
 
-    this.strup = function (string) {
+    GLib.strup = function (string) {
         _warnNotIntrospectable('GLib.strup()',
             'String.toUpperCase() or GLib.ascii_strup()');
         return string.toUpperCase();
     };
 
-    this.strdown = function (string) {
+    GLib.strdown = function (string) {
         _warnNotIntrospectable('GLib.strdown()',
             'String.toLowerCase() or GLib.ascii_strdown()');
         return string.toLowerCase();
     };
 
-    this.strreverse = function (string) {
+    GLib.strreverse = function (string) {
         _warnNotIntrospectable('GLib.strreverse()',
             'Array.reverse() and String.join()');
         return [...string].reverse().join('');
     };
 
-    this.ascii_dtostr = function (unused, len, number) {
+    GLib.ascii_dtostr = function (unused, len, number) {
         _warnNotIntrospectable('GLib.ascii_dtostr()', 'JS string conversion');
         return `${number}`.slice(0, len);
     };
 
-    this.ascii_formatd = function () {
+    GLib.ascii_formatd = function () {
         throw _notIntrospectableError('GLib.ascii_formatd()',
             'Number.toExponential() and string interpolation');
     };
 
-    this.strchug = function (string) {
+    GLib.strchug = function (string) {
         _warnNotIntrospectable('GLib.strchug()', 'String.trimStart()');
         return string.trimStart();
     };
 
-    this.strchomp = function (string) {
+    GLib.strchomp = function (string) {
         _warnNotIntrospectable('GLib.strchomp()', 'String.trimEnd()');
         return string.trimEnd();
     };
 
     // g_strstrip() is a macro and therefore doesn't even appear in the GIR
     // file, but we may as well include it here since it's trivial
-    this.strstrip = function (string) {
+    GLib.strstrip = function (string) {
         _warnNotIntrospectable('GLib.strstrip()', 'String.trim()');
         return string.trim();
     };
 
-    this.strdelimit = function (string, delimiters, newDelimiter) {
+    GLib.strdelimit = function (string, delimiters, newDelimiter) {
         _warnNotIntrospectable('GLib.strdelimit()', 'String.replace()');
 
         if (delimiters === null)
@@ -494,7 +494,7 @@ function _init() {
         return string.replace(delimiterRegex, newDelimiter);
     };
 
-    this.strcanon = function (string, validChars, substitutor) {
+    GLib.strcanon = function (string, validChars, substitutor) {
         _warnNotIntrospectable('GLib.strcanon()', 'String.replace()');
 
         if (typeof substitutor === 'number')
@@ -505,4 +505,4 @@ function _init() {
         const invalidRegex = new RegExp(`[^${escapedValidArray.join('')}]`, 'g');
         return string.replace(invalidRegex, substitutor);
     };
-}
+})();
diff --git a/modules/core/overrides/GObject.js b/modules/overrides/GObject.js
similarity index 98%
rename from modules/core/overrides/GObject.js
rename to modules/overrides/GObject.js
index 8ed662f1f..abe604bb3 100644
--- a/modules/core/overrides/GObject.js
+++ b/modules/overrides/GObject.js
@@ -3,12 +3,11 @@
 // SPDX-FileCopyrightText: 2011 Jasper St. Pierre
 // SPDX-FileCopyrightText: 2017 Philip Chimento <philip chimento gmail com>, <philip endlessm com>
 
-const Gi = imports._gi;
-const {GjsPrivate, GLib} = imports.gi;
-const {_checkAccessors, _registerType} = imports._common;
-const Legacy = imports._legacy;
+import * as Legacy from '../deprecated/_legacy.js';
+import {_checkAccessors, _registerType} from '../common/class.js';
 
-let GObject;
+const Gi = import.meta.importSync('_gi');
+const {GjsPrivate, GLib, GObject} = import.meta.importSync('gi');
 
 var GTypeName = Symbol('GType name');
 var GTypeFlags = Symbol('GType flags');
@@ -23,6 +22,9 @@ var _gtkCssName = Symbol('GTK widget CSS name');
 var _gtkInternalChildren = Symbol('GTK widget template internal children');
 var _gtkTemplate = Symbol('GTK widget template');
 
+/**
+ * @param {...any} args
+ */
 function registerClass(...args) {
     let klass = args[0];
     if (args.length === 2) {
@@ -80,6 +82,7 @@ function registerClass(...args) {
     return klass;
 }
 
+
 function _resolveLegacyClassFunction(klass, func) {
     // Find the "least derived" class with a _classInit static function; there
     // definitely is one, since this class must inherit from GObject
@@ -89,6 +92,7 @@ function _resolveLegacyClassFunction(klass, func) {
     return initclass[func];
 }
 
+
 function _defineGType(klass, giPrototype, registeredType) {
     const config = {
         enumerable: false,
@@ -124,6 +128,7 @@ function _defineGType(klass, giPrototype, registeredType) {
 
 // Some common functions between GObject.Class and GObject.Interface
 
+
 function _createSignals(gtype, sigs) {
     for (let signalName in sigs) {
         let obj = sigs[signalName];
@@ -140,6 +145,7 @@ function _createSignals(gtype, sigs) {
     }
 }
 
+
 function _getCallerBasename() {
     const stackLines = new Error().stack.trim().split('\n');
     const lineRegex = new RegExp(/@(.+:\/\/)?(.*\/)?(.+)\.js:\d+(:[\d]+)?$/);
@@ -281,9 +287,7 @@ function _checkProperties(klass) {
         _checkAccessors(klass.prototype, pspec, GObject);
 }
 
-function _init() {
-    GObject = this;
-
+(function () {
     function _makeDummyClass(obj, name, upperName, gtypeName, actual) {
         let gtype = GObject.type_from_name(gtypeName);
         obj[`TYPE_${upperName}`] = gtype;
@@ -295,7 +299,7 @@ function _init() {
 
     GObject.gtypeNameBasedOnJSPath = false;
 
-    _makeDummyClass(GObject, 'VoidType', 'NONE', 'void', function () {});
+    _makeDummyClass(GObject, 'VoidType', 'NONE', 'void', function () { });
     _makeDummyClass(GObject, 'Char', 'CHAR', 'gchar', Number);
     _makeDummyClass(GObject, 'UChar', 'UCHAR', 'guchar', Number);
     _makeDummyClass(GObject, 'Unichar', 'UNICHAR', 'gint', String);
@@ -476,6 +480,7 @@ function _init() {
         },
     });
 
+
     let {GObjectMeta, GObjectInterface} = Legacy.defineGObjectLegacyObjects(GObject);
     GObject.Class = GObjectMeta;
     GObject.Interface = GObjectInterface;
@@ -750,9 +755,9 @@ function _init() {
      *   a successful match.
      */
     GObject.signal_handler_find = function (instance, match) {
-        // For backwards compatibility
+    // For backwards compatibility
         if (arguments.length === 7)
-            // eslint-disable-next-line prefer-rest-params
+        // eslint-disable-next-line prefer-rest-params
             return GObject._real_signal_handler_find(...arguments);
         return instance[Gi.signal_find_symbol](match);
     };
@@ -777,9 +782,9 @@ function _init() {
      * @returns {number} The number of handlers that matched.
      */
     GObject.signal_handlers_block_matched = function (instance, match) {
-        // For backwards compatibility
+    // For backwards compatibility
         if (arguments.length === 7)
-            // eslint-disable-next-line prefer-rest-params
+        // eslint-disable-next-line prefer-rest-params
             return GObject._real_signal_handlers_block_matched(...arguments);
         return instance[Gi.signals_block_symbol](match);
     };
@@ -807,9 +812,9 @@ function _init() {
      * @returns {number} The number of handlers that matched.
      */
     GObject.signal_handlers_unblock_matched = function (instance, match) {
-        // For backwards compatibility
+    // For backwards compatibility
         if (arguments.length === 7)
-            // eslint-disable-next-line prefer-rest-params
+        // eslint-disable-next-line prefer-rest-params
             return GObject._real_signal_handlers_unblock_matched(...arguments);
         return instance[Gi.signals_unblock_symbol](match);
     };
@@ -835,9 +840,9 @@ function _init() {
      * @returns {number} The number of handlers that matched.
      */
     GObject.signal_handlers_disconnect_matched = function (instance, match) {
-        // For backwards compatibility
+    // For backwards compatibility
         if (arguments.length === 7)
-            // eslint-disable-next-line prefer-rest-params
+        // eslint-disable-next-line prefer-rest-params
             return GObject._real_signal_handlers_disconnect_matched(...arguments);
         return instance[Gi.signals_disconnect_symbol](match);
     };
@@ -881,4 +886,4 @@ function _init() {
         throw new Error('GObject.signal_handlers_disconnect_by_data() is not \
 introspectable. Use GObject.signal_handlers_disconnect_by_func() instead.');
     };
-}
+})();
diff --git a/modules/core/overrides/Gio.js b/modules/overrides/Gio.js
similarity index 95%
rename from modules/core/overrides/Gio.js
rename to modules/overrides/Gio.js
index be2e52470..ec877d720 100644
--- a/modules/core/overrides/Gio.js
+++ b/modules/overrides/Gio.js
@@ -1,10 +1,10 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2011 Giovanni Campagna
 
-var GLib = imports.gi.GLib;
-var GjsPrivate = imports.gi.GjsPrivate;
-var Signals = imports.signals;
-var Gio;
+import * as signals from '../deprecated/signals.js';
+
+const {Gio, GjsPrivate, GLib} = import.meta.importSync('gi');
+
 
 // Ensures that a Gio.UnixFDList being passed into or out of a DBus method with
 // a parameter type that includes 'h' somewhere, actually has entries in it for
@@ -29,7 +29,7 @@ function _validateFDVariant(variant, fdList) {
         const numFds = fdList.get_length();
         if (val >= numFds) {
             throw new Error(`handle ${val} is out of range of Gio.UnixFDList ` +
-                `containing ${numFds} FDs`);
+                    `containing ${numFds} FDs`);
         }
         return;
     }
@@ -72,8 +72,7 @@ function _proxyInvoker(methodName, sync, inSignature, argArray) {
     var maxNumberArgs = signatureLength + 4;
 
     if (argArray.length < minNumberArgs) {
-        throw new Error(`Not enough arguments passed for method: ${
-            methodName}. Expected ${minNumberArgs}, got ${argArray.length}`);
+        throw new Error(`Not enough arguments passed for method: ${methodName}. Expected ${minNumberArgs}, 
got ${argArray.length}`);
     } else if (argArray.length > maxNumberArgs) {
         throw new Error(`Too many arguments passed for method ${methodName}. ` +
             `Maximum is ${maxNumberArgs} including one callback, ` +
@@ -149,7 +148,7 @@ function _makeProxyMethod(method, sync) {
 }
 
 function _convertToNativeSignal(proxy, senderName, signalName, parameters) {
-    Signals._emit.call(proxy, signalName, senderName, parameters.deepUnpack());
+    signals._emit.call(proxy, signalName, senderName, parameters.deepUnpack());
 }
 
 function _propertyGetter(name) {
@@ -168,8 +167,7 @@ function _propertySetter(name, signature, value) {
             try {
                 this.call_finish(result);
             } catch (e) {
-                log(`Could not set property ${name} on remote object ${
-                    this.g_object_path}: ${e.message}`);
+                log(`Could not set property ${name} on remote object ${this.g_object_path}: ${e.message}`);
             }
         });
 }
@@ -439,9 +437,7 @@ function _promisify(proto, asyncFunc,
     };
 }
 
-function _init() {
-    Gio = this;
-
+(function () {
     Gio.DBus = {
         get session() {
             return Gio.bus_get_sync(Gio.BusType.SESSION, null);
@@ -483,8 +479,9 @@ function _init() {
     _injectToStaticMethod(Gio.DBusProxy, 'new_finish', _addDBusConvenience);
     _injectToStaticMethod(Gio.DBusProxy, 'new_for_bus_sync', _addDBusConvenience);
     _injectToStaticMethod(Gio.DBusProxy, 'new_for_bus_finish', _addDBusConvenience);
-    Gio.DBusProxy.prototype.connectSignal = Signals._connect;
-    Gio.DBusProxy.prototype.disconnectSignal = Signals._disconnect;
+
+    Gio.DBusProxy.prototype.connectSignal = signals._connect;
+    Gio.DBusProxy.prototype.disconnectSignal = signals._disconnect;
 
     Gio.DBusProxy.makeProxyWrapper = _makeProxyWrapper;
 
@@ -537,14 +534,14 @@ function _init() {
     Object.assign(Gio.Settings.prototype, {
         _realInit: Gio.Settings.prototype._init,  // add manually, not enumerable
         _init(props = {}) {
-            // 'schema' is a deprecated alias for schema_id
+        // 'schema' is a deprecated alias for schema_id
             const schemaIdProp = ['schema', 'schema-id', 'schema_id',
                 'schemaId'].find(prop => prop in props);
             const settingsSchemaProp = ['settings-schema', 'settings_schema',
                 'settingsSchema'].find(prop => prop in props);
             if (!schemaIdProp && !settingsSchemaProp) {
                 throw new Error('One of property \'schema-id\' or ' +
-                    '\'settings-schema\' are required for Gio.Settings');
+                '\'settings-schema\' are required for Gio.Settings');
             }
 
             const source = Gio.SettingsSchemaSource.get_default();
@@ -558,21 +555,21 @@ function _init() {
             const settingsSchemaPath = settingsSchema.get_path();
             if (props['path'] === undefined && !settingsSchemaPath) {
                 throw new Error('Attempting to create schema ' +
-                    `'${settingsSchema.get_id()}' without a path`);
+                `'${settingsSchema.get_id()}' without a path`);
             }
 
             if (props['path'] !== undefined && settingsSchemaPath &&
-                props['path'] !== settingsSchemaPath) {
+            props['path'] !== settingsSchemaPath) {
                 throw new Error(`GSettings created for path '${props['path']}'` +
-                    `, but schema specifies '${settingsSchemaPath}'`);
+                `, but schema specifies '${settingsSchemaPath}'`);
             }
 
             return this._realInit(props);
         },
 
         _checkKey(key) {
-            // Avoid using has_key(); checking a JS array is faster than calling
-            // through G-I.
+        // Avoid using has_key(); checking a JS array is faster than calling
+        // through G-I.
             if (!this._keys)
                 this._keys = this.settings_schema.list_keys();
 
@@ -621,4 +618,4 @@ function _init() {
 
         get_child: createCheckedMethod('get_child', '_checkChild'),
     });
-}
+})();
diff --git a/modules/core/overrides/Gtk.js b/modules/overrides/Gtk.js
similarity index 93%
rename from modules/core/overrides/Gtk.js
rename to modules/overrides/Gtk.js
index 611d46066..0ee5fd1f0 100644
--- a/modules/core/overrides/Gtk.js
+++ b/modules/overrides/Gtk.js
@@ -2,16 +2,14 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2013 Giovanni Campagna
 
-const Legacy = imports._legacy;
-const {Gio, GjsPrivate, GObject} = imports.gi;
-const {_registerType} = imports._common;
+import * as Legacy from '../deprecated/_legacy.js';
+import {_registerType} from '../common/class.js';
 
-let Gtk;
-let BuilderScope;
+const {Gtk, Gio, GjsPrivate, GObject} = import.meta.importSync('gi');
 
-function _init() {
-    Gtk = this;
+let BuilderScope;
 
+(function () {
     Gtk.children = GObject.__gtkChildren__;
     Gtk.cssName = GObject.__gtkCssName__;
     Gtk.internalChildren = GObject.__gtkInternalChildren__;
@@ -51,13 +49,13 @@ function _init() {
             let children = wrapper.constructor[Gtk.children] || [];
             for (let child of children) {
                 wrapper[child.replace(/-/g, '_')] =
-                    wrapper.get_template_child(wrapper.constructor, child);
+                wrapper.get_template_child(wrapper.constructor, child);
             }
 
             let internalChildren = wrapper.constructor[Gtk.internalChildren] || [];
             for (let child of internalChildren) {
                 wrapper[`_${child.replace(/-/g, '_')}`] =
-                    wrapper.get_template_child(wrapper.constructor, child);
+                wrapper.get_template_child(wrapper.constructor, child);
             }
         }
 
@@ -142,7 +140,7 @@ function _init() {
             }
         });
     }
-}
+})();
 
 function _createClosure(builder, thisArg, handlerName, swapped, connectObject) {
     connectObject = connectObject || thisArg;
diff --git a/modules/core/overrides/cairo.js b/modules/overrides/cairo.js
similarity index 63%
rename from modules/core/overrides/cairo.js
rename to modules/overrides/cairo.js
index 1d3ba0f94..78c7451cf 100644
--- a/modules/core/overrides/cairo.js
+++ b/modules/overrides/cairo.js
@@ -3,7 +3,8 @@
 
 // This override adds the builtin Cairo bindings to imports.gi.cairo.
 // (It's confusing to have two incompatible ways to import Cairo.)
+import Cairo from 'cairo';
 
-function _init() {
-    Object.assign(this, imports.cairo);
-}
+const {cairo} = import.meta.importSync('gi');
+console.log(`cairo exports: ${Object.keys(Cairo)}`);
+Object.assign(cairo, Cairo);
diff --git a/modules/script/cairo.js b/modules/script/cairo.js
index 3401f3d60..288dc580c 100644
--- a/modules/script/cairo.js
+++ b/modules/script/cairo.js
@@ -1,6 +1,3 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2010 litl, LLC.
 
-// Merge stuff defined in the shared imports._cairo and then in native code
-Object.assign(this, imports._cairo, imports.cairoNative);
-
diff --git a/modules/script/format.js b/modules/script/format.js
index 72b587c08..cbebf16f2 100644
--- a/modules/script/format.js
+++ b/modules/script/format.js
@@ -5,25 +5,4 @@
 
 /* exported format, printf, vprintf */
 
-var {vprintf} = imports._format;
-
-function printf(fmt, ...args) {
-    print(vprintf(fmt, args));
-}
-
-/*
- * This function is intended to extend the String object and provide a
- * String.format API for string formatting.
- * It has to be set up using String.prototype.format = Format.format;
- * Usage:
- * "somestring %s %d".format('hello', 5);
- * It supports %s, %d, %x and %f.
- * For %f it also supports precisions like "%.2f".format(1.526).
- * All specifiers can be prefixed with a minimum field width, e.g.
- * "%5s".format("foo").
- * Unless the width is prefixed with '0', the formatted string will be padded
- * with spaces.
- */
-function format(...args) {
-    return vprintf(this, args);
-}
+// This file is a placeholder, imports.format is defined in deprecated/imports.js
diff --git a/modules/script/gettext.js b/modules/script/gettext.js
index 9a3ef79dd..f0108e3c9 100644
--- a/modules/script/gettext.js
+++ b/modules/script/gettext.js
@@ -1,20 +1,4 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2019 Evan Welsh
 
-/* exported LocaleCategory, bindtextdomain, dcgettext, dgettext, dngettext,
-    domain, dpgettext, gettext, ngettext, pgettext, setlocale, textdomain */
-
-var {
-    LocaleCategory,
-    bindtextdomain,
-    dcgettext,
-    dgettext,
-    dngettext,
-    domain,
-    dpgettext,
-    gettext,
-    ngettext,
-    pgettext,
-    setlocale,
-    textdomain,
-} = imports._gettext;
+// This file is a placeholder, imports.gettext is defined in deprecated/imports.js
diff --git a/modules/script/lang.js b/modules/script/lang.js
index 98082995f..9e2b496d8 100644
--- a/modules/script/lang.js
+++ b/modules/script/lang.js
@@ -6,8 +6,6 @@ getMetaClass, Interface */
 
 // Utilities that are "meta-language" things like manipulating object props
 
-var {Class, Interface, getMetaClass} = imports._legacy;
-
 function countProperties(obj) {
     let count = 0;
     for (let unusedProperty in obj)
diff --git a/modules/script/overrides/__init__.js b/modules/script/overrides/__init__.js
new file mode 100644
index 000000000..ddba652fb
--- /dev/null
+++ b/modules/script/overrides/__init__.js
@@ -0,0 +1 @@
+// Placeholder for backwards compatibility (ensures imports.overrides resolves)
diff --git a/modules/script/signals.js b/modules/script/signals.js
index cd10605c0..d338504dd 100644
--- a/modules/script/signals.js
+++ b/modules/script/signals.js
@@ -1,21 +1,4 @@
 // SPDX-FileCopyrightText: 2008 litl, LLC
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 
-/* exported addSignalMethods, WithSignals */
-
-const Lang = imports.lang;
-
-// Private API, remains exported for backwards compatibility reasons
-var {_connect, _disconnect, _emit, _signalHandlerIsConnected, _disconnectAll} = imports._signals;
-
-// Public API
-var {addSignalMethods} = imports._signals;
-
-var WithSignals = new Lang.Interface({
-    Name: 'WithSignals',
-    connect: _connect,
-    disconnect: _disconnect,
-    emit: _emit,
-    signalHandlerIsConnected: _signalHandlerIsConnected,
-    disconnectAll: _disconnectAll,
-});
+// This file is a placeholder, imports.signals is defined in deprecated/imports.js


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]