summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Chimento <philip.chimento@gmail.com>2017-04-16 23:08:54 -0700
committerPhilip Chimento <philip.chimento@gmail.com>2017-04-17 21:41:12 -0700
commit663a1008691f2115b654699955d759fbe4ed6eb8 (patch)
treec36576dabae0f91f72b5052c477f32599636e365
parentac3eb9c0107ef232eba3dba2b94f070fce2626a0 (diff)
downloadgjs-663a1008691f2115b654699955d759fbe4ed6eb8.tar.gz
js: Split compilation from execution in some places
In a few places, we need to split up compilation from execution in order to be able to use new scoping rules for JS evaluation. In SpiderMonkey 45, you cannot pass in a custom global object anymore to JS::Evaluate(). Instead, you can either use the context's global object, or pass in a "scope chain". The scope chain implicitly has the global object at the end. In our case, we can pass in a scope chain of one object to get the previous behaviour of gjs_eval_with_scope(). There is also a scope chain variant of JS::Evaluate(), but it does not take a UTF-8 char * buffer. When evaluating a script in another compartment, we need to use JS::CloneAndExecuteScript() since we can't pass in the compartment's global object either. This also requires a precompiled JSScript. We have to duplicate the compile options and stripping the shebang line in gjs_context_eval_file_in_compartment(), and change gjs_strip_unix_shebang() to take an unsigned length. Not great, but I think the alternative would cause even more churn. https://bugzilla.gnome.org/show_bug.cgi?id=781429
-rw-r--r--gjs/coverage.cpp21
-rw-r--r--gjs/jsapi-util.cpp15
-rw-r--r--gjs/jsapi-util.h2
-rw-r--r--test/gjs-tests.cpp12
4 files changed, 33 insertions, 17 deletions
diff --git a/gjs/coverage.cpp b/gjs/coverage.cpp
index 09a6fc3a..44a11c30 100644
--- a/gjs/coverage.cpp
+++ b/gjs/coverage.cpp
@@ -1298,18 +1298,27 @@ gjs_context_eval_file_in_compartment(GjsContext *context,
g_object_unref(file);
+ int start_line_number = 1;
+ const char *stripped_script = gjs_strip_unix_shebang(script, &script_len,
+ &start_line_number);
+
JSContext *js_context = (JSContext *) gjs_context_get_native_context(context);
JSAutoCompartment compartment(js_context, compartment_object);
- JS::RootedValue return_value(js_context);
- if (!gjs_eval_with_scope(js_context,
- compartment_object,
- script, script_len, filename,
- &return_value)) {
+ JS::CompileOptions options(js_context);
+ options.setUTF8(true)
+ .setFileAndLine(filename, start_line_number)
+ .setSourceIsLazy(true);
+ JS::RootedScript compiled_script(js_context);
+ if (!JS::Compile(js_context, compartment_object, options, stripped_script,
+ script_len, &compiled_script))
+ return false;
+
+ if (!JS::CloneAndExecuteScript(js_context, compartment_object,
+ compiled_script)) {
g_free(script);
gjs_log_exception(js_context);
- g_free(script);
g_set_error(error, GJS_ERROR, GJS_ERROR_FAILED, "Failed to evaluate %s", filename);
return false;
}
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 4d59d595..900b1b48 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -867,7 +867,7 @@ gjs_schedule_gc_if_needed (JSContext *context)
*/
const char *
gjs_strip_unix_shebang(const char *script,
- gssize *script_len,
+ size_t *script_len,
int *start_line_number_out)
{
g_assert(script_len);
@@ -913,12 +913,13 @@ gjs_eval_with_scope(JSContext *context,
{
int start_line_number = 1;
JSAutoRequest ar(context);
+ size_t real_len = script_len;
if (script_len < 0)
- script_len = strlen(script);
+ real_len = strlen(script);
script = gjs_strip_unix_shebang(script,
- &script_len,
+ &real_len,
&start_line_number);
/* log and clear exception if it's set (should not be, normally...) */
@@ -936,7 +937,13 @@ gjs_eval_with_scope(JSContext *context,
.setFileAndLine(filename, start_line_number)
.setSourceIsLazy(true);
- if (!JS::Evaluate(context, eval_obj, options, script, script_len, retval))
+ JS::RootedScript compiled_script(context);
+ if (!JS::Compile(context, object, options, script, real_len, &compiled_script))
+ return false;
+
+ JS::AutoObjectVector scope_chain(context);
+ scope_chain.append(eval_obj);
+ if (!JS_ExecuteScript(context, scope_chain, compiled_script, retval))
return false;
gjs_schedule_gc_if_needed(context);
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 718a82f2..e05e12b0 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -272,7 +272,7 @@ typedef enum {
} GjsConstString;
const char * gjs_strip_unix_shebang(const char *script,
- gssize *script_len,
+ size_t *script_len,
int *new_start_line_number);
/* These four functions wrap JS_GetPropertyById(), etc., but with a
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index febfe0eb..f5119e50 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -330,8 +330,8 @@ static void
gjstest_test_strip_shebang_no_advance_for_no_shebang(void)
{
const char *script = "foo\nbar";
- gssize script_len_original = strlen(script);
- gssize script_len = script_len_original;
+ size_t script_len_original = strlen(script);
+ size_t script_len = script_len_original;
int line_number = 1;
const char *stripped = gjs_strip_unix_shebang(script,
@@ -347,8 +347,8 @@ static void
gjstest_test_strip_shebang_advance_for_shebang(void)
{
const char *script = "#!foo\nbar";
- gssize script_len_original = strlen(script);
- gssize script_len = script_len_original;
+ size_t script_len_original = strlen(script);
+ size_t script_len = script_len_original;
int line_number = 1;
const char *stripped = gjs_strip_unix_shebang(script,
@@ -364,8 +364,8 @@ static void
gjstest_test_strip_shebang_return_null_for_just_shebang(void)
{
const char *script = "#!foo";
- gssize script_len_original = strlen(script);
- gssize script_len = script_len_original;
+ size_t script_len_original = strlen(script);
+ size_t script_len = script_len_original;
int line_number = 1;
const char *stripped = gjs_strip_unix_shebang(script,