void gjs_explain_scope(JSContext *context, const char *title) { JSContext *load_context; JSContext *call_context; JSObject *global; JSObject *parent; GString *chain; gjs_debug(GJS_DEBUG_SCOPE, "=== %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)" : ""); global = JS_GetGlobalObject(context); gjs_debug(GJS_DEBUG_SCOPE, " Global: %p %s", global, gjs_value_debug_string(context, OBJECT_TO_JSVAL(global))); parent = JS_GetScopeChain(context); chain = g_string_new(NULL); while (parent != NULL) { const char *debug; debug = gjs_value_debug_string(context, OBJECT_TO_JSVAL(parent)); if (chain->len > 0) g_string_append(chain, ", "); g_string_append_printf(chain, "%p %s", parent, debug); parent = JS_GetParent(context, parent); } gjs_debug(GJS_DEBUG_SCOPE, " Chain: %s", chain->str); g_string_free(chain, TRUE); JS_LeaveLocalRootScope(context); JS_EndRequest(call_context); JS_EndRequest(load_context); JS_EndRequest(context); }
/* Mimick the behaviour exposed by standard Error objects (http://mxr.mozilla.org/mozilla-central/source/js/src/jsexn.cpp#554) */ static char* jsvalue_to_string(JSContext* cx, jsval val, gboolean* is_string) { char* value = NULL; JSString* value_str = NULL; if (JSVAL_IS_PRIMITIVE(val)) { value_str = JS_ValueToSource(cx, val); } else { JSObject *obj = JSVAL_TO_OBJECT(val); if (JS_ObjectIsFunction(cx, obj)) { JSFunction *fn = JS_ValueToFunction(cx, val); value_str = JS_GetFunctionId(fn); if (!value_str) value = g_strdup("[unknown function]"); } else { value = g_strdup_printf("[object %s]", JS_GetClass(cx, obj)->name); } } if (!value && value_str) value = gjs_value_debug_string(cx, val); if (is_string) *is_string = JSVAL_IS_STRING(val); return value; }
void gjs_log_object_props(JSContext *context, JSObject *obj, GjsDebugTopic topic, const char *prefix) { 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. */ JS_EnterLocalRootScope(context); props_iter = JS_NewPropertyIterator(context, obj); if (props_iter == NULL) { gjs_debug(GJS_DEBUG_ERROR, "Failed to create property iterator for object props"); goto done; } prop_id = JSVAL_VOID; if (!JS_NextProperty(context, props_iter, &prop_id)) goto done; while (prop_id != JSVAL_VOID) { jsval nameval; const char *name; jsval propval; if (!JS_IdToValue(context, prop_id, &nameval)) goto next; if (!gjs_get_string_id(nameval, &name)) goto next; if (!gjs_object_get_property(context, obj, name, &propval)) goto next; gjs_debug(topic, "%s%s = '%s'", prefix, name, gjs_value_debug_string(context, propval)); next: prop_id = JSVAL_VOID; if (!JS_NextProperty(context, props_iter, &prop_id)) break; } done: JS_LeaveLocalRootScope(context); JS_EndRequest(context); }
JSBool gjs_console_interact(JSContext *context, uintN argc, jsval *vp) { JSObject *object = JS_THIS_OBJECT(context, vp); gboolean eof = FALSE; JSObject *script = NULL; jsval result; JSString *str; GString *buffer = NULL; char *temp_buf = NULL; gunichar2 *u16_buffer; glong u16_buffer_len; int lineno; int startline; GError *error = NULL; FILE *file = stdin; JS_SetErrorReporter(context, gjs_console_error_reporter); /* It's an interactive filehandle; drop into read-eval-print loop. */ lineno = 1; do { /* * Accumulate lines until we get a 'compilable unit' - one that either * generates an error (before running out of source) or that compiles * cleanly. This should be whenever we get a complete statement that * coincides with the end of a line. */ startline = lineno; buffer = g_string_new(""); do { if (!gjs_console_readline(context, &temp_buf, file, startline == lineno ? "gjs> " : ".... ")) { eof = JS_TRUE; break; } g_string_append(buffer, temp_buf); g_free(temp_buf); lineno++; /* Note in this case, we are trying to parse the buffer as * ISO-8859-1 which is broken for non-ASCII. */ } while (!JS_BufferIsCompilableUnit(context, object, buffer->str, buffer->len)); if ((u16_buffer = g_utf8_to_utf16 (buffer->str, buffer->len, NULL, &u16_buffer_len, &error)) == NULL) { g_printerr ("%s\n", error->message); g_clear_error (&error); continue; } script = JS_CompileUCScript(context, object, u16_buffer, u16_buffer_len, "typein", startline); g_free (u16_buffer); if (script) JS_ExecuteScript(context, object, script, &result); if (JS_GetPendingException(context, &result)) { str = JS_ValueToString(context, result); JS_ClearPendingException(context); } else if (JSVAL_IS_VOID(result)) { goto next; } else { str = JS_ValueToString(context, result); } if (str) { char *display_str; display_str = gjs_value_debug_string(context, result); if (display_str != NULL) { g_fprintf(stdout, "%s\n", display_str); g_free(display_str); } } next: g_string_free(buffer, TRUE); } while (!eof); g_fprintf(stdout, "\n"); if (file != stdin) fclose(file); return JS_TRUE; }
JSBool gjs_console_interact(JSContext *context, unsigned argc, jsval *vp) { JSObject *object = JS_THIS_OBJECT(context, vp); gboolean eof = FALSE; jsval result; JSString *str; GString *buffer = NULL; char *temp_buf = NULL; int lineno; int startline; FILE *file = stdin; JS_SetErrorReporter(context, gjs_console_error_reporter); /* It's an interactive filehandle; drop into read-eval-print loop. */ lineno = 1; do { /* * Accumulate lines until we get a 'compilable unit' - one that either * generates an error (before running out of source) or that compiles * cleanly. This should be whenever we get a complete statement that * coincides with the end of a line. */ startline = lineno; buffer = g_string_new(""); do { if (!gjs_console_readline(context, &temp_buf, file, startline == lineno ? "cjs> " : ".... ")) { eof = JS_TRUE; break; } g_string_append(buffer, temp_buf); g_free(temp_buf); lineno++; } while (!JS_BufferIsCompilableUnit(context, object, buffer->str, buffer->len)); JS::CompileOptions options(context); options.setUTF8(true) .setFileAndLine("typein", startline); js::RootedObject rootedObj(context, object); JS::Evaluate(context, rootedObj, options, buffer->str, buffer->len, &result); gjs_schedule_gc_if_needed(context); if (JS_GetPendingException(context, &result)) { str = JS_ValueToString(context, result); JS_ClearPendingException(context); } else if (JSVAL_IS_VOID(result)) { goto next; } else { str = JS_ValueToString(context, result); } if (str) { char *display_str; display_str = gjs_value_debug_string(context, result); if (display_str != NULL) { g_fprintf(stdout, "%s\n", display_str); g_free(display_str); } } next: g_string_free(buffer, TRUE); } while (!eof); g_fprintf(stdout, "\n"); if (file != stdin) fclose(file); return JS_TRUE; }