diff options
-rw-r--r-- | .eslintrc.yml | 5 | ||||
-rw-r--r-- | gi/repo.cpp | 124 | ||||
-rw-r--r-- | gjs/context.cpp | 2 | ||||
-rw-r--r-- | gjs/engine.cpp | 13 | ||||
-rw-r--r-- | gjs/global.cpp | 5 | ||||
-rw-r--r-- | gjs/importer.cpp | 1 | ||||
-rw-r--r-- | gjs/module.cpp | 83 | ||||
-rw-r--r-- | gjs/module.h | 2 | ||||
-rw-r--r-- | installed-tests/js/testGObject.js | 2 | ||||
-rw-r--r-- | js.gresource.xml | 35 | ||||
-rw-r--r-- | modules/_bootstrap/.eslintrc.yml (renamed from modules/script/_bootstrap/.eslintrc.yml) | 0 | ||||
-rw-r--r-- | modules/_bootstrap/coverage.js (renamed from modules/script/_bootstrap/coverage.js) | 0 | ||||
-rw-r--r-- | modules/_bootstrap/debugger.js (renamed from modules/script/_bootstrap/debugger.js) | 0 | ||||
-rw-r--r-- | modules/_bootstrap/default.js (renamed from modules/script/_bootstrap/default.js) | 0 | ||||
-rw-r--r-- | modules/common/class.js (renamed from modules/core/_common.js) | 6 | ||||
-rw-r--r-- | modules/core/_cairo.js | 128 | ||||
-rw-r--r-- | modules/core/_gettext.js | 83 | ||||
-rw-r--r-- | modules/deprecated/.eslintrc.yml (renamed from modules/core/.eslintrc.yml) | 6 | ||||
-rw-r--r-- | modules/deprecated/_legacy.js (renamed from modules/script/_legacy.js) | 16 | ||||
-rw-r--r-- | modules/deprecated/format.js (renamed from modules/core/_format.js) | 46 | ||||
-rw-r--r-- | modules/deprecated/legacyImports.js | 38 | ||||
-rw-r--r-- | modules/deprecated/signals.js (renamed from modules/core/_signals.js) | 12 | ||||
-rw-r--r-- | modules/esm/_bootstrap/default.js | 9 | ||||
-rw-r--r-- | modules/esm/_bootstrap/legacyImports.js | 9 | ||||
-rw-r--r-- | modules/esm/cairo.js | 145 | ||||
-rw-r--r-- | modules/esm/gettext.js | 101 | ||||
-rw-r--r-- | modules/internal/.eslintrc.yml | 1 | ||||
-rw-r--r-- | modules/internal/loader.js | 89 | ||||
-rw-r--r-- | modules/overrides/.eslintrc.yml (renamed from modules/core/overrides/.eslintrc.yml) | 7 | ||||
-rw-r--r-- | modules/overrides/GLib.js (renamed from modules/core/overrides/GLib.js) | 95 | ||||
-rw-r--r-- | modules/overrides/GObject.js (renamed from modules/core/overrides/GObject.js) | 41 | ||||
-rw-r--r-- | modules/overrides/Gio.js (renamed from modules/core/overrides/Gio.js) | 36 | ||||
-rw-r--r-- | modules/overrides/Gtk.js (renamed from modules/core/overrides/Gtk.js) | 16 | ||||
-rw-r--r-- | modules/overrides/cairo.js (renamed from modules/core/overrides/cairo.js) | 7 | ||||
-rw-r--r-- | modules/print.cpp | 31 | ||||
-rw-r--r-- | modules/script/cairo.js | 3 | ||||
-rw-r--r-- | modules/script/format.js | 23 | ||||
-rw-r--r-- | modules/script/gettext.js | 18 | ||||
-rw-r--r-- | modules/script/lang.js | 5 | ||||
-rw-r--r-- | modules/script/overrides/__init__.js | 1 | ||||
-rw-r--r-- | modules/script/signals.js | 19 |
41 files changed, 747 insertions, 516 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml index 97e728f9..3da99101 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 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, diff --git a/gjs/context.cpp b/gjs/context.cpp index 4e22825d..1a1a18ef 100644 --- a/gjs/context.cpp +++ b/gjs/context.cpp @@ -577,7 +577,7 @@ static bool add_promise_reactions(JSContext* cx, JS::HandleValue promise, static void load_context_module(JSContext* cx, const char* uri, const char* debug_identifier) { - JS::RootedObject loader(cx, gjs_module_load(cx, uri, uri)); + JS::RootedObject loader(cx, gjs_module_load(cx, uri, uri, true)); if (!loader) { gjs_log_exception(cx); diff --git a/gjs/engine.cpp b/gjs/engine.cpp index 16d84cc1..fe3ea516 100644 --- a/gjs/engine.cpp +++ b/gjs/engine.cpp @@ -79,7 +79,7 @@ class GjsSourceHook : public js::SourceHook { #ifdef G_OS_WIN32 HMODULE gjs_dll; -static bool gjs_is_inited = false; +static bool _gjs_is_inited = false; BOOL WINAPI DllMain (HINSTANCE hinstDLL, @@ -90,7 +90,7 @@ LPVOID lpvReserved) { case DLL_PROCESS_ATTACH: gjs_dll = hinstDLL; - gjs_is_inited = JS_Init(); + _gjs_is_inited = JS_Init(); break; case DLL_THREAD_DETACH: @@ -105,6 +105,7 @@ LPVOID lpvReserved) return TRUE; } +static bool gjs_is_inited() { return _gjs_is_inited; } #else class GjsInit { public: @@ -120,11 +121,15 @@ public: explicit operator bool() const { return true; } }; -static GjsInit gjs_is_inited; +static bool gjs_is_inited() { + static GjsInit gjs_is_inited; + + return !!gjs_is_inited; +} #endif JSContext* gjs_create_js_context(GjsContextPrivate* uninitialized_gjs) { - g_assert(gjs_is_inited); + g_assert(gjs_is_inited()); JSContext *cx = JS_NewContext(32 * 1024 * 1024 /* max bytes */); if (!cx) return nullptr; diff --git a/gjs/global.cpp b/gjs/global.cpp index 56fe8602..8f3f4cce 100644 --- a/gjs/global.cpp +++ b/gjs/global.cpp @@ -88,7 +88,7 @@ class GjsBaseGlobal { static bool run_bootstrap(JSContext* cx, const char* bootstrap_script, JS::HandleObject global) { GjsAutoChar uri = g_strdup_printf( - "resource:///org/gnome/gjs/modules/script/_bootstrap/%s.js", + "resource:///org/gnome/gjs/modules/_bootstrap/%s.js", bootstrap_script); JSAutoRealm ar(cx, global); @@ -288,6 +288,7 @@ class GjsInternalGlobal : GjsBaseGlobal { 0), JS_FN("setModulePrivate", gjs_internal_set_module_private, 2, 0), JS_FN("uriExists", gjs_internal_uri_exists, 1, 0), + JS_FN("loadNative", &load_native_module, 1, 0), JS_FS_END}; static constexpr JSClass klass = { @@ -486,7 +487,7 @@ bool gjs_global_registry_get(JSContext* cx, JS::HandleObject registry, * @global: a JS global object that has not yet been passed to this function * @realm_name: (nullable): name of the realm, for debug output * @bootstrap_script: (nullable): name of a bootstrap script (found at - * resource://org/gnome/gjs/modules/script/_bootstrap/@bootstrap_script) or + * resource://org/gnome/gjs/modules/_bootstrap/@bootstrap_script) or * %NULL for none * * Defines properties on the global object such as 'window' and 'imports', and diff --git a/gjs/importer.cpp b/gjs/importer.cpp index c8bc553e..c94d428e 100644 --- a/gjs/importer.cpp +++ b/gjs/importer.cpp @@ -798,7 +798,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 3b54a3fc..502e8e47 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,7 +331,7 @@ 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_module_load can only be called from module-enabled " @@ -378,9 +352,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, diff --git a/gjs/module.h b/gjs/module.h index f6b3a353..5e2d477d 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 160f85ab..d8848723 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/js.gresource.xml b/js.gresource.xml index e12dea12..817818fa 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/legacyImports.js</file> <file>modules/esm/_bootstrap/default.js</file> <file>modules/esm/_encoding/encoding.js</file> @@ -22,19 +25,18 @@ <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/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 +44,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/legacyImports.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 index fda87577..fda87577 100644 --- a/modules/script/_bootstrap/.eslintrc.yml +++ b/modules/_bootstrap/.eslintrc.yml diff --git a/modules/script/_bootstrap/coverage.js b/modules/_bootstrap/coverage.js index 1af74c42..1af74c42 100644 --- a/modules/script/_bootstrap/coverage.js +++ b/modules/_bootstrap/coverage.js diff --git a/modules/script/_bootstrap/debugger.js b/modules/_bootstrap/debugger.js index 6ae0d9c2..6ae0d9c2 100644 --- a/modules/script/_bootstrap/debugger.js +++ b/modules/_bootstrap/debugger.js diff --git a/modules/script/_bootstrap/default.js b/modules/_bootstrap/default.js index 8c211a5a..8c211a5a 100644 --- a/modules/script/_bootstrap/default.js +++ b/modules/_bootstrap/default.js diff --git a/modules/core/_common.js b/modules/common/class.js index 1a7fe772..7b514c84 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/_cairo.js b/modules/core/_cairo.js deleted file mode 100644 index 0bea8cad..00000000 --- a/modules/core/_cairo.js +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later -// SPDX-FileCopyrightText: 2010 litl, LLC. - -/* exported Antialias, Content, Extend, FillRule, Filter, FontSlant, FontWeight, -Format, LineCap, LineJoin, Operator, PatternType, SurfaceType */ - -var Antialias = { - DEFAULT: 0, - NONE: 1, - GRAY: 2, - SUBPIXEL: 3, -}; - -var Content = { - COLOR: 0x1000, - ALPHA: 0x2000, - COLOR_ALPHA: 0x3000, -}; - -var Extend = { - NONE: 0, - REPEAT: 1, - REFLECT: 2, - PAD: 3, -}; - -var FillRule = { - WINDING: 0, - EVEN_ODD: 1, -}; - -var Filter = { - FAST: 0, - GOOD: 1, - BEST: 2, - NEAREST: 3, - BILINEAR: 4, - GAUSSIAN: 5, -}; - -var FontSlant = { - NORMAL: 0, - ITALIC: 1, - OBLIQUE: 2, -}; - -var FontWeight = { - NORMAL: 0, - BOLD: 1, -}; - -var Format = { - ARGB32: 0, - RGB24: 1, - A8: 2, - A1: 3, - // The value of 4 is reserved by a deprecated enum value - RGB16_565: 5, -}; - -var LineCap = { - BUTT: 0, - ROUND: 1, - SQUASH: 2, -}; - -var LineJoin = { - MITER: 0, - ROUND: 1, - BEVEL: 2, -}; - -var 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, -}; - -var PatternType = { - SOLID: 0, - SURFACE: 1, - LINEAR: 2, - RADIAL: 3, -}; - -var 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, -}; - diff --git a/modules/core/_gettext.js b/modules/core/_gettext.js deleted file mode 100644 index 376ad93f..00000000 --- a/modules/core/_gettext.js +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later -// SPDX-FileCopyrightText: 2009 Red Hat, Inc. - -/* 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!"); - */ - -const GLib = imports.gi.GLib; -const GjsPrivate = imports.gi.GjsPrivate; - -var LocaleCategory = GjsPrivate.LocaleCategory; - -function setlocale(category, locale) { - return GjsPrivate.setlocale(category, locale); -} - -function textdomain(dom) { - return GjsPrivate.textdomain(dom); -} -function bindtextdomain(dom, location) { - return GjsPrivate.bindtextdomain(dom, location); -} - -function gettext(msgid) { - return GLib.dgettext(null, msgid); -} -function dgettext(dom, msgid) { - return GLib.dgettext(dom, msgid); -} -function dcgettext(dom, msgid, category) { - return GLib.dcgettext(dom, msgid, category); -} - -function ngettext(msgid1, msgid2, n) { - return GLib.dngettext(null, msgid1, msgid2, n); -} -function dngettext(dom, msgid1, msgid2, n) { - return GLib.dngettext(dom, msgid1, msgid2, n); -} -// FIXME: missing dcngettext ? - -function pgettext(context, msgid) { - return GLib.dpgettext2(null, context, msgid); -} -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 - */ -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); - }, - }; -} diff --git a/modules/core/.eslintrc.yml b/modules/deprecated/.eslintrc.yml index 6c9c0253..84e48aef 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 index 135d2517..4500c5fa 100644 --- a/modules/script/_legacy.js +++ b/modules/deprecated/_legacy.js @@ -1,6 +1,5 @@ /* -*- mode: js; indent-tabs-mode: nil; -*- */ -/* exported Class, Interface, defineGObjectLegacyObjects, -defineGtkLegacyObjects */ +/* eslint-disable jsdoc/require-jsdoc, no-invalid-this */ // SPDX-License-Identifier: MIT // SPDX-FileCopyrightText: 2008 litl, LLC // SPDX-FileCopyrightText: 2011 Jasper St. Pierre @@ -9,6 +8,10 @@ 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'); } @@ -411,10 +414,7 @@ Interface.prototype._init = function (params) { // GObject Lang.Class magic -function defineGObjectLegacyObjects(GObject) { - const Gi = imports._gi; - const {_checkAccessors} = imports._common; - +export function defineGObjectLegacyObjects(GObject) { // Some common functions between GObject.Class and GObject.Interface function _createSignals(gtype, signals) { @@ -646,7 +646,7 @@ function defineGObjectLegacyObjects(GObject) { return {GObjectMeta, GObjectInterface}; } -function defineGtkLegacyObjects(GObject, Gtk) { +export function defineGtkLegacyObjects(GObject, Gtk) { const GtkWidgetClass = new Class({ Name: 'GtkWidgetClass', Extends: GObject.Class, @@ -715,3 +715,5 @@ function defineGtkLegacyObjects(GObject, Gtk) { return {GtkWidgetClass}; } + +export {Class, Interface, getMetaClass}; diff --git a/modules/core/_format.js b/modules/deprecated/format.js index eb6f0319..55e652af 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/legacyImports.js b/modules/deprecated/legacyImports.js new file mode 100644 index 00000000..02c026d2 --- /dev/null +++ b/modules/deprecated/legacyImports.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 index 25dcfd47..7a9941fe 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 ff1f28bf..5a3972c5 100644 --- a/modules/esm/_bootstrap/default.js +++ b/modules/esm/_bootstrap/default.js @@ -9,3 +9,12 @@ import '_encoding/encoding'; import 'console'; // Bootstrap the Timers API import '_timers'; + +// Import remaining modules +import 'gettext'; + +// Bootstrap the gi module +import 'gi'; + +// globalThis.imports compatibility +import './legacyImports.js'; diff --git a/modules/esm/_bootstrap/legacyImports.js b/modules/esm/_bootstrap/legacyImports.js new file mode 100644 index 00000000..3b353ba1 --- /dev/null +++ b/modules/esm/_bootstrap/legacyImports.js @@ -0,0 +1,9 @@ +import gettext from 'gettext'; +import cairo from 'cairo'; + +import '../../deprecated/legacyImports.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 d6127ff1..1dc013ef 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 bcef3863..5c303a0c 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/.eslintrc.yml b/modules/internal/.eslintrc.yml index 7c187793..269a2dfe 100644 --- a/modules/internal/.eslintrc.yml +++ b/modules/internal/.eslintrc.yml @@ -7,6 +7,7 @@ parserOptions: ecmaVersion: 2022 globals: ARGV: off + loadNative: readonly Debugger: readonly GIRepositoryGType: off imports: off diff --git a/modules/internal/loader.js b/modules/internal/loader.js index 2f3f71d8..5ad6d83c 100644 --- a/modules/internal/loader.js +++ b/modules/internal/loader.js @@ -14,6 +14,8 @@ /** @typedef {{ [key: string]: string | undefined; }} Query */ /** @typedef {(uri: string, contents: string) => Module} CompileFunc */ +const {debug} = loadNative('_print'); + /** * Thrown when there is an error importing a module. */ @@ -32,6 +34,8 @@ class ImportError extends moduleGlobalThis.Error { * ModulePrivate is the "private" object of every module. */ class ModulePrivate { + #override; + /** * * @param {string} id the module's identifier @@ -42,6 +46,17 @@ class ModulePrivate { this.id = id; this.uri = uri; this.internal = internal; + + if (internal) { + Object.defineProperty(this, 'override', { + get: () => { + return this.#override; + }, + set: override => { + this.#override = override; + }, + }); + } } } @@ -108,8 +123,11 @@ class InternalModuleLoader { } if (isRelativePath(specifier)) { - if (!parentURI) - throw new ImportError('Cannot import relative path when module path is unknown.'); + if (!parentURI) { + throw new ImportError( + 'Cannot import relative path when module path is unknown.' + ); + } return this.resolveRelativePath(specifier, parentURI); } @@ -131,7 +149,10 @@ class InternalModuleLoader { parseURI(importingModuleURI); // Handle relative imports from URI-based modules. - const relativeURI = resolveRelativeResourceOrFile(importingModuleURI, relativePath); + const relativeURI = resolveRelativeResourceOrFile( + importingModuleURI, + relativePath + ); if (!relativeURI) throw new ImportError('File does not have a valid parent!'); return parseURI(relativeURI); @@ -154,12 +175,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 +202,15 @@ class InternalModuleLoader { if (!result) return null; - const [text, internal = false] = result; + const [text, internal] = result; - const priv = new ModulePrivate(uri.uri, uri.uri, internal); + debug(`Importing ${specifier} ${internal ? '(internal)' : ''}`); + + const priv = new ModulePrivate( + uri.uri, + uri.uri, + internal ?? importingModulePriv.internal + ); const compiled = this.compileModule(priv, text); registry.set(uri.uri, compiled); @@ -193,15 +221,18 @@ 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` @@ -311,8 +342,11 @@ class ModuleLoader extends InternalModuleLoader { throw new ImportError(`Unknown module: '${specifier}'`); const parsed = parseURI(uri); - if (parsed.scheme !== 'file' && parsed.scheme !== 'resource') - throw new ImportError('Only file:// and resource:// URIs are currently supported.'); + if (parsed.scheme !== 'file' && parsed.scheme !== 'resource') { + throw new ImportError( + 'Only file:// and resource:// URIs are currently supported.' + ); + } const text = loadResourceOrFile(parsed.uri); const priv = new ModulePrivate(specifier, uri, true); @@ -335,7 +369,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; @@ -345,21 +379,26 @@ class ModuleLoader extends InternalModuleLoader { moduleResolveAsyncHook(importingModulePriv, specifier) { // importingModulePriv should never be missing. If it is then a JSScript // is missing a private object - if (!importingModulePriv || !importingModulePriv.uri) - throw new ImportError('Cannot resolve relative imports from an unknown file.'); + 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 +424,13 @@ 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); @@ -436,7 +479,9 @@ setGlobalModuleLoader(moduleGlobalThis, moduleLoader); function generateGIModule(namespace, version) { return ` import $$gi from 'gi'; - export default $$gi.require('${namespace}'${version !== undefined ? `, '${version}'` : ''}); + export default $$gi.require('${namespace}'${ + version !== undefined ? `, '${version}'` : '' +}); `; } diff --git a/modules/core/overrides/.eslintrc.yml b/modules/overrides/.eslintrc.yml index 8a5f8fd9..bd5a206c 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 index cb8f177e..312377a8 100644 --- a/modules/core/overrides/GLib.js +++ b/modules/overrides/GLib.js @@ -1,9 +1,7 @@ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2011 Giovanni Campagna -const ByteArray = imports.byteArray; - -let GLib; +const {GLib} = import.meta.importSync('gi'); const SIMPLE_TYPES = ['b', 'y', 'n', 'q', 'i', 'u', 'x', 't', 'h', 'd', 's', 'o', 'g']; @@ -101,10 +99,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 +201,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 +245,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 +259,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 +275,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 +294,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 +355,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 +380,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 +400,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 +415,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 +423,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 +434,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 +493,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 +504,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 index df6f9dc2..782f05b6 100644 --- a/modules/core/overrides/GObject.js +++ b/modules/overrides/GObject.js @@ -3,12 +3,12 @@ // 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 +23,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 +83,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 +93,7 @@ function _resolveLegacyClassFunction(klass, func) { return initclass[func]; } + function _defineGType(klass, giPrototype, registeredType) { const config = { enumerable: false, @@ -124,6 +129,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 +146,7 @@ function _createSignals(gtype, sigs) { } } + function _getCallerBasename() { const stackLines = new Error().stack.trim().split('\n'); const lineRegex = new RegExp(/@(.+:\/\/)?(.*\/)?(.+)\.js:\d+(:[\d]+)?$/); @@ -281,9 +288,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 +300,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); @@ -751,9 +756,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); }; @@ -778,9 +783,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); }; @@ -808,9 +813,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); }; @@ -836,9 +841,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); }; @@ -882,4 +887,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 index 6cc29b17..d06eb0f8 100644 --- a/modules/core/overrides/Gio.js +++ b/modules/overrides/Gio.js @@ -1,10 +1,9 @@ // 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 +28,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 +71,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, ` + @@ -168,8 +166,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}`); } }); } @@ -453,9 +450,7 @@ function _promisify(proto, asyncFunc, }; } -function _init() { - Gio = this; - +(function () { Gio.DBus = { get session() { return Gio.bus_get_sync(Gio.BusType.SESSION, null); @@ -497,6 +492,7 @@ 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; @@ -551,14 +547,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(); @@ -572,21 +568,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(); @@ -635,4 +631,4 @@ function _init() { get_child: createCheckedMethod('get_child', '_checkChild'), }); -} +})(); diff --git a/modules/core/overrides/Gtk.js b/modules/overrides/Gtk.js index ce63ba4e..dd27e169 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; -function _init() { - Gtk = this; +const {Gtk, Gio, GjsPrivate, GObject} = import.meta.importSync('gi'); +(function () { Gtk.children = GObject.__gtkChildren__; Gtk.cssName = GObject.__gtkCssName__; Gtk.internalChildren = GObject.__gtkInternalChildren__; @@ -58,13 +56,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); } } @@ -149,7 +147,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 index 1d3ba0f9..3864df6e 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'); + +Object.assign(cairo, Cairo); diff --git a/modules/print.cpp b/modules/print.cpp index 2b07a27b..e2dbc16b 100644 --- a/modules/print.cpp +++ b/modules/print.cpp @@ -162,12 +162,43 @@ static bool set_pretty_print_function(JSContext*, unsigned argc, return true; } +GJS_JSAPI_RETURN_CONVENTION +static bool gjs_debug_js(JSContext* cx, unsigned argc, JS::Value* vp) { + JS::CallArgs argv = JS::CallArgsFromVp(argc, vp); + + if (argc != 1) { + gjs_throw(cx, "Must pass a single argument to log()"); + return false; + } + + /* JS::ToString might throw, in which case we will only log that the value + * could not be converted to string */ + JS::AutoSaveExceptionState exc_state(cx); + JS::RootedString jstr(cx, JS::ToString(cx, argv[0])); + exc_state.restore(); + + if (!jstr) { + g_message("JS LOG: <cannot convert value to string>"); + return true; + } + + JS::UniqueChars s(JS_EncodeStringToUTF8(cx, jstr)); + if (!s) + return false; + + gjs_debug(GJS_DEBUG_IMPORTER, s.get()); + + argv.rval().setUndefined(); + return true; +} + // clang-format off static constexpr JSFunctionSpec funcs[] = { JS_FN("log", gjs_log, 1, GJS_MODULE_PROP_FLAGS), JS_FN("logError", gjs_log_error, 2, GJS_MODULE_PROP_FLAGS), JS_FN("print", gjs_print, 0, GJS_MODULE_PROP_FLAGS), JS_FN("printerr", gjs_printerr, 0, GJS_MODULE_PROP_FLAGS), + JS_FN("debug", gjs_debug_js, 0, GJS_MODULE_PROP_FLAGS), JS_FN("setPrettyPrintFunction", set_pretty_print_function, 1, GJS_MODULE_PROP_FLAGS), JS_FS_END}; // clang-format on diff --git a/modules/script/cairo.js b/modules/script/cairo.js index 3401f3d6..288dc580 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 72b587c0..560d29d9 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/legacyImports.js diff --git a/modules/script/gettext.js b/modules/script/gettext.js index 9a3ef79d..ef3faa9e 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/legacyImports.js diff --git a/modules/script/lang.js b/modules/script/lang.js index 98082995..900d3db6 100644 --- a/modules/script/lang.js +++ b/modules/script/lang.js @@ -1,13 +1,10 @@ /* -*- mode: js; indent-tabs-mode: nil; -*- */ -/* exported bind, copyProperties, copyPublicProperties, countProperties, Class, -getMetaClass, Interface */ +/* exported bind, copyProperties, copyPublicProperties, countProperties */ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2008 litl, LLC // 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 00000000..ddba652f --- /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 cd10605c..90956729 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/legacyImports.js |