[gjs/esm/static-imports: 57/60] console: Add --module evaluation option.




commit 5c3ba44dbd8ce198a91c2cca21709f7bc2ff8a4e
Author: Evan Welsh <noreply evanwelsh com>
Date:   Wed Oct 28 19:21:53 2020 -0500

    console: Add --module evaluation option.

 gjs/console.cpp       | 41 +++++++++++++++++++++++-----
 gjs/context-private.h |  8 ++++++
 gjs/context.cpp       | 74 +++++++++++++++++++++++++++++++++++++++++++++++++--
 gjs/context.h         | 13 +++++++++
 4 files changed, 127 insertions(+), 9 deletions(-)
---
diff --git a/gjs/console.cpp b/gjs/console.cpp
index 9654f0b0..1c4aff07 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -5,6 +5,7 @@
 #include <config.h>  // for PACKAGE_STRING
 
 #include <locale.h>  // for setlocale, LC_ALL
+#include <stdint.h>  // for uint8_t
 #include <stdlib.h>  // for exit
 #include <string.h>  // for strcmp, strlen
 
@@ -19,6 +20,7 @@
 #include <glib.h>
 
 #include <gjs/gjs.h>
+#include <gjs/jsapi-util.h>
 
 static char **include_path = NULL;
 static char **coverage_prefixes = NULL;
@@ -28,6 +30,7 @@ static char *command = NULL;
 static gboolean print_version = false;
 static gboolean print_js_version = false;
 static gboolean debugging = false;
+static gboolean exec_as_module = false;
 static bool enable_profiler = false;
 
 static gboolean parse_profile_arg(const char *, const char *, void *, GError **);
