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
.*;
40 import com
.metaweb
.util
.javascript
.DOM
.*;
45 * Can execute scripts interactively or in batch mode at the command line.
46 * An example of controlling the JavaScript engine.
50 public class Shell
extends ScriptableObject
52 private static final long serialVersionUID
= -5638074146250193112L;
55 public String
getClassName()
63 * Process arguments as would a normal Java program. Also
64 * create a new Context and associate it with the current thread.
65 * Then set up the execution environment and begin to
68 public static void main(String args
[]) throws Exception
{
69 // Associate a new Context with this thread
70 Context cx
= Context
.enter();
72 // Initialize the standard objects (Object, Function, etc.)
73 // This must be done before scripts can be executed.
74 Shell shell
= new Shell();
75 cx
.setOptimizationLevel(-1);
76 cx
.initStandardObjects(shell
);
77 ScriptableObject
.defineClass(shell
, JSAttr
.class, false, true);
78 ScriptableObject
.defineClass(shell
, JSCDATASection
.class, false, true);
79 ScriptableObject
.defineClass(shell
, JSCharacterData
.class, false, true);
80 ScriptableObject
.defineClass(shell
, JSComment
.class, false, true);
81 ScriptableObject
.defineClass(shell
, JSDOMException
.class, false, true);
82 ScriptableObject
.defineClass(shell
, JSDOMImplementation
.class, false, true);
83 ScriptableObject
.defineClass(shell
, JSDocument
.class, false, true);
84 ScriptableObject
.defineClass(shell
, JSDocumentFragment
.class, false, true);
85 ScriptableObject
.defineClass(shell
, JSDocumentType
.class, false, true);
86 ScriptableObject
.defineClass(shell
, JSElement
.class, false, true);
87 ScriptableObject
.defineClass(shell
, JSEntity
.class, false, true);
88 ScriptableObject
.defineClass(shell
, JSEntityReference
.class, false, true);
89 ScriptableObject
.defineClass(shell
, JSNamedNodeMap
.class, false, true);
90 ScriptableObject
.defineClass(shell
, JSNode
.class, false, true);
91 ScriptableObject
.defineClass(shell
, JSNodeList
.class, false, true);
92 ScriptableObject
.defineClass(shell
, JSNotation
.class, false, true);
93 ScriptableObject
.defineClass(shell
, JSProcessingInstruction
.class, false, true);
94 ScriptableObject
.defineClass(shell
, JSText
.class, false, true);
95 ScriptableObject
.defineClass(shell
, JSDOMParser
.class, false, true);
98 // Define some global functions particular to the shell. Note
99 // that these functions are not part of ECMA.
100 String
[] names
= { "print", "quit", "version", "_load", "help" };
101 shell
.defineFunctionProperties(names
, Shell
.class,
102 ScriptableObject
.DONTENUM
);
104 args
= processOptions(cx
, args
);
106 // Set up "arguments" in the global shell to contain the command
107 // line arguments after the name of the script to execute
109 if (args
.length
== 0) {
110 array
= new Object
[0];
112 int length
= args
.length
- 1;
113 array
= new Object
[length
];
114 System
.arraycopy(args
, 1, array
, 0, length
);
116 Scriptable argsObj
= cx
.newArray(shell
, array
);
117 shell
.defineProperty("arguments", argsObj
,
118 ScriptableObject
.DONTENUM
);
120 shell
.processSource(cx
, args
.length
== 0 ?
null : args
[0]);
129 public static String
[] processOptions(Context cx
, String args
[]) {
130 for (int i
=0; i
< args
.length
; i
++) {
131 String arg
= args
[i
];
132 if (!arg
.startsWith("-")) {
133 String
[] result
= new String
[args
.length
- i
];
134 for (int j
=i
; j
< args
.length
; j
++)
135 result
[j
-i
] = args
[j
];
138 if (arg
.equals("-version")) {
139 if (++i
== args
.length
)
141 double d
= Context
.toNumber(args
[i
]);
144 cx
.setLanguageVersion((int) d
);
149 return new String
[0];
153 * Print a usage message.
155 private static void usage(String s
) {
156 p("Didn't understand \"" + s
+ "\".");
157 p("Valid arguments are:");
158 p("-version 100|110|120|130|140|150|160|170");
163 * Print a help message.
165 * This method is defined as a JavaScript function.
169 p("Command Description");
170 p("======= ===========");
171 p("help() Display usage and help messages. ");
172 p("defineClass(className) Define an extension using the Java class");
173 p(" named with the string argument. ");
174 p(" Uses ScriptableObject.defineClass(). ");
175 p("load(['foo.js', ...]) Load JavaScript source files named by ");
176 p(" string arguments. ");
177 p("loadClass(className) Load a class named by a string argument.");
178 p(" The class must be a script compiled to a");
180 p("print([expr ...]) Evaluate and print expressions. ");
181 p("quit() Quit the shell. ");
182 p("version([number]) Get or set the JavaScript version number.");
187 * Print the string values of its arguments.
189 * This method is defined as a JavaScript function.
190 * Note that its arguments are of the "varargs" form, which
191 * allows it to handle an arbitrary number of arguments
192 * supplied to the JavaScript function.
195 public static void print(Context cx
, Scriptable thisObj
,
196 Object
[] args
, Function funObj
)
198 for (int i
=0; i
< args
.length
; i
++) {
200 System
.out
.print(" ");
202 // Convert the arbitrary JavaScript value into a string form.
203 String s
= Context
.toString(args
[i
]);
207 System
.out
.println();
213 * This only affects the interactive mode.
215 * This method is defined as a JavaScript function.
223 * Get and set the language version.
225 * This method is defined as a JavaScript function.
227 public static double version(Context cx
, Scriptable thisObj
,
228 Object
[] args
, Function funObj
)
230 double result
= cx
.getLanguageVersion();
231 if (args
.length
> 0) {
232 double d
= Context
.toNumber(args
[0]);
233 cx
.setLanguageVersion((int) d
);
239 * Load and execute a set of JavaScript source files.
241 * This method is defined as a JavaScript function.
244 public static void _load(Context cx
, Scriptable thisObj
,
245 Object
[] args
, Function funObj
)
247 Shell shell
= (Shell
)getTopLevelScope(thisObj
);
248 for (int i
= 0; i
< args
.length
; i
++) {
249 shell
.processSource(cx
, Context
.toString(args
[i
]));
255 * Evaluate JavaScript source.
257 * @param cx the current context
258 * @param filename the name of the file to compile, or null
259 * for interactive mode.
261 private void processSource(Context cx
, String filename
)
263 if (filename
== null) {
264 BufferedReader in
= new BufferedReader
265 (new InputStreamReader(System
.in
));
266 String sourceName
= "<stdin>";
268 boolean hitEOF
= false;
270 int startline
= lineno
;
271 System
.err
.print("js> ");
275 // Collect lines of source to compile.
278 newline
= in
.readLine();
279 if (newline
== null) {
283 source
= source
+ newline
+ "\n";
285 // Continue collecting as long as more lines
286 // are needed to complete the current
287 // statement. stringIsCompilableUnit is also
288 // true if the source statement will result in
289 // any error other than one that might be
290 // resolved by appending more source.
291 if (cx
.stringIsCompilableUnit(source
))
294 Object result
= cx
.evaluateString(this, source
,
295 sourceName
, startline
,
297 if (result
!= Context
.getUndefinedValue()) {
298 System
.err
.println(Context
.toString(result
));
301 catch (WrappedException we
) {
302 // Some form of exception was caught by JavaScript and
304 System
.err
.println(we
.getWrappedException().toString());
305 we
.printStackTrace();
307 catch (EvaluatorException ee
) {
308 // Some form of JavaScript error.
309 System
.err
.println("js: " + ee
.getMessage());
311 catch (JavaScriptException jse
) {
312 // Some form of JavaScript error.
313 System
.err
.println("js: " + jse
.getMessage());
315 catch (IOException ioe
) {
316 System
.err
.println(ioe
.toString());
319 // The user executed the quit() function.
323 System
.err
.println();
325 FileReader in
= null;
327 in
= new FileReader(filename
);
329 catch (FileNotFoundException ex
) {
330 Context
.reportError("Couldn't open file \"" + filename
+ "\".");
335 // Here we evalute the entire contents of the file as
336 // a script. Text is printed only if the print() function
338 cx
.evaluateReader(this, in
, filename
, 1, null);
340 catch (WrappedException we
) {
341 System
.err
.println(we
.getWrappedException().toString());
342 we
.printStackTrace();
344 catch (EvaluatorException ee
) {
345 System
.err
.println("js: " + ee
.getMessage());
347 catch (JavaScriptException jse
) {
348 System
.err
.println("js: " + jse
.getMessage());
350 catch (IOException ioe
) {
351 System
.err
.println(ioe
.toString());
357 catch (IOException ioe
) {
358 System
.err
.println(ioe
.toString());
364 private static void p(String s
) {
365 System
.out
.println(s
);
368 private boolean quitting
;