Пример #1
0
 /** REPL: Loop */
 private void loop() throws InterruptedException {
   Realm realm = newRealm();
   World world = realm.getWorld();
   TaskSource taskSource = createTaskSource(realm);
   for (; ; ) {
     try {
       world.runEventLoop(taskSource);
       return;
     } catch (StopExecutionException e) {
       if (e.getReason() == Reason.Quit) {
         System.exit(0);
       }
     } catch (ParserExceptionWithSource e) {
       handleException(e);
     } catch (ScriptException e) {
       handleException(realm, e);
     } catch (UnhandledRejectionException e) {
       handleException(realm, e);
     } catch (StackOverflowError e) {
       handleException(realm, e);
     } catch (OutOfMemoryError e) {
       handleException(realm, e);
     } catch (InternalException e) {
       handleException(e);
     } catch (BootstrapMethodError e) {
       handleException(e.getCause());
     } catch (UncheckedIOException e) {
       handleException(e.getCause());
     }
   }
 }
Пример #2
0
 /**
  * REPL: Eval
  *
  * @param realm the realm instance
  * @param parsedScript the parsed script node
  * @return the evaluated script result
  */
 private Object eval(Realm realm, com.github.anba.es6draft.ast.Script parsedScript) {
   String className = "#typein_" + scriptCounter.incrementAndGet();
   Script script;
   if (options.noInterpreter) {
     script = realm.getScriptLoader().compile(parsedScript, className);
   } else {
     script = realm.getScriptLoader().load(parsedScript, className);
   }
   return script.evaluate(realm);
 }
Пример #3
0
 private static void enqueueScriptTask(Realm realm, Init init) {
   realm.enqueueScriptTask(
       () -> {
         try {
           init.apply();
         } catch (IOException e) {
           throw new UncheckedIOException(e);
         } catch (URISyntaxException e) {
           throw new UncheckedIOException(new IOException(e));
         } catch (MalformedNameException | ResolutionException e) {
           throw e.toScriptException(realm.defaultContext());
         }
       });
 }
Пример #4
0
 private void handleException(Realm realm, StackOverflowError e) {
   // Create script exception with stacktrace from stackoverflow-error.
   ScriptException exception =
       newInternalError(realm.defaultContext(), Messages.Key.StackOverflow);
   exception.setStackTrace(e.getStackTrace());
   handleException(realm, exception);
 }
Пример #5
0
 private void printScriptFrames(StringBuilder sb, Realm realm, Throwable e, int level) {
   final String indent = Strings.repeat('\t', level);
   final int maxDepth = options.stacktraceDepth;
   int depth = 0;
   StackTraceElement[] stackTrace = StackTraces.scriptStackTrace(e);
   for (; depth < Math.min(stackTrace.length, maxDepth); ++depth) {
     StackTraceElement element = stackTrace[depth];
     String methodName = element.getMethodName();
     String fileName = element.getFileName();
     int lineNumber = element.getLineNumber();
     sb.append(indent)
         .append("at ")
         .append(methodName)
         .append(" (")
         .append(fileName)
         .append(':')
         .append(lineNumber)
         .append(")\n");
   }
   if (depth < stackTrace.length) {
     int skipped = stackTrace.length - depth;
     sb.append("\t.. ").append(skipped).append(" frames omitted\n");
   }
   if (e.getSuppressed().length > 0 && level == 1) {
     Throwable suppressed = e.getSuppressed()[0];
     String message;
     if (suppressed instanceof ScriptException) {
       message = ((ScriptException) suppressed).getMessage(realm.defaultContext());
     } else {
       message = Objects.toString(suppressed.getMessage(), suppressed.getClass().getSimpleName());
     }
     sb.append(indent).append(formatMessage("suppressed_exception", message)).append('\n');
     printScriptFrames(sb, realm, suppressed, level + 1);
   }
 }
Пример #6
0
 private void handleException(Realm realm, OutOfMemoryError e) {
   // Try to recover after OOM.
   Runtime rt = Runtime.getRuntime();
   long beforeGc = rt.freeMemory();
   rt.gc();
   long afterGc = rt.freeMemory();
   if (afterGc > beforeGc && (afterGc - beforeGc) < 50_000_000) {
     // Calling gc() cleared less than 50MB, assume unrecoverable OOM and rethrow error.
     throw e;
   }
   // Create script exception with stacktrace from oom-error.
   ScriptException exception =
       newInternalError(realm.defaultContext(), Messages.Key.OutOfMemoryVM);
   exception.setStackTrace(e.getStackTrace());
   handleException(realm, exception);
 }
Пример #7
0
 private TaskSource createTaskSource(Realm realm) {
   ArrayList<TaskSource> sources = new ArrayList<>();
   if (options.interactive) {
     sources.add(new InteractiveTaskSource(realm));
   }
   if (options.timers) {
     sources.add(realm.createGlobalProperties(new Timers(), Timers.class));
   }
   switch (sources.size()) {
     case 0:
       return new EmptyTaskSource();
     case 1:
       return sources.get(0);
     default:
       return new MultiTaskSource(sources);
   }
 }
