[gjs/wip/ptomato/mozjs52: 32/35] console: Refactor read-eval-print loop
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/ptomato/mozjs52: 32/35] console: Refactor read-eval-print loop
- Date: Sun, 11 Jun 2017 03:14:53 +0000 (UTC)
commit 05a8c591f45569c539535e60fa9c6164347df178
Author: Philip Chimento <philip chimento gmail com>
Date: Mon Jun 5 23:30:18 2017 -0700
console: Refactor read-eval-print loop
This makes the REPL look more like the code from the SpiderMonkey shell
in mozjs52. This is because in SpiderMonkey 52, error reporter callbacks
and JS_ReportPendingException() are going away. We can anticipate this
change by introducing an AutoReportException class which prints any
pending exception when it goes out of scope. (We will do something
similar in the rest of GJS, but the interactive console prints errors
differently, so it requires slightly different code.)
modules/console.cpp | 132 ++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 98 insertions(+), 34 deletions(-)
---
diff --git a/modules/console.cpp b/modules/console.cpp
index df0d5f8..224a635 100644
--- a/modules/console.cpp
+++ b/modules/console.cpp
@@ -58,7 +58,7 @@
#include "gjs/jsapi-wrapper.h"
static void
-gjs_console_error_reporter(JSContext *cx, const char *message, JSErrorReport *report)
+gjs_console_print_error(const char *message, JSErrorReport *report)
{
/* Code modified from SpiderMonkey js/src/jscntxt.cpp, js::PrintError() */
@@ -134,6 +134,59 @@ gjs_console_error_reporter(JSContext *cx, const char *message, JSErrorReport *re
g_free(prefix);
}
+static void
+gjs_console_error_reporter(JSContext *cx, const char *message, JSErrorReport *report)
+{
+ gjs_console_print_error(message, report);
+}
+
+/* Based on js::shell::AutoReportException from SpiderMonkey. Different from
+ * GjsAutoReportException because we have different error reporting code in the
+ * interactive shell. */
+class AutoReportException {
+ JSContext *m_cx;
+
+public:
+ explicit AutoReportException(JSContext *cx) : m_cx(cx) {}
+
+ ~AutoReportException() {
+ if (!JS_IsExceptionPending(m_cx))
+ return;
+
+ /* Get exception object before printing and clearing exception. */
+ JS::RootedValue v_exn(m_cx);
+ (void) JS_GetPendingException(m_cx, &v_exn);
+
+ JS_ClearPendingException(m_cx);
+
+ JS::RootedObject exn(m_cx, &v_exn.toObject());
+ JSErrorReport *report = JS_ErrorFromException(m_cx, exn);
+ if (!report) {
+ fprintf(stderr, "out of memory initializing ErrorReport\n");
+ fflush(stderr);
+ JS_ClearPendingException(m_cx);
+ return;
+ }
+
+ MOZ_ASSERT(!JSREPORT_IS_WARNING(report->flags));
+
+ gjs_console_print_error(report);
+
+ {
+ JS::AutoSaveExceptionState savedExc(m_cx);
+ JS::RootedObject stack(m_cx, ExceptionStackOrNull(exn));
+ if (stack) {
+ JS::RootedString stack_trace(m_cx);
+ if (!JS::BuildStackString(m_cx, stack, &stack_trace, 2))
+ fputs("(Unable to print stack trace)\n", stderr);
+ }
+ savedExc.restore();
+ }
+
+ JS_ClearPendingException(m_cx);
+ }
+};
+
#ifdef HAVE_READLINE_READLINE_H
static bool
gjs_console_readline(JSContext *cx, char **bufp, FILE *file, const char *prompt)
@@ -161,6 +214,44 @@ gjs_console_readline(JSContext *cx, char **bufp, FILE *file, const char *prompt)
}
#endif
+/* Return value of false indicates an uncatchable exception, rather than any
+ * exception. (This is because the exception should be auto-printed around the
+ * invocation of this function.)
+ */
+static bool
+gjs_console_eval_and_print(JSContext *cx,
+ const char *bytes,
+ size_t length,
+ int lineno)
+{
+ JS::CompileOptions options(cx);
+ options.setUTF8(true)
+ .setFileAndLine("typein", lineno);
+
+ JS::RootedValue result(cx);
+ if (!JS::Evaluate(cx, options, bytes, length, &result)) {
+ if (!JS_IsExceptionPending(cx))
+ return false;
+ }
+
+ gjs_schedule_gc_if_needed(cx);
+
+ if (result.isUndefined())
+ return true;
+
+ JS::RootedString str(cx, JS::ToString(cx, result));
+ if (!str)
+ return true;
+
+ char *display_str;
+ display_str = gjs_value_debug_string(cx, result);
+ if (display_str) {
+ g_fprintf(stdout, "%s\n", display_str);
+ g_free(display_str);
+ }
+ return true;
+}
+
static bool
gjs_console_interact(JSContext *context,
unsigned argc,
@@ -168,8 +259,6 @@ gjs_console_interact(JSContext *context,
{
JS::CallArgs argv = JS::CallArgsFromVp(argc, vp);
bool eof = false;
- JS::RootedValue result(context);
- JS::RootedString str(context);
JS::RootedObject global(context, gjs_get_import_global(context));
GString *buffer = NULL;
char *temp_buf = NULL;
@@ -202,44 +291,18 @@ gjs_console_interact(JSContext *context,
} while (!JS_BufferIsCompilableUnit(context, global,
buffer->str, buffer->len));
- JS::CompileOptions options(context);
- options.setUTF8(true)
- .setFileAndLine("typein", startline);
- if (!JS::Evaluate(context, options, buffer->str, buffer->len,
- &result)) {
+ AutoReportException are(context);
+ if (!gjs_console_eval_and_print(context, buffer->str, buffer->len,
+ startline)) {
/* If this was an uncatchable exception, throw another uncatchable
* exception on up to the surrounding JS::Evaluate() in main(). This
* happens when you run gjs-console and type imports.system.exit(0);
* at the prompt. If we don't throw another uncatchable exception
* here, then it's swallowed and main() won't exit. */
- if (!JS_IsExceptionPending(context)) {
- argv.rval().set(result);
- return false;
- }
- }
-
- gjs_schedule_gc_if_needed(context);
-
- if (JS_GetPendingException(context, &result)) {
- if (!JS_ReportPendingException(context))
- return false;
- goto next;
- } else if (result.isUndefined()) {
- goto next;
- } else {
- str = JS::ToString(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);
- }
+ g_string_free(buffer, true);
+ return false;
}
- next:
g_string_free(buffer, true);
} while (!eof);
@@ -248,6 +311,7 @@ gjs_console_interact(JSContext *context,
if (file != stdin)
fclose(file);
+ argv.rval().setUndefined();
return true;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]