[gjs: 1/2] Implement system.programPath API
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 1/2] Implement system.programPath API
- Date: Thu, 11 Feb 2021 07:19:03 +0000 (UTC)
commit f6d0013666b7c55a4812592db0a80aa21acdd570
Author: Evan Welsh <contact evanwelsh com>
Date: Sun Jan 31 16:22:04 2021 -0800
Implement system.programPath API
This API exposes the full path of the executed program from gjs-console.
gjs/atoms.h | 1 +
gjs/console.cpp | 10 +++++++---
gjs/context-private.h | 3 +++
gjs/context.cpp | 17 +++++++++++++++++
installed-tests/js/testSystem.js | 6 ++++++
installed-tests/scripts/testCommandLine.sh | 16 +++++++++++++++-
modules/system.cpp | 19 ++++++++++++++++---
7 files changed, 65 insertions(+), 7 deletions(-)
---
diff --git a/gjs/atoms.h b/gjs/atoms.h
index 7fe061f1..424f6ea2 100644
--- a/gjs/atoms.h
+++ b/gjs/atoms.h
@@ -53,6 +53,7 @@ class JSTracer;
macro(param_spec, "ParamSpec") \
macro(parent_module, "__parentModule__") \
macro(program_invocation_name, "programInvocationName") \
+ macro(program_path, "programPath") \
macro(prototype, "prototype") \
macro(search_path, "searchPath") \
macro(signal_id, "signalId") \
diff --git a/gjs/console.cpp b/gjs/console.cpp
index e355bf85..7c39f39e 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -286,6 +286,7 @@ main(int argc, char **argv)
exit(0);
}
+ GjsAutoChar program_path = nullptr;
gjs_argc = g_strv_length(gjs_argv);
if (command != NULL) {
script = command;
@@ -308,10 +309,13 @@ main(int argc, char **argv)
/* All unprocessed options should be in script_argv */
g_assert(gjs_argc == 2);
error = NULL;
- if (!g_file_get_contents(gjs_argv[1], &script, &len, &error)) {
+ GjsAutoUnref<GFile> input = g_file_new_for_commandline_arg(gjs_argv[1]);
+ if (!g_file_load_contents(input, nullptr, &script, &len, nullptr,
+ &error)) {
g_printerr("%s\n", error->message);
exit(1);
}
+ program_path = g_file_get_path(input);
filename = gjs_argv[1];
program_name = gjs_argv[1];
}
@@ -347,8 +351,8 @@ main(int argc, char **argv)
js_context = GJS_CONTEXT(g_object_new(
GJS_TYPE_CONTEXT, "search-path", include_path, "program-name",
- program_name, "profiler-enabled", enable_profiler, "exec-as-module",
- exec_as_module, nullptr));
+ program_name, "program-path", program_path.get(), "profiler-enabled",
+ enable_profiler, "exec-as-module", exec_as_module, nullptr));
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 3a1db048..6f5cba47 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -75,6 +75,7 @@ class GjsContextPrivate : public JS::JobQueue {
GThread* m_owner_thread;
char* m_program_name;
+ char* m_program_path;
char** m_search_path;
@@ -180,6 +181,8 @@ class GjsContextPrivate : public JS::JobQueue {
[[nodiscard]] bool sweeping() const { return m_in_gc_sweep; }
[[nodiscard]] const char* program_name() const { return m_program_name; }
void set_program_name(char* value) { m_program_name = value; }
+ GJS_USE const char* program_path(void) const { return m_program_path; }
+ void set_program_path(char* value) { m_program_path = 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; }
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 379f623d..59310a69 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -127,6 +127,7 @@ GjsContextPrivate* GjsContextPrivate::from_current_context() {
enum {
PROP_0,
+ PROP_PROGRAM_PATH,
PROP_SEARCH_PATH,
PROP_PROGRAM_NAME,
PROP_PROFILER_ENABLED,
@@ -248,6 +249,15 @@ gjs_context_class_init(GjsContextClass *klass)
pspec);
g_param_spec_unref(pspec);
+ pspec = g_param_spec_string(
+ "program-path", "Executed File Path",
+ "The full path of the launched file or NULL if GJS was launched from "
+ "the C API or interactive console.",
+ nullptr, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property(object_class, PROP_PROGRAM_PATH, pspec);
+ g_param_spec_unref(pspec);
+
/**
* GjsContext:profiler-enabled:
*
@@ -418,6 +428,7 @@ void GjsContextPrivate::dispose(void) {
GjsContextPrivate::~GjsContextPrivate(void) {
g_clear_pointer(&m_search_path, g_strfreev);
+ g_clear_pointer(&m_program_path, g_free);
g_clear_pointer(&m_program_name, g_free);
}
@@ -600,6 +611,9 @@ gjs_context_get_property (GObject *object,
case PROP_PROGRAM_NAME:
g_value_set_string(value, gjs->program_name());
break;
+ case PROP_PROGRAM_PATH:
+ g_value_set_string(value, gjs->program_path());
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -621,6 +635,9 @@ gjs_context_set_property (GObject *object,
case PROP_PROGRAM_NAME:
gjs->set_program_name(g_value_dup_string(value));
break;
+ case PROP_PROGRAM_PATH:
+ gjs->set_program_path(g_value_dup_string(value));
+ break;
case PROP_PROFILER_ENABLED:
gjs->set_should_profile(g_value_get_boolean(value));
break;
diff --git a/installed-tests/js/testSystem.js b/installed-tests/js/testSystem.js
index 9cd5b8ef..e805f7bb 100644
--- a/installed-tests/js/testSystem.js
+++ b/installed-tests/js/testSystem.js
@@ -55,3 +55,9 @@ describe('System.dumpHeap()', function () {
expect(() => System.dumpHeap('/does/not/exist')).toThrow();
});
});
+
+describe('System.programPath', function () {
+ it('is null when executed from minijasmine', function () {
+ expect(System.programPath).toBe(null);
+ });
+});
diff --git a/installed-tests/scripts/testCommandLine.sh b/installed-tests/scripts/testCommandLine.sh
index 539e6929..f3bb9c9f 100755
--- a/installed-tests/scripts/testCommandLine.sh
+++ b/installed-tests/scripts/testCommandLine.sh
@@ -65,6 +65,16 @@ import 'gi://Gio?version=2.0';
import 'gi://Gio?version=75.94';
EOF
+# this JS script is used to test ARGV handling
+cat <<EOF >argv.js
+const System = imports.system;
+
+if (System.programPath.endsWith('/argv.js'))
+ System.exit(0);
+else
+ System.exit(1);
+EOF
+
total=0
report () {
@@ -106,6 +116,10 @@ $gjs -c 'imports.system.exit(42)'
test $? -eq 42
report "System.exit(42) should exit with the correct exit code"
+# Test the System.programPath works in gjs-console
+$gjs argv.js
+report "System.programPath should end in '/argv.js' when gjs argv.js is run"
+
# FIXME: should check -eq 42 specifically, but in debug mode we will be
# hitting an assertion. For this reason, skip when running under valgrind
# since nothing will be freed. Also suppress LSan for the same reason.
@@ -265,6 +279,6 @@ rm -f coverage.lcov
$gjs -m doublegi.js 2>&1 | grep -q 'already loaded'
report "avoid statically importing two versions of the same module"
-rm -f exit.js help.js promise.js awaitcatch.js doublegi.js
+rm -f exit.js help.js promise.js awaitcatch.js doublegi.js argv.js
echo "1..$total"
diff --git a/modules/system.cpp b/modules/system.cpp
index 6195fe34..936584c2 100644
--- a/modules/system.cpp
+++ b/modules/system.cpp
@@ -20,6 +20,7 @@
#include <js/PropertySpec.h>
#include <js/RootingAPI.h>
#include <js/TypeDecls.h>
+#include <js/Value.h> // for NullValue
#include <jsapi.h> // for JS_DefinePropertyById, JS_DefineF...
#include <jsfriendapi.h> // for DumpHeap, IgnoreNurseryObjects
@@ -203,13 +204,25 @@ gjs_js_define_system_stuff(JSContext *context,
GjsContextPrivate* gjs = GjsContextPrivate::from_cx(context);
const char* program_name = gjs->program_name();
+ const char* program_path = gjs->program_path();
- JS::RootedValue value(context);
- return gjs_string_from_utf8(context, program_name, &value) &&
+ JS::RootedValue v_program_invocation_name(context);
+ JS::RootedValue v_program_path(context, JS::NullValue());
+ if (program_path) {
+ if (!gjs_string_from_utf8(context, program_path, &v_program_path))
+ return false;
+ }
+
+ return gjs_string_from_utf8(context, program_name,
+ &v_program_invocation_name) &&
/* The name is modeled after program_invocation_name, part of glibc
*/
JS_DefinePropertyById(context, module,
- gjs->atoms().program_invocation_name(), value,
+ gjs->atoms().program_invocation_name(),
+ v_program_invocation_name,
+ GJS_MODULE_PROP_FLAGS | JSPROP_READONLY) &&
+ JS_DefinePropertyById(context, module, gjs->atoms().program_path(),
+ v_program_path,
GJS_MODULE_PROP_FLAGS | JSPROP_READONLY) &&
JS_DefinePropertyById(context, module, gjs->atoms().version(),
GJS_VERSION,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]