[gjs] Remove support for multiple contexts within a runtime



commit 244f1864d2d0a9ab20afa7d793f26843a6cf22e4
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Thu Jan 3 23:23:50 2013 -0500

    Remove support for multiple contexts within a runtime
    
    Remove code and support code to allow for multiple contexts, and
    simply store one context. In a thread-safe world, we'd put each
    context in thread-local storage, but gjs is not thread-safe, nor
    do we expect it will be in the future.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=691109

 gi/closure.c       |    2 +-
 gi/function.c      |    8 +--
 gi/object.c        |    2 +-
 gi/value.c         |    2 +-
 gjs/context.c      |   13 +----
 gjs/jsapi-util.c   |  168 ++++------------------------------------------------
 gjs/jsapi-util.h   |   11 +---
 modules/mainloop.c |    4 +-
 8 files changed, 22 insertions(+), 188 deletions(-)
---
diff --git a/gi/closure.c b/gi/closure.c
index 96a7477..1d51aea 100644
--- a/gi/closure.c
+++ b/gi/closure.c
@@ -266,7 +266,7 @@ gjs_closure_invoke(GClosure *closure,
         return;
     }
 
-    context = gjs_runtime_get_current_context(c->runtime);
+    context = gjs_runtime_get_context(c->runtime);
     JS_BeginRequest(context);
 
     if (JS_IsExceptionPending(context)) {
diff --git a/gi/function.c b/gi/function.c
index 1a2c190..a37fb85 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -80,7 +80,7 @@ gjs_callback_trampoline_unref(GjsCallbackTrampoline *trampoline)
     if (trampoline->ref_count == 0) {
         JSContext *context;
 
-        context = gjs_runtime_get_current_context(trampoline->runtime);
+        context = gjs_runtime_get_context(trampoline->runtime);
 
         if (!trampoline->is_vfunc) {
             JS_BeginRequest(context);
@@ -180,7 +180,7 @@ gjs_callback_closure(ffi_cif *cif,
     g_assert(trampoline);
     gjs_callback_trampoline_ref(trampoline);
 
-    context = gjs_runtime_get_current_context(trampoline->runtime);
+    context = gjs_runtime_get_context(trampoline->runtime);
     JS_BeginRequest(context);
 
     n_args = g_callable_info_get_n_args(trampoline->info);
@@ -878,8 +878,6 @@ gjs_invoke_c_function(JSContext      *context,
          * separately */
     }
 
-    gjs_runtime_push_context(JS_GetRuntime(context), context);
-
     g_assert_cmpuint(c_arg_pos, ==, c_argc);
     g_assert_cmpuint(gi_arg_pos, ==, gi_argc);
 
@@ -894,8 +892,6 @@ gjs_invoke_c_function(JSContext      *context,
         return_value_p = &return_value.v_long;
     ffi_call(&(function->invoker.cif), function->invoker.native_address, return_value_p, ffi_arg_pointers);
 
-    gjs_runtime_pop_context(JS_GetRuntime(context));
-
     /* Return value and out arguments are valid only if invocation doesn't
      * return error. In arguments need to be released always.
      */
diff --git a/gi/object.c b/gi/object.c
index 3e909c7..91841d9 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -783,7 +783,7 @@ wrapped_gobj_toggle_notify(gpointer      data,
      * Or if !is_last_ref, we do not want to convert to a strong
      * ref since we want everything collected on runtime destroy.
      */
-    context = gjs_runtime_get_current_context(runtime);
+    context = gjs_runtime_get_context(runtime);
     if (!context)
         return;
 
diff --git a/gi/value.c b/gi/value.c
index 0119d90..909742d 100644
--- a/gi/value.c
+++ b/gi/value.c
@@ -73,7 +73,7 @@ closure_marshal(GClosure        *closure,
     }
 
     runtime = gjs_closure_get_runtime(closure);
-    context = gjs_runtime_get_current_context(runtime);
+    context = gjs_runtime_get_context(runtime);
     JS_BeginRequest(context);
 
     argc = n_param_values;
diff --git a/gjs/context.c b/gjs/context.c
index efec0d2..68643dd 100644
--- a/gjs/context.c
+++ b/gjs/context.c
@@ -368,7 +368,6 @@ gjs_context_dispose(GObject *object)
         gjs_debug(GJS_DEBUG_CONTEXT,
                   "Destroying JS context");
 
-        gjs_runtime_set_default_context(js_context->runtime, NULL);
         JS_DestroyContext(js_context->context);
         js_context->context = NULL;
     }
@@ -545,12 +544,13 @@ gjs_context_constructor (GType                  type,
     if (js_context->runtime == NULL)
         gjs_fatal("Failed to create javascript runtime");
     JS_SetGCParameter(js_context->runtime, JSGC_MAX_BYTES, 0xffffffff);
-    gjs_runtime_init(js_context->runtime);
 
     js_context->context = JS_NewContext(js_context->runtime, 8192 /* stack chunk size */);
     if (js_context->context == NULL)
         gjs_fatal("Failed to create javascript context");
 
+    gjs_runtime_init(js_context->runtime, js_context->context);
+
     JS_BeginRequest(js_context->context);
 
 
@@ -630,13 +630,6 @@ gjs_context_constructor (GType                  type,
                            4, GJS_MODULE_PROP_FLAGS))
         gjs_fatal("Failed to define printerr function");
 
-    /* We need to know what the default context is, since it's the context whose
-     * global object is used to load imported JS modules. We currently say that
-     * it's the context of the runtime's owner, but if we needed to support
-     * externally created runtimes, we could define it in some other fashion.
-     */
-    gjs_runtime_set_default_context(js_context->runtime, js_context->context);
-
     /* We create the global-to-runtime root importer with the
      * passed-in search path. If someone else already created
      * the root importer, this is a no-op.
@@ -983,7 +976,6 @@ gjs_context_eval(GjsContext *js_context,
     /* JS_EvaluateScript requires a request even though it sort of seems like
      * it means we're always in a request?
      */
-    gjs_runtime_push_context(js_context->runtime, js_context->context);
     JS_BeginRequest(js_context->context);
 
     retval = JSVAL_VOID;
@@ -1051,7 +1043,6 @@ gjs_context_eval(GjsContext *js_context,
     }
 
     JS_EndRequest(js_context->context);
-    gjs_runtime_pop_context(js_context->runtime);
 
     g_object_unref(G_OBJECT(js_context));
 
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
index 3198ec7..61b07ac 100644
--- a/gjs/jsapi-util.c
+++ b/gjs/jsapi-util.c
@@ -43,17 +43,6 @@ gjs_util_error_quark (void)
 
 typedef struct {
     JSContext *context;
-    int depth;
-} ContextFrame;
-
-typedef struct {
-    JSObject *import_global;
-
-    JSContext *default_context;
-
-    /* In a thread-safe future we'd keep this in per-thread data */
-    ContextFrame current_frame;
-    GSList *context_stack;
 } RuntimeData;
 
 static RuntimeData* get_data_from_runtime(JSRuntime *runtime);
@@ -63,7 +52,7 @@ static RuntimeData* get_data_from_runtime(JSRuntime *runtime);
  * @context: a #JSContext
  *
  * Gets the "import global" for the context's runtime. The import
- * global object is the global object for the default context. It is used
+ * global object is the global object for the context. It is used
  * as the root object for the scope of modules loaded by GJS in this
  * runtime, and should also be used as the globals 'obj' argument passed
  * to JS_InitClass() and the parent argument passed to JS_ConstructObject()
@@ -80,151 +69,24 @@ static RuntimeData* get_data_from_runtime(JSRuntime *runtime);
 JSObject*
 gjs_get_import_global(JSContext *context)
 {
-    JSRuntime *runtime = JS_GetRuntime(context);
-    RuntimeData *rd;
-
-    rd = get_data_from_runtime(runtime);
-
-    return rd->import_global;
+    return JS_GetGlobalObject(context);
 }
 
 /**
- * gjs_runtime_push_context:
+ * gjs_runtime_get_context:
  * @runtime: a #JSRuntime
- * @context: a #JSRuntime
- *
- * Make @context the currently active context for @runtime.
- * A stack is maintained, although switching between different contexts
- * in a nested fashion in the same thread ecan trigger misbehavior in
- * Spidermonkey, so is not recommended. This does not call JS_BeginRequest();
- * the caller needs to do it themselves.
  *
- * Should be called when calling from Javascript into native code that
- * could result in callbacks back to Javascript. The context stack allows
- * the callbacks to find the right context to use via gjs_get_current_context().
- *
- * When GJS is made threadsafe, this needs to maintain a per-thread stack
- * rather than a global stack.
- */
-void
-gjs_runtime_push_context(JSRuntime *runtime,
-                         JSContext *context)
-{
-    RuntimeData *rd;
-
-    rd = get_data_from_runtime(runtime);
-
-    if (context == rd->current_frame.context) {
-        rd->current_frame.depth++;
-    } else {
-        rd->context_stack = g_slist_prepend(rd->context_stack,
-                                            g_slice_dup(ContextFrame, &rd->current_frame));
-        rd->current_frame.context = context;
-        rd->current_frame.depth = 0;
-    }
-}
-
-/**
- * gjs_runtime_pop_context:
- * @runtime: a #JSRuntime
+ * Gets the context associated with this runtime.
  *
- * Pops a context pushed onto the stack of active contexts by
- * gjs_runtime_push_context().
- */
-void
-gjs_runtime_pop_context(JSRuntime *runtime)
-{
-    RuntimeData *rd;
-
-    rd = get_data_from_runtime(runtime);
-
-    if (rd->current_frame.depth == 0) {
-        if (rd->context_stack == NULL)
-            gjs_fatal("gjs_runtime_pop_context() called more times than gjs_runtime_push_context()");
-
-        rd->current_frame = *(ContextFrame *)rd->context_stack->data;
-        g_slice_free(ContextFrame, rd->context_stack->data);
-        rd->context_stack = g_slist_delete_link(rd->context_stack, rd->context_stack);
-    } else {
-        rd->current_frame.depth--;
-    }
-}
-
-/**
- * gjs_runtime_set_default_context:
- * @runtime: a #JSRuntime
- * @context: a #JSContext
- *
- * Makes @context the default context for @runtime. The default context is the
- * context used for executing callbacks when no other context is active.
- * This generally should only be called by GJS - GJS sets the default context
- * when #GjsContext creates a runtime, and subsequent calls to this function
- * will produce an error.
- */
-void
-gjs_runtime_set_default_context(JSRuntime *runtime,
-                                JSContext *context)
-{
-    RuntimeData *rd;
-
-    rd = get_data_from_runtime(runtime);
-
-    if (rd->context_stack != NULL || rd->current_frame.depth != 0)
-        gjs_fatal("gjs_runtime_set_default_context() called during gjs_push_context()");
-
-    if (context != NULL) {
-        if (rd->default_context != NULL)
-            gjs_fatal("gjs_runtime_set_default_context() called twice on the same JSRuntime");
-        rd->default_context = context;
-        rd->current_frame.context = context;
-        rd->import_global = JS_GetGlobalObject(rd->default_context);
-    } else {
-        rd->default_context = NULL;
-        rd->current_frame.context = NULL;
-        rd->import_global = NULL;
-    }
-}
-
-/**
- * gjs_runtime_get_default_context:
- * @runtime: a #JSRuntime
- *
- * Gets the default context for @runtime. Generally you should use
- * gjs_runtime_get_current_context() instead.
- *
- * Return value: the default context, or %NULL if GJS hasn't been initialized
- *  for the runtime or is being shut down.
+ * Return value: the context, or %NULL if GJS hasn't been initialized
+ * for the runtime or is being shut down.
  */
 JSContext *
-gjs_runtime_get_default_context(JSRuntime *runtime)
+gjs_runtime_get_context(JSRuntime *runtime)
 {
     RuntimeData *rd;
-
     rd = get_data_from_runtime(runtime);
-
-    return rd->default_context;
-}
-
-/**
- * gjs_runtime_get_current_context:
- * @runtime: a #JSRuntime
- *
- * Gets the right context to use for code that doesn't already have a JSContext
- * passed to it, like a callback from native code. If a context is currently
- * active (see gjs_push_context()), uses that, otherwise uses the default
- * context for the runtime.
- *
- * Return value: the current context, or %NULL if GJS hasn't been initialized
- *  for the runtime or is being shut down.
- */
-JSContext *
-gjs_runtime_get_current_context(JSRuntime *runtime)
-{
-    RuntimeData *rd;
-
-    rd = get_data_from_runtime(runtime);
-
-    return rd->current_frame.context;
+    return rd->context;
 }
 
 static JSClass global_class = {
@@ -264,22 +126,16 @@ gjs_init_context_standard (JSContext       *context)
  * This should only be called by GJS, not by applications.
  */
 void
-gjs_runtime_init(JSRuntime *runtime)
+gjs_runtime_init(JSRuntime *runtime,
+                 JSContext *context)
 {
     RuntimeData *rd;
 
-    /* If we went back to supporting foreign contexts, we couldn't use
-     * JS_SetRuntimePrivate() because the runtime's owner might
-     * already be using it. A simple solution would be to just store
-     * the runtime data in a global variable - multiple copies of GJS
-     * in the same process at the same time have issues anyways
-     * because of limitations of GObject toggle references - if two
-     * separate entities toggle reference an object it will leak.
-     */
     if (JS_GetRuntimePrivate(runtime) != NULL)
         gjs_fatal("JSRuntime already initialized or private data in use by someone else");
 
     rd = g_slice_new0(RuntimeData);
+    rd->context = context;
     JS_SetRuntimePrivate(runtime, rd);
 }
 
@@ -302,8 +158,6 @@ gjs_runtime_destroy(JSRuntime *runtime)
     RuntimeData *rd;
 
     rd = JS_GetRuntimePrivate(runtime);
-    if (rd->context_stack != NULL || rd->current_frame.depth != 0)
-        gjs_fatal("gjs_runtime_destroy() called during gjs_push_context()");
 
     gjs_debug(GJS_DEBUG_CONTEXT,
               "Destroying JS runtime");
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 3c14c5c..e825b5f 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -181,16 +181,11 @@ jsval gjs_##cname##_create_proto(JSContext *context, JSObject *module, const cha
 
 gboolean    gjs_init_context_standard        (JSContext       *context);
 
-void        gjs_runtime_init                 (JSRuntime       *runtime);
+void        gjs_runtime_init                 (JSRuntime       *runtime,
+                                              JSContext       *context);
 void        gjs_runtime_destroy              (JSRuntime       *runtime);
 
-JSContext*  gjs_runtime_get_current_context  (JSRuntime       *runtime);
-void        gjs_runtime_set_default_context  (JSRuntime       *runtime,
-                                              JSContext       *context);
-JSContext*  gjs_runtime_get_default_context  (JSRuntime       *runtime);
-void        gjs_runtime_push_context         (JSRuntime       *runtime,
-                                              JSContext       *context);
-void        gjs_runtime_pop_context          (JSRuntime       *runtime);
+JSContext*  gjs_runtime_get_context          (JSRuntime       *runtime);
 JSObject*   gjs_get_import_global            (JSContext       *context);
 gboolean    gjs_object_has_property          (JSContext       *context,
                                               JSObject        *obj,
diff --git a/modules/mainloop.c b/modules/mainloop.c
index 015740a..cbf4069 100644
--- a/modules/mainloop.c
+++ b/modules/mainloop.c
@@ -101,9 +101,7 @@ gjs_main_loop_run(JSContext *context,
               context);
     g_free(cancel_id);
 
-    gjs_runtime_push_context(JS_GetRuntime(context), context);
     g_main_loop_run(main_loop);
-    gjs_runtime_pop_context(JS_GetRuntime(context));
 
     g_main_loop_unref(main_loop);
     return JS_TRUE;
@@ -124,7 +122,7 @@ closure_source_func(void *data)
         return FALSE;
 
     runtime = gjs_closure_get_runtime(closure);
-    context = gjs_runtime_get_current_context(runtime);
+    context = gjs_runtime_get_context(runtime);
 
     JS_BeginRequest(context);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]