[gjs/refactor-globals: 4/5] Add native registry for GI modules.
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/refactor-globals: 4/5] Add native registry for GI modules.
- Date: Sat, 27 Jun 2020 02:05:28 +0000 (UTC)
commit a67640cd43e8c278fb37f2ec0cdd125182062873
Author: Evan Welsh <noreply evanwelsh com>
Date: Tue Jun 16 16:25:28 2020 -0500
Add native registry for GI modules.
gi/repo.cpp | 57 ++++++++++++++++++++++++++++++++++++++------------------
gjs/global.cpp | 42 +++++++++++++++++++++++++++++++----------
gjs/global.h | 3 ++-
gjs/importer.cpp | 16 +++++++++++++++-
gjs/module.cpp | 12 +++++++++++-
gjs/module.h | 44 +++++++++++++++++++++++++++++++++++++++++++
6 files changed, 143 insertions(+), 31 deletions(-)
---
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 57458c69..73ec1839 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -61,6 +61,7 @@
#include "gjs/jsapi-class.h"
#include "gjs/jsapi-util.h"
#include "gjs/mem-private.h"
+#include "gjs/module.h"
#include "util/log.h"
struct JSFunctionSpec;
@@ -153,8 +154,13 @@ static bool resolve_namespace_object(JSContext* context,
return false;
JS::RootedValue override(context);
- if (!lookup_override_function(context, ns_id, &override))
- return false;
+
+ // We do not load overrides on the internal global.
+ if (gjs_global_is_type(context, GjsGlobalType::DEFAULT)) {
+ if (!lookup_override_function(context, ns_id, &override)) {
+ return false;
+ }
+ }
JS::RootedValue result(context);
if (!override.isUndefined() &&
@@ -640,37 +646,52 @@ lookup_override_function(JSContext *cx,
}
return true;
- fail:
+fail:
saved_exc.drop();
return false;
}
-JSObject*
-gjs_lookup_namespace_object_by_name(JSContext *context,
- JS::HandleId ns_name)
-{
- auto global = gjs_get_import_global(context);
- JS::RootedValue importer(
- context, gjs_get_global_slot(global, GjsGlobalSlot::IMPORTS));
- g_assert(importer.isObject());
-
- JS::RootedObject repo(context), importer_obj(context, &importer.toObject());
- const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
- if (!gjs_object_require_property(context, importer_obj, "importer",
- atoms.gi(), &repo)) {
+GJS_JSAPI_RETURN_CONVENTION
+static JSObject* lookup_namespace(JSContext* context, JS::HandleId ns_name) {
+ auto native_registry = gjs_get_native_module_registry(context);
+ auto it = native_registry->lookup("gi");
+ if (!it.found()) {
gjs_log_exception(context);
- gjs_throw(context, "No gi property in importer");
+ gjs_throw(context, "No gi property in native registry");
return NULL;
}
+ JS::RootedObject gi(context, it->value());
JS::RootedObject retval(context);
- if (!gjs_object_require_property(context, repo, "GI repository object",
+ if (!gjs_object_require_property(context, gi, "GI repository object",
ns_name, &retval))
return NULL;
return retval;
}
+JSObject* gjs_lookup_namespace_object_by_name(JSContext* context,
+ JS::HandleId ns_name) {
+ JSObject* global = JS::CurrentGlobalOrNull(context);
+ JSObject* ns = nullptr;
+
+ switch (gjs_global_get_type(global)) {
+ case GjsGlobalType::DEFAULT:
+ ns = lookup_namespace(context, ns_name);
+ break;
+ case GjsGlobalType::DEBUGGER:
+ ns = nullptr;
+ break;
+ }
+
+ if (!ns) {
+ return nullptr;
+ }
+
+ JS::RootedObject retval(context, ns);
+ return retval;
+}
+
const char*
gjs_info_type_name(GIInfoType type)
{
diff --git a/gjs/global.cpp b/gjs/global.cpp
index b68a2461..4e4d6b92 100644
--- a/gjs/global.cpp
+++ b/gjs/global.cpp
@@ -273,13 +273,32 @@ gjs_printerr(JSContext *context,
const JSClassOps defaultclassops = JS::DefaultGlobalClassOps;
class GjsGlobal {
+ static void finalize(JSFreeOp* op G_GNUC_UNUSED, JSObject* obj) {
+ delete static_cast<GjsModuleRegistry*>(
+ gjs_get_global_slot(obj, GjsGlobalSlot::NATIVE_REGISTRY)
+ .toPrivate());
+ }
+
+ static constexpr JSClassOps classops = {nullptr, // addProperty
+ nullptr, // deleteProperty
+ nullptr, // enumerate
+ JS_NewEnumerateStandardClasses,
+ JS_ResolveStandardClass,
+ JS_MayResolveStandardClass,
+ GjsGlobal::finalize,
+ nullptr, // call
+ nullptr, // hasInstance
+ nullptr, // construct
+ JS_GlobalObjectTraceHook};
+
static constexpr JSClass klass = {
// Keep this as "GjsGlobal" until Jasmine is upgraded to support
// globalThis
"GjsGlobal",
- JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(
- static_cast<uint32_t>(GjsGlobalSlot::LAST)),
- &defaultclassops,
+ JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_PRIVATE |
+ JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(
+ static_cast<uint32_t>(GjsGlobalSlot::LAST)),
+ &classops,
};
static constexpr JSFunctionSpec static_funcs[] = {
@@ -320,6 +339,9 @@ class GjsGlobal {
// const_cast is allowed here if we never free the realm data
JS::SetRealmPrivate(realm, const_cast<char*>(realm_name));
+ gjs_set_global_slot(global, GjsGlobalSlot::NATIVE_REGISTRY,
+ JS::PrivateValue(new GjsModuleRegistry()));
+
JS::Value v_importer =
gjs_get_global_slot(global, GjsGlobalSlot::IMPORTS);
g_assert(((void)"importer should be defined before passing null "
@@ -422,9 +444,7 @@ JSObject* gjs_create_global_object(JSContext* cx, GjsGlobalType global_type,
}
}
-GjsGlobalType gjs_global_get_type(JSContext* cx) {
- auto global = JS::CurrentGlobalOrNull(cx);
-
+GjsGlobalType gjs_global_get_type(JSObject* global) {
g_assert(global && "gjs_global_get_type called when no global is present");
auto global_type = gjs_get_global_slot(global, GjsGlobalSlot::GLOBAL_TYPE);
@@ -435,13 +455,14 @@ GjsGlobalType gjs_global_get_type(JSContext* cx) {
return static_cast<GjsGlobalType>(global_type.toInt32());
}
-GjsGlobalType gjs_global_get_type(JSObject* global) {
+bool gjs_global_is_type(JSContext* context, GjsGlobalType type) {
+ auto global = JS::CurrentGlobalOrNull(context);
auto global_type = gjs_get_global_slot(global, GjsGlobalSlot::GLOBAL_TYPE);
g_assert(global_type.isInt32() &&
"Invalid type for GLOBAL_TYPE slot. Expected int32.");
- return static_cast<GjsGlobalType>(global_type.toInt32());
+ return type == static_cast<GjsGlobalType>(global_type.toInt32());
}
/**
@@ -484,9 +505,9 @@ bool gjs_define_global_properties(JSContext* cx, JS::HandleObject global,
case GjsGlobalType::DEBUGGER:
return GjsDebuggerGlobal::define_properties(cx, global, realm_name,
bootstrap_script);
- default:
- return true;
}
+
+ return false;
}
template <typename GlobalSlot>
@@ -505,6 +526,7 @@ JS::Value gjs_get_global_slot(JSObject* global, GlobalSlot slot) {
template JS::Value gjs_get_global_slot(JSObject* global, GjsGlobalSlot slot);
decltype(GjsGlobal::klass) constexpr GjsGlobal::klass;
+decltype(GjsGlobal::classops) constexpr GjsGlobal::classops;
decltype(GjsGlobal::static_funcs) constexpr GjsGlobal::static_funcs;
decltype(GjsDebuggerGlobal::klass) constexpr GjsDebuggerGlobal::klass;
diff --git a/gjs/global.h b/gjs/global.h
index 5dca88ab..31810d77 100644
--- a/gjs/global.h
+++ b/gjs/global.h
@@ -40,6 +40,7 @@ enum class GjsGlobalType {
enum class GjsGlobalSlot : uint32_t {
GLOBAL_TYPE = 0,
IMPORTS,
+ NATIVE_REGISTRY,
PROTOTYPE_gtype,
PROTOTYPE_importer,
PROTOTYPE_function,
@@ -63,7 +64,7 @@ enum class GjsGlobalSlot : uint32_t {
LAST,
};
-GjsGlobalType gjs_global_get_type(JSContext* cx);
+bool gjs_global_is_type(JSContext* cx, GjsGlobalType type);
GjsGlobalType gjs_global_get_type(JSObject* global);
GJS_JSAPI_RETURN_CONVENTION
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 71ec6683..5809b6c3 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -300,10 +300,24 @@ gjs_import_native_module(JSContext *cx,
{
gjs_debug(GJS_DEBUG_IMPORTER, "Importing '%s'", parse_name);
+ auto native_registry = gjs_get_native_module_registry(cx);
+ auto it = native_registry->lookupForAdd(parse_name);
+
JS::RootedObject module(cx);
+
+ if (it.found()) {
+ module.set(it->value().get());
+ return define_meta_properties(cx, module, nullptr, parse_name,
+ importer) &&
+ JS_DefineProperty(cx, importer, parse_name, module,
+ GJS_MODULE_PROP_FLAGS);
+ }
+
return gjs_load_native_module(cx, parse_name, &module) &&
+ native_registry->put(parse_name, module) &&
define_meta_properties(cx, module, nullptr, parse_name, importer) &&
- JS_DefineProperty(cx, importer, parse_name, module, GJS_MODULE_PROP_FLAGS);
+ JS_DefineProperty(cx, importer, parse_name, module,
+ GJS_MODULE_PROP_FLAGS);
}
GJS_JSAPI_RETURN_CONVENTION
diff --git a/gjs/module.cpp b/gjs/module.cpp
index a7d7b7ee..f028a25b 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -1,6 +1,7 @@
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
* Copyright (c) 2017 Philip Chimento <philip chimento gmail com>
+ * Copyright (c) 2020 Evan Welsh <contact evanwelsh com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -43,6 +44,7 @@
#include <jsapi.h> // for JS_DefinePropertyById, ...
#include "gjs/context-private.h"
+#include "gjs/global.h"
#include "gjs/jsapi-util.h"
#include "gjs/mem-private.h"
#include "gjs/module.h"
@@ -51,7 +53,7 @@
class GjsScriptModule {
char *m_name;
- GjsScriptModule(const char* name) {
+ explicit GjsScriptModule(const char* name) {
m_name = g_strdup(name);
GJS_INC_COUNTER(module);
}
@@ -269,3 +271,11 @@ gjs_module_import(JSContext *cx,
decltype(GjsScriptModule::klass) constexpr GjsScriptModule::klass;
decltype(GjsScriptModule::class_ops) constexpr GjsScriptModule::class_ops;
+
+GjsModuleRegistry* gjs_get_native_module_registry(JSContext* js_context) {
+ auto global = gjs_get_import_global(js_context);
+ auto native_registry =
+ gjs_get_global_slot(global, GjsGlobalSlot::NATIVE_REGISTRY);
+
+ return static_cast<GjsModuleRegistry*>(native_registry.toPrivate());
+}
diff --git a/gjs/module.h b/gjs/module.h
index c63d6852..a843cda9 100644
--- a/gjs/module.h
+++ b/gjs/module.h
@@ -1,6 +1,7 @@
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
* Copyright (c) 2017 Philip Chimento <philip chimento gmail com>
+ * Copyright (c) 2020 Evan Welsh <contact evanwelsh com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -28,10 +29,50 @@
#include <gio/gio.h>
+#include <js/GCHashTable.h>
#include <js/TypeDecls.h>
+#include <string>
+
#include "gjs/macros.h"
+namespace JS {
+template <typename T>
+struct GCPolicy;
+template <typename T>
+class Heap;
+} // namespace JS
+
+namespace js {
+class SystemAllocPolicy;
+}
+
+class CppStringHashPolicy {
+ public:
+ typedef std::string Lookup;
+
+ static js::HashNumber hash(const Lookup& l) {
+ return std::hash<std::string>{}(std::string(l));
+ }
+
+ static bool match(const std::string& k, const Lookup& l) {
+ return k.compare(l) == 0;
+ }
+
+ static void rekey(std::string* k, const std::string& newKey) {
+ *k = newKey;
+ }
+};
+
+namespace JS {
+template <>
+struct GCPolicy<std::string> : public IgnoreGCPolicy<std::string> {};
+} // namespace JS
+
+using GjsModuleRegistry =
+ JS::GCHashMap<std::string, JS::Heap<JSObject*>, CppStringHashPolicy,
+ js::SystemAllocPolicy>;
+
GJS_JSAPI_RETURN_CONVENTION
JSObject *
gjs_module_import(JSContext *cx,
@@ -40,4 +81,7 @@ gjs_module_import(JSContext *cx,
const char *name,
GFile *file);
+GJS_JSAPI_RETURN_CONVENTION
+GjsModuleRegistry* gjs_get_native_module_registry(JSContext* js_context);
+
#endif // GJS_MODULE_H_
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]