[gjs] add JS_BeginRequest/JS_EndRequest calls throughout the codebase.
- From: Havoc Pennington <hp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] add JS_BeginRequest/JS_EndRequest calls throughout the codebase.
- Date: Sat, 1 May 2010 13:55:50 +0000 (UTC)
commit ccc6e7ce6cf9d2f42b2667d1998598f376c86f76
Author: Havoc Pennington <hp pobox com>
Date: Sat May 1 00:33:01 2010 -0400
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
gi/closure.c | 12 +++++
gi/function.c | 6 ++
gi/keep-alive.c | 34 ++++++++++++-
gi/ns.c | 6 ++
gi/repo.c | 30 +++++++++--
gi/value.c | 3 +
gjs/context.c | 34 ++++++++++++-
gjs/importer.c | 23 +++++++--
gjs/jsapi-util-array.c | 13 +++++
gjs/jsapi-util-error.c | 9 +++
gjs/jsapi-util-string.c | 39 +++++++++++++-
gjs/jsapi-util.c | 125 ++++++++++++++++++++++++++++++++++++++++++----
modules/dbus-exports.c | 14 ++++--
modules/dbus.c | 21 ++++++++
modules/mainloop.c | 4 +-
15 files changed, 340 insertions(+), 33 deletions(-)
---
diff --git a/gi/closure.c b/gi/closure.c
index 722279a..7cf084c 100644
--- a/gi/closure.c
+++ b/gi/closure.c
@@ -255,6 +255,8 @@ gjs_closure_invoke(GClosure *closure,
return;
}
+ JS_BeginRequest(context);
+
if (JS_IsExceptionPending(context)) {
gjs_debug_closure("Exception was pending before invoking callback??? "
"Not expected");
@@ -279,6 +281,8 @@ gjs_closure_invoke(GClosure *closure,
if (gjs_log_exception(context, NULL)) {
gjs_debug_closure("Closure invocation succeeded but an exception was set");
}
+
+ JS_EndRequest(context);
}
gboolean
@@ -294,6 +298,8 @@ gjs_closure_invoke_simple(JSContext *context,
jsval *argv;
int i;
+ JS_BeginRequest(context);
+
va_start(ap, format);
argv = JS_PushArgumentsVA(context, &stack_space, format, ap);
va_end(ap);
@@ -313,6 +319,8 @@ gjs_closure_invoke_simple(JSContext *context,
JS_PopArguments(context, stack_space);
+ JS_EndRequest(context);
+
return TRUE;
}
@@ -352,6 +360,8 @@ gjs_closure_new(JSContext *context,
* is invoked (as long as the runtime lives)
*/
c->context = gjs_runtime_get_load_context(c->runtime);
+ JS_BeginRequest(c->context);
+
c->obj = callable;
c->unref_on_global_object_finalized = FALSE;
@@ -371,6 +381,8 @@ gjs_closure_new(JSContext *context,
gjs_debug_closure("Create closure %p which calls object %p '%s'",
c, c->obj, description);
+ JS_EndRequest(c->context);
+
return &c->base;
}
diff --git a/gi/function.c b/gi/function.c
index 0bf5744..98343f5 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -1033,10 +1033,13 @@ gjs_define_function(JSContext *context,
JSContext *load_context;
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
function = function_new(load_context, info);
if (function == NULL) {
gjs_move_exception(load_context, context);
+
+ JS_EndRequest(load_context);
return NULL;
}
@@ -1046,9 +1049,12 @@ gjs_define_function(JSContext *context,
NULL, NULL,
GJS_MODULE_PROP_FLAGS)) {
gjs_debug(GJS_DEBUG_GFUNCTION, "Failed to define function");
+
+ JS_EndRequest(load_context);
return NULL;
}
+ JS_EndRequest(load_context);
return function;
}
diff --git a/gi/keep-alive.c b/gi/keep-alive.c
index 160a9ca..8e2c4ab 100644
--- a/gi/keep-alive.c
+++ b/gi/keep-alive.c
@@ -217,6 +217,8 @@ gjs_keep_alive_new(JSContext *context)
g_assert(context != NULL);
+ JS_BeginRequest(context);
+
/* put constructor in the global namespace */
global = JS_GetGlobalObject(context);
@@ -277,6 +279,8 @@ gjs_keep_alive_new(JSContext *context)
gjs_fatal("Failed to create keep_alive object");
}
+ JS_EndRequest(context);
+
return keep_alive;
}
@@ -292,7 +296,9 @@ gjs_keep_alive_add_child(JSContext *context,
g_assert(keep_alive != NULL);
+ JS_BeginRequest(context);
priv = priv_from_js(context, keep_alive);
+ JS_EndRequest(context);
g_assert(priv != NULL);
@@ -323,7 +329,9 @@ gjs_keep_alive_remove_child(JSContext *context,
KeepAlive *priv;
Child child;
+ JS_BeginRequest(context);
priv = priv_from_js(context, keep_alive);
+ JS_EndRequest(context);
g_assert(priv != NULL);
@@ -345,15 +353,22 @@ gjs_keep_alive_get_global(JSContext *context)
{
jsval value;
JSObject *global;
+ JSObject *result;
+
+ JS_BeginRequest(context);
global = JS_GetGlobalObject(context);
gjs_object_get_property(context, global, GLOBAL_KEEP_ALIVE_NAME, &value);
if (JSVAL_IS_OBJECT(value))
- return JSVAL_TO_OBJECT(value);
+ result = JSVAL_TO_OBJECT(value);
+ else
+ result = NULL;
- return NULL;
+ JS_EndRequest(context);
+
+ return result;
}
static JSObject*
@@ -362,6 +377,8 @@ gjs_keep_alive_create_in_global(JSContext *context)
JSObject *keep_alive;
JSObject *global;
+ JS_BeginRequest(context);
+
global = JS_GetGlobalObject(context);
keep_alive = gjs_keep_alive_new(context);
@@ -376,6 +393,7 @@ gjs_keep_alive_create_in_global(JSContext *context)
JSPROP_READONLY | JSPROP_PERMANENT))
gjs_fatal("no memory to define keep_alive property");
+ JS_EndRequest(context);
return keep_alive;
}
@@ -387,6 +405,8 @@ gjs_keep_alive_add_global_child(JSContext *context,
{
JSObject *keep_alive;
+ JS_BeginRequest(context);
+
keep_alive = gjs_keep_alive_get_global(context);
if (!keep_alive)
@@ -398,6 +418,8 @@ gjs_keep_alive_add_global_child(JSContext *context,
gjs_keep_alive_add_child(context,
keep_alive,
notify, child, data);
+
+ JS_EndRequest(context);
}
void
@@ -408,6 +430,8 @@ gjs_keep_alive_remove_global_child(JSContext *context,
{
JSObject *keep_alive;
+ JS_BeginRequest(context);
+
keep_alive = gjs_keep_alive_get_global(context);
if (!keep_alive)
@@ -417,6 +441,8 @@ gjs_keep_alive_remove_global_child(JSContext *context,
gjs_keep_alive_remove_child(context,
gjs_keep_alive_get_global(context),
notify, child, data);
+
+ JS_EndRequest(context);
}
JSObject*
@@ -429,6 +455,8 @@ gjs_keep_alive_get_for_load_context(JSRuntime *runtime)
g_assert(context != NULL);
+ JS_BeginRequest(context);
+
keep_alive = gjs_keep_alive_get_global(context);
if (!keep_alive)
@@ -437,5 +465,7 @@ gjs_keep_alive_get_for_load_context(JSRuntime *runtime)
if (!keep_alive)
gjs_fatal("could not create keep_alive on global object, no memory?");
+ JS_EndRequest(context);
+
return keep_alive;
}
diff --git a/gi/ns.c b/gi/ns.c
index 7ab93f8..85652dd 100644
--- a/gi/ns.c
+++ b/gi/ns.c
@@ -89,6 +89,7 @@ ns_new_resolve(JSContext *context,
return JS_TRUE; /* we are the prototype, or have the wrong class */
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
repo = g_irepository_get_default();
@@ -101,15 +102,18 @@ ns_new_resolve(JSContext *context,
obj,
NULL);
if (gjs_move_exception(load_context, context)) {
+ JS_EndRequest(load_context);
return JS_FALSE;
} else {
*objp = obj; /* we defined the property in this object */
+ JS_EndRequest(load_context);
return JS_TRUE;
}
} else {
gjs_throw(context,
"No symbol '%s' in namespace '%s'",
name, priv->namespace);
+ JS_EndRequest(load_context);
return JS_FALSE;
}
}
@@ -123,6 +127,7 @@ ns_new_resolve(JSContext *context,
if (gjs_define_info(load_context, obj, info)) {
g_base_info_unref(info);
*objp = obj; /* we defined the property in this object */
+ JS_EndRequest(load_context);
return JS_TRUE;
} else {
gjs_debug(GJS_DEBUG_GNAMESPACE,
@@ -137,6 +142,7 @@ ns_new_resolve(JSContext *context,
"Defining info failed but no exception set");
}
+ JS_EndRequest(load_context);
return JS_FALSE;
}
}
diff --git a/gi/repo.c b/gi/repo.c
index 4f073ba..cff1b24 100644
--- a/gi/repo.c
+++ b/gi/repo.c
@@ -64,11 +64,16 @@ resolve_namespace_object(JSContext *context,
JSObject *versions;
jsval version_val;
const char *version;
+ JSObject *result;
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
+
if (!gjs_object_require_property(load_context, repo_obj, "GI repository object", "versions", &versions_val) ||
!JSVAL_IS_OBJECT(versions_val)) {
gjs_throw(context, "No 'versions' property in GI repository object");
+
+ JS_EndRequest(load_context);
return NULL;
}
@@ -89,6 +94,7 @@ resolve_namespace_object(JSContext *context,
"Requiring %s, version %s: %s",
ns_name, version?version:"none", error->message);
g_error_free(error);
+ JS_EndRequest(load_context);
return JS_FALSE;
}
@@ -96,7 +102,9 @@ resolve_namespace_object(JSContext *context,
* with the given namespace name, pointing to that namespace
* in the repo.
*/
- return gjs_define_ns(context, repo_obj, ns_name, repo);
+ result = gjs_define_ns(context, repo_obj, ns_name, repo);
+ JS_EndRequest(load_context);
+ return result;
}
/*
@@ -140,11 +148,14 @@ repo_new_resolve(JSContext *context,
return JS_TRUE; /* we are the prototype, or have the wrong class */
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
resolve_namespace_object(load_context, obj, name);
if (gjs_move_exception(load_context, context)) {
+ JS_EndRequest(load_context);
return JS_FALSE;
} else {
*objp = obj; /* store the object we defined the prop in */
+ JS_EndRequest(load_context);
return JS_TRUE;
}
}
@@ -507,6 +518,7 @@ gjs_lookup_namespace_object_by_name(JSContext *context,
*/
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
global = JS_GetGlobalObject(load_context);
importer = JSVAL_VOID;
@@ -514,7 +526,7 @@ gjs_lookup_namespace_object_by_name(JSContext *context,
!JSVAL_IS_OBJECT(importer)) {
gjs_log_exception(load_context, NULL);
gjs_throw(context, "No imports property in global object");
- return NULL;
+ goto fail;
}
girepository = JSVAL_VOID;
@@ -523,20 +535,26 @@ gjs_lookup_namespace_object_by_name(JSContext *context,
!JSVAL_IS_OBJECT(girepository)) {
gjs_log_exception(load_context, NULL);
gjs_throw(context, "No gi property in importer");
- return NULL;
+ goto fail;
}
repo_obj = JSVAL_TO_OBJECT(girepository);
- if (!gjs_object_require_property(context, repo_obj, "GI repository object", ns, &ns_obj))
- return NULL;
+ if (!gjs_object_require_property(context, repo_obj, "GI repository object", ns, &ns_obj)) {
+ goto fail;
+ }
if (!JSVAL_IS_OBJECT(ns_obj)) {
gjs_throw(context, "Namespace '%s' is not an object?", ns);
- return NULL;
+ goto fail;
}
+ JS_EndRequest(load_context);
return JSVAL_TO_OBJECT(ns_obj);
+
+ fail:
+ JS_EndRequest(load_context);
+ return NULL;
}
const char*
diff --git a/gi/value.c b/gi/value.c
index ab80ac9..49df3dc 100644
--- a/gi/value.c
+++ b/gi/value.c
@@ -66,6 +66,8 @@ closure_marshal(GClosure *closure,
return;
}
+ JS_BeginRequest(context);
+
argc = n_param_values;
argv = g_newa(jsval, n_param_values);
rval = JSVAL_VOID;
@@ -133,6 +135,7 @@ closure_marshal(GClosure *closure,
cleanup:
gjs_unroot_value_locations(context, argv, argc);
JS_RemoveRoot(context, &rval);
+ JS_EndRequest(context);
}
GClosure*
diff --git a/gjs/context.c b/gjs/context.c
index 035c8d3..743bb1a 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 8d11e9d..c7902f6 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 d3ce3f7..b4c7360 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 2b86718..50d4449 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 fc669a0..4a57176 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 25bdf5c..e2f7f14 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;
}
diff --git a/modules/dbus-exports.c b/modules/dbus-exports.c
index f407667..bed9b7d 100644
--- a/modules/dbus-exports.c
+++ b/modules/dbus-exports.c
@@ -1852,24 +1852,30 @@ gjs_js_define_dbus_exports(JSContext *context,
{
JSObject *exports;
JSContext *load_context;
+ JSBool success;
+ success = JS_FALSE;
load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
+ JS_BeginRequest(load_context);
exports = exports_new(load_context, which_bus);
if (exports == NULL) {
gjs_move_exception(load_context, context);
- return JS_FALSE;
+ goto fail;
}
if (!add_connect_funcs(context, exports, which_bus))
- return JS_FALSE;
+ goto fail;
if (!JS_DefineProperty(context, in_object,
"exports",
OBJECT_TO_JSVAL(exports),
NULL, NULL,
GJS_MODULE_PROP_FLAGS))
- return JS_FALSE;
+ goto fail;
- return JS_TRUE;
+ success = JS_TRUE;
+ fail:
+ JS_EndRequest(load_context);
+ return success;
}
diff --git a/modules/dbus.c b/modules/dbus.c
index f1311b4..c6007c9 100644
--- a/modules/dbus.c
+++ b/modules/dbus.c
@@ -632,9 +632,12 @@ signal_handler_callback(DBusConnection *connection,
return;
}
+ JS_BeginRequest(context);
+
dbus_message_iter_init(message, &arg_iter);
if (!gjs_js_values_from_dbus(context, &arg_iter, &arguments)) {
gjs_debug(GJS_DEBUG_DBUS, "Failed to marshal dbus signal to JS");
+ JS_EndRequest(context);
return;
}
@@ -657,6 +660,8 @@ signal_handler_callback(DBusConnection *connection,
gjs_rooted_array_free(context, arguments, TRUE);
signal_handler_unref(handler); /* for safety */
+
+ JS_EndRequest(context);
}
/* Args are bus_name, object_path, iface, signal, and callback */
@@ -997,6 +1002,8 @@ on_name_acquired(DBusConnection *connection,
return;
}
+ JS_BeginRequest(context);
+
argc = 1;
argv[0] = STRING_TO_JSVAL(JS_NewStringCopyZ(context, name));
@@ -1010,6 +1017,8 @@ on_name_acquired(DBusConnection *connection,
JS_RemoveRoot(context, &argv[0]);
JS_RemoveRoot(context, &rval);
+
+ JS_EndRequest(context);
}
static void
@@ -1032,6 +1041,8 @@ on_name_lost(DBusConnection *connection,
return;
}
+ JS_BeginRequest(context);
+
argc = 1;
argv[0] = STRING_TO_JSVAL(JS_NewStringCopyZ(context, name));
@@ -1045,6 +1056,8 @@ on_name_lost(DBusConnection *connection,
JS_RemoveRoot(context, &argv[0]);
JS_RemoveRoot(context, &rval);
+
+ JS_EndRequest(context);
}
static void
@@ -1209,6 +1222,8 @@ on_name_appeared(DBusConnection *connection,
return;
}
+ JS_BeginRequest(context);
+
argc = 2;
gjs_set_values(context, argv, argc, JSVAL_VOID);
@@ -1225,6 +1240,8 @@ on_name_appeared(DBusConnection *connection,
JS_RemoveRoot(context, &rval);
gjs_unroot_value_locations(context, argv, argc);
+
+ JS_EndRequest(context);
}
static void
@@ -1248,6 +1265,8 @@ on_name_vanished(DBusConnection *connection,
return;
}
+ JS_BeginRequest(context);
+
argc = 2;
gjs_set_values(context, argv, argc, JSVAL_VOID);
@@ -1264,6 +1283,8 @@ on_name_vanished(DBusConnection *connection,
JS_RemoveRoot(context, &rval);
gjs_unroot_value_locations(context, argv, argc);
+
+ JS_EndRequest(context);
}
static const GjsDBusWatchNameFuncs watch_name_funcs = {
diff --git a/modules/mainloop.c b/modules/mainloop.c
index 814619d..7208e45 100644
--- a/modules/mainloop.c
+++ b/modules/mainloop.c
@@ -123,6 +123,7 @@ closure_source_func(void *data)
/* closure is invalid now */
return FALSE;
}
+ JS_BeginRequest(context);
retval = JSVAL_VOID;
JS_AddRoot(context, &retval);
@@ -135,12 +136,13 @@ closure_source_func(void *data)
* JavaScript always makes some sense of any value in
* an "if (value) {}" context.
*/
- if (!JS_ValueToBoolean(gjs_closure_get_context(closure),
+ if (!JS_ValueToBoolean(context,
retval, &bool_val))
bool_val = FALSE;
JS_RemoveRoot(context, &retval);
+ JS_EndRequest(context);
return bool_val;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]