private void handleException(ParserExceptionWithSource exception) { ParserException e = exception.getCause(); String sourceCode = exception.getSourceCode(); int lineOffset = exception.getSource().getLine(); String sourceInfo = String.format("%s:%d:%d", e.getFile(), e.getLine(), e.getColumn()); int start = skipLines(sourceCode, e.getLine() - lineOffset); int end = nextLineTerminator(sourceCode, start); String offendingLine = sourceCode.substring(start, end); String marker = Strings.repeat('.', Math.max(e.getColumn() - 1, 0)) + '^'; console.printf("%s %s: %s%n", sourceInfo, e.getType(), e.getFormattedMessage()); console.printf("%s %s%n", sourceInfo, offendingLine); console.printf("%s %s%n", sourceInfo, marker); 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; }