[gjs/ewlsh/refactor-argv] Refactor ARGV handling and add system.scriptArgv.




commit 229a8449190dc6b61041791d3fcbd8285e530439
Author: Evan Welsh <contact evanwelsh com>
Date:   Sat Jan 30 14:02:40 2021 -0800

    Refactor ARGV handling and add system.scriptArgv.

 gjs/console.cpp                      | 11 ++---------
 gjs/context-private.h                |  6 ++++++
 gjs/context.cpp                      | 23 +++++++++++++++++++++++
 gjs/context.h                        |  5 +++++
 js.gresource.xml                     |  1 +
 modules/modules.cpp                  |  2 +-
 modules/script/_bootstrap/default.js | 14 ++++++++++++++
 modules/script/system.js             | 16 ++++++++++++++++
 modules/system.cpp                   | 13 +++++++++++++
 9 files changed, 81 insertions(+), 10 deletions(-)
---
diff --git a/gjs/console.cpp b/gjs/console.cpp
index 9654f0b0..fcc8d5e8 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -161,16 +161,9 @@ check_script_args_for_stray_gjs_args(int           argc,
 int define_argv_and_eval_script(GjsContext* js_context, int argc,
                                 char* const* argv, const char* script,
                                 size_t len, const char* filename) {
-    GError* error = nullptr;
-
-    /* prepare command line arguments */
-    if (!gjs_context_define_string_array(
-            js_context, "ARGV", argc, const_cast<const char**>(argv), &error)) {
-        g_critical("Failed to define ARGV: %s", error->message);
-        g_clear_error(&error);
-        return 1;
-    }
+    gjs_context_set_argv(js_context, argc, const_cast<const char**>(argv));
 
+    GError* error = nullptr;
     /* evaluate the script */
     int code;
     if (!gjs_context_eval(js_context, script, len, filename, &code, &error)) {
diff --git a/gjs/context-private.h b/gjs/context-private.h
index 4f5adc8a..cdac27e5 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -10,8 +10,10 @@
 #include <stdint.h>
 #include <sys/types.h>  // for ssize_t
 
+#include <string>
 #include <type_traits>  // for is_same
 #include <unordered_map>
+#include <vector>
 
 #include <glib-object.h>
 #include <glib.h>
@@ -81,6 +83,8 @@ class GjsContextPrivate : public JS::JobQueue {
 
     GjsAtoms* m_atoms;
 
+    std::vector<std::string> m_args;
+
     JobQueueStorage m_job_queue;
     unsigned m_idle_drain_handler;
 
@@ -175,6 +179,8 @@ class GjsContextPrivate : public JS::JobQueue {
     void set_should_listen_sigusr2(bool value) {
         m_should_listen_sigusr2 = value;
     }
+    void set_args(const std::vector<std::string>& args);
+    [[nodiscard]] JSObject* build_args_array();
     [[nodiscard]] bool is_owner_thread() const {
         return m_owner_thread == g_thread_self();
     }
diff --git a/gjs/context.cpp b/gjs/context.cpp
index f302409c..174d18a0 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -508,6 +508,14 @@ GjsContextPrivate::GjsContextPrivate(JSContext* cx, GjsContext* public_context)
     }
 }
 
+void GjsContextPrivate::set_args(const std::vector<std::string>& args) {
+    m_args = args;
+}
+
+JSObject* GjsContextPrivate::build_args_array() {
+    return gjs_build_string_array(m_cx, m_args);
+}
+
 static void
 gjs_context_get_property (GObject     *object,
                           guint        prop_id,
@@ -1109,6 +1117,13 @@ gjs_context_define_string_array(GjsContext  *js_context,
         strings = {array_values, array_values + array_length};
     }
 
+    // ARGV is a special case to preserve backwards compatibility.
+    if (strcmp(array_name, "ARGV") == 0) {
+        gjs->set_args(strings);
+
+        return true;
+    }
+
     JS::RootedObject global_root(gjs->context(), gjs->global());
     if (!gjs_define_string_array(gjs->context(), global_root, array_name,
                                  strings, JSPROP_READONLY | JSPROP_PERMANENT)) {
@@ -1123,6 +1138,14 @@ gjs_context_define_string_array(GjsContext  *js_context,
     return true;
 }
 
+void gjs_context_set_argv(GjsContext* js_context, ssize_t array_length,
+                          const char** array_values) {
+    g_return_if_fail(GJS_IS_CONTEXT(js_context));
+    GjsContextPrivate* gjs = GjsContextPrivate::from_object(js_context);
+    std::vector<std::string> args(array_values, array_values + array_length);
+    gjs->set_args(args);
+}
+
 static GjsContext *current_context;
 
 GjsContext *
diff --git a/gjs/context.h b/gjs/context.h
index 43f936b5..af828417 100644
--- a/gjs/context.h
+++ b/gjs/context.h
@@ -12,6 +12,7 @@
 #endif
 
 #include <stdbool.h>    /* IWYU pragma: keep */
+#include <sys/types.h>  // for ssize_t
 
 #ifndef _WIN32
 #    include <signal.h> /* for siginfo_t */
@@ -52,6 +53,10 @@ GJS_EXPORT GJS_USE bool gjs_context_define_string_array(
     GjsContext* js_context, const char* array_name, gssize array_length,
     const char** array_values, GError** error);
 
+GJS_EXPORT void gjs_context_set_argv(GjsContext* js_context,
+                                     ssize_t array_length,
+                                     const char** array_values);
+
 GJS_EXPORT GJS_USE GList* gjs_context_get_all(void);
 
 GJS_EXPORT GJS_USE GjsContext* gjs_context_get_current(void);
diff --git a/js.gresource.xml b/js.gresource.xml
index bdb6b665..d6eb46ea 100644
--- a/js.gresource.xml
+++ b/js.gresource.xml
@@ -20,6 +20,7 @@
     <file>modules/script/mainloop.js</file>
     <file>modules/script/jsUnit.js</file>
     <file>modules/script/signals.js</file>
+    <file>modules/script/system.js</file>
     <file>modules/script/format.js</file>
     <file>modules/script/package.js</file>
 
diff --git a/modules/modules.cpp b/modules/modules.cpp
index c9b7061d..b95f193b 100644
--- a/modules/modules.cpp
+++ b/modules/modules.cpp
@@ -20,7 +20,7 @@ gjs_register_static_modules (void)
 #ifdef ENABLE_CAIRO
     gjs_register_native_module("cairoNative", gjs_js_define_cairo_stuff);
 #endif
-    gjs_register_native_module("system", gjs_js_define_system_stuff);
+    gjs_register_native_module("_systemNative", gjs_js_define_system_stuff);
     gjs_register_native_module("console", gjs_define_console_stuff);
     gjs_register_native_module("_print", gjs_define_print_stuff);
 }
diff --git a/modules/script/_bootstrap/default.js b/modules/script/_bootstrap/default.js
index e31d80cb..0ede409a 100644
--- a/modules/script/_bootstrap/default.js
+++ b/modules/script/_bootstrap/default.js
@@ -6,8 +6,22 @@
     'use strict';
 
     const {print, printerr, log, logError} = imports._print;
+    const {buildScriptArgv} = imports._systemNative;
+
+    let ARGV = null;
 
     Object.defineProperties(exports, {
+        ARGV: {
+            configurable: false,
+            enumerable: true,
+            get() {
+                if (!ARGV)
+                    ARGV = buildScriptArgv();
+
+
+                return ARGV;
+            },
+        },
         print: {
             configurable: false,
             enumerable: true,
diff --git a/modules/script/system.js b/modules/script/system.js
new file mode 100644
index 00000000..75d6a8bd
--- /dev/null
+++ b/modules/script/system.js
@@ -0,0 +1,16 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+// SPDX-FileCopyrightText: 2021 Evan Welsh <contact evanwelsh com>
+
+/* exported scriptArgv */
+
+var scriptArgv;
+
+(() => {
+    const {buildScriptArgv, ..._systemNative} = imports._systemNative;
+
+    Object.assign(this, _systemNative);
+
+    scriptArgv = buildScriptArgv();
+})();
diff --git a/modules/system.cpp b/modules/system.cpp
index 6195fe34..878ce4a2 100644
--- a/modules/system.cpp
+++ b/modules/system.cpp
@@ -181,6 +181,18 @@ static bool gjs_clear_date_caches(JSContext*, unsigned argc, JS::Value* vp) {
     return true;
 }
 
+static bool gjs_build_script_argv(JSContext* cx, unsigned argc, JS::Value* vp) {
+    JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+    GjsContextPrivate* priv = GjsContextPrivate::from_cx(cx);
+
+    JS::RootedObject array(cx, priv->build_args_array());
+    if (!array)
+        return false;
+
+    args.rval().setObject(*array);
+    return true;
+}
+
 static JSFunctionSpec module_funcs[] = {
     JS_FN("addressOf", gjs_address_of, 1, GJS_MODULE_PROP_FLAGS),
     JS_FN("addressOfGObject", gjs_address_of_gobject, 1, GJS_MODULE_PROP_FLAGS),
@@ -190,6 +202,7 @@ static JSFunctionSpec module_funcs[] = {
     JS_FN("gc", gjs_gc, 0, GJS_MODULE_PROP_FLAGS),
     JS_FN("exit", gjs_exit, 0, GJS_MODULE_PROP_FLAGS),
     JS_FN("clearDateCaches", gjs_clear_date_caches, 0, GJS_MODULE_PROP_FLAGS),
+    JS_FN("buildScriptArgv", gjs_build_script_argv, GJS_MODULE_PROP_FLAGS, 0),
     JS_FS_END};
 
 bool


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