25
26 package jdk.nashorn.tools;
27
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileReader;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34 import java.io.OutputStream;
35 import java.io.PrintStream;
36 import java.io.PrintWriter;
37 import java.util.List;
38 import java.util.Locale;
39 import java.util.ResourceBundle;
40 import jdk.nashorn.api.scripting.NashornException;
41 import jdk.nashorn.internal.codegen.Compiler;
42 import jdk.nashorn.internal.ir.FunctionNode;
43 import jdk.nashorn.internal.ir.debug.ASTWriter;
44 import jdk.nashorn.internal.ir.debug.PrintVisitor;
45 import jdk.nashorn.internal.parser.Parser;
46 import jdk.nashorn.internal.runtime.Context;
47 import jdk.nashorn.internal.runtime.ErrorManager;
48 import jdk.nashorn.internal.runtime.JSType;
49 import jdk.nashorn.internal.runtime.Property;
50 import jdk.nashorn.internal.runtime.ScriptEnvironment;
51 import jdk.nashorn.internal.runtime.ScriptFunction;
52 import jdk.nashorn.internal.runtime.ScriptObject;
53 import jdk.nashorn.internal.runtime.ScriptRuntime;
54 import jdk.nashorn.internal.runtime.Source;
55 import jdk.nashorn.internal.runtime.options.Options;
56
57 /**
58 * Command line Shell for processing JavaScript files.
59 */
60 public class Shell {
61
62 /**
63 * Resource name for properties file
64 */
131 }
132
133 /**
134 * Run method logic.
135 *
136 * @param in input stream for Shell
137 * @param out output stream for Shell
138 * @param err error stream for Shell
139 * @param args arguments to Shell
140 *
141 * @return exit code
142 *
143 * @throws IOException if there's a problem setting up the streams
144 */
145 protected final int run(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) throws IOException {
146 final Context context = makeContext(in, out, err, args);
147 if (context == null) {
148 return COMMANDLINE_ERROR;
149 }
150
151 final ScriptObject global = context.createGlobal();
152 final ScriptEnvironment env = context.getEnv();
153 final List<String> files = env.getFiles();
154 if (files.isEmpty()) {
155 return readEvalPrint(context, global);
156 }
157
158 if (env._compile_only) {
159 return compileScripts(context, global, files);
160 }
161
162 if (env._fx) {
163 return runFXScripts(context, global, files);
164 }
165
166 return runScripts(context, global, files);
167 }
168
169 /**
170 * Make a new Nashorn Context to compile and/or run JavaScript files.
171 *
214 } catch (final IOException e) {
215 // ignore this. File IO errors will be reported later anyway
216 }
217 }
218 }
219 }
220
221 return new Context(options, errors, wout, werr, Thread.currentThread().getContextClassLoader());
222 }
223
224 /**
225 * Compiles the given script files in the command line
226 *
227 * @param context the nashorn context
228 * @param global the global scope
229 * @param files the list of script files to compile
230 *
231 * @return error code
232 * @throws IOException when any script file read results in I/O error
233 */
234 private static int compileScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
235 final ScriptObject oldGlobal = Context.getGlobal();
236 final boolean globalChanged = (oldGlobal != global);
237 final ScriptEnvironment env = context.getEnv();
238 try {
239 if (globalChanged) {
240 Context.setGlobal(global);
241 }
242 final ErrorManager errors = context.getErrorManager();
243
244 // For each file on the command line.
245 for (final String fileName : files) {
246 final FunctionNode functionNode = new Parser(env, new Source(fileName, new File(fileName)), errors).parse();
247
248 if (errors.getNumberOfErrors() != 0) {
249 return COMPILATION_ERROR;
250 }
251
252 if (env._print_ast) {
253 context.getErr().println(new ASTWriter(functionNode));
254 }
255
264 env.getOut().flush();
265 env.getErr().flush();
266 if (globalChanged) {
267 Context.setGlobal(oldGlobal);
268 }
269 }
270
271 return SUCCESS;
272 }
273
274 /**
275 * Runs the given JavaScript files in the command line
276 *
277 * @param context the nashorn context
278 * @param global the global scope
279 * @param files the list of script files to run
280 *
281 * @return error code
282 * @throws IOException when any script file read results in I/O error
283 */
284 private int runScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
285 final ScriptObject oldGlobal = Context.getGlobal();
286 final boolean globalChanged = (oldGlobal != global);
287 try {
288 if (globalChanged) {
289 Context.setGlobal(global);
290 }
291 final ErrorManager errors = context.getErrorManager();
292
293 // For each file on the command line.
294 for (final String fileName : files) {
295 if ("-".equals(fileName)) {
296 final int res = readEvalPrint(context, global);
297 if (res != SUCCESS) {
298 return res;
299 }
300 continue;
301 }
302
303 final File file = new File(fileName);
304 final ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global);
305 if (script == null || errors.getNumberOfErrors() != 0) {
322 context.getErr().flush();
323 if (globalChanged) {
324 Context.setGlobal(oldGlobal);
325 }
326 }
327
328 return SUCCESS;
329 }
330
331 /**
332 * Runs launches "fx:bootstrap.js" with the given JavaScript files provided
333 * as arguments.
334 *
335 * @param context the nashorn context
336 * @param global the global scope
337 * @param files the list of script files to provide
338 *
339 * @return error code
340 * @throws IOException when any script file read results in I/O error
341 */
342 private static int runFXScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
343 final ScriptObject oldGlobal = Context.getGlobal();
344 final boolean globalChanged = (oldGlobal != global);
345 try {
346 if (globalChanged) {
347 Context.setGlobal(global);
348 }
349
350 global.addOwnProperty("$GLOBAL", Property.NOT_ENUMERABLE, global);
351 global.addOwnProperty("$SCRIPTS", Property.NOT_ENUMERABLE, files);
352 context.load(global, "fx:bootstrap.js");
353 } catch (final NashornException e) {
354 context.getErrorManager().error(e.toString());
355 if (context.getEnv()._dump_on_error) {
356 e.printStackTrace(context.getErr());
357 }
358
359 return RUNTIME_ERROR;
360 } finally {
361 context.getOut().flush();
362 context.getErr().flush();
363 if (globalChanged) {
372 * Hook to ScriptFunction "apply". A performance metering shell may
373 * introduce enter/exit timing here.
374 *
375 * @param target target function for apply
376 * @param self self reference for apply
377 *
378 * @return result of the function apply
379 */
380 protected Object apply(final ScriptFunction target, final Object self) {
381 return ScriptRuntime.apply(target, self);
382 }
383
384 /**
385 * read-eval-print loop for Nashorn shell.
386 *
387 * @param context the nashorn context
388 * @param global global scope object to use
389 * @return return code
390 */
391 @SuppressWarnings("resource")
392 private static int readEvalPrint(final Context context, final ScriptObject global) {
393 final String prompt = bundle.getString("shell.prompt");
394 final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
395 final PrintWriter err = context.getErr();
396 final ScriptObject oldGlobal = Context.getGlobal();
397 final boolean globalChanged = (oldGlobal != global);
398 final ScriptEnvironment env = context.getEnv();
399
400 try {
401 if (globalChanged) {
402 Context.setGlobal(global);
403 }
404
405 // initialize with "shell.js" script
406 try {
407 final Source source = new Source("<shell.js>", Shell.class.getResource("resources/shell.js"));
408 context.eval(global, source.getString(), global, "<shell.js>", false);
409 } catch (final Exception e) {
410 err.println(e);
411 if (env._dump_on_error) {
412 e.printStackTrace(err);
413 }
414
415 return INTERNAL_ERROR;
416 }
|
25
26 package jdk.nashorn.tools;
27
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileReader;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34 import java.io.OutputStream;
35 import java.io.PrintStream;
36 import java.io.PrintWriter;
37 import java.util.List;
38 import java.util.Locale;
39 import java.util.ResourceBundle;
40 import jdk.nashorn.api.scripting.NashornException;
41 import jdk.nashorn.internal.codegen.Compiler;
42 import jdk.nashorn.internal.ir.FunctionNode;
43 import jdk.nashorn.internal.ir.debug.ASTWriter;
44 import jdk.nashorn.internal.ir.debug.PrintVisitor;
45 import jdk.nashorn.internal.objects.Global;
46 import jdk.nashorn.internal.parser.Parser;
47 import jdk.nashorn.internal.runtime.Context;
48 import jdk.nashorn.internal.runtime.ErrorManager;
49 import jdk.nashorn.internal.runtime.JSType;
50 import jdk.nashorn.internal.runtime.Property;
51 import jdk.nashorn.internal.runtime.ScriptEnvironment;
52 import jdk.nashorn.internal.runtime.ScriptFunction;
53 import jdk.nashorn.internal.runtime.ScriptObject;
54 import jdk.nashorn.internal.runtime.ScriptRuntime;
55 import jdk.nashorn.internal.runtime.Source;
56 import jdk.nashorn.internal.runtime.options.Options;
57
58 /**
59 * Command line Shell for processing JavaScript files.
60 */
61 public class Shell {
62
63 /**
64 * Resource name for properties file
65 */
132 }
133
134 /**
135 * Run method logic.
136 *
137 * @param in input stream for Shell
138 * @param out output stream for Shell
139 * @param err error stream for Shell
140 * @param args arguments to Shell
141 *
142 * @return exit code
143 *
144 * @throws IOException if there's a problem setting up the streams
145 */
146 protected final int run(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) throws IOException {
147 final Context context = makeContext(in, out, err, args);
148 if (context == null) {
149 return COMMANDLINE_ERROR;
150 }
151
152 final Global global = context.createGlobal();
153 final ScriptEnvironment env = context.getEnv();
154 final List<String> files = env.getFiles();
155 if (files.isEmpty()) {
156 return readEvalPrint(context, global);
157 }
158
159 if (env._compile_only) {
160 return compileScripts(context, global, files);
161 }
162
163 if (env._fx) {
164 return runFXScripts(context, global, files);
165 }
166
167 return runScripts(context, global, files);
168 }
169
170 /**
171 * Make a new Nashorn Context to compile and/or run JavaScript files.
172 *
215 } catch (final IOException e) {
216 // ignore this. File IO errors will be reported later anyway
217 }
218 }
219 }
220 }
221
222 return new Context(options, errors, wout, werr, Thread.currentThread().getContextClassLoader());
223 }
224
225 /**
226 * Compiles the given script files in the command line
227 *
228 * @param context the nashorn context
229 * @param global the global scope
230 * @param files the list of script files to compile
231 *
232 * @return error code
233 * @throws IOException when any script file read results in I/O error
234 */
235 private static int compileScripts(final Context context, final Global global, final List<String> files) throws IOException {
236 final Global oldGlobal = Context.getGlobal();
237 final boolean globalChanged = (oldGlobal != global);
238 final ScriptEnvironment env = context.getEnv();
239 try {
240 if (globalChanged) {
241 Context.setGlobal(global);
242 }
243 final ErrorManager errors = context.getErrorManager();
244
245 // For each file on the command line.
246 for (final String fileName : files) {
247 final FunctionNode functionNode = new Parser(env, new Source(fileName, new File(fileName)), errors).parse();
248
249 if (errors.getNumberOfErrors() != 0) {
250 return COMPILATION_ERROR;
251 }
252
253 if (env._print_ast) {
254 context.getErr().println(new ASTWriter(functionNode));
255 }
256
265 env.getOut().flush();
266 env.getErr().flush();
267 if (globalChanged) {
268 Context.setGlobal(oldGlobal);
269 }
270 }
271
272 return SUCCESS;
273 }
274
275 /**
276 * Runs the given JavaScript files in the command line
277 *
278 * @param context the nashorn context
279 * @param global the global scope
280 * @param files the list of script files to run
281 *
282 * @return error code
283 * @throws IOException when any script file read results in I/O error
284 */
285 private int runScripts(final Context context, final Global global, final List<String> files) throws IOException {
286 final Global oldGlobal = Context.getGlobal();
287 final boolean globalChanged = (oldGlobal != global);
288 try {
289 if (globalChanged) {
290 Context.setGlobal(global);
291 }
292 final ErrorManager errors = context.getErrorManager();
293
294 // For each file on the command line.
295 for (final String fileName : files) {
296 if ("-".equals(fileName)) {
297 final int res = readEvalPrint(context, global);
298 if (res != SUCCESS) {
299 return res;
300 }
301 continue;
302 }
303
304 final File file = new File(fileName);
305 final ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global);
306 if (script == null || errors.getNumberOfErrors() != 0) {
323 context.getErr().flush();
324 if (globalChanged) {
325 Context.setGlobal(oldGlobal);
326 }
327 }
328
329 return SUCCESS;
330 }
331
332 /**
333 * Runs launches "fx:bootstrap.js" with the given JavaScript files provided
334 * as arguments.
335 *
336 * @param context the nashorn context
337 * @param global the global scope
338 * @param files the list of script files to provide
339 *
340 * @return error code
341 * @throws IOException when any script file read results in I/O error
342 */
343 private static int runFXScripts(final Context context, final Global global, final List<String> files) throws IOException {
344 final Global oldGlobal = Context.getGlobal();
345 final boolean globalChanged = (oldGlobal != global);
346 try {
347 if (globalChanged) {
348 Context.setGlobal(global);
349 }
350
351 global.addOwnProperty("$GLOBAL", Property.NOT_ENUMERABLE, global);
352 global.addOwnProperty("$SCRIPTS", Property.NOT_ENUMERABLE, files);
353 context.load(global, "fx:bootstrap.js");
354 } catch (final NashornException e) {
355 context.getErrorManager().error(e.toString());
356 if (context.getEnv()._dump_on_error) {
357 e.printStackTrace(context.getErr());
358 }
359
360 return RUNTIME_ERROR;
361 } finally {
362 context.getOut().flush();
363 context.getErr().flush();
364 if (globalChanged) {
373 * Hook to ScriptFunction "apply". A performance metering shell may
374 * introduce enter/exit timing here.
375 *
376 * @param target target function for apply
377 * @param self self reference for apply
378 *
379 * @return result of the function apply
380 */
381 protected Object apply(final ScriptFunction target, final Object self) {
382 return ScriptRuntime.apply(target, self);
383 }
384
385 /**
386 * read-eval-print loop for Nashorn shell.
387 *
388 * @param context the nashorn context
389 * @param global global scope object to use
390 * @return return code
391 */
392 @SuppressWarnings("resource")
393 private static int readEvalPrint(final Context context, final Global global) {
394 final String prompt = bundle.getString("shell.prompt");
395 final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
396 final PrintWriter err = context.getErr();
397 final Global oldGlobal = Context.getGlobal();
398 final boolean globalChanged = (oldGlobal != global);
399 final ScriptEnvironment env = context.getEnv();
400
401 try {
402 if (globalChanged) {
403 Context.setGlobal(global);
404 }
405
406 // initialize with "shell.js" script
407 try {
408 final Source source = new Source("<shell.js>", Shell.class.getResource("resources/shell.js"));
409 context.eval(global, source.getString(), global, "<shell.js>", false);
410 } catch (final Exception e) {
411 err.println(e);
412 if (env._dump_on_error) {
413 e.printStackTrace(err);
414 }
415
416 return INTERNAL_ERROR;
417 }
|