summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Hergert <chergert@redhat.com>2023-03-21 11:51:46 -0700
committerChristian Hergert <chergert@redhat.com>2023-03-22 16:14:24 -0700
commit7be1145593f918f902ffbb6a5846a80d557fb89d (patch)
treea1948de92dc23f3ed89834a1907ba155d19586fd
parent2f717ec4c98d054a12e4e21a03948eaa930d6c93 (diff)
downloadlibpeas-wip/chergert/gjs-loader.tar.gz
-rw-r--r--libpeas/peas-engine.c2
-rw-r--r--libpeas/peas-plugin-info.c3
-rw-r--r--libpeas/peas-utils.c5
-rw-r--r--libpeas/peas-utils.h5
-rw-r--r--loaders/gjs/meson.build52
-rw-r--r--loaders/gjs/peas-gjs.gresource.xml6
-rw-r--r--loaders/gjs/peas-plugin-loader-gjs.cpp242
-rw-r--r--loaders/gjs/peas-plugin-loader-gjs.h36
-rw-r--r--loaders/gjs/plugin.js14
-rw-r--r--loaders/meson.build4
-rw-r--r--meson.build4
-rw-r--r--meson_options.txt4
12 files changed, 371 insertions, 6 deletions
diff --git a/libpeas/peas-engine.c b/libpeas/peas-engine.c
index 2d448f1..34b6376 100644
--- a/libpeas/peas-engine.c
+++ b/libpeas/peas-engine.c
@@ -967,7 +967,7 @@ get_plugin_loader (PeasEngine *engine,
* Enable a loader, enables a loader for plugins.
*
* The C plugin loader is always enabled. The other plugin
- * loaders are: lua5.1, python and python3.
+ * loaders are: gjs, lua5.1, python and python3.
*
* For instance, the following code will enable Python 2 plugins
* to be loaded:
diff --git a/libpeas/peas-plugin-info.c b/libpeas/peas-plugin-info.c
index 42058bc..f96a7e9 100644
--- a/libpeas/peas-plugin-info.c
+++ b/libpeas/peas-plugin-info.c
@@ -387,7 +387,8 @@ _peas_plugin_info_new (const char *filename,
goto error;
}
}
- else if (is_resource)
+ else if (is_resource &&
+ info->loader_id != PEAS_UTILS_GJS_LOADER_ID)
{
g_warning ("Bad plugin file '%s': resource plugins must be embedded",
filename);
diff --git a/libpeas/peas-utils.c b/libpeas/peas-utils.c
index 433e6cf..5b2691a 100644
--- a/libpeas/peas-utils.c
+++ b/libpeas/peas-utils.c
@@ -31,17 +31,18 @@
#include "peas-utils.h"
static const char *all_plugin_loaders[] = {
- "c", "lua5.1", "python",
+ "c", "lua5.1", "python", "gjs",
};
static const char *all_plugin_loader_modules[] = {
- "cloader", "lua51loader", "pythonloader",
+ "cloader", "lua51loader", "pythonloader", "gjsloader",
};
static const int conflicting_plugin_loaders[PEAS_UTILS_N_LOADERS][2] = {
{ -1, -1 }, /* c => {} */
{ -1, -1 }, /* lua5.1 => {} */
{ -1, -1 }, /* python => {} */
+ { -1, -1 }, /* gjs => {} */
};
G_STATIC_ASSERT (G_N_ELEMENTS (all_plugin_loaders) == PEAS_UTILS_N_LOADERS);
diff --git a/libpeas/peas-utils.h b/libpeas/peas-utils.h
index a01c4b6..a1a4c85 100644
--- a/libpeas/peas-utils.h
+++ b/libpeas/peas-utils.h
@@ -25,8 +25,9 @@
#include <glib-object.h>
-#define PEAS_UTILS_C_LOADER_ID 0
-#define PEAS_UTILS_N_LOADERS 3
+#define PEAS_UTILS_C_LOADER_ID 0
+#define PEAS_UTILS_N_LOADERS 4
+#define PEAS_UTILS_GJS_LOADER_ID 3
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
gboolean peas_utils_properties_array_to_parameter_list (GType exten_type,
diff --git a/loaders/gjs/meson.build b/loaders/gjs/meson.build
new file mode 100644
index 0000000..4d1ffb2
--- /dev/null
+++ b/loaders/gjs/meson.build
@@ -0,0 +1,52 @@
+add_languages('cpp')
+
+cxx = meson.get_compiler('cpp')
+
+gjs_loader_name = 'gjsloader'
+
+gjs_loader_c = files(
+ 'peas-plugin-loader-gjs.cpp',
+)
+
+gjs_loader_res = gnome.compile_resources(
+ 'peas-gjs-resources',
+ 'peas-gjs.gresource.xml',
+ export: false,
+)
+
+gjs_loader_deps = [
+ libpeas_dep,
+ gjs_dep,
+]
+
+gjs_loader_c_args = [
+ '-DPEAS_LOCALEDIR="@0@"'.format(localedir),
+]
+
+gjs_loader_cpp_args = []
+test_cpp_args = [
+ '-Wno-missing-field-initializers',
+ '-Wno-unused-parameter',
+]
+foreach arg: test_cpp_args
+ if cxx.has_multi_arguments(arg)
+ gjs_loader_cpp_args += arg
+ endif
+endforeach
+
+
+gjs_loader_sha = shared_module(
+ gjs_loader_name,
+ gjs_loader_c + gjs_loader_res,
+ include_directories: rootdir,
+ dependencies: gjs_loader_deps,
+ c_args: project_c_args + gjs_loader_c_args,
+ cpp_args: gjs_loader_cpp_args,
+ install: true,
+ install_dir: join_paths(
+ pkglibdir,
+ 'loaders',
+ ),
+ name_suffix: module_suffix,
+ gnu_symbol_visibility: 'hidden'
+)
diff --git a/loaders/gjs/peas-gjs.gresource.xml b/loaders/gjs/peas-gjs.gresource.xml
new file mode 100644
index 0000000..a3d6dc8
--- /dev/null
+++ b/loaders/gjs/peas-gjs.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/libpeas/loaders/gjs">
+ <file>plugin.js</file>
+ </gresource>
+</gresources>
diff --git a/loaders/gjs/peas-plugin-loader-gjs.cpp b/loaders/gjs/peas-plugin-loader-gjs.cpp
new file mode 100644
index 0000000..324f4b2
--- /dev/null
+++ b/loaders/gjs/peas-plugin-loader-gjs.cpp
@@ -0,0 +1,242 @@
+/*
+ * peas-plugin-loader-gjs.c
+ * This file is part of libpeas
+ *
+ * Copyright 2023 Christian Hergert <chergert@redhat.com>
+ *
+ * libpeas is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * libpeas is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <gjs/gjs.h>
+
+#include <jsapi.h>
+
+#include <js/Modules.h>
+#include <js/String.h>
+
+#include "peas-plugin-loader-gjs.h"
+
+#include "libpeas/peas-plugin-info-priv.h"
+
+struct _PeasPluginLoaderGjs {
+ PeasPluginLoader parent_instance;
+ GjsContext *context;
+};
+
+G_DEFINE_FINAL_TYPE (PeasPluginLoaderGjs, peas_plugin_loader_gjs, PEAS_TYPE_PLUGIN_LOADER)
+
+static GQuark quark_extension_type;
+static const JSClass g_PeasLoader = { "PeasLoader", JSCLASS_GLOBAL_FLAGS, &JS::DefaultGlobalClassOps };
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ PEAS_TYPE_PLUGIN_LOADER,
+ PEAS_TYPE_PLUGIN_LOADER_GJS);
+}
+
+static gboolean
+peas_plugin_loader_gjs_provides_extension (PeasPluginLoader *loader,
+ PeasPluginInfo *info,
+ GType exten_type)
+{
+ PeasPluginLoaderGjs *gjsloader = PEAS_PLUGIN_LOADER_GJS (loader);
+ const char *type_name = g_type_name (exten_type);
+ const char *module_name = peas_plugin_info_get_module_name (info);
+ GType the_type = G_TYPE_INVALID;
+
+ g_print ("Checking for %s\n", g_type_name (exten_type));
+
+#if 0
+ JSContext *cx = (JSContext *)gjs_context_get_native_context (gjsloader->context);
+ JS::RealmOptions options;
+ options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
+ JS::RootedObject global(cx, JS_NewGlobalObject (cx, &g_PeasLoader, nullptr, JS::OnNewGlobalHookOption::DontFireOnNewGlobalHook, options));
+
+
+ JS::UTF8Chars chars(module_name, strlen (module_name));
+ JSString *moduleName = JS_NewStringCopyUTF8N (cx, chars);
+ JS::HandleObject moduleNameHandle(moduleName);
+ JSObject *object = JS::GetModuleObject (moduleNameHandle);
+#endif
+
+ return the_type != G_TYPE_INVALID;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+static GObject *
+peas_plugin_loader_gjs_create_extension (PeasPluginLoader *loader,
+ PeasPluginInfo *info,
+ GType exten_type,
+ guint n_parameters,
+ GParameter *parameters)
+{
+ GObject *object = NULL;
+ GType the_type;
+
+ the_type = G_TYPE_INVALID;
+ if (the_type == G_TYPE_INVALID)
+ goto out;
+
+ object = (GObject *)g_object_newv (the_type, n_parameters, parameters);
+ if (object == NULL)
+ goto out;
+
+ /* Sink floating references if necessary */
+ if (g_object_is_floating (object))
+ g_object_ref_sink (object);
+
+ /* We have to remember which interface we are instantiating
+ * for the deprecated peas_extension_get_extension_type().
+ */
+ g_object_set_qdata (object, quark_extension_type,
+ GSIZE_TO_POINTER (exten_type));
+
+out:
+ g_print ("Creating extension %s = %p\n", g_type_name (exten_type), object);
+ return object;
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+static gboolean
+peas_plugin_loader_gjs_load (PeasPluginLoader *loader,
+ PeasPluginInfo *info)
+{
+ PeasPluginLoaderGjs *gjsloader = PEAS_PLUGIN_LOADER_GJS (loader);
+ const char *module_dir, *module_name;
+ JSContext *cx;
+ char *module_dir_uri = NULL;
+ char *module_name_js = NULL;
+ char *module_uri = NULL;
+ gboolean ret = FALSE;
+ GError *error = NULL;
+
+ module_dir = peas_plugin_info_get_module_dir (info);
+ module_name = peas_plugin_info_get_module_name (info);
+ module_name_js = g_strconcat (module_name, ".js", NULL);
+ if (g_str_has_prefix (module_dir, "resource://"))
+ module_dir_uri = g_strdup (module_dir);
+ else
+ module_dir_uri = g_strconcat ("file://", module_dir, NULL);
+ module_uri = g_build_filename (module_dir_uri, module_name_js, NULL);
+
+ cx = gjs_context_get_native_context (gjsloader->context);
+
+ if (!gjs_context_register_module (gjsloader->context, module_name, module_uri, &error))
+ {
+ g_warning ("Registering module %s threw exception: %s",
+ module_uri, error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ info->loader_data = gjsloader;
+ ret = TRUE;
+
+out:
+ g_free (module_name_js);
+ g_free (module_dir_uri);
+ g_free (module_uri);
+
+ return ret;
+}
+
+static void
+peas_plugin_loader_gjs_unload (PeasPluginLoader *loader,
+ PeasPluginInfo *info)
+{
+}
+
+static void
+peas_plugin_loader_gjs_garbage_collect (PeasPluginLoader *loader)
+{
+ PeasPluginLoaderGjs *gjsloader = PEAS_PLUGIN_LOADER_GJS (loader);
+
+ if (gjsloader->context != NULL)
+ gjs_context_maybe_gc (gjsloader->context);
+}
+
+static gboolean
+peas_plugin_loader_gjs_initialize (PeasPluginLoader *loader)
+{
+ static const char *search_path[] = {
+ "resource:///org/gnome/libpeas/loaders/gjs/",
+ NULL
+ };
+ PeasPluginLoaderGjs *gjsloader = PEAS_PLUGIN_LOADER_GJS (loader);
+ gboolean ret = FALSE;
+
+ gjsloader->context = (GjsContext *)g_object_new (GJS_TYPE_CONTEXT,
+ "search-path", search_path,
+ NULL);
+
+ if (gjsloader->context != NULL)
+ {
+ GError *error = NULL;
+ guint8 status;
+
+ if (!gjs_context_eval_module_file (gjsloader->context,
+ "resource:///org/gnome/libpeas/loaders/gjs/plugin.js",
+ &status,
+ &error))
+ {
+ g_warning ("Failed to load plugin.js: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ ret = TRUE;
+ }
+
+out:
+
+ return ret;
+}
+
+static void
+peas_plugin_loader_gjs_init (PeasPluginLoaderGjs *gjsloader)
+{
+}
+
+static void
+peas_plugin_loader_gjs_finalize (GObject *object)
+{
+ PeasPluginLoaderGjs *gjsloader = PEAS_PLUGIN_LOADER_GJS (object);
+
+ g_clear_object (&gjsloader->context);
+
+ G_OBJECT_CLASS (peas_plugin_loader_gjs_parent_class)->finalize (object);
+}
+
+static void
+peas_plugin_loader_gjs_class_init (PeasPluginLoaderGjsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ PeasPluginLoaderClass *loader_class = PEAS_PLUGIN_LOADER_CLASS (klass);
+
+ quark_extension_type = g_quark_from_static_string ("peas-extension-type");
+
+ object_class->finalize = peas_plugin_loader_gjs_finalize;
+
+ loader_class->initialize = peas_plugin_loader_gjs_initialize;
+ loader_class->load = peas_plugin_loader_gjs_load;
+ loader_class->unload = peas_plugin_loader_gjs_unload;
+ loader_class->create_extension = peas_plugin_loader_gjs_create_extension;
+ loader_class->provides_extension = peas_plugin_loader_gjs_provides_extension;
+ loader_class->garbage_collect = peas_plugin_loader_gjs_garbage_collect;
+}
diff --git a/loaders/gjs/peas-plugin-loader-gjs.h b/loaders/gjs/peas-plugin-loader-gjs.h
new file mode 100644
index 0000000..8bc4128
--- /dev/null
+++ b/loaders/gjs/peas-plugin-loader-gjs.h
@@ -0,0 +1,36 @@
+/*
+ * peas-plugin-loader-gjs.h
+ * This file is part of libpeas
+ *
+ * Copyright 2023 Christian Hergert <chergert@redhat.com>
+ *
+ * libpeas is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * libpeas is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <libpeas.h>
+
+#include "libpeas/peas-plugin-loader.h"
+
+G_BEGIN_DECLS
+
+#define PEAS_TYPE_PLUGIN_LOADER_GJS (peas_plugin_loader_gjs_get_type())
+
+G_DECLARE_FINAL_TYPE (PeasPluginLoaderGjs, peas_plugin_loader_gjs, PEAS, PLUGIN_LOADER_GJS, PeasPluginLoader)
+
+G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module);
+
+G_END_DECLS
diff --git a/loaders/gjs/plugin.js b/loaders/gjs/plugin.js
new file mode 100644
index 0000000..aceb86d
--- /dev/null
+++ b/loaders/gjs/plugin.js
@@ -0,0 +1,14 @@
+function providesExtension(moduleName, extensionType) {
+ const GObject = import('gi://GObject')
+ const module = import(moduleName);
+
+ for (key in module) {
+ if ('$gtype' in module[key]) {
+ if (GObject.type_is_a(module[key]['$gtype'], extensionType)) {
+ return module[key]['$gtype'];
+ }
+ }
+ }
+
+ return GObject.TYPE_INVALID;
+}
diff --git a/loaders/meson.build b/loaders/meson.build
index 6235ff9..d75c384 100644
--- a/loaders/meson.build
+++ b/loaders/meson.build
@@ -5,3 +5,7 @@ endif
if build_python3_loader == true
subdir('python')
endif
+
+if build_gjs_loader == true
+ subdir('gjs')
+endif
diff --git a/meson.build b/meson.build
index bea1739..cd0ca2d 100644
--- a/meson.build
+++ b/meson.build
@@ -102,6 +102,7 @@ pygobject_req = '>= 3.2.0'
lua_req = '>= 5.1.0'
lua_lgi_req = '>= 0.9.0'
luajit_req = '>= 2.0'
+gjs_req = '>= 1.74'
glib_dep = dependency('glib-2.0', version: glib_req)
gobject_dep = dependency('gobject-2.0', version: glib_req)
@@ -113,6 +114,7 @@ gi_docgen_dep = dependency('gi-docgen', version: '>= 2021.7',
fallback: ['gi-docgen', 'dummy_dep'],
native: true,
required: get_option('gtk_doc'))
+gjs_dep = dependency('gjs-1.0', version: gjs_req, required: get_option('gjs'))
# From python 3.8 we neeed python3-embed
python3_dep = dependency('python3-embed', required: false)
@@ -334,6 +336,8 @@ if generate_gir and not introspection_dep.found()
generate_gir = false
endif
+build_gjs_loader = get_option('gjs')
+
build_lua51_loader = get_option('lua51')
lua51_found = (luajit_dep.found() or lua51_dep.found()) and lua_lgi_found
if build_lua51_loader and not lua51_found
diff --git a/meson_options.txt b/meson_options.txt
index 0a07dc9..48a7e8d 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,3 +1,7 @@
+option('gjs',
+ type: 'boolean', value: true,
+ description: 'Enable GJS support (requires gjs-1.0)')
+
option('lua51',
type: 'boolean', value: true,
description: 'Enable Lua 5.1 support (requires lua-lgi)')