Bug 880575, part 1 - Factor out ReadEvalPrintLoop() from Process(). r=jwalden.
authorJason Orendorff <jorendorff@mozilla.com>
Fri, 07 Jun 2013 22:25:07 -0500
changeset 141560 df75bae8a436bb5d8826fec23b08baf127132b95
parent 141559 d27cb123e9dead57ad319fce486cc976aadf21ab
child 141561 42975d6638db828bd9d66161e031f2dd962fb0fc
push id3911
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 20:17:26 +0000
treeherdermozilla-aurora@7e26ca8db92b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs880575
milestone24.0a1
Bug 880575, part 1 - Factor out ReadEvalPrintLoop() from Process(). r=jwalden.
js/src/shell/js.cpp
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -399,88 +399,30 @@ SkipUTF8BOM(FILE* file)
         ungetc(ch3, file);
     if (ch2 != EOF)
         ungetc(ch2, file);
     if (ch1 != EOF)
         ungetc(ch1, file);
 }
 
 static void
-Process(JSContext *cx, JSObject *obj_, const char *filename, bool forceTTY)
+ReadEvalPrintLoop(JSContext *cx, JSObject *obj, FILE *file, bool compileOnly)
 {
     bool ok, hitEOF;
     RootedScript script(cx);
     RootedValue result(cx);
     RootedString str(cx);
     char *buffer;
     size_t size;
     jschar *uc_buffer;
     size_t uc_len;
     int lineno;
     int startline;
-    FILE *file;
     uint32_t oldopts;
 
-    RootedObject obj(cx, obj_);
-
-    if (forceTTY || !filename || strcmp(filename, "-") == 0) {
-        file = stdin;
-    } else {
-        file = fopen(filename, "r");
-        if (!file) {
-            JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
-                                 JSSMSG_CANT_OPEN, filename, strerror(errno));
-            gExitCode = EXITCODE_FILE_NOT_FOUND;
-            return;
-        }
-    }
-
-    SetContextOptions(cx);
-
-    if (!forceTTY && !isatty(fileno(file)))
-    {
-        SkipUTF8BOM(file);
-
-        /*
-         * It's not interactive - just execute it.  Support the UNIX #! shell
-         * hack, and gobble the first line if it starts with '#'.
-         */
-        int ch = fgetc(file);
-        if (ch == '#') {
-            while((ch = fgetc(file)) != EOF) {
-                if (ch == '\n' || ch == '\r')
-                    break;
-            }
-        }
-        ungetc(ch, file);
-
-        int64_t t1 = PRMJ_Now();
-        oldopts = JS_GetOptions(cx);
-        gGotError = false;
-        JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-        CompileOptions options(cx);
-        options.setUTF8(true)
-               .setFileAndLine(filename, 1);
-        script = JS::Compile(cx, obj, options, file);
-        JS_SetOptions(cx, oldopts);
-        JS_ASSERT_IF(!script, gGotError);
-        if (script && !compileOnly) {
-            if (!JS_ExecuteScript(cx, obj, script, NULL)) {
-                if (!gQuitting && !gTimedOut)
-                    gExitCode = EXITCODE_RUNTIME_ERROR;
-            }
-            int64_t t2 = PRMJ_Now() - t1;
-            if (printTiming)
-                printf("runtime = %.3f ms\n", double(t2) / PRMJ_USEC_PER_MSEC);
-        }
-
-        goto cleanup;
-    }
-
-    /* It's an interactive filehandle; drop into read-eval-print loop. */
     lineno = 1;
     hitEOF = false;
     buffer = NULL;
     size = 0;           /* assign here to avoid warnings */
     do {
         /*
          * Accumulate lines until we get a 'compilable unit' - one that either
          * generates an error (before running out of source) or that compiles
@@ -494,17 +436,17 @@ Process(JSContext *cx, JSObject *obj_, c
             gTimedOut = false;
             errno = 0;
 
             char *line = GetLine(file, startline == lineno ? "js> " : "");
             if (!line) {
                 if (errno) {
                     JS_ReportError(cx, strerror(errno));
                     free(buffer);
-                    goto cleanup;
+                    return;
                 }
                 hitEOF = true;
                 break;
             }
             if (!buffer) {
                 buffer = line;
                 len = strlen(buffer);
                 size = len + 1;
@@ -515,17 +457,17 @@ Process(JSContext *cx, JSObject *obj_, c
                 size_t newlen = strlen(line) + (len ? len + 1 : 0);
                 if (newlen + 1 > size) {
                     size = newlen + 1 > size * 2 ? newlen + 1 : size * 2;
                     char *newBuf = (char *) realloc(buffer, size);
                     if (!newBuf) {
                         free(buffer);
                         free(line);
                         JS_ReportOutOfMemory(cx);
-                        goto cleanup;
+                        return;
                     }
                     buffer = newBuf;
                 }
                 char *current = buffer + len;
                 if (startline != lineno)
                     *current++ = '\n';
                 strcpy(current, line);
                 len = newlen;
@@ -580,20 +522,92 @@ Process(JSContext *cx, JSObject *obj_, c
             }
         }
         *buffer = '\0';
         free(uc_buffer);
     } while (!hitEOF && !gQuitting);
 
     free(buffer);
     fprintf(gOutFile, "\n");
-cleanup:
-    if (file != stdin)
-        fclose(file);
-    return;
+}
+
+class AutoCloseInputFile
+{
+  private:
+    FILE *f_;
+  public:
+    explicit AutoCloseInputFile(FILE *f) : f_(f) {}
+    ~AutoCloseInputFile() {
+        if (f_ && f_ != stdin)
+            fclose(f_);
+    }
+};
+
+static void
+Process(JSContext *cx, JSObject *obj_, const char *filename, bool forceTTY)
+{
+    RootedObject obj(cx, obj_);
+
+    FILE *file;
+    if (forceTTY || !filename || strcmp(filename, "-") == 0) {
+        file = stdin;
+    } else {
+        file = fopen(filename, "r");
+        if (!file) {
+            JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+                                 JSSMSG_CANT_OPEN, filename, strerror(errno));
+            gExitCode = EXITCODE_FILE_NOT_FOUND;
+            return;
+        }
+    }
+    AutoCloseInputFile autoClose(file);
+
+    SetContextOptions(cx);
+
+    if (!forceTTY && !isatty(fileno(file))) {
+        SkipUTF8BOM(file);
+
+        /*
+         * It's not interactive - just execute it.  Support the UNIX #! shell
+         * hack, and gobble the first line if it starts with '#'.
+         */
+        int ch = fgetc(file);
+        if (ch == '#') {
+            while ((ch = fgetc(file)) != EOF) {
+                if (ch == '\n' || ch == '\r')
+                    break;
+            }
+        }
+        ungetc(ch, file);
+
+        int64_t t1 = PRMJ_Now();
+        uint32_t oldopts = JS_GetOptions(cx);
+        gGotError = false;
+        JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+        CompileOptions options(cx);
+        options.setUTF8(true)
+               .setFileAndLine(filename, 1);
+
+        RootedScript script(cx);
+        script = JS::Compile(cx, obj, options, file);
+        JS_SetOptions(cx, oldopts);
+        JS_ASSERT_IF(!script, gGotError);
+        if (script && !compileOnly) {
+            if (!JS_ExecuteScript(cx, obj, script, NULL)) {
+                if (!gQuitting && !gTimedOut)
+                    gExitCode = EXITCODE_RUNTIME_ERROR;
+            }
+            int64_t t2 = PRMJ_Now() - t1;
+            if (printTiming)
+                printf("runtime = %.3f ms\n", double(t2) / PRMJ_USEC_PER_MSEC);
+        }
+    } else {
+        // It's an interactive filehandle; drop into read-eval-print loop.
+        ReadEvalPrintLoop(cx, obj, file, compileOnly);
+    }
 }
 
 /*
  * JSContext option name to flag map. The option names are in alphabetical
  * order for better reporting.
  */
 static const struct JSOption {
     const char  *name;