1
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3
* ***** BEGIN LICENSE BLOCK *****
4
* Version: MPL 1.1/GPL 2.0
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 1.1 (the "License"); you may not use this file except in compliance with
8
* the License. You may obtain a copy of the License at
9
* http://www.mozilla.org/MPL/
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
16
* The Original Code is Rhino code, released
19
* The Initial Developer of the Original Code is
20
* Netscape Communications Corporation.
21
* Portions created by the Initial Developer are Copyright (C) 1997-1999
22
* the Initial Developer. All Rights Reserved.
26
* Alternatively, the contents of this file may be used under the terms of
27
* the GNU General Public License Version 2 or later (the "GPL"), in which
28
* case the provisions of the GPL are applicable instead of those above. If
29
* you wish to allow use of your version of this file only under the terms of
30
* the GPL and not to allow others to use your version of this file under the
31
* MPL, indicate your decision by deleting the provisions above and replacing
32
* them with the notice and other provisions required by the GPL. If you do
33
* not delete the provisions above, a recipient may use your version of this
34
* file under either the MPL or the GPL.
36
* ***** END LICENSE BLOCK ***** */
38
import org.mozilla.javascript.*;
44
* Can execute scripts interactively or in batch mode at the command line.
45
* An example of controlling the JavaScript engine.
49
public class Shell extends ScriptableObject
51
public String getClassName()
59
* Process arguments as would a normal Java program. Also
60
* create a new Context and associate it with the current thread.
61
* Then set up the execution environment and begin to
64
public static void main(String args[]) {
65
// Associate a new Context with this thread
66
Context cx = Context.enter();
68
// Initialize the standard objects (Object, Function, etc.)
69
// This must be done before scripts can be executed.
70
Shell shell = new Shell();
71
cx.initStandardObjects(shell);
73
// Define some global functions particular to the shell. Note
74
// that these functions are not part of ECMA.
75
String[] names = { "print", "quit", "version", "load", "help" };
76
shell.defineFunctionProperties(names, Shell.class,
77
ScriptableObject.DONTENUM);
79
args = processOptions(cx, args);
81
// Set up "arguments" in the global scope to contain the command
82
// line arguments after the name of the script to execute
84
if (args.length == 0) {
85
array = new Object[0];
87
int length = args.length - 1;
88
array = new Object[length];
89
System.arraycopy(args, 1, array, 0, length);
91
Scriptable argsObj = cx.newArray(shell, array);
92
shell.defineProperty("arguments", argsObj,
93
ScriptableObject.DONTENUM);
95
shell.processSource(cx, args.length == 0 ? null : args[0]);
104
public static String[] processOptions(Context cx, String args[]) {
105
for (int i=0; i < args.length; i++) {
106
String arg = args[i];
107
if (!arg.startsWith("-")) {
108
String[] result = new String[args.length - i];
109
for (int j=i; j < args.length; j++)
110
result[j-i] = args[j];
113
if (arg.equals("-version")) {
114
if (++i == args.length)
116
double d = Context.toNumber(args[i]);
119
cx.setLanguageVersion((int) d);
124
return new String[0];
128
* Print a usage message.
130
private static void usage(String s) {
131
p("Didn't understand \"" + s + "\".");
132
p("Valid arguments are:");
133
p("-version 100|110|120|130|140|150|160|170");
138
* Print a help message.
140
* This method is defined as a JavaScript function.
144
p("Command Description");
145
p("======= ===========");
146
p("help() Display usage and help messages. ");
147
p("defineClass(className) Define an extension using the Java class");
148
p(" named with the string argument. ");
149
p(" Uses ScriptableObject.defineClass(). ");
150
p("load(['foo.js', ...]) Load JavaScript source files named by ");
151
p(" string arguments. ");
152
p("loadClass(className) Load a class named by a string argument.");
153
p(" The class must be a script compiled to a");
155
p("print([expr ...]) Evaluate and print expressions. ");
156
p("quit() Quit the shell. ");
157
p("version([number]) Get or set the JavaScript version number.");
162
* Print the string values of its arguments.
164
* This method is defined as a JavaScript function.
165
* Note that its arguments are of the "varargs" form, which
166
* allows it to handle an arbitrary number of arguments
167
* supplied to the JavaScript function.
170
public static void print(Context cx, Scriptable thisObj,
171
Object[] args, Function funObj)
173
for (int i=0; i < args.length; i++) {
175
System.out.print(" ");
177
// Convert the arbitrary JavaScript value into a string form.
178
String s = Context.toString(args[i]);
182
System.out.println();
188
* This only affects the interactive mode.
190
* This method is defined as a JavaScript function.
198
* Get and set the language version.
200
* This method is defined as a JavaScript function.
202
public static double version(Context cx, Scriptable thisObj,
203
Object[] args, Function funObj)
205
double result = cx.getLanguageVersion();
206
if (args.length > 0) {
207
double d = Context.toNumber(args[0]);
208
cx.setLanguageVersion((int) d);
214
* Load and execute a set of JavaScript source files.
216
* This method is defined as a JavaScript function.
219
public static void load(Context cx, Scriptable thisObj,
220
Object[] args, Function funObj)
222
Shell shell = (Shell)getTopLevelScope(thisObj);
223
for (int i = 0; i < args.length; i++) {
224
shell.processSource(cx, Context.toString(args[i]));
230
* Evaluate JavaScript source.
232
* @param cx the current context
233
* @param filename the name of the file to compile, or null
234
* for interactive mode.
236
private void processSource(Context cx, String filename)
238
if (filename == null) {
239
BufferedReader in = new BufferedReader
240
(new InputStreamReader(System.in));
241
String sourceName = "<stdin>";
243
boolean hitEOF = false;
245
int startline = lineno;
246
System.err.print("js> ");
250
// Collect lines of source to compile.
253
newline = in.readLine();
254
if (newline == null) {
258
source = source + newline + "\n";
260
// Continue collecting as long as more lines
261
// are needed to complete the current
262
// statement. stringIsCompilableUnit is also
263
// true if the source statement will result in
264
// any error other than one that might be
265
// resolved by appending more source.
266
if (cx.stringIsCompilableUnit(source))
269
Object result = cx.evaluateString(this, source,
270
sourceName, startline,
272
if (result != Context.getUndefinedValue()) {
273
System.err.println(Context.toString(result));
276
catch (WrappedException we) {
277
// Some form of exception was caught by JavaScript and
279
System.err.println(we.getWrappedException().toString());
280
we.printStackTrace();
282
catch (EvaluatorException ee) {
283
// Some form of JavaScript error.
284
System.err.println("js: " + ee.getMessage());
286
catch (JavaScriptException jse) {
287
// Some form of JavaScript error.
288
System.err.println("js: " + jse.getMessage());
290
catch (IOException ioe) {
291
System.err.println(ioe.toString());
294
// The user executed the quit() function.
298
System.err.println();
300
FileReader in = null;
302
in = new FileReader(filename);
304
catch (FileNotFoundException ex) {
305
Context.reportError("Couldn't open file \"" + filename + "\".");
310
// Here we evalute the entire contents of the file as
311
// a script. Text is printed only if the print() function
313
cx.evaluateReader(this, in, filename, 1, null);
315
catch (WrappedException we) {
316
System.err.println(we.getWrappedException().toString());
317
we.printStackTrace();
319
catch (EvaluatorException ee) {
320
System.err.println("js: " + ee.getMessage());
322
catch (JavaScriptException jse) {
323
System.err.println("js: " + jse.getMessage());
325
catch (IOException ioe) {
326
System.err.println(ioe.toString());
332
catch (IOException ioe) {
333
System.err.println(ioe.toString());
339
private static void p(String s) {
340
System.out.println(s);
343
private boolean quitting;