/** 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()); } } }
/** * 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); }
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()); } }); }
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); }
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); } }
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); }
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); } }
/** * 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)); } }
private static com.github.anba.es6draft.ast.Script parse( Realm realm, Source source, String sourceCode) throws ParserException { return realm.getScriptLoader().parseScript(source, sourceCode); }
private void handleException(Realm realm, UnhandledRejectionException e) { String message = formatMessage("unhandled_rejection", e.getMessage(realm.defaultContext())); console.printf("%s%n", message); printStackTrace(e.getCauseIfPresent()); }
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); }
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; }