summaryrefslogtreecommitdiff
path: root/gjs
diff options
context:
space:
mode:
authorHavoc Pennington <hp@pobox.com>2010-05-01 00:33:01 -0400
committerHavoc Pennington <hp@pobox.com>2010-05-01 01:19:21 -0400
commitccc6e7ce6cf9d2f42b2667d1998598f376c86f76 (patch)
tree99eed51691ecdde6ac7a80658358fc0e04f1c1dd /gjs
parent941791d4cbcf4a42ecac63d47ab2333613d847b8 (diff)
downloadgjs-ccc6e7ce6cf9d2f42b2667d1998598f376c86f76.tar.gz
add JS_BeginRequest/JS_EndRequest calls throughout the codebase.
This is one step toward thread safety. Remaining work includes at least: * put locks on our own global state * JS_SuspendRequest() when blocking in native code * JS_SetContextThread() on load and call contexts
Diffstat (limited to 'gjs')
-rw-r--r--gjs/context.c34
-rw-r--r--gjs/importer.c23
-rw-r--r--gjs/jsapi-util-array.c13
-rw-r--r--gjs/jsapi-util-error.c9
-rw-r--r--gjs/jsapi-util-string.c39
-rw-r--r--gjs/jsapi-util.c125
6 files changed, 223 insertions, 20 deletions
diff --git a/gjs/context.c b/gjs/context.c
index 035c8d3a..743bb1a3 100644
--- a/gjs/context.c
+++ b/gjs/context.c
@@ -107,6 +107,8 @@ gjs_log(JSContext *context,
return JS_FALSE;
}
+ JS_BeginRequest(context);
+
/* JS_ValueToString might throw, in which we will only
*log that the value could be converted to string */
exc_state = JS_SaveExceptionState(context);
@@ -117,15 +119,19 @@ gjs_log(JSContext *context,
if (jstr == NULL) {
gjs_debug(GJS_DEBUG_LOG, "<cannot convert value to string>");
+ JS_EndRequest(context);
return JS_TRUE;
}
- if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(jstr), &s))
+ if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(jstr), &s)) {
+ JS_EndRequest(context);
return JS_FALSE;
+ }
gjs_debug(GJS_DEBUG_LOG, "%s", s);
g_free(s);
+ JS_EndRequest(context);
return JS_TRUE;
}
@@ -146,6 +152,8 @@ gjs_log_error(JSContext *context,
return JS_FALSE;
}
+ JS_BeginRequest(context);
+
exc = argv[0];
/* JS_ValueToString might throw, in which we will only
@@ -159,16 +167,20 @@ gjs_log_error(JSContext *context,
if (jstr == NULL) {
gjs_debug(GJS_DEBUG_ERROR, "<cannot convert value to string>");
gjs_log_exception_props(context, exc);
+ JS_EndRequest(context);
return JS_TRUE;
}
- if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(jstr), &s))
+ if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(jstr), &s)) {
+ JS_EndRequest(context);
return JS_FALSE;
+ }
gjs_debug(GJS_DEBUG_ERROR, "%s", s);
gjs_log_exception_props(context, exc);
g_free(s);
+ JS_EndRequest(context);
return JS_TRUE;
}
@@ -182,6 +194,8 @@ gjs_print_parse_args(JSContext *context,
gchar *s;
guint n;
+ JS_BeginRequest(context);
+
str = g_string_new("");
JS_EnterLocalRootScope(context);
for (n = 0; n < argc; ++n) {
@@ -201,6 +215,7 @@ gjs_print_parse_args(JSContext *context,
if (jstr != NULL) {
if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(jstr), &s)) {
JS_LeaveLocalRootScope(context);
+ JS_EndRequest(context);
g_string_free(str, TRUE);
return JS_FALSE;
}
@@ -211,6 +226,7 @@ gjs_print_parse_args(JSContext *context,
g_string_append_c(str, ' ');
} else {
JS_LeaveLocalRootScope(context);
+ JS_EndRequest(context);
*buffer = g_string_free(str, TRUE);
if (!*buffer)
*buffer = g_strdup("<invalid string>");
@@ -221,6 +237,7 @@ gjs_print_parse_args(JSContext *context,
JS_LeaveLocalRootScope(context);
*buffer = g_string_free(str, FALSE);
+ JS_EndRequest(context);
return JS_TRUE;
}
@@ -330,7 +347,9 @@ gjs_context_dispose(GObject *object)
}
if (js_context->global != NULL) {
+ JS_BeginRequest(js_context->context);
JS_RemoveRoot(js_context->context, &js_context->global);
+ JS_EndRequest(js_context->context);
js_context->global = NULL;
}
@@ -537,6 +556,8 @@ gjs_context_constructor (GType type,
if (js_context->context == NULL)
gjs_fatal("Failed to create javascript context");
+ JS_BeginRequest(js_context->context);
+
/* same as firefox, see discussion at
* https://bugzilla.mozilla.org/show_bug.cgi?id=420869 */
JS_SetScriptStackQuota(js_context->context, 100*1024*1024);
@@ -652,6 +673,8 @@ gjs_context_constructor (GType type,
js_context->profiler = gjs_profiler_new(js_context->runtime);
}
+ JS_EndRequest(js_context->context);
+
g_static_mutex_lock (&contexts_lock);
all_contexts = g_list_prepend(all_contexts, object);
g_static_mutex_unlock (&contexts_lock);
@@ -805,6 +828,11 @@ gjs_context_eval(GjsContext *js_context,
"Exception was set prior to JS_EvaluateScript()");
}
+ /* JS_EvaluateScript requires a request even though it sort of seems like
+ * it means we're always in a request?
+ */
+ JS_BeginRequest(js_context->context);
+
retval = JSVAL_VOID;
if (!JS_EvaluateScript(js_context->context,
js_context->global,
@@ -869,6 +897,8 @@ gjs_context_eval(GjsContext *js_context,
g_object_unref(G_OBJECT(js_context));
+ JS_EndRequest(js_context->context);
+
return success;
}
diff --git a/gjs/importer.c b/gjs/importer.c
index 8d11e9d5..c7902f61 100644
--- a/gjs/importer.c
+++ b/gjs/importer.c
@@ -925,8 +925,10 @@ importer_new_resolve(JSContext *context,
/* We always import in the special load context. */
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
if (do_import(load_context, obj, priv, name)) {
*objp = obj;
+ JS_EndRequest(load_context);
return JS_TRUE;
} else {
/* Move the exception to the calling context from load context.
@@ -935,6 +937,7 @@ importer_new_resolve(JSContext *context,
/* set an exception since none was set */
gjs_throw(context, "No exception was set, but import failed somehow");
}
+ JS_EndRequest(load_context);
return JS_FALSE;
}
}
@@ -1182,19 +1185,25 @@ gjs_create_root_importer(JSRuntime *runtime,
context = gjs_runtime_get_load_context(runtime);
+ JS_BeginRequest(context);
+
if (!gjs_object_has_property(context,
JS_GetGlobalObject(context),
"imports")) {
if (gjs_define_importer(context, JS_GetGlobalObject(context),
"imports",
- initial_search_path, add_standard_search_path) == NULL)
+ initial_search_path, add_standard_search_path) == NULL) {
+ JS_EndRequest(context);
return JS_FALSE;
+ }
} else {
gjs_debug(GJS_DEBUG_IMPORTER,
"Someone else already created root importer, ignoring second request");
+ JS_EndRequest(context);
return JS_TRUE;
}
+ JS_EndRequest(context);
return JS_TRUE;
}
@@ -1205,15 +1214,18 @@ gjs_define_root_importer(JSContext *context,
{
JSContext *load_context;
jsval value;
+ JSBool success;
+ success = JS_FALSE;
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
if (!gjs_object_require_property(load_context,
JS_GetGlobalObject(load_context), "global object",
"imports", &value) ||
!JSVAL_IS_OBJECT(value)) {
gjs_debug(GJS_DEBUG_IMPORTER, "Root importer did not exist, couldn't get from load context; must create it");
- return JS_FALSE;
+ goto fail;
}
if (!JS_DefineProperty(context, in_object,
@@ -1222,8 +1234,11 @@ gjs_define_root_importer(JSContext *context,
GJS_MODULE_PROP_FLAGS)) {
gjs_debug(GJS_DEBUG_IMPORTER, "DefineProperty %s on %p failed",
importer_name, in_object);
- return JS_FALSE;
+ goto fail;
}
- return JS_TRUE;
+ success = JS_TRUE;
+ fail:
+ JS_EndRequest(load_context);
+ return success;
}
diff --git a/gjs/jsapi-util-array.c b/gjs/jsapi-util-array.c
index d3ce3f7a..b4c7360e 100644
--- a/gjs/jsapi-util-array.c
+++ b/gjs/jsapi-util-array.c
@@ -59,7 +59,9 @@ static void
add_root_jsval(JSContext *context,
jsval *value_p)
{
+ JS_BeginRequest(context);
JS_AddRoot(context, value_p);
+ JS_EndRequest(context);
}
/* typesafe wrapper */
@@ -67,7 +69,9 @@ static void
remove_root_jsval(JSContext *context,
jsval *value_p)
{
+ JS_BeginRequest(context);
JS_RemoveRoot(context, value_p);
+ JS_EndRequest(context);
}
/**
@@ -190,9 +194,11 @@ gjs_root_value_locations(JSContext *context,
g_return_if_fail(locations != NULL);
g_return_if_fail(n_locations >= 0);
+ JS_BeginRequest(context);
for (i = 0; i < n_locations; i++) {
add_root_jsval(context, ((jsval*)locations) + i);
}
+ JS_EndRequest(context);
}
/**
@@ -215,9 +221,11 @@ gjs_unroot_value_locations(JSContext *context,
g_return_if_fail(locations != NULL);
g_return_if_fail(n_locations >= 0);
+ JS_BeginRequest(context);
for (i = 0; i < n_locations; i++) {
remove_root_jsval(context, ((jsval*)locations) + i);
}
+ JS_EndRequest(context);
}
/**
@@ -302,6 +310,9 @@ gjstest_test_func_gjs_jsapi_util_array(void)
runtime = JS_NewRuntime(1024*1024 /* max bytes */);
context = JS_NewContext(runtime, 8192);
+
+ JS_BeginRequest(context);
+
global = JS_NewObject(context, NULL, NULL, NULL);
JS_SetGlobalObject(context, global);
JS_InitStandardClasses(context, global);
@@ -332,6 +343,8 @@ gjstest_test_func_gjs_jsapi_util_array(void)
gjs_rooted_array_free(context, array, TRUE);
+ JS_EndRequest(context);
+
JS_DestroyContext(context);
JS_DestroyRuntime(runtime);
JS_ShutDown();
diff --git a/gjs/jsapi-util-error.c b/gjs/jsapi-util-error.c
index 2b867183..50d4449b 100644
--- a/gjs/jsapi-util-error.c
+++ b/gjs/jsapi-util-error.c
@@ -55,6 +55,8 @@ gjs_throw_valist(JSContext *context,
s = g_strdup_vprintf(format, args);
+ JS_BeginRequest(context);
+
if (JS_IsExceptionPending(context)) {
/* Often it's unclear whether a given jsapi.h function
* will throw an exception, so we will throw ourselves
@@ -138,6 +140,8 @@ gjs_throw_valist(JSContext *context,
s);
}
g_free(s);
+
+ JS_EndRequest(context);
}
/* Throws an exception, like "throw new Error(message)"
@@ -212,6 +216,9 @@ gjstest_test_func_gjs_jsapi_util_error_throw(void)
*/
runtime = JS_NewRuntime(1024*1024 /* max bytes */);
context = JS_NewContext(runtime, 8192);
+
+ JS_BeginRequest(context);
+
global = JS_NewObject(context, NULL, NULL, NULL);
JS_SetGlobalObject(context, global);
JS_InitStandardClasses(context, global);
@@ -266,6 +273,8 @@ gjstest_test_func_gjs_jsapi_util_error_throw(void)
JS_RemoveRoot(context, &previous);
+ JS_EndRequest(context);
+
JS_DestroyContext(context);
JS_DestroyRuntime(runtime);
JS_ShutDown();
diff --git a/gjs/jsapi-util-string.c b/gjs/jsapi-util-string.c
index fc669a02..4a571761 100644
--- a/gjs/jsapi-util-string.c
+++ b/gjs/jsapi-util-string.c
@@ -41,9 +41,12 @@ gjs_try_string_to_utf8 (JSContext *context,
long utf8_length;
GError *convert_error = NULL;
+ JS_BeginRequest(context);
+
if (!JSVAL_IS_STRING(string_val)) {
g_set_error_literal(error, GJS_UTIL_ERROR, GJS_UTIL_ERROR_ARGUMENT_TYPE_MISMATCH,
"Object is not a string, cannot convert to UTF-8");
+ JS_EndRequest(context);
return FALSE;
}
@@ -55,6 +58,9 @@ gjs_try_string_to_utf8 (JSContext *context,
&read_items, &utf8_length,
&convert_error);
+ /* ENDING REQUEST - no JSAPI after this point */
+ JS_EndRequest(context);
+
if (!utf8_string) {
g_set_error(error, GJS_UTIL_ERROR, GJS_UTIL_ERROR_ARGUMENT_INVALID,
"Failed to convert JS string to UTF-8: %s",
@@ -136,15 +142,20 @@ gjs_string_from_utf8(JSContext *context,
return JS_FALSE;
}
+ JS_BeginRequest(context);
+
s = JS_NewUCStringCopyN(context,
(jschar*)u16_string,
u16_string_length);
g_free(u16_string);
- if (!s)
+ if (!s) {
+ JS_EndRequest(context);
return JS_FALSE;
+ }
*value_p = STRING_TO_JSVAL(s);
+ JS_EndRequest(context);
return JS_TRUE;
}
@@ -301,14 +312,18 @@ gjs_string_get_binary_data(JSContext *context,
{
char *js_data;
+ JS_BeginRequest(context);
+
if (!JSVAL_IS_STRING(value)) {
gjs_throw(context,
"Value is not a string, can't return binary data from it");
return JS_FALSE;
}
- if (throw_if_binary_strings_broken(context))
+ if (throw_if_binary_strings_broken(context)) {
+ JS_EndRequest(context);
return JS_FALSE;
+ }
js_data = JS_GetStringBytes(JSVAL_TO_STRING(value));
/* GetStringLength returns number of 16-bit jschar;
@@ -317,6 +332,8 @@ gjs_string_get_binary_data(JSContext *context,
*len_p = JS_GetStringLength(JSVAL_TO_STRING(value));
*data_p = g_memdup(js_data, *len_p);
+ JS_EndRequest(context);
+
return JS_TRUE;
}
@@ -339,8 +356,12 @@ gjs_string_from_binary_data(JSContext *context,
{
JSString *s;
- if (throw_if_binary_strings_broken(context))
+ JS_BeginRequest(context);
+
+ if (throw_if_binary_strings_broken(context)) {
+ JS_EndRequest(context);
return JS_FALSE;
+ }
/* store each byte in a 16-bit jschar so all high bytes are 0;
* we can't put two bytes per jschar because then we'd lose
@@ -350,10 +371,12 @@ gjs_string_from_binary_data(JSContext *context,
if (s == NULL) {
/* gjs_throw() does nothing if exception already set */
gjs_throw(context, "Failed to allocate binary string");
+ JS_EndRequest(context);
return JS_FALSE;
}
*value_p = STRING_TO_JSVAL(s);
+ JS_EndRequest(context);
return JS_TRUE;
}
@@ -378,9 +401,12 @@ gjs_string_get_uint16_data(JSContext *context,
{
jschar *js_data;
+ JS_BeginRequest(context);
+
if (!JSVAL_IS_STRING(value)) {
gjs_throw(context,
"Value is not a string, can't return binary data from it");
+ JS_EndRequest(context);
return JS_FALSE;
}
@@ -388,6 +414,7 @@ gjs_string_get_uint16_data(JSContext *context,
*len_p = JS_GetStringLength(JSVAL_TO_STRING(value));
*data_p = g_memdup(js_data, sizeof(*js_data)*(*len_p));
+ JS_EndRequest(context);
return JS_TRUE;
}
@@ -439,6 +466,7 @@ gjstest_test_func_gjs_jsapi_util_string_js_string_utf8(void)
runtime = JS_NewRuntime(1024*1024 /* max bytes */);
context = JS_NewContext(runtime, 8192);
+ JS_BeginRequest(context);
global = JS_NewObject(context, NULL, NULL, NULL);
JS_SetGlobalObject(context, global);
JS_InitStandardClasses(context, global);
@@ -450,6 +478,7 @@ gjstest_test_func_gjs_jsapi_util_string_js_string_utf8(void)
g_assert(JSVAL_IS_STRING(js_string));
g_assert(gjs_string_to_utf8(context, js_string, &utf8_result) == JS_TRUE);
+ JS_EndRequest(context);
JS_DestroyContext(context);
JS_DestroyRuntime(runtime);
@@ -470,6 +499,7 @@ gjstest_test_func_gjs_jsapi_util_string_get_ascii(void)
runtime = JS_NewRuntime(1024*1024 /* max bytes */);
context = JS_NewContext(runtime, 8192);
+ JS_BeginRequest(context);
global = JS_NewObject(context, NULL, NULL, NULL);
JS_SetGlobalObject(context, global);
JS_InitStandardClasses(context, global);
@@ -482,6 +512,7 @@ gjstest_test_func_gjs_jsapi_util_string_get_ascii(void)
g_assert(gjs_string_get_ascii_checked(context, void_value) == NULL);
g_assert(JS_IsExceptionPending(context));
+ JS_EndRequest(context);
JS_DestroyContext(context);
JS_DestroyRuntime(runtime);
}
@@ -504,6 +535,7 @@ gjstest_test_func_gjs_jsapi_util_string_get_binary(void)
runtime = JS_NewRuntime(1024*1024 /* max bytes */);
context = JS_NewContext(runtime, 8192);
+ JS_BeginRequest(context);
global = JS_NewObject(context, NULL, NULL, NULL);
JS_SetGlobalObject(context, global);
JS_InitStandardClasses(context, global);
@@ -550,6 +582,7 @@ gjstest_test_func_gjs_jsapi_util_string_get_binary(void)
&data, &len));
g_assert(JS_IsExceptionPending(context));
+ JS_EndRequest(context);
JS_DestroyContext(context);
JS_DestroyRuntime(runtime);
}
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
index 25bdf5ce..e2f7f14b 100644
--- a/gjs/jsapi-util.c
+++ b/gjs/jsapi-util.c
@@ -242,6 +242,8 @@ gjs_object_get_property(JSContext *context,
jsval value;
JSExceptionState *state;
+ JS_BeginRequest(context);
+
value = JSVAL_VOID;
state = JS_SaveExceptionState(context);
JS_GetProperty(context, obj, property_name, &value);
@@ -250,6 +252,8 @@ gjs_object_get_property(JSContext *context,
if (value_p)
*value_p = value;
+ JS_EndRequest(context);
+
return value != JSVAL_VOID;
}
@@ -269,6 +273,8 @@ gjs_object_require_property(JSContext *context,
{
jsval value;
+ JS_BeginRequest(context);
+
value = JSVAL_VOID;
JS_GetProperty(context, obj, property_name, &value);
@@ -277,6 +283,7 @@ gjs_object_require_property(JSContext *context,
if (value != JSVAL_VOID) {
JS_ClearPendingException(context); /* in case JS_GetProperty() was on crack */
+ JS_EndRequest(context);
return TRUE;
} else {
/* remember gjs_throw() is a no-op if JS_GetProperty()
@@ -290,6 +297,8 @@ gjs_object_require_property(JSContext *context,
gjs_throw(context,
"No property '%s' in object %p (or its value was undefined)",
property_name, obj);
+
+ JS_EndRequest(context);
return FALSE;
}
}
@@ -318,6 +327,8 @@ gjs_init_class_dynamic(JSContext *context,
return NULL;
}
+ JS_BeginRequest(context);
+
/* We replace the passed-in context and global object with our
* runtime-global permanent load context. Otherwise, in a
* process with multiple contexts, we'd arbitrarily define
@@ -325,6 +336,7 @@ gjs_init_class_dynamic(JSContext *context,
* class first, which is not desirable.
*/
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
/* JS_InitClass() wants to define the constructor in the global object, so
* we give it a private and namespaced name... passing in the namespace
@@ -397,6 +409,8 @@ gjs_init_class_dynamic(JSContext *context,
GJS_MODULE_PROP_FLAGS))
goto error;
+ JS_EndRequest(load_context);
+ JS_EndRequest(context);
return prototype;
error:
@@ -407,18 +421,23 @@ gjs_init_class_dynamic(JSContext *context,
gjs_throw(context, "No exception was set, but class initialize failed somehow");
}
+ JS_EndRequest(load_context);
+ JS_EndRequest(context);
return NULL;
}
gboolean
gjs_check_constructing(JSContext *context)
{
+ JS_BeginRequest(context);
if (!JS_IsConstructing(context)) {
+ JS_EndRequest(context);
gjs_throw(context,
"Constructor called as normal method. Use 'new SomeObject()' not 'SomeObject()'");
return FALSE;
}
+ JS_EndRequest(context);
return TRUE;
}
@@ -430,12 +449,15 @@ gjs_get_instance_private_dynamic(JSContext *context,
{
RuntimeData *rd;
JSClass *obj_class;
+ void *instance;
if (static_clasp->name != NULL) {
g_warning("Dynamic class should not have a name in the JSClass struct");
return NULL;
}
+ JS_BeginRequest(context);
+
obj_class = JS_GET_CLASS(context, obj);
g_assert(obj_class != NULL);
@@ -447,15 +469,20 @@ gjs_get_instance_private_dynamic(JSContext *context,
gjs_throw(context,
"Object %p proto %p doesn't have a dynamically-registered class, it has %s",
obj, JS_GetPrototype(context, obj), obj_class->name);
+ JS_EndRequest(context);
return NULL;
}
if (static_clasp != ((DynamicJSClass*) obj_class)->static_class) {
gjs_throw(context, "Object is not a dynamically-registered class based on expected static class pointer");
+ JS_EndRequest(context);
return NULL;
}
- return JS_GetInstancePrivate(context, obj, obj_class, argv);
+ instance = JS_GetInstancePrivate(context, obj, obj_class, argv);
+ JS_EndRequest(context);
+
+ return instance;
}
void*
@@ -466,12 +493,15 @@ gjs_get_instance_private_dynamic_with_typecheck(JSContext *context,
{
RuntimeData *rd;
JSClass *obj_class;
+ void *instance;
if (static_clasp->name != NULL) {
g_warning("Dynamic class should not have a name in the JSClass struct");
return NULL;
}
+ JS_BeginRequest(context);
+
obj_class = JS_GET_CLASS(context, obj);
g_assert(obj_class != NULL);
@@ -480,14 +510,18 @@ gjs_get_instance_private_dynamic_with_typecheck(JSContext *context,
/* Check that it's safe to cast to DynamicJSClass */
if (g_hash_table_lookup(rd->dynamic_classes, obj_class) == NULL) {
+ JS_EndRequest(context);
return NULL;
}
if (static_clasp != ((DynamicJSClass*) obj_class)->static_class) {
+ JS_EndRequest(context);
return NULL;
}
- return JS_GetInstancePrivate(context, obj, obj_class, argv);
+ instance = JS_GetInstancePrivate(context, obj, obj_class, argv);
+ JS_EndRequest(context);
+ return instance;
}
JSObject*
@@ -501,12 +535,15 @@ gjs_construct_object_dynamic(JSContext *context,
JSContext *load_context;
JSObject *result;
+ JS_BeginRequest(context);
+
/* We replace the passed-in context and global object with our
* runtime-global permanent load context. Otherwise, JS_ConstructObject
* can't find the constructor in whatever random global object is set
* on the passed-in context.
*/
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
proto_class = JS_GET_CLASS(load_context, proto);
@@ -530,6 +567,8 @@ gjs_construct_object_dynamic(JSContext *context,
if (!result)
goto error;
+ JS_EndRequest(load_context);
+ JS_EndRequest(context);
return result;
error:
@@ -540,6 +579,8 @@ gjs_construct_object_dynamic(JSContext *context,
gjs_throw(context, "No exception was set, but object construction failed somehow");
}
+ JS_EndRequest(load_context);
+ JS_EndRequest(context);
return NULL;
}
@@ -555,6 +596,8 @@ gjs_define_string_array(JSContext *context,
JSObject *array;
int i;
+ JS_BeginRequest(context);
+
if (!JS_EnterLocalRootScope(context))
return JS_FALSE;
@@ -580,6 +623,8 @@ gjs_define_string_array(JSContext *context,
}
JS_LeaveLocalRootScope(context);
+
+ JS_EndRequest(context);
return array;
}
@@ -588,6 +633,9 @@ gjs_value_debug_string(JSContext *context,
jsval value)
{
JSString *str;
+ const char *bytes;
+
+ JS_BeginRequest(context);
str = JS_ValueToString(context, value);
@@ -616,7 +664,11 @@ gjs_value_debug_string(JSContext *context,
g_assert(str != NULL);
- return JS_GetStringBytes(str);
+ bytes = JS_GetStringBytes(str);
+
+ JS_EndRequest(context);
+
+ return bytes;
}
void
@@ -628,6 +680,8 @@ gjs_log_object_props(JSContext *context,
JSObject *props_iter;
jsid prop_id;
+ JS_BeginRequest(context);
+
/* We potentially create new strings, plus the property iterator,
* that could get collected as we go through this process. So
* create a local root scope.
@@ -672,6 +726,7 @@ gjs_log_object_props(JSContext *context,
done:
JS_LeaveLocalRootScope(context);
+ JS_EndRequest(context);
}
void
@@ -691,6 +746,10 @@ gjs_explain_scope(JSContext *context,
load_context = gjs_runtime_peek_load_context(JS_GetRuntime(context));
call_context = gjs_runtime_peek_call_context(JS_GetRuntime(context));
+ JS_BeginRequest(context);
+ JS_BeginRequest(load_context);
+ JS_BeginRequest(call_context);
+
JS_EnterLocalRootScope(context);
gjs_debug(GJS_DEBUG_SCOPE,
@@ -724,12 +783,18 @@ gjs_explain_scope(JSContext *context,
g_string_free(chain, TRUE);
JS_LeaveLocalRootScope(context);
+
+ JS_EndRequest(call_context);
+ JS_EndRequest(load_context);
+ JS_EndRequest(context);
}
void
gjs_log_exception_props(JSContext *context,
jsval exc)
{
+ JS_BeginRequest(context);
+
/* This is useful when the exception was never sent to an error reporter
* due to JSOPTION_DONT_REPORT_UNCAUGHT, or if the exception was not
* a normal Error object so jsapi didn't know how to report it sensibly.
@@ -766,6 +831,7 @@ gjs_log_exception_props(JSContext *context,
gjs_debug(GJS_DEBUG_ERROR,
"Exception had some strange type");
}
+ JS_EndRequest(context);
}
static JSBool
@@ -778,6 +844,8 @@ log_and_maybe_keep_exception(JSContext *context,
char *message;
JSBool retval = JS_FALSE;
+ JS_BeginRequest(context);
+
if (message_p)
*message_p = NULL;
@@ -824,6 +892,8 @@ log_and_maybe_keep_exception(JSContext *context,
out:
JS_RemoveRoot(context, &exc);
+ JS_EndRequest(context);
+
return retval;
}
@@ -850,39 +920,51 @@ try_to_chain_stack_trace(JSContext *src_context, JSContext *dst_context,
jsval chained, src_stack, dst_stack, new_stack;
JSString *new_stack_str;
+ JS_BeginRequest(src_context);
+ JS_BeginRequest(dst_context);
+
if (!JSVAL_IS_OBJECT(src_exc))
- return; // src_exc doesn't have a stack trace
+ goto out; // src_exc doesn't have a stack trace
/* create a new exception in dst_context to get a stack trace */
gjs_throw_literal(dst_context, "Chained exception");
if (!(JS_GetPendingException(dst_context, &chained) &&
JSVAL_IS_OBJECT(chained)))
- return; // gjs_throw_literal didn't work?!
+ goto out; // gjs_throw_literal didn't work?!
JS_ClearPendingException(dst_context);
/* get stack trace for src_exc and chained */
if (!(gjs_object_get_property(dst_context, JSVAL_TO_OBJECT(chained),
"stack", &dst_stack) &&
JSVAL_IS_STRING(dst_stack)))
- return; // couldn't get chained stack
+ goto out; // couldn't get chained stack
if (!(gjs_object_get_property(src_context, JSVAL_TO_OBJECT(src_exc),
"stack", &src_stack) &&
JSVAL_IS_STRING(src_stack)))
- return; // couldn't get source stack
+ goto out; // couldn't get source stack
/* add chained exception's stack trace to src_exc */
new_stack_str = JS_ConcatStrings
(dst_context, JSVAL_TO_STRING(src_stack), JSVAL_TO_STRING(dst_stack));
if (new_stack_str==NULL)
- return; // couldn't concatenate src and dst stacks?!
+ goto out; // couldn't concatenate src and dst stacks?!
new_stack = STRING_TO_JSVAL(new_stack_str);
JS_SetProperty(dst_context, JSVAL_TO_OBJECT(src_exc), "stack", &new_stack);
+
+ out:
+ JS_EndRequest(dst_context);
+ JS_EndRequest(src_context);
}
JSBool
gjs_move_exception(JSContext *src_context,
JSContext *dest_context)
{
+ JSBool success;
+
+ JS_BeginRequest(src_context);
+ JS_BeginRequest(dest_context);
+
/* NOTE: src and dest could be the same. */
jsval exc;
if (JS_GetPendingException(src_context, &exc)) {
@@ -894,10 +976,15 @@ gjs_move_exception(JSContext *src_context,
JS_SetPendingException(dest_context, exc);
JS_ClearPendingException(src_context);
}
- return JS_TRUE;
+ success = JS_TRUE;
} else {
- return JS_FALSE;
+ success = JS_FALSE;
}
+
+ JS_EndRequest(dest_context);
+ JS_EndRequest(src_context);
+
+ return success;
}
JSBool
@@ -911,12 +998,17 @@ gjs_call_function_value(JSContext *context,
JSBool result;
JSContext *call_context;
+ JS_BeginRequest(context);
+
call_context = gjs_runtime_get_call_context(JS_GetRuntime(context));
+ JS_BeginRequest(call_context);
result = JS_CallFunctionValue(call_context, obj, fval,
argc, argv, rval);
gjs_move_exception(call_context, context);
+ JS_EndRequest(call_context);
+ JS_EndRequest(context);
return result;
}
@@ -1014,6 +1106,9 @@ gjs_date_from_time_t (JSContext *context, time_t time)
JSObject *date_constructor;
jsval date_prototype;
jsval args[1];
+ jsval result;
+
+ JS_BeginRequest(context);
if (!JS_EnterLocalRootScope(context))
return JSVAL_VOID;
@@ -1033,8 +1128,11 @@ gjs_date_from_time_t (JSContext *context, time_t time)
date = JS_ConstructObjectWithArguments(context, date_class,
NULL, NULL, 1, args);
+ result = OBJECT_TO_JSVAL(date);
JS_LeaveLocalRootScope(context);
- return OBJECT_TO_JSVAL(date);
+ JS_EndRequest(context);
+
+ return result;
}
/**
@@ -1083,6 +1181,8 @@ gjs_parse_args (JSContext *context,
guint n_total;
guint consumed_args;
+ JS_BeginRequest(context);
+
va_start (args, argv);
/* Check for optional argument specifier */
@@ -1219,6 +1319,8 @@ gjs_parse_args (JSContext *context,
}
va_end (args);
+
+ JS_EndRequest(context);
return JS_TRUE;
error_unwind:
@@ -1227,5 +1329,6 @@ gjs_parse_args (JSContext *context,
for (i = 0; i < n_unwind; i++) {
g_free (unwind_strings[i]);
}
+ JS_EndRequest(context);
return JS_FALSE;
}