@@ -41,6 +44,8 @@ static GOptionEntry entries[] = {
     { "coverage-prefix", 'C', 0, G_OPTION_ARG_STRING_ARRAY, &coverage_prefixes, "Add the prefix PREFIX to 
the list of files to generate coverage info for", "PREFIX" },
     { "coverage-output", 0, 0, G_OPTION_ARG_STRING, &coverage_output_path, "Write coverage output to a 
directory DIR. This option is mandatory when using --coverage-prefix", "DIR", },
     { "include-path", 'I', 0, G_OPTION_ARG_STRING_ARRAY, &include_path, "Add the directory DIR to the list 
of directories to search for js files.", "DIR" },
+    { "module", 'm', 0, G_OPTION_ARG_NONE, &exec_as_module,
+                        "Execute the input as a js module (implies strict mode)" },
     { "profile", 0, G_OPTION_FLAG_OPTIONAL_ARG | G_OPTION_FLAG_FILENAME,
         G_OPTION_ARG_CALLBACK, reinterpret_cast<void *>(&parse_profile_arg),
         "Enable the profiler and write output to FILE (default: gjs-$PID.syscap)",
@@ -173,7 +178,22 @@ int define_argv_and_eval_script(GjsContext* js_context, int argc,
 
     /* evaluate the script */
     int code;
-    if (!gjs_context_eval(js_context, script, len, filename, &code, &error)) {
+    if (exec_as_module) {
+        GjsAutoUnref<GFile> output = g_file_new_for_commandline_arg(filename);
+        char* uri = g_file_get_uri(output);
+        if (!gjs_context_register_module(js_context, uri, uri, &error)) {
+            g_printerr("%s\n", error->message);
+            code = 1;
+        }
+
+        uint8_t code_8 = 0;
+        if (!gjs_context_eval_module(js_context, uri, &code_8, &error)) {
+            code = code_8;
+            if (!g_error_matches(error, GJS_ERROR, GJS_ERROR_SYSTEM_EXIT))
+                g_critical("%s", error->message);
+        }
+    } else if (!gjs_context_eval(js_context, script, len, filename, &code,
+                                 &error)) {
         if (!g_error_matches(error, GJS_ERROR, GJS_ERROR_SYSTEM_EXIT))
             g_critical("%s", error->message);
         g_clear_error(&error);
@@ -240,6 +260,7 @@ main(int argc, char **argv)
     print_version = false;
     print_js_version = false;
     debugging = false;
+    exec_as_module = false;
     g_option_context_set_ignore_unknown_options(context, false);
     g_option_context_set_help_enabled(context, true);
     if (!g_option_context_parse_strv(context, &gjs_argv, &error)) {
@@ -269,7 +290,14 @@ main(int argc, char **argv)
         filename = "<command line>";
         program_name = gjs_argv[0];
     } else if (gjs_argc == 1) {
-        script = g_strdup("const Console = imports.console; Console.interact();");
+        if (exec_as_module) {
+            script = g_strdup(
+                "throw new Error('Console interaction is not implemented with "
+                "the --module option. Exiting with error.')");
+        } else {
+            script = g_strdup(
+                "const Console = imports.console; Console.interact();");
+        }
         len = strlen(script);
         filename = "<stdin>";
         program_name = gjs_argv[0];
@@ -315,11 +343,10 @@ main(int argc, char **argv)
     if (coverage_prefixes)
         gjs_coverage_enable();
 
-    js_context = (GjsContext*) g_object_new(GJS_TYPE_CONTEXT,
-                                            "search-path", include_path,
-                                            "program-name", program_name,
-                                            "profiler-enabled", enable_profiler,
-                                            NULL);
+    js_context = (GjsContext*)g_object_new(
+        GJS_TYPE_CONTEXT, "search-path", include_path, "program-name",
+        program_name, "profiler-enabled", enable_profiler, "modules",
+        exec_as_module, NULL);
 
     env_coverage_output_path = g_getenv("GJS_COVERAGE_OUTPUT");
     if (env_coverage_output_path != NULL) {
diff --git a/gjs/context-private.h b/gjs/context-private.h
index 8add9c2b..bdc22120 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -119,6 +119,7 @@ class GjsContextPrivate : public JS::JobQueue {
     bool m_force_gc : 1;
     bool m_draining_job_queue : 1;
     bool m_should_profile : 1;
+    bool m_exec_as_module : 1;
     bool m_should_listen_sigusr2 : 1;
 
     int64_t m_sweep_begin_time;
@@ -172,6 +173,7 @@ class GjsContextPrivate : public JS::JobQueue {
     void set_program_name(char* value) { m_program_name = value; }
     void set_search_path(char** value) { m_search_path = value; }
     void set_should_profile(bool value) { m_should_profile = value; }
+    void set_execute_as_module(bool value) { m_exec_as_module = value; }
     void set_should_listen_sigusr2(bool value) {
         m_should_listen_sigusr2 = value;
     }
@@ -199,6 +201,9 @@ class GjsContextPrivate : public JS::JobQueue {
                          ssize_t script_len, const char* filename,
                          JS::MutableHandleValue retval);
     GJS_JSAPI_RETURN_CONVENTION
+    bool eval_module(const char* identifier, uint8_t* exit_code_p,
+                     GError** error);
+    GJS_JSAPI_RETURN_CONVENTION
     bool call_function(JS::HandleObject this_obj, JS::HandleValue func_val,
                        const JS::HandleValueArray& args,
                        JS::MutableHandleValue rval);
@@ -226,6 +231,9 @@ class GjsContextPrivate : public JS::JobQueue {
     void register_unhandled_promise_rejection(uint64_t id, GjsAutoChar&& stack);
     void unregister_unhandled_promise_rejection(uint64_t id);
 
+    bool register_module(const char* identifier, const char* filename,
+                         GError** error);
+
     void set_sweeping(bool value);
 
     static void trace(JSTracer* trc, void* data);
diff --git a/gjs/context.cpp b/gjs/context.cpp
index f302409c..e28e7109 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -5,7 +5,7 @@
 #include <config.h>
 
 #include <signal.h>  // for sigaction, SIGUSR1, sa_handler
-#include <stdint.h>
+#include <stdint.h>  // for uint64_t
 #include <stdio.h>      // for FILE, fclose, size_t
 #include <string.h>     // for memset
 
@@ -123,6 +123,7 @@ enum {
     PROP_PROGRAM_NAME,
     PROP_PROFILER_ENABLED,
     PROP_PROFILER_SIGUSR2,
+    PROP_MODULES_ENABLED,
 };
 
 static GMutex contexts_lock;
@@ -272,6 +273,13 @@ gjs_context_class_init(GjsContextClass *klass)
     g_object_class_install_property(object_class, PROP_PROFILER_SIGUSR2, pspec);
     g_param_spec_unref(pspec);
 
+    pspec = g_param_spec_boolean(
+        "modules", "Modules enabled",
+        "Whether to profile JS code run by this context", FALSE,
+        GParamFlags(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property(object_class, PROP_MODULES_ENABLED, pspec);
+    g_param_spec_unref(pspec);
+
     /* For GjsPrivate */
     {
 #ifdef G_OS_WIN32
@@ -547,8 +555,11 @@ gjs_context_set_property (GObject      *object,
     case PROP_PROFILER_SIGUSR2:
         gjs->set_should_listen_sigusr2(g_value_get_boolean(value));
         break;
+    case PROP_MODULES_ENABLED:
+        gjs->set_execute_as_module(g_value_get_boolean(value));
+        break;
     default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
     }
 }
@@ -913,6 +924,26 @@ gjs_context_eval(GjsContext   *js_context,
     return gjs->eval(script, script_len, filename, exit_status_p, error);
 }
 
+bool gjs_context_eval_module(GjsContext* js_context, const char* name,
+                             uint8_t* exit_code, GError** error) {
+    g_return_val_if_fail(GJS_IS_CONTEXT(js_context), false);
+
+    GjsAutoUnref<GjsContext> js_context_ref(js_context, GjsAutoTakeOwnership());
+
+    GjsContextPrivate* gjs = GjsContextPrivate::from_object(js_context);
+    return gjs->eval_module(name, exit_code, error);
+}
+
+bool gjs_context_register_module(GjsContext* js_context, const char* identifier,
+                                 const char* filename, GError** error) {
+    g_return_val_if_fail(GJS_IS_CONTEXT(js_context), false);
+
+    GjsAutoUnref<GjsContext> js_context_ref(js_context, GjsAutoTakeOwnership());
+
+    GjsContextPrivate* gjs = GjsContextPrivate::from_object(js_context);
+    return gjs->register_module(identifier, filename, error);
+}
+
 bool GjsContextPrivate::eval(const char* script, ssize_t script_len,
                              const char* filename, int* exit_status_p,
                              GError** error) {
@@ -985,6 +1016,36 @@ bool GjsContextPrivate::eval(const char* script, ssize_t script_len,
     return true;
 }
 
+bool GjsContextPrivate::eval_module(const char* identifier,
+                                    uint8_t* exit_status_p, GError** error) {
+    // TODO(ewlsh): Implement eval_module
+    g_print("GjsContextPrivate::eval_module called on identifier %s.",
+            identifier);
+
+    *exit_status_p = 1;
+    *error = nullptr;
+
+    g_error(
+        "GjsContextPrivate::eval_module is not implemented. Exiting with "
+        "error.");
+
+    return false;
+}
+
+bool GjsContextPrivate::register_module(const char* identifier,
+                                        const char* filename,
+                                        GError** error G_GNUC_UNUSED) {
+    // TODO(ewlsh): Implement register_module
+    g_warning(
+        "GjsContextPrivate::register_module is not yet implemented. Printing "
+        "module...");
+
+    *error = nullptr;
+
+    g_warning("Identifier: %s\nFilename: %s\n", identifier, filename);
+    return true;
+}
+
 bool
 gjs_context_eval_file(GjsContext    *js_context,
                       const char    *filename,
@@ -1004,6 +1065,15 @@ gjs_context_eval_file(GjsContext    *js_context,
                             exit_status_p, error);
 }
 
+bool gjs_context_eval_module_file(GjsContext* js_context, const char* filename,
+                                  uint8_t* exit_status_p, GError** error) {
+    GjsAutoUnref<GFile> file = g_file_new_for_commandline_arg(filename);
+    char* fileuri = g_file_get_uri(file);
+
+    return gjs_context_register_module(js_context, fileuri, fileuri, error) &&
+           gjs_context_eval_module(js_context, fileuri, exit_status_p, error);
+}
+
 /*
  * GjsContextPrivate::eval_with_scope:
  * @scope_object: an object to use as the global scope, or nullptr
diff --git a/gjs/context.h b/gjs/context.h
index 43f936b5..af0a9d33 100644
--- a/gjs/context.h
+++ b/gjs/context.h
@@ -12,6 +12,7 @@
 #endif
 
 #include <stdbool.h>    /* IWYU pragma: keep */
+#include <stdint.h>
 
 #ifndef _WIN32
 #    include <signal.h> /* for siginfo_t */
@@ -44,10 +45,22 @@ GJS_EXPORT GJS_USE bool gjs_context_eval_file(GjsContext* js_context,
                                               const char* filename,
                                               int* exit_status_p,
                                               GError** error);
+GJS_EXPORT GJS_USE bool gjs_context_eval_module_file(GjsContext* js_context,
+                                                     const char* filename,
+                                                     uint8_t* exit_status_p,
+                                                     GError** error);
 GJS_EXPORT GJS_USE bool gjs_context_eval(GjsContext* js_context,
                                          const char* script, gssize script_len,
                                          const char* filename,
                                          int* exit_status_p, GError** error);
+GJS_EXPORT GJS_USE bool gjs_context_register_module(GjsContext* context,
+                                                    const char* name,
+                                                    const char* filename,
+                                                    GError** error);
+GJS_EXPORT GJS_USE bool gjs_context_eval_module(GjsContext* context,
+                                                const char* name,
+                                                uint8_t* exit_code,
+                                                GError** error);
 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);


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