Пример #8
0
 /**
  * REPL: Print
  *
  * @param realm the realm instance
  * @param result the object to be printed
  */
 private void print(Realm realm, Object result) {
   if (result != UNDEFINED) {
     console.printf("%s%n", sourceBuilder.toSource(realm.defaultContext(), result));
   }
 }
Пример #9
0
 private static com.github.anba.es6draft.ast.Script parse(
     Realm realm, Source source, String sourceCode) throws ParserException {
   return realm.getScriptLoader().parseScript(source, sourceCode);
 }
Пример #10
0
 private void handleException(Realm realm, UnhandledRejectionException e) {
   String message = formatMessage("unhandled_rejection", e.getMessage(realm.defaultContext()));
   console.printf("%s%n", message);
   printStackTrace(e.getCauseIfPresent());
 }
Пример #11
0
 private void handleException(Realm realm, ScriptException e) {
   String message = formatMessage("uncaught_exception", e.getMessage(realm.defaultContext()));
   console.printf("%s%n", message);
   printScriptStackTrace(realm, e);
   printStackTrace(e);
 }
Пример #12
0
  private Realm newRealm() {
    ObjectAllocator<? extends ShellGlobalObject> allocator;
    if (options.shellMode == ShellMode.Mozilla) {
      allocator = MozShellGlobalObject::new;
    } else if (options.shellMode == ShellMode.V8) {
      allocator = V8ShellGlobalObject::new;
    } else {
      allocator = SimpleShellGlobalObject::new;
    }

    BiFunction<RuntimeContext, ScriptLoader, ModuleLoader> moduleLoader;
    switch (options.moduleLoaderMode) {
      case Default:
        moduleLoader = FileModuleLoader::new;
        break;
      case Node:
        moduleLoader = NodeModuleLoader::new;
        break;
      case NodeStandard:
        moduleLoader = NodeStandardModuleLoader::new;
        break;
      default:
        throw new AssertionError();
    }

    /* @formatter:off */
    RuntimeContext context =
        new RuntimeContext.Builder()
            .setBaseDirectory(Paths.get("").toAbsolutePath())
            .setGlobalAllocator(allocator)
            .setModuleLoader(moduleLoader)
            .setConsole(console)
            .setWorkerErrorReporter(this::errorReporter)
            .setOptions(compatibilityOptions(options))
            .setParserOptions(parserOptions(options))
            .setCompilerOptions(compilerOptions(options))
            .build();
    /* @formatter:on */

    World world = new World(context);
    Realm realm = world.newRealm();
    ExecutionContext cx = realm.defaultContext();

    // Add completion to console
    console.addCompleter(new ShellCompleter(realm));

    // Execute global specific initialization
    enqueueScriptTask(
        realm,
        () -> {
          InitializeHostDefinedRealm(realm);

          // Add global "arguments" property
          ScriptObject arguments = CreateArrayFromList(cx, options.arguments);
          CreateMethodProperty(cx, realm.getGlobalObject(), "arguments", arguments);
        });
    if (options.console) {
      enqueueScriptTask(
          realm,
          () -> {
            ScriptObject console = ConsoleObject.createConsole(realm);
            CreateMethodProperty(cx, realm.getGlobalObject(), "console", console);
          });
    }
    if (options.moduleLoaderMode == ModuleLoaderMode.Node) {
      // TODO: Add default initialize(Realm) method to ModuleLoader interface?
      enqueueScriptTask(
          realm,
          () -> {
            NodeModuleLoader nodeLoader = (NodeModuleLoader) world.getModuleLoader();
            nodeLoader.initialize(realm);
          });
    }

    // Run eval expressions and files
    for (EvalScript evalScript : options.evalScripts) {
      if (options.module) {
        enqueueScriptTask(
            realm,
            () -> {
              ModuleSource moduleSource = evalScript.getModuleSource();
              SourceIdentifier moduleName = evalScript.getModuleName();
              try {
                ModuleEvaluationJob(realm, moduleName, moduleSource);
              } catch (ParserException e) {
                Source source = moduleSource.toSource();
                String file = e.getFile();
                if (file.equals(source.getFileString())) {
                  throw new ParserExceptionWithSource(e, source, moduleSource.sourceCode());
                }
                Path filePath = Paths.get(file).toAbsolutePath();
                Source errorSource = new Source(filePath, file, 1);
                String code = new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8);
                throw new ParserExceptionWithSource(e, errorSource, code);
              }
            });
      } else {
        enqueueScriptTask(
            realm,
            () -> {
              Source source = evalScript.getSource();
              String sourceCode = evalScript.getSourceCode();
              try {
                eval(realm, parse(realm, source, sourceCode));
              } catch (ParserException e) {
                throw new ParserExceptionWithSource(e, source, sourceCode);
              }
            });
      }
    }

    return realm;
  }