[gjs/wip/xulrunner-1.9.3-rebase6: 1/8] Drop load and call contexts



commit b024ed5b255c4e12633c625767eadaeed40f1753
Author: Colin Walters <walters verbum org>
Date:   Wed Sep 22 16:11:23 2010 -0400

    Drop load and call contexts
    
    Apparently for XULRunner embedding reasons, multiple different
    contexts were added to gjs.  We're using these in a way not really
    intended by Spidermonkey.  The default intended design is that there's
    one (active) JSContext * per thread.
    
    In particular, stacking JS_BeginRequest(context_a);
    JS_BeginRequest(context_b) is "dubious" in current Spidermonkey.
    
    For the load context: If we want to e.g. avoid having modules loaded
    multiple times even if run from a non-default context (and thus a
    non-default global object), the obvious implementation technique is to
    just hook them off the GjsRuntime default global object.
    
    For the callback context: We need to assume that we have a standard
    context provided by Gjs, which is the thread default one.  Actually,
    one possibility here is to root the global object for a given
    callback.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=622896

 Makefile.am            |    1 -
 gi/closure.c           |   31 +-----
 gi/function.c          |   14 +--
 gi/keep-alive.c        |    5 +-
 gi/keep-alive.h        |    2 +-
 gi/ns.c                |   44 +++-----
 gi/object.c            |    9 +-
 gi/repo.c              |   58 +++++------
 gjs/byteArray.c        |    7 +-
 gjs/context-jsapi.h    |   37 -------
 gjs/context.c          |  138 ++++++++-----------------
 gjs/importer.c         |   34 +++----
 gjs/importer.h         |    4 +-
 gjs/jsapi-private.cpp  |    1 -
 gjs/jsapi-util.c       |  268 +++---------------------------------------------
 gjs/jsapi-util.h       |   16 +---
 gjs/stack.c            |    2 +-
 modules/dbus-exports.c |    9 +-
 18 files changed, 138 insertions(+), 542 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index f12fd70..c0d0e71 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -29,7 +29,6 @@ nobase_gjsinclude_HEADERS =	\
 
 noinst_HEADERS +=		\
 	gjs/compat.h		\
-	gjs/context-jsapi.h	\
 	gjs/jsapi-private.h	\
 	gjs/profiler.h		\
 	gjs/unit-test-utils.h	\
diff --git a/gi/closure.c b/gi/closure.c
index 3eb5a33..56de829 100644
--- a/gi/closure.c
+++ b/gi/closure.c
@@ -40,30 +40,7 @@ typedef struct {
 } Closure;
 
 /*
- * Memory management of closures is "interesting" because we're keeping around
- * a JSContext* and then trying to use it spontaneously from the main loop.
- * I don't think that's really quite kosher, and perhaps the problem is that
- * (in xulrunner) we just need to save a different context.
- *
- * Or maybe the right fix is to create our own context just for this?
- *
- * But for the moment, we save the context that was used to create the closure.
- *
- * Here's the problem: this context can be destroyed. AFTER the
- * context is destroyed, or at least potentially after, the objects in
- * the context's global object may be garbage collected. Remember that
- * JSObject* belong to a runtime, not a context.
- *
- * There is apparently no robust way to track context destruction in
- * SpiderMonkey, because the context can be destroyed without running
- * the garbage collector, and xulrunner takes over the JS_SetContextCallback()
- * callback. So there's no callback for us.
- *
- * So, when we go to use our context, we iterate the contexts in the runtime
- * and see if ours is still in the valid list, and decide to invalidate
- * the closure if it isn't.
- *
- * The closure can thus be destroyed in several cases:
+ * The closure can be destroyed in several cases:
  * - invalidation by unref, e.g. when a signal is disconnected, closure is unref'd
  * - invalidation because we were invoked while the context was dead
  * - invalidation through finalization (we were garbage collected)
@@ -356,11 +333,7 @@ gjs_closure_new(JSContext  *context,
 
     c = (Closure*) g_closure_new_simple(sizeof(Closure), NULL);
     c->runtime = JS_GetRuntime(context);
-    /* Closure are executed in our special "load-context" (one per runtime).
-     * This ensures that the context is still alive when the closure
-     * is invoked (as long as the runtime lives)
-     */
-    c->context = gjs_runtime_get_load_context(c->runtime);
+    c->context = context;
     JS_BeginRequest(c->context);
 
     c->obj = callable;
diff --git a/gi/function.c b/gi/function.c
index b8aa2a0..80c051a 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -1036,16 +1036,12 @@ gjs_define_function(JSContext      *context,
                     GIFunctionInfo *info)
 {
     JSObject *function;
-    JSContext *load_context;
 
-    load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
-    JS_BeginRequest(load_context);
+    JS_BeginRequest(context);
 
-    function = function_new(load_context, info);
+    function = function_new(context, info);
     if (function == NULL) {
-        gjs_move_exception(load_context, context);
-
-        JS_EndRequest(load_context);
+        JS_EndRequest(context);
         return NULL;
     }
 
@@ -1056,11 +1052,11 @@ gjs_define_function(JSContext      *context,
                            GJS_MODULE_PROP_FLAGS)) {
         gjs_debug(GJS_DEBUG_GFUNCTION, "Failed to define function");
 
-        JS_EndRequest(load_context);
+        JS_EndRequest(context);
         return NULL;
     }
 
-    JS_EndRequest(load_context);
+    JS_EndRequest(context);
     return function;
 }
 
diff --git a/gi/keep-alive.c b/gi/keep-alive.c
index 8e2c4ab..8d903f7 100644
--- a/gi/keep-alive.c
+++ b/gi/keep-alive.c
@@ -446,13 +446,10 @@ gjs_keep_alive_remove_global_child(JSContext         *context,
 }
 
 JSObject*
-gjs_keep_alive_get_for_load_context(JSRuntime *runtime)
+gjs_keep_alive_get_for_context(JSContext *context)
 {
-    JSContext *context;
     JSObject *keep_alive;
 
-    context = gjs_runtime_get_load_context(runtime);
-
     g_assert(context != NULL);
 
     JS_BeginRequest(context);
diff --git a/gi/keep-alive.h b/gi/keep-alive.h
index 7c4d0c2..4f81459 100644
--- a/gi/keep-alive.h
+++ b/gi/keep-alive.h
@@ -73,7 +73,7 @@ void      gjs_keep_alive_remove_global_child       (JSContext         *context,
                                                     GjsUnrootedFunc  notify,
                                                     JSObject          *child,
                                                     void              *data);
-JSObject* gjs_keep_alive_get_for_load_context      (JSRuntime         *runtime);
+JSObject* gjs_keep_alive_get_for_context           (JSContext         *context);
 
 
 
diff --git a/gi/ns.c b/gi/ns.c
index 85652dd..6d85241 100644
--- a/gi/ns.c
+++ b/gi/ns.c
@@ -70,7 +70,7 @@ ns_new_resolve(JSContext *context,
     const char *name;
     GIRepository *repo;
     GIBaseInfo *info;
-    JSContext *load_context;
+    JSBool retval = JS_FALSE;
 
     *objp = NULL;
 
@@ -88,8 +88,7 @@ ns_new_resolve(JSContext *context,
     if (priv == NULL)
         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);
+    JS_BeginRequest(context);
 
     repo = g_irepository_get_default();
 
@@ -98,23 +97,17 @@ ns_new_resolve(JSContext *context,
         /* Special-case fallback hack for GParamSpec */
         if (strcmp(name, "ParamSpec") == 0 &&
             strcmp(priv->namespace, "GLib") == 0) {
-            gjs_define_param_class(load_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;
-            }
+            if (!gjs_define_param_class(context,
+                                        obj,
+                                        NULL))
+                goto out;
+            *objp = obj; /* we defined the property in this object */
+            retval = JS_TRUE;
         } else {
             gjs_throw(context,
                       "No symbol '%s' in namespace '%s'",
                       name, priv->namespace);
-            JS_EndRequest(load_context);
-            return JS_FALSE;
+            goto out;
         }
     }
 
@@ -124,27 +117,22 @@ ns_new_resolve(JSContext *context,
               g_base_info_get_name(info),
               g_base_info_get_namespace(info));
 
-    if (gjs_define_info(load_context, obj, info)) {
+    if (gjs_define_info(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,
                   "Failed to define info '%s'",
                   g_base_info_get_name(info));
 
         g_base_info_unref(info);
-
-        if (!gjs_move_exception(load_context, context)) {
-            /* set an exception if none was set */
-            gjs_throw(context,
-                         "Defining info failed but no exception set");
-        }
-
-        JS_EndRequest(load_context);
-        return JS_FALSE;
+        goto out;
     }
+
+    retval = JS_TRUE;
+ out:
+    JS_EndRequest(context);
+    return retval;
 }
 
 /* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
diff --git a/gi/object.c b/gi/object.c
index caacce5..fadc780 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -566,7 +566,10 @@ 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_peek_load_context(runtime);
+    {
+        context = NULL;
+        JS_ContextIterator(runtime, &context);
+    }
     if (!context)
         return;
 
@@ -598,7 +601,7 @@ wrapped_gobj_toggle_notify(gpointer      data,
          */
         if (priv->keep_alive == NULL) {
             gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "Adding object to keep alive");
-            priv->keep_alive = gjs_keep_alive_get_for_load_context(runtime);
+            priv->keep_alive = gjs_keep_alive_get_for_context(context);
             gjs_keep_alive_add_child(context, priv->keep_alive,
                                      gobj_no_longer_kept_alive_func,
                                      obj,
@@ -746,7 +749,7 @@ object_instance_constructor(JSContext *context,
          * the wrapper to be garbage collected (and thus unref the
          * wrappee).
          */
-        priv->keep_alive = gjs_keep_alive_get_for_load_context(JS_GetRuntime(context));
+        priv->keep_alive = gjs_keep_alive_get_for_context(context);
         gjs_keep_alive_add_child(context,
                                  priv->keep_alive,
                                  gobj_no_longer_kept_alive_func,
diff --git a/gi/repo.c b/gi/repo.c
index cff1b24..3dd8166 100644
--- a/gi/repo.c
+++ b/gi/repo.c
@@ -59,28 +59,26 @@ resolve_namespace_object(JSContext  *context,
 {
     GIRepository *repo;
     GError *error;
-    JSContext *load_context;
     jsval versions_val;
     JSObject *versions;
     jsval version_val;
     const char *version;
     JSObject *result;
 
-    load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
-    JS_BeginRequest(load_context);
+    JS_BeginRequest(context);
 
-    if (!gjs_object_require_property(load_context, repo_obj, "GI repository object", "versions", &versions_val) ||
+    if (!gjs_object_require_property(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);
+        JS_EndRequest(context);
         return NULL;
     }
 
     versions = JSVAL_TO_OBJECT(versions_val);
 
     version = NULL;
-    if (JS_GetProperty(load_context, versions, ns_name, &version_val) &&
+    if (JS_GetProperty(context, versions, ns_name, &version_val) &&
         JSVAL_IS_STRING(version_val)) {
         version = gjs_string_get_ascii(version_val);
     }
@@ -94,7 +92,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);
+        JS_EndRequest(context);
         return JS_FALSE;
     }
 
@@ -103,7 +101,7 @@ resolve_namespace_object(JSContext  *context,
      * in the repo.
      */
     result = gjs_define_ns(context, repo_obj, ns_name, repo);
-    JS_EndRequest(load_context);
+    JS_EndRequest(context);
     return result;
 }
 
@@ -129,7 +127,7 @@ repo_new_resolve(JSContext *context,
 {
     Repo *priv;
     const char *name;
-    JSContext *load_context;
+    JSBool retval = JS_FALSE;
 
     *objp = NULL;
 
@@ -147,17 +145,17 @@ repo_new_resolve(JSContext *context,
     if (priv == NULL)
         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;
-    }
+    JS_BeginRequest(context);
+
+    if (!resolve_namespace_object(context, obj, name))
+        goto out;
+        
+    retval = JS_TRUE;
+    *objp = obj; /* store the object we defined the prop in */
+
+ out:
+    JS_EndRequest(context);
+    return retval;
 }
 
 /* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
@@ -505,7 +503,6 @@ JSObject*
 gjs_lookup_namespace_object_by_name(JSContext      *context,
                                     const char     *ns)
 {
-    JSContext *load_context;
     JSObject *global;
     JSObject *repo_obj;
     jsval importer;
@@ -517,23 +514,22 @@ gjs_lookup_namespace_object_by_name(JSContext      *context,
      * in the load context.
      */
 
-    load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
-    JS_BeginRequest(load_context);
-    global = JS_GetGlobalObject(load_context);
+    JS_BeginRequest(context);
+    global = JS_GetGlobalObject(context);
 
     importer = JSVAL_VOID;
-    if (!gjs_object_require_property(load_context, global, "global object", "imports", &importer) ||
+    if (!gjs_object_require_property(context, global, "global object", "imports", &importer) ||
         !JSVAL_IS_OBJECT(importer)) {
-        gjs_log_exception(load_context, NULL);
+        gjs_log_exception(context, NULL);
         gjs_throw(context, "No imports property in global object");
         goto fail;
     }
 
     girepository = JSVAL_VOID;
-    if (!gjs_object_require_property(load_context, JSVAL_TO_OBJECT(importer), "importer",
-                                        "gi", &girepository) ||
+    if (!gjs_object_require_property(context, JSVAL_TO_OBJECT(importer), "importer",
+                                     "gi", &girepository) ||
         !JSVAL_IS_OBJECT(girepository)) {
-        gjs_log_exception(load_context, NULL);
+        gjs_log_exception(context, NULL);
         gjs_throw(context, "No gi property in importer");
         goto fail;
     }
@@ -549,11 +545,11 @@ gjs_lookup_namespace_object_by_name(JSContext      *context,
         goto fail;
     }
 
-    JS_EndRequest(load_context);
+    JS_EndRequest(context);
     return JSVAL_TO_OBJECT(ns_obj);
 
  fail:
-    JS_EndRequest(load_context);
+    JS_EndRequest(context);
     return NULL;
 }
 
diff --git a/gjs/byteArray.c b/gjs/byteArray.c
index d0157e9..8a5993b 100644
--- a/gjs/byteArray.c
+++ b/gjs/byteArray.c
@@ -843,9 +843,8 @@ JSBool
 gjs_define_byte_array_stuff(JSContext      *context,
                             JSObject       *in_object)
 {
-    JSContext *load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
     JSObject *global = JS_GetGlobalObject(context);
-    gjs_byte_array_prototype = JS_InitClass(load_context, global,
+    gjs_byte_array_prototype = JS_InitClass(context, global,
                              NULL,
                              &gjs_byte_array_class,
                              byte_array_constructor,
@@ -857,14 +856,12 @@ gjs_define_byte_array_stuff(JSContext      *context,
     jsval rval;
 
     if (gjs_byte_array_prototype == NULL) {
-        gjs_move_exception(load_context, context);
         return JS_FALSE;
     }
 
     if (!gjs_object_require_property(
-            load_context, global, NULL,
+            context, global, NULL,
             "ByteArray", &rval)) {
-        gjs_move_exception(load_context, context);
         return JS_FALSE;
     }
 
diff --git a/gjs/context.c b/gjs/context.c
index 28f1c8c..9c20266 100644
--- a/gjs/context.c
+++ b/gjs/context.c
@@ -24,7 +24,6 @@
 #include <config.h>
 
 #include "context.h"
-#include "context-jsapi.h"
 #include "importer.h"
 #include "jsapi-util.h"
 #include "profiler.h"
@@ -62,9 +61,6 @@ struct _GjsContext {
     GjsProfiler *profiler;
 
     char **search_path;
-
-    unsigned int we_own_runtime : 1;
-    unsigned int is_load_context : 1;
 };
 
 struct _GjsContextClass {
@@ -83,9 +79,7 @@ static int signals[LAST_SIGNAL];
 
 enum {
     PROP_0,
-    PROP_SEARCH_PATH,
-    PROP_RUNTIME,
-    PROP_IS_LOAD_CONTEXT
+    PROP_SEARCH_PATH
 };
 
 
@@ -316,25 +310,6 @@ gjs_context_class_init(GjsContextClass *klass)
                                     PROP_SEARCH_PATH,
                                     pspec);
 
-    pspec = g_param_spec_pointer("runtime",
-                                 "JSRuntime",
-                                 "A runtime to use instead of creating our own",
-                                 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
-
-    g_object_class_install_property(object_class,
-                                    PROP_RUNTIME,
-                                    pspec);
-
-    pspec = g_param_spec_boolean("is-load-context",
-                                 "IsLoadContext",
-                                 "Whether this is the load context",
-                                 FALSE,
-                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-
-    g_object_class_install_property(object_class,
-                                    PROP_IS_LOAD_CONTEXT,
-                                    pspec);
-
     gjs_register_native_module("byteArray", gjs_define_byte_array_stuff, 0);
 }
 
@@ -358,42 +333,34 @@ gjs_context_dispose(GObject *object)
     }
 
     if (js_context->context != NULL) {
-
-        gjs_debug(GJS_DEBUG_CONTEXT,
-                  "Destroying JS context%s",
-                  js_context->is_load_context ? " (load context)" : "");
+        gjs_debug(GJS_DEBUG_CONTEXT, "Destroying JS context");
 
         JS_DestroyContext(js_context->context);
         js_context->context = NULL;
     }
 
     if (js_context->runtime != NULL) {
-        if (js_context->we_own_runtime) {
-            /* Avoid keeping JSContext with a dangling pointer to the
-             * runtime.
-             */
-            gjs_runtime_clear_call_context(js_context->runtime);
-            gjs_runtime_clear_load_context(js_context->runtime);
-
-            gjs_debug(GJS_DEBUG_CONTEXT,
-                      "Destroying JS runtime");
+        /* Avoid keeping JSContext with a dangling pointer to the
+         * runtime.
+         */
+        gjs_debug(GJS_DEBUG_CONTEXT,
+                  "Destroying JS runtime");
 
-            JS_DestroyRuntime(js_context->runtime);
+        JS_DestroyRuntime(js_context->runtime);
 
-            /* finalize the dataset from jsapi-util.c ...  for
-             * "foreign" runtimes this just never happens for
-             * now... we do this after the runtime itself is destroyed
-             * because we might have finalizers run by
-             * JS_DestroyRuntime() that rely on data we've set on the
-             * runtime, such as the dynamic class structs.
-             */
-            gjs_debug(GJS_DEBUG_CONTEXT,
-                      "Destroying any remaining dataset items on runtime");
+        /* finalize the dataset from jsapi-util.c ...  for
+         * "foreign" runtimes this just never happens for
+         * now... we do this after the runtime itself is destroyed
+         * because we might have finalizers run by
+         * JS_DestroyRuntime() that rely on data we've set on the
+         * runtime, such as the dynamic class structs.
+         */
+        gjs_debug(GJS_DEBUG_CONTEXT,
+                  "Destroying any remaining dataset items on runtime");
 
-            g_dataset_destroy(js_context->runtime);
-        }
-        js_context->runtime = NULL;
+        g_dataset_destroy(js_context->runtime);
     }
+    js_context->runtime = NULL;
 
     G_OBJECT_CLASS(gjs_context_parent_class)->dispose(object);
 }
@@ -553,7 +520,6 @@ 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);
-        js_context->we_own_runtime = TRUE;
     }
 
     js_context->context = JS_NewContext(js_context->runtime, 8192 /* stack chunk size */);
@@ -648,34 +614,26 @@ gjs_context_constructor (GType                  type,
                            4, GJS_MODULE_PROP_FLAGS))
         gjs_fatal("Failed to define printerr function");
 
-    /* If we created the root importer in the load context,
-     * there would be infinite recursion since the load context
-     * is a GjsContext
+    /* 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.
      */
-    if (!js_context->is_load_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.
-         */
-        if (!gjs_create_root_importer(js_context->runtime,
-                                      js_context->search_path ?
-                                      (const char**) js_context->search_path :
-                                      NULL,
-                                      TRUE))
-            gjs_fatal("Failed to create root importer");
-
-        /* Now copy the global root importer (which we just created,
-         * if it didn't exist) to our global object
-         */
-        if (!gjs_define_root_importer(js_context->context,
-                                      js_context->global,
-                                      "imports"))
-            gjs_fatal("Failed to point 'imports' property at root importer");
-    }
+    if (!gjs_create_root_importer(js_context,
+                                  js_context->search_path ?
+                                  (const char**) js_context->search_path :
+                                  NULL,
+                                  TRUE))
+        gjs_fatal("Failed to create root importer");
+
+    /* Now copy the global root importer (which we just created,
+     * if it didn't exist) to our global object
+     */
+    if (!gjs_define_root_importer(js_context,
+                                  js_context->global,
+                                  "imports"))
+        gjs_fatal("Failed to point 'imports' property at root importer");
 
-    if (js_context->we_own_runtime) {
-        js_context->profiler = gjs_profiler_new(js_context->runtime);
-    }
+    js_context->profiler = gjs_profiler_new(js_context->runtime);
 
     JS_EndRequest(js_context->context);
 
@@ -697,8 +655,8 @@ gjs_context_get_property (GObject     *object,
     js_context = GJS_CONTEXT (object);
 
     switch (prop_id) {
-    case PROP_IS_LOAD_CONTEXT:
-        g_value_set_boolean(value, js_context->is_load_context);
+    case PROP_SEARCH_PATH:
+        g_value_set_boxed(value, js_context->search_path);
         break;
 
     default:
@@ -721,12 +679,6 @@ gjs_context_set_property (GObject      *object,
     case PROP_SEARCH_PATH:
         js_context->search_path = g_strdupv(g_value_get_pointer(value));
         break;
-    case PROP_RUNTIME:
-        js_context->runtime = g_value_get_pointer(value);
-        break;
-    case PROP_IS_LOAD_CONTEXT:
-        js_context->is_load_context = g_value_get_boolean(value);
-        break;
 
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -784,12 +736,6 @@ gjs_context_get_native_context (GjsContext *js_context)
 }
 
 gboolean
-gjs_context_is_load_context(GjsContext *js_context)
-{
-    return js_context->is_load_context;
-}
-
-gboolean
 gjs_context_eval(GjsContext *js_context,
                  const char   *script,
                  gssize        script_len,
diff --git a/gjs/importer.c b/gjs/importer.c
index f2d1bd1..d0c347a 100644
--- a/gjs/importer.c
+++ b/gjs/importer.c
@@ -913,7 +913,6 @@ importer_new_resolve(JSContext *context,
 {
     Importer *priv;
     const char *name;
-    JSContext *load_context;
 
     *objp = NULL;
 
@@ -932,20 +931,13 @@ importer_new_resolve(JSContext *context,
         return JS_TRUE; /* we are the prototype, or have the wrong class */
 
     /* 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)) {
+    JS_BeginRequest(context);
+    if (do_import(context, obj, priv, name)) {
         *objp = obj;
-        JS_EndRequest(load_context);
+        JS_EndRequest(context);
         return JS_TRUE;
     } else {
-        /* Move the exception to the calling context from load context.
-         */
-        if (!gjs_move_exception(load_context, context)) {
-            /* set an exception since none was set */
-            gjs_throw(context, "No exception was set, but import failed somehow");
-        }
-        JS_EndRequest(load_context);
+        JS_EndRequest(context);
         return JS_FALSE;
     }
 }
@@ -1185,13 +1177,13 @@ gjs_define_importer(JSContext    *context,
  * we just ignore all calls after the first and hope the args are the same.
  */
 JSBool
-gjs_create_root_importer(JSRuntime   *runtime,
+gjs_create_root_importer(GjsContext  *gjs_context,
                          const char **initial_search_path,
                          gboolean     add_standard_search_path)
 {
     JSContext *context;
 
-    context = gjs_runtime_get_load_context(runtime);
+    context = gjs_context_get_native_context(gjs_context);
 
     JS_BeginRequest(context);
 
@@ -1216,20 +1208,20 @@ gjs_create_root_importer(JSRuntime   *runtime,
 }
 
 JSBool
-gjs_define_root_importer(JSContext   *context,
+gjs_define_root_importer(GjsContext  *gjs_context,
                          JSObject    *in_object,
                          const char  *importer_name)
 {
-    JSContext *load_context;
+    JSContext *context;
     jsval value;
     JSBool success;
 
     success = JS_FALSE;
-    load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
-    JS_BeginRequest(load_context);
+    context = gjs_context_get_native_context(gjs_context);
+    JS_BeginRequest(context);
 
-    if (!gjs_object_require_property(load_context,
-                                     JS_GetGlobalObject(load_context), "global object",
+    if (!gjs_object_require_property(context,
+                                     JS_GetGlobalObject(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");
@@ -1247,6 +1239,6 @@ gjs_define_root_importer(JSContext   *context,
 
     success = JS_TRUE;
  fail:
-    JS_EndRequest(load_context);
+    JS_EndRequest(context);
     return success;
 }
diff --git a/gjs/importer.h b/gjs/importer.h
index 2bd99e0..50e7753 100644
--- a/gjs/importer.h
+++ b/gjs/importer.h
@@ -34,10 +34,10 @@
 
 G_BEGIN_DECLS
 
-JSBool    gjs_create_root_importer (JSRuntime   *runtime,
+JSBool    gjs_create_root_importer (GjsContext  *context,
                                     const char **initial_search_path,
                                     gboolean     add_standard_search_path);
-JSBool    gjs_define_root_importer (JSContext   *context,
+JSBool    gjs_define_root_importer (GjsContext  *context,
                                     JSObject    *in_object,
                                     const char  *importer_name);
 JSObject* gjs_define_importer      (JSContext   *context,
diff --git a/gjs/jsapi-private.cpp b/gjs/jsapi-private.cpp
index b27935a..ad47065 100644
--- a/gjs/jsapi-private.cpp
+++ b/gjs/jsapi-private.cpp
@@ -29,7 +29,6 @@
 
 #include "jsapi-util.h"
 #include "jsapi-private.h"
-#include "context-jsapi.h"
 
 #include <string.h>
 #include <jscntxt.h>
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
index e2f7f14..3dc9178 100644
--- a/gjs/jsapi-util.c
+++ b/gjs/jsapi-util.c
@@ -29,7 +29,6 @@
 #include <util/misc.h>
 
 #include "jsapi-util.h"
-#include "context-jsapi.h"
 #include "jsapi-private.h"
 
 #include <string.h>
@@ -65,112 +64,6 @@ gjs_runtime_set_data(JSRuntime      *runtime,
     g_dataset_set_data_full(runtime, name, data, dnotify);
 }
 
-/* The "load context" is the one we use for loading
- * modules and initializing classes.
- */
-JSContext*
-gjs_runtime_get_load_context(JSRuntime *runtime)
-{
-    GjsContext *context;
-
-    context = gjs_runtime_get_data(runtime, "gjs-load-context");
-    if (context == NULL) {
-        gjs_debug(GJS_DEBUG_CONTEXT,
-                  "Creating load context for runtime %p",
-                  runtime);
-        context = g_object_new(GJS_TYPE_CONTEXT,
-                               "runtime", runtime,
-                               "is-load-context", TRUE,
-                               NULL);
-        gjs_runtime_set_data(runtime,
-                             "gjs-load-context",
-                             context,
-                             g_object_unref);
-    }
-
-    return (JSContext*)gjs_context_get_native_context(context);
-}
-
-JSContext*
-gjs_runtime_peek_load_context(JSRuntime *runtime)
-{
-    GjsContext *context;
-
-    context = gjs_runtime_get_data(runtime, "gjs-load-context");
-    if (context == NULL) {
-        return NULL;
-    } else {
-        return (JSContext*)gjs_context_get_native_context(context);
-    }
-}
-
-void
-gjs_runtime_clear_load_context(JSRuntime *runtime)
-{
-    gjs_debug(GJS_DEBUG_CONTEXT, "Clearing load context");
-    gjs_runtime_set_data(runtime,
-                         "gjs-load-context",
-                         NULL,
-                         NULL);
-    gjs_debug(GJS_DEBUG_CONTEXT, "Load context cleared");
-}
-
-/* The call context exists because when we call a closure, the scope
- * chain on the context is set to the original scope chain of the
- * closure. We want to avoid using any existing context (especially
- * the load context) because the closure "messes up" the scope chain
- * on the context.
- *
- * Unlike the load context, which is expected to be an eternal
- * singleton, we only cache the call context for efficiency. It would
- * be just as workable to recreate it for each call.
- */
-JSContext*
-gjs_runtime_get_call_context(JSRuntime *runtime)
-{
-    GjsContext *context;
-
-    context = gjs_runtime_get_data(runtime, "gjs-call-context");
-    if (context == NULL) {
-        gjs_debug(GJS_DEBUG_CONTEXT,
-                  "Creating call context for runtime %p",
-                  runtime);
-        context = g_object_new(GJS_TYPE_CONTEXT,
-                               "runtime", runtime,
-                               NULL);
-        gjs_runtime_set_data(runtime,
-                             "gjs-call-context",
-                             context,
-                             g_object_unref);
-    }
-
-    return (JSContext*)gjs_context_get_native_context(context);
-}
-
-static JSContext*
-gjs_runtime_peek_call_context(JSRuntime *runtime)
-{
-    GjsContext *context;
-
-    context = gjs_runtime_get_data(runtime, "gjs-call-context");
-    if (context == NULL) {
-        return NULL;
-    } else {
-        return (JSContext*)gjs_context_get_native_context(context);
-    }
-}
-
-void
-gjs_runtime_clear_call_context(JSRuntime *runtime)
-{
-    gjs_debug(GJS_DEBUG_CONTEXT, "Clearing call context");
-    gjs_runtime_set_data(runtime,
-                         "gjs-call-context",
-                         NULL,
-                         NULL);
-    gjs_debug(GJS_DEBUG_CONTEXT, "Call context cleared");
-}
-
 static void
 runtime_data_destroy_notify(void *data)
 {
@@ -320,7 +213,6 @@ gjs_init_class_dynamic(JSContext      *context,
     jsval value;
     char *private_name;
     JSObject *prototype;
-    JSContext *load_context;
 
     if (clasp->name != NULL) {
         g_warning("Dynamic class should not have a name in the JSClass struct");
@@ -329,15 +221,6 @@ gjs_init_class_dynamic(JSContext      *context,
 
     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
-     * the class in whatever global object initialized the
-     * 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
      * object instead of global object seems to break JS_ConstructObject()
@@ -347,17 +230,17 @@ gjs_init_class_dynamic(JSContext      *context,
     private_name = g_strdup_printf("_private_%s_%s", ns_name, class_name);
 
     prototype = NULL;
-    if (gjs_object_get_property(load_context, JS_GetGlobalObject(load_context),
+    if (gjs_object_get_property(context, JS_GetGlobalObject(context),
                                 private_name, &value) &&
         JSVAL_IS_OBJECT(value)) {
         jsval proto_val;
 
         g_free(private_name); /* don't need it anymore */
 
-        if (!gjs_object_require_property(load_context, JSVAL_TO_OBJECT(value), NULL,
+        if (!gjs_object_require_property(context, JSVAL_TO_OBJECT(value), NULL,
                                          "prototype", &proto_val) ||
             !JSVAL_IS_OBJECT(proto_val)) {
-            gjs_throw(load_context, "prototype was not defined or not an object?");
+            gjs_throw(context, "prototype was not defined or not an object?");
             goto error;
         }
         prototype = JSVAL_TO_OBJECT(proto_val);
@@ -365,7 +248,7 @@ gjs_init_class_dynamic(JSContext      *context,
         DynamicJSClass *class_copy;
         RuntimeData *rd;
 
-        rd = get_data_from_context(load_context);
+        rd = get_data_from_context(context);
 
         class_copy = g_slice_new0(DynamicJSClass);
         class_copy->base = *clasp;
@@ -383,7 +266,7 @@ gjs_init_class_dynamic(JSContext      *context,
                   "Initializing dynamic class %s %p",
                   class_name, class_copy);
 
-        prototype = JS_InitClass(load_context, JS_GetGlobalObject(load_context),
+        prototype = JS_InitClass(context, JS_GetGlobalObject(context),
                                  parent_proto, &class_copy->base,
                                  constructor, nargs,
                                  ps, fs,
@@ -392,7 +275,7 @@ gjs_init_class_dynamic(JSContext      *context,
         /* Retrieve the property again so we can define it in
          * in_object
          */
-        if (!gjs_object_require_property(load_context, JS_GetGlobalObject(load_context), NULL,
+        if (!gjs_object_require_property(context, JS_GetGlobalObject(context), NULL,
                                          class_copy->base.name, &value))
             goto error;
     }
@@ -402,26 +285,17 @@ gjs_init_class_dynamic(JSContext      *context,
     /* Now manually define our constructor with a sane name, in the
      * namespace object.
      */
-    if (!JS_DefineProperty(load_context, in_object,
+    if (!JS_DefineProperty(context, in_object,
                            class_name,
                            value,
                            NULL, NULL,
                            GJS_MODULE_PROP_FLAGS))
         goto error;
 
-    JS_EndRequest(load_context);
     JS_EndRequest(context);
     return prototype;
 
  error:
-    /* Move the exception to the calling context from load context.
-     */
-    if (!gjs_move_exception(load_context, context)) {
-        /* set an exception since none was set */
-        gjs_throw(context, "No exception was set, but class initialize failed somehow");
-    }
-
-    JS_EndRequest(load_context);
     JS_EndRequest(context);
     return NULL;
 }
@@ -532,26 +406,17 @@ gjs_construct_object_dynamic(JSContext      *context,
 {
     RuntimeData *rd;
     JSClass *proto_class;
-    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);
+    proto_class = JS_GET_CLASS(context, proto);
 
-    rd = get_data_from_context(load_context);
+    rd = get_data_from_context(context);
 
     /* Check that it's safe to cast to DynamicJSClass */
     if (g_hash_table_lookup(rd->dynamic_classes, proto_class) == NULL) {
-        gjs_throw(load_context, "Prototype is not for a dynamically-registered class");
+        gjs_throw(context, "Prototype is not for a dynamically-registered class");
         goto error;
     }
 
@@ -560,26 +425,18 @@ gjs_construct_object_dynamic(JSContext      *context,
                         proto_class->name, proto_class, proto);
 
     if (argc > 0)
-        result = JS_ConstructObjectWithArguments(load_context, proto_class, proto, NULL, argc, argv);
+        result = JS_ConstructObjectWithArguments(context, proto_class, proto, NULL, argc, argv);
     else
-        result = JS_ConstructObject(load_context, proto_class, proto, NULL);
+        result = JS_ConstructObject(context, proto_class, proto, NULL);
 
     if (!result)
         goto error;
 
-    JS_EndRequest(load_context);
     JS_EndRequest(context);
     return result;
 
  error:
-    /* Move the exception to the calling context from load context.
-     */
-    if (!gjs_move_exception(load_context, context)) {
-        /* set an exception since none was set */
-        gjs_throw(context, "No exception was set, but object construction failed somehow");
-    }
 
-    JS_EndRequest(load_context);
     JS_EndRequest(context);
     return NULL;
 }
@@ -733,8 +590,6 @@ void
 gjs_explain_scope(JSContext  *context,
                   const char *title)
 {
-    JSContext *load_context;
-    JSContext *call_context;
     JSObject *global;
     JSObject *parent;
     GString *chain;
@@ -743,21 +598,11 @@ gjs_explain_scope(JSContext  *context,
               "=== %s ===",
               title);
 
-    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,
-              "  Context: %p %s",
-              context,
-              context == load_context ? "(LOAD CONTEXT)" :
-              context == call_context ? "(CALL CONTEXT)" :
-              "");
+    gjs_debug(GJS_DEBUG_SCOPE, "  Context: %p", context);
 
     global = JS_GetGlobalObject(context);
     gjs_debug(GJS_DEBUG_SCOPE,
@@ -784,8 +629,6 @@ gjs_explain_scope(JSContext  *context,
 
     JS_LeaveLocalRootScope(context);
 
-    JS_EndRequest(call_context);
-    JS_EndRequest(load_context);
     JS_EndRequest(context);
 }
 
@@ -911,82 +754,6 @@ gjs_log_and_keep_exception(JSContext *context,
     return log_and_maybe_keep_exception(context, message_p, TRUE);
 }
 
-static void
-try_to_chain_stack_trace(JSContext *src_context, JSContext *dst_context,
-                         jsval src_exc) {
-    /* append current stack of dst_context to stack trace for src_exc.
-     * we bail if anything goes wrong, just using the src_exc unmodified
-     * in that case. */
-    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))
-        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)))
-        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)))
-        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)))
-        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)
-        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)) {
-        if (src_context != dest_context) {
-            /* try to add the current stack of dest_context to the
-             * stack trace of exc */
-            try_to_chain_stack_trace(src_context, dest_context, exc);
-            /* move the exception to dest_context */
-            JS_SetPendingException(dest_context, exc);
-            JS_ClearPendingException(src_context);
-        }
-        success = JS_TRUE;
-    } else {
-        success = JS_FALSE;
-    }
-
-    JS_EndRequest(dest_context);
-    JS_EndRequest(src_context);
-
-    return success;
-}
-
 JSBool
 gjs_call_function_value(JSContext      *context,
                         JSObject       *obj,
@@ -996,18 +763,11 @@ gjs_call_function_value(JSContext      *context,
                         jsval          *rval)
 {
     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,
+    result = JS_CallFunctionValue(context, obj, fval,
                                   argc, argv, rval);
-    gjs_move_exception(call_context, context);
 
-    JS_EndRequest(call_context);
     JS_EndRequest(context);
     return result;
 }
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 9921805..51db961 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -164,11 +164,10 @@ static struct JSClass cname##_class = { \
 jsval cname##_create_proto(JSContext *context, JSObject *module, const char *proto_name, JSObject *parent) \
 { \
     jsval rval; \
-    JSContext *load_context = gjs_runtime_get_load_context(JS_GetRuntime(context)); \
     JSObject *global = JS_GetGlobalObject(context); \
-    if (!gjs_object_has_property(load_context, global, \
+    if (!gjs_object_has_property(context, global, \
                                  cname##_class.name)) { \
-        JSObject *prototype = JS_InitClass(load_context, global, \
+        JSObject *prototype = JS_InitClass(context, global, \
                                  parent, \
                                  &cname##_class, \
                                  ctor, \
@@ -178,13 +177,11 @@ jsval cname##_create_proto(JSContext *context, JSObject *module, const char *pro
                                  NULL, \
                                  NULL); \
         if (prototype == NULL) { \
-            gjs_move_exception(load_context, context); \
             return JSVAL_NULL; \
         } \
         if (!gjs_object_require_property( \
-                load_context, global, NULL, \
+                context, global, NULL, \
                 cname##_class.name, &rval)) { \
-            gjs_move_exception(load_context, context); \
             return JSVAL_NULL; \
         } \
     } \
@@ -201,11 +198,6 @@ void        gjs_runtime_set_data             (JSRuntime       *runtime,
                                                  const char      *name,
                                                  void            *data,
                                                  GDestroyNotify   dnotify);
-JSContext*  gjs_runtime_get_load_context     (JSRuntime       *runtime);
-JSContext*  gjs_runtime_peek_load_context    (JSRuntime       *runtime);
-void        gjs_runtime_clear_load_context   (JSRuntime       *runtime);
-JSContext*  gjs_runtime_get_call_context     (JSRuntime       *runtime);
-void        gjs_runtime_clear_call_context   (JSRuntime       *runtime);
 gboolean    gjs_object_has_property          (JSContext       *context,
                                               JSObject        *obj,
                                               const char      *property_name);
@@ -262,8 +254,6 @@ JSBool      gjs_log_exception                (JSContext       *context,
                                               char           **message_p);
 JSBool      gjs_log_and_keep_exception       (JSContext       *context,
                                               char           **message_p);
-JSBool      gjs_move_exception               (JSContext       *src_context,
-                                              JSContext       *dest_context);
 void        gjs_log_exception_props          (JSContext       *context,
                                               jsval            exc);
 #ifdef __GJS_UTIL_LOG_H__
diff --git a/gjs/stack.c b/gjs/stack.c
index 410fc24..8e0e5ac 100644
--- a/gjs/stack.c
+++ b/gjs/stack.c
@@ -41,10 +41,10 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include <config.h>
-#include "context-jsapi.h"
 #include <glib.h>
 #include <string.h>
 #include <jsdbgapi.h>
+#include "context.h"
 
 static const char*
 jsvalue_to_string(JSContext* cx, jsval val, gboolean* is_string)
diff --git a/modules/dbus-exports.c b/modules/dbus-exports.c
index 99259a0..87889f9 100644
--- a/modules/dbus-exports.c
+++ b/modules/dbus-exports.c
@@ -1860,16 +1860,13 @@ gjs_js_define_dbus_exports(JSContext      *context,
                            DBusBusType     which_bus)
 {
     JSObject *exports;
-    JSContext *load_context;
     JSBool success;
 
     success = JS_FALSE;
-    load_context = gjs_runtime_get_load_context(JS_GetRuntime(context));
-    JS_BeginRequest(load_context);
+    JS_BeginRequest(context);
 
-    exports = exports_new(load_context, which_bus);
+    exports = exports_new(context, which_bus);
     if (exports == NULL) {
-        gjs_move_exception(load_context, context);
         goto fail;
     }
 
@@ -1885,6 +1882,6 @@ gjs_js_define_dbus_exports(JSContext      *context,
 
     success = JS_TRUE;
  fail:
-    JS_EndRequest(load_context);
+    JS_EndRequest(context);
     return success;
 }



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