[gjs] coverage: Allow root importer definition in other compartments



commit c93f1edf7b839f40556bdee242b6b706eee4ce58
Author: Sam Spilsbury <smspillaz gmail com>
Date:   Sat Jun 13 10:37:51 2015 +0800

    coverage: Allow root importer definition in other compartments

 gjs/coverage-internal.h |   39 +++++++++++++++++++++++
 gjs/coverage.cpp        |   78 ++++++++++++++++++++++++++++++++++++++++++++++-
 gjs/importer.cpp        |   26 ++++++++++++---
 gjs/importer.h          |    4 ++-
 4 files changed, 140 insertions(+), 7 deletions(-)
---
diff --git a/gjs/coverage-internal.h b/gjs/coverage-internal.h
new file mode 100644
index 0000000..681dc11
--- /dev/null
+++ b/gjs/coverage-internal.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2015 Endless Mobile, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authored By: Sam Spilsbury <sam endlessm com>
+ */
+
+#ifndef _GJS_COVERAGE_INTERNAL_H
+#define _GJS_COVERAGE_INTERNAL_H
+
+#ifndef GJS_COMPILATION
+#error This file is for internal use and use in the tests only
+#endif
+
+#include "jsapi-util.h"
+#include "coverage.h"
+
+gboolean gjs_run_script_in_coverage_compartment(GjsCoverage *coverage,
+                                                const char  *script);
+gboolean gjs_inject_value_into_coverage_compartment(GjsCoverage     *coverage,
+                                                    JS::HandleValue value,
+                                                    const char      *property);
+
+extern const char *GJS_COVERAGE_CACHE_FILE_NAME;
+
+#endif
diff --git a/gjs/coverage.cpp b/gjs/coverage.cpp
index dd15924..2e2e2fc 100644
--- a/gjs/coverage.cpp
+++ b/gjs/coverage.cpp
@@ -950,8 +950,12 @@ gjs_context_eval_file_in_compartment(GjsContext *context,
                               &script,
                               &script_len,
                               NULL,
-                              error))
+                              error)) {
+        g_object_unref(file);
         return FALSE;
+    }
+
+    g_object_unref(file);
 
     jsval return_value;
 
@@ -964,6 +968,7 @@ gjs_context_eval_file_in_compartment(GjsContext *context,
                              script, script_len, filename,
                              &return_value)) {
         gjs_log_exception(js_context);
+        g_free(script);
         g_set_error(error, GJS_ERROR, GJS_ERROR_FAILED, "Failed to evaluate %s", filename);
         return FALSE;
     }
@@ -1074,6 +1079,77 @@ coverage_statistics_tracer(JSTracer *trc, void *data)
     JS_CallObjectTracer(trc, &priv->coverage_statistics, "coverage_statistics");
 }
 
