# HG changeset patch # User sundar # Date 1427185771 -19800 # Node ID c847904b447b47ee7798c6e00f5dbd6424632860 # Parent bfea11f8c8f284c7fc20c3694b0e9376836fe963 8074410: Startup time: Port shell.js to Java Reviewed-by: lagergren, hannesw diff --git a/src/jdk/nashorn/internal/objects/Global.java b/src/jdk/nashorn/internal/objects/Global.java --- a/src/jdk/nashorn/internal/objects/Global.java +++ b/src/jdk/nashorn/internal/objects/Global.java @@ -77,6 +77,7 @@ import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.regexp.RegExpResult; import jdk.nashorn.internal.scripts.JO; +import jdk.nashorn.tools.ShellFunctions; /** * Representation of global scope. @@ -1817,6 +1818,17 @@ return invocation; } + /** + * Adds jjs shell interactive mode builtin functions to global scope. + */ + public void addShellBuiltins() { + Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT); + addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); + + value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT); + addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); + } + private synchronized SwitchPoint getLexicalScopeSwitchPoint() { SwitchPoint switchPoint = lexicalScopeSwitchPoint; if (switchPoint == null || switchPoint.hasBeenInvalidated()) { diff --git a/src/jdk/nashorn/tools/Shell.java b/src/jdk/nashorn/tools/Shell.java --- a/src/jdk/nashorn/tools/Shell.java +++ b/src/jdk/nashorn/tools/Shell.java @@ -417,18 +417,7 @@ Context.setGlobal(global); } - // initialize with "shell.js" script - try { - final Source source = sourceFor("", Shell.class.getResource("resources/shell.js")); - context.eval(global, source.getString(), global, "", false); - } catch (final Exception e) { - err.println(e); - if (env._dump_on_error) { - e.printStackTrace(err); - } - - return INTERNAL_ERROR; - } + global.addShellBuiltins(); while (true) { err.print(prompt); diff --git a/src/jdk/nashorn/tools/ShellFunctions.java b/src/jdk/nashorn/tools/ShellFunctions.java new file mode 100644 --- /dev/null +++ b/src/jdk/nashorn/tools/ShellFunctions.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.tools; + +import static jdk.nashorn.internal.lookup.Lookup.MH; +import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.objects.Global; + +/** + * Global functions supported only in shell interactive mode. + */ +public final class ShellFunctions { + + /** Handle to implementation of {@link ShellFunctions#input} - Nashorn extension */ + public static final MethodHandle INPUT = findOwnMH("input", Object.class, Object.class, Object.class, Object.class); + + /** Handle to implementation of {@link ShellFunctions#evalinput} - Nashorn extension */ + public static final MethodHandle EVALINPUT = findOwnMH("evalinput", Object.class, Object.class, Object.class, Object.class); + + private ShellFunctions() { + } + + /** + * Nashorn extension: global.input (shell-interactive-mode-only) + * Read one or more lines of input from the standard input till the + * given end marker is seen in standard input. + * + * @param self self reference + * @param endMarker String used as end marker for input + * @param prompt String used as input prompt + * + * @return line that was read + * + * @throws IOException if an exception occurs + */ + public static Object input(final Object self, final Object endMarker, final Object prompt) throws IOException { + final String endMarkerStr = (endMarker != UNDEFINED)? JSType.toString(endMarker) : ""; + final String promptStr = (prompt != UNDEFINED)? JSType.toString(prompt) : ">> "; + final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + final StringBuilder buf = new StringBuilder(); + while (true) { + System.out.print(promptStr); + final String line = reader.readLine(); + if (line == null || line.equals(endMarkerStr)) { + break; + } + buf.append(line); + buf.append('\n'); + } + return buf.toString(); + } + + /** + * Nashorn extension: Reads zero or more lines from standard input and + * evaluates the concatenated string as code + * + * @param self self reference + * @param endMarker String used as end marker for input + * @param prompt String used as input prompt + * + * @return output from evaluating the script + * + * @throws IOException if an exception occurs + */ + public static Object evalinput(final Object self, final Object endMarker, final Object prompt) throws IOException { + return Global.eval(self, input(self, endMarker, prompt)); + } + + private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { + return MH.findStatic(MethodHandles.lookup(), ShellFunctions.class, name, MH.type(rtype, types)); + } +} diff --git a/src/jdk/nashorn/tools/resources/shell.js b/src/jdk/nashorn/tools/resources/shell.js deleted file mode 100644 --- a/src/jdk/nashorn/tools/resources/shell.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Initialization script for shell when running in interactive mode. - */ - -/** - * Reads zero or more lines from standard input and returns concatenated string - * - * @param endMarker marker string that signals end of input - * @param prompt prompt printed for each line - */ -Object.defineProperty(this, "input", { - value: function input(endMarker, prompt) { - if (!endMarker) { - endMarker = ""; - } - - if (!prompt) { - prompt = " >> "; - } - - var imports = new JavaImporter(java.io, java.lang); - var str = ""; - with (imports) { - var reader = new BufferedReader(new InputStreamReader(System['in'])); - var line; - while (true) { - System.out.print(prompt); - line = reader.readLine(); - if (line == null || line == endMarker) { - break; - } - str += line + "\n"; - } - } - - return str; - }, - enumerable: false, - writable: true, - configurable: true -}); - - -/** - * Reads zero or more lines from standard input and evaluates the concatenated - * string as code - * - * @param endMarker marker string that signals end of input - * @param prompt prompt printed for each line - */ -Object.defineProperty(this, "evalinput", { - value: function evalinput(endMarker, prompt) { - var code = input(endMarker, prompt); - // make sure everything is evaluated in global scope! - return this.eval(code); - }, - enumerable: false, - writable: true, - configurable: true -});