/** * shell_global_gc: * @global: A #ShellGlobal * * Start a garbage collection process. For more information, see * https://developer.mozilla.org/En/JS_GC */ void shell_global_gc (ShellGlobal *global) { JSContext *context = gjs_context_get_native_context (global->js_context); JS_GC (context); }
/* * _gjs_profiler_new: * @context: The #GjsContext to profile * * This creates a new profiler for the #JSContext. It is important that * this instance is freed with _gjs_profiler_free() before the context is * destroyed. * * Call gjs_profiler_start() to enable the profiler, and gjs_profiler_stop() * when you have finished. * * The profiler works by enabling the JS profiler in spidermonkey so that * sample information is available. A POSIX timer is used to signal SIGPROF * to the process on a regular interval to collect the most recent profile * sample and stash it away. It is a programming error to mask SIGPROF from * the thread controlling the JS context. * * If another #GjsContext already has a profiler, or @context already has one, * then returns %NULL instead. * * Returns: (transfer full) (nullable): A newly allocated #GjsProfiler */ GjsProfiler * _gjs_profiler_new(GjsContext *context) { g_return_val_if_fail(context, nullptr); if (profiling_context == context) { g_critical("You can only create one profiler at a time."); return nullptr; } if (profiling_context) { g_message("Not going to profile GjsContext %p; you can only profile " "one context at a time.", context); return nullptr; } GjsProfiler *self = g_new0(GjsProfiler, 1); #ifdef ENABLE_PROFILER self->cx = static_cast<JSContext *>(gjs_context_get_native_context(context)); self->pid = getpid(); #endif profiling_context = context; return self; }
static bool bootstrap_coverage(GjsCoverage *coverage) { GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage); JSContext *context = (JSContext *) gjs_context_get_native_context(priv->context); JSAutoRequest ar(context); JSObject *debuggee = gjs_get_import_global(context); JS::RootedObject debugger_compartment(context, gjs_create_global_object(context)); { JSAutoCompartment compartment(context, debugger_compartment); JS::RootedObject debuggeeWrapper(context, debuggee); if (!JS_WrapObject(context, &debuggeeWrapper)) return false; JS::RootedValue debuggeeWrapperValue(context, JS::ObjectValue(*debuggeeWrapper)); if (!JS_SetProperty(context, debugger_compartment, "debuggee", debuggeeWrapperValue) || !gjs_define_global_properties(context, debugger_compartment, "coverage")) return false; /* Add a tracer, as suggested by jdm on #jsapi */ JS_AddExtraGCRootsTracer(context, coverage_tracer, coverage); priv->compartment = debugger_compartment; } return true; }
static void _gjs_unit_test_fixture_begin (GjsUnitTestFixture *fixture) { fixture->gjs_context = gjs_context_new (); fixture->context = (JSContext *) gjs_context_get_native_context (fixture->gjs_context); JS_BeginRequest(fixture->context); JS_SetErrorReporter(fixture->context, test_error_reporter); }
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_context_print_stack_to_buffer(GjsContext* context, void *initial, GString *buf) { JSContext *js_context = (JSContext*)gjs_context_get_native_context(context); JSStackFrame* fp = initial; int num = 0; while (fp) { format_frame(js_context, fp, buf, num); num++; JS_FrameIterator(js_context, &fp); } }
static void gjs_coverage_constructed(GObject *object) { G_OBJECT_CLASS(gjs_coverage_parent_class)->constructed(object); GjsCoverage *coverage = GJS_COVERAGE(object); GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage); new (&priv->compartment) JS::Heap<JSObject *>(); if (!bootstrap_coverage(coverage)) { JSContext *context = static_cast<JSContext *>(gjs_context_get_native_context(priv->context)); JSAutoCompartment compartment(context, gjs_get_import_global(context)); gjs_log_exception(context); } }
static void gjs_coverage_dispose(GObject *object) { GjsCoverage *coverage = GJS_COVERAGE(object); GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage); /* Decomission objects inside of the JSContext before * disposing of the context */ auto cx = static_cast<JSContext *>(gjs_context_get_native_context(priv->context)); JS_RemoveExtraGCRootsTracer(cx, coverage_tracer, coverage); priv->compartment = nullptr; g_clear_object(&priv->context); G_OBJECT_CLASS(gjs_coverage_parent_class)->dispose(object); }
/** * shell_global_add_extension_importer: * @target_object_script: JavaScript code evaluating to a target object * @target_property: Name of property to use for importer * @directory: Source directory: * @error: A #GError * * This function sets a property named @target_property on the object * resulting from the evaluation of @target_object_script code, which * acts as a GJS importer for directory @directory. * * Returns: %TRUE on success */ gboolean shell_global_add_extension_importer (ShellGlobal *global, const char *target_object_script, const char *target_property, const char *directory, GError **error) { jsval target_object; JSObject *importer; JSContext *context = gjs_context_get_native_context (global->js_context); char *search_path[2] = { 0, 0 }; // This is a bit of a hack; ideally we'd be able to pass our target // object directly into this function, but introspection doesn't // support that at the moment. Instead evaluate a string to get it. if (!JS_EvaluateScript(context, JS_GetGlobalObject(context), target_object_script, strlen (target_object_script), "<target_object_script>", 0, &target_object)) { char *message; gjs_log_exception(context, &message); g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s", message ? message : "(unknown)"); g_free(message); return FALSE; } if (!JSVAL_IS_OBJECT (target_object)) { g_error ("shell_global_add_extension_importer: invalid target object"); return FALSE; } search_path[0] = (char*)directory; importer = gjs_define_importer (context, JSVAL_TO_OBJECT (target_object), target_property, (const char **)search_path, FALSE); return TRUE; }
/** * gjs_coverage_write_statistics: * @coverage: A #GjsCoverage * @output_directory: A directory to write coverage information to. * * Scripts which were provided as part of the #GjsCoverage:prefixes * construction property will be written out to @output_directory, in the same * directory structure relative to the source dir where the tests were run. * * This function takes all available statistics and writes them out to either * the file provided or to files of the pattern (filename).info in the same * directory as the scanned files. It will provide coverage data for all files * ending with ".js" in the coverage directories. */ void gjs_coverage_write_statistics(GjsCoverage *coverage) { auto priv = static_cast<GjsCoveragePrivate *>(gjs_coverage_get_instance_private(coverage)); GError *error = nullptr; auto cx = static_cast<JSContext *>(gjs_context_get_native_context(priv->context)); JSAutoCompartment ac(cx, gjs_get_import_global(cx)); JSAutoRequest ar(cx); GjsAutoUnref<GFile> output_file = write_statistics_internal(coverage, cx, &error); if (!output_file) { g_critical("Error writing coverage data: %s", error->message); g_error_free(error); return; } GjsAutoChar output_file_path = g_file_get_path(output_file); g_message("Wrote coverage statistics to %s", output_file_path.get()); }
/* 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); }