[gjs/esm-local-imports: 1/6] console: Add --module evaluation option.
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/esm-local-imports: 1/6] console: Add --module evaluation option.
- Date: Mon, 15 Jun 2020 16:40:57 +0000 (UTC)
commit 0e33eb327134e6e1bc8b1577fb051379f5b51c40
Author: Evan Welsh <noreply evanwelsh com>
Date: Sat Apr 11 11:04:57 2020 -0500
console: Add --module evaluation option.
gjs/console.cpp | 41 +++++++++++++++++++++++-----
gjs/context-private.h | 8 ++++++
gjs/context.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++-
gjs/context.h | 12 +++++++++
4 files changed, 128 insertions(+), 8 deletions(-)
---
diff --git a/gjs/console.cpp b/gjs/console.cpp
index 9e335594..e3729ed7 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -38,6 +38,7 @@
#include <glib.h>
#include <gjs/gjs.h>
+#include <gjs/jsapi-util.h>
static char **include_path = NULL;
static char **coverage_prefixes = NULL;
@@ -47,6 +48,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 **);
@@ -60,6 +62,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-path", "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)",
@@ -201,7 +205,23 @@ 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* full_path = g_file_get_path(output);
+ if (!gjs_context_register_module(js_context, full_path, full_path,
+ script, len, &error)) {
+ g_printerr("%s\n", error->message);
+ code = 1;
+ }
+
+ uint8_t code_8 = 0;
+ if (!gjs_context_eval_module(js_context, full_path, &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);
@@ -269,6 +289,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)) {
@@ -298,7 +319,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];
@@ -335,11 +363,10 @@ main(int argc, char **argv)
g_unsetenv("GJS_TRACE_FD"); /* ignore env var in eval() */
}
- 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 1b1e5562..e109743f 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -141,6 +141,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;
@@ -190,6 +191,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;
}
@@ -218,6 +220,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);
@@ -245,6 +250,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,
+ const char* mod_text, size_t mod_len, 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 04f28f73..0063056d 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -33,6 +33,7 @@
# include <process.h>
#endif
+#include <codecvt>
#include <new>
#include <string> // for u16string
#include <unordered_map>
@@ -81,6 +82,7 @@
#include "gjs/error-types.h"
#include "gjs/global.h"
#include "gjs/importer.h"
+#include "gjs/jsapi-util-args.h"
#include "gjs/jsapi-util.h"
#include "gjs/mem.h"
#include "gjs/native.h"
@@ -150,6 +152,7 @@ enum {
PROP_PROGRAM_NAME,
PROP_PROFILER_ENABLED,
PROP_PROFILER_SIGUSR2,
+ PROP_MODULES_ENABLED,
};
static GMutex contexts_lock;
@@ -299,6 +302,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
@@ -571,8 +581,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;
}
}
@@ -936,6 +949,28 @@ 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, const char* module,
+ size_t module_len, 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, module, module_len,
+ error);
+}
+
bool GjsContextPrivate::eval(const char* script, ssize_t script_len,
const char* filename, int* exit_status_p,
GError** error) {
@@ -1008,6 +1043,28 @@ 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 Implement eval_module
+ g_error(
+ "GjsContextPrivate::eval_module is not implemented. Exiting with "
+ "error.");
+
+ return false;
+}
+
+bool GjsContextPrivate::register_module(const char* identifier,
+ const char* filename,
+ const char* module, size_t module_len,
+ GError** error) {
+ // TODO Implement register_module
+ g_warning(
+ "GjsContextPrivate::register_module is not yet implemented. Printing "
+ "module text...");
+ g_warning("%s", module);
+ return true;
+}
+
bool
gjs_context_eval_file(GjsContext *js_context,
const char *filename,
@@ -1027,6 +1084,22 @@ 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) {
+ char* module;
+ size_t module_len;
+ GjsAutoUnref<GFile> file = g_file_new_for_commandline_arg(filename);
+
+ if (!g_file_load_contents(file, nullptr, &module, &module_len, nullptr,
+ error))
+ return false;
+ GjsAutoChar module_ref = module;
+
+ return gjs_context_register_module(js_context, filename, filename, module,
+ module_len, error) &&
+ gjs_context_eval_module(js_context, filename, 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 13be25b9..1b1846ab 100644
--- a/gjs/context.h
+++ b/gjs/context.h
@@ -29,6 +29,7 @@
#endif
#include <stdbool.h> /* IWYU pragma: keep */
+#include <stdint.h>
#ifndef _WIN32
# include <signal.h> /* for siginfo_t */
@@ -61,10 +62,21 @@ 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,
+ const char* module, size_t module_len, 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]