diff options
author | Philip Chimento <philip.chimento@gmail.com> | 2017-04-16 23:08:54 -0700 |
---|---|---|
committer | Philip Chimento <philip.chimento@gmail.com> | 2017-04-17 21:41:12 -0700 |
commit | 663a1008691f2115b654699955d759fbe4ed6eb8 (patch) | |
tree | c36576dabae0f91f72b5052c477f32599636e365 | |
parent | ac3eb9c0107ef232eba3dba2b94f070fce2626a0 (diff) | |
download | gjs-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.cpp | 21 | ||||
-rw-r--r-- | gjs/jsapi-util.cpp | 15 | ||||
-rw-r--r-- | gjs/jsapi-util.h | 2 | ||||
-rw-r--r-- | test/gjs-tests.cpp | 12 |
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, |