+/* This function is mainly used in the tests in order to fiddle with
+ * the internals of the coverage statisics collector on the coverage
+ * compartment side */
+gboolean
+gjs_run_script_in_coverage_compartment(GjsCoverage *coverage,
+                                       const char  *script)
+{
+    GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
+    JSContext          *js_context = (JSContext *) gjs_context_get_native_context(priv->context);
+    JSAutoCompartment ac(js_context, priv->coverage_statistics);
+    jsval rval;
+    if (!gjs_eval_with_scope(js_context,
+                             priv->coverage_statistics,
+                             script,
+                             strlen(script),
+                             "<coverage_modifier>",
+                             &rval)) {
+        gjs_log_exception(js_context);
+        g_warning("Failed to evaluate <coverage_modifier>");
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+gboolean
+gjs_inject_value_into_coverage_compartment(GjsCoverage     *coverage,
+                                           JS::HandleValue handle_value,
+                                           const char      *property)
+{
+    GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
+
+    JSContext     *js_context = (JSContext *) gjs_context_get_native_context(priv->context);
+    JSAutoRequest ar(js_context);
+    JSAutoCompartment ac(js_context, priv->coverage_statistics);
+
+    JS::RootedObject coverage_global_scope(JS_GetRuntime(js_context),
+                                           JS_GetGlobalForObject(js_context, priv->coverage_statistics));
+
+    jsval value = handle_value;
+    if (!JS_SetProperty(js_context, coverage_global_scope, property, &value)) {
+        g_warning("Failed to set property %s to requested value", property);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/* Gets the root import and wraps it into a cross-compartment
+ * object so that it can be used in the debugger compartment */
+static JSObject *
+gjs_wrap_root_importer_in_compartment(JSContext *context,
+                                      JS::HandleObject compartment)
+{
+    JSAutoRequest ar(context);
+    JSAutoCompartment ac(context, compartment);
+    JS::RootedValue importer (JS_GetRuntime(context),
+                              gjs_get_global_slot(context,
+                                                  GJS_GLOBAL_SLOT_IMPORTS));
+
+    g_assert (!JSVAL_IS_VOID(importer));
+
+    JS::RootedObject wrapped_importer(JS_GetRuntime(context),
+                                      JSVAL_TO_OBJECT(importer));
+    if (!JS_WrapObject(context, wrapped_importer.address())) {
+        return NULL;
+    }
+
+    return wrapped_importer;
+}
+
 static gboolean
 bootstrap_coverage(GjsCoverage *coverage)
 {
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 3b163e3..1708e0a 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -1145,24 +1145,25 @@ gjs_create_root_importer(JSContext   *context,
 }
 
 JSBool
-gjs_define_root_importer(JSContext   *context,
-                         JSObject    *in_object)
+gjs_define_root_importer_object(JSContext        *context,
+                                JS::HandleObject  in_object,
+                                JS::HandleObject  root_importer)
 {
-    jsval importer;
     JSBool success;
     jsid imports_name;
 
     success = JS_FALSE;
     JS_BeginRequest(context);
 
-    importer = gjs_get_global_slot(context, GJS_GLOBAL_SLOT_IMPORTS);
+    JS::RootedValue importer (JS_GetRuntime(context),
+                              OBJECT_TO_JSVAL(root_importer));
     imports_name = gjs_context_get_const_string(context, GJS_STRING_IMPORTS);
     if (!JS_DefinePropertyById(context, in_object,
                                imports_name, importer,
                                NULL, NULL,
                                GJS_MODULE_PROP_FLAGS)) {
         gjs_debug(GJS_DEBUG_IMPORTER, "DefineProperty imports on %p failed",
-                  in_object);
+                  (JSObject *) in_object);
         goto fail;
     }
 
@@ -1171,3 +1172,18 @@ gjs_define_root_importer(JSContext   *context,
     JS_EndRequest(context);
     return success;
 }
+
+JSBool
+gjs_define_root_importer(JSContext   *context,
+                         JSObject    *in_object)
+{
+    JS::RootedValue importer(JS_GetRuntime(context),
+                             gjs_get_global_slot(context, GJS_GLOBAL_SLOT_IMPORTS));
+    JS::RootedObject rooted_in_object(JS_GetRuntime(context),
+                                      in_object);
+    JS::RootedObject rooted_importer(JS_GetRuntime(context),
+                                     JSVAL_TO_OBJECT(importer));
+    return gjs_define_root_importer_object(context,
+                                           rooted_in_object,
+                                           rooted_importer);
+}
diff --git a/gjs/importer.h b/gjs/importer.h
index afd4ab1..e49fe96 100644
--- a/gjs/importer.h
+++ b/gjs/importer.h
@@ -38,13 +38,15 @@ JSBool    gjs_create_root_importer (JSContext   *context,
                                     gboolean     add_standard_search_path);
 JSBool    gjs_define_root_importer (JSContext   *context,
                                     JSObject    *in_object);
+JSBool    gjs_define_root_importer_object(JSContext        *context,
+                                          JS::HandleObject  in_object,
+                                          JS::HandleObject  root_importer);
 JSObject* gjs_define_importer      (JSContext   *context,
                                     JSObject    *in_object,
                                     const char  *importer_name,
                                     const char **initial_search_path,
                                     gboolean     add_standard_search_path);
 
-
 G_END_DECLS
 
 #endif  /* __GJS_IMPORTER_H__ */


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