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-2000
22
* the Initial Developer. All Rights Reserved.
27
* Alternatively, the contents of this file may be used under the terms of
28
* the GNU General Public License Version 2 or later (the "GPL"), in which
29
* case the provisions of the GPL are applicable instead of those above. If
30
* you wish to allow use of your version of this file only under the terms of
31
* the GPL and not to allow others to use your version of this file under the
32
* MPL, indicate your decision by deleting the provisions above and replacing
33
* them with the notice and other provisions required by the GPL. If you do
34
* not delete the provisions above, a recipient may use your version of this
35
* file under either the MPL or the GPL.
37
* ***** END LICENSE BLOCK ***** */
41
package org.mozilla.javascript;
43
import java.beans.PropertyChangeEvent;
44
import java.beans.PropertyChangeListener;
45
import java.io.CharArrayWriter;
46
import java.io.IOException;
47
import java.io.PrintWriter;
48
import java.io.Reader;
49
import java.io.StringWriter;
50
import java.io.Writer;
51
import java.lang.reflect.InvocationTargetException;
52
import java.lang.reflect.Method;
53
import java.util.Hashtable;
54
import java.util.Locale;
56
import org.mozilla.javascript.debug.DebuggableScript;
57
import org.mozilla.javascript.debug.Debugger;
58
import org.mozilla.javascript.xml.XMLLib;
61
* This class represents the runtime context of an executing script.
63
* Before executing a script, an instance of Context must be created
64
* and associated with the thread that will be executing the script.
65
* The Context will be used to store information about the executing
66
* of the script such as the call stack. Contexts are associated with
67
* the current thread using the {@link #call(ContextAction)}
68
* or {@link #enter()} methods.<p>
70
* Different forms of script execution are supported. Scripts may be
71
* evaluated from the source directly, or first compiled and then later
72
* executed. Interactive execution is also supported.<p>
74
* Some aspects of script execution, such as type conversions and
75
* object creation, may be accessed directly through methods of
80
* @author Brendan Eich
88
* All integral values are reserved for future version numbers.
92
* The unknown version.
94
public static final int VERSION_UNKNOWN = -1;
97
* The default version.
99
public static final int VERSION_DEFAULT = 0;
104
public static final int VERSION_1_0 = 100;
109
public static final int VERSION_1_1 = 110;
114
public static final int VERSION_1_2 = 120;
119
public static final int VERSION_1_3 = 130;
124
public static final int VERSION_1_4 = 140;
129
public static final int VERSION_1_5 = 150;
134
public static final int VERSION_1_6 = 160;
139
public static final int VERSION_1_7 = 170;
142
* Controls behaviour of <tt>Date.prototype.getYear()</tt>.
143
* If <tt>hasFeature(FEATURE_NON_ECMA_GET_YEAR)</tt> returns true,
144
* Date.prototype.getYear subtructs 1900 only if 1900 <= date < 2000.
145
* The default behavior of {@link #hasFeature(int)} is always to subtruct
146
* 1900 as rquired by ECMAScript B.2.4.
148
public static final int FEATURE_NON_ECMA_GET_YEAR = 1;
151
* Control if member expression as function name extension is available.
152
* If <tt>hasFeature(FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)</tt> returns
153
* true, allow <tt>function memberExpression(args) { body }</tt> to be
154
* syntax sugar for <tt>memberExpression = function(args) { body }</tt>,
155
* when memberExpression is not a simple identifier.
156
* See ECMAScript-262, section 11.2 for definition of memberExpression.
157
* By default {@link #hasFeature(int)} returns false.
159
public static final int FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME = 2;
162
* Control if reserved keywords are treated as identifiers.
163
* If <tt>hasFeature(RESERVED_KEYWORD_AS_IDENTIFIER)</tt> returns true,
164
* treat future reserved keyword (see Ecma-262, section 7.5.3) as ordinary
165
* identifiers but warn about this usage.
167
* By default {@link #hasFeature(int)} returns false.
169
public static final int FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER = 3;
172
* Control if <tt>toString()</tt> should returns the same result
173
* as <tt>toSource()</tt> when applied to objects and arrays.
174
* If <tt>hasFeature(FEATURE_TO_STRING_AS_SOURCE)</tt> returns true,
175
* calling <tt>toString()</tt> on JS objects gives the same result as
176
* calling <tt>toSource()</tt>. That is it returns JS source with code
177
* to create an object with all enumeratable fields of the original object
178
* instead of printing <tt>[object <i>result of
179
* {@link Scriptable#getClassName()}</i>]</tt>.
181
* By default {@link #hasFeature(int)} returns true only if
182
* the current JS version is set to {@link #VERSION_1_2}.
184
public static final int FEATURE_TO_STRING_AS_SOURCE = 4;
187
* Control if properties <tt>__proto__</tt> and <tt>__parent__</tt>
188
* are treated specially.
189
* If <tt>hasFeature(FEATURE_PARENT_PROTO_PROPERTIES)</tt> returns true,
190
* treat <tt>__parent__</tt> and <tt>__proto__</tt> as special properties.
192
* The properties allow to query and set scope and prototype chains for the
193
* objects. The special meaning of the properties is available
194
* only when they are used as the right hand side of the dot operator.
195
* For example, while <tt>x.__proto__ = y</tt> changes the prototype
196
* chain of the object <tt>x</tt> to point to <tt>y</tt>,
197
* <tt>x["__proto__"] = y</tt> simply assigns a new value to the property
198
* <tt>__proto__</tt> in <tt>x</tt> even when the feature is on.
200
* By default {@link #hasFeature(int)} returns true.
202
public static final int FEATURE_PARENT_PROTO_PROPERTIES = 5;
205
* @deprecated In previous releases, this name was given to
206
* FEATURE_PARENT_PROTO_PROPERTIES.
208
public static final int FEATURE_PARENT_PROTO_PROPRTIES = 5;
211
* Control if support for E4X(ECMAScript for XML) extension is available.
212
* If hasFeature(FEATURE_E4X) returns true, the XML syntax is available.
214
* By default {@link #hasFeature(int)} returns true if
215
* the current JS version is set to {@link #VERSION_DEFAULT}
216
* or is at least {@link #VERSION_1_6}.
217
* @since 1.6 Release 1
219
public static final int FEATURE_E4X = 6;
222
* Control if dynamic scope should be used for name access.
223
* If hasFeature(FEATURE_DYNAMIC_SCOPE) returns true, then the name lookup
224
* during name resolution will use the top scope of the script or function
225
* which is at the top of JS execution stack instead of the top scope of the
226
* script or function from the current stack frame if the top scope of
227
* the top stack frame contains the top scope of the current stack frame
228
* on its prototype chain.
230
* This is useful to define shared scope containing functions that can
231
* be called from scripts and functions using private scopes.
233
* By default {@link #hasFeature(int)} returns false.
234
* @since 1.6 Release 1
236
public static final int FEATURE_DYNAMIC_SCOPE = 7;
239
* Control if strict variable mode is enabled.
240
* When the feature is on Rhino reports runtime errors if assignment
241
* to a global variable that does not exist is executed. When the feature
242
* is off such assignments creates new variable in the global scope as
243
* required by ECMA 262.
245
* By default {@link #hasFeature(int)} returns false.
246
* @since 1.6 Release 1
248
public static final int FEATURE_STRICT_VARS = 8;
251
* Control if strict eval mode is enabled.
252
* When the feature is on Rhino reports runtime errors if non-string
253
* argument is passed to the eval function. When the feature is off
254
* eval simply return non-string argument as is without performing any
255
* evaluation as required by ECMA 262.
257
* By default {@link #hasFeature(int)} returns false.
258
* @since 1.6 Release 1
260
public static final int FEATURE_STRICT_EVAL = 9;
263
* When the feature is on Rhino will add a "fileName" and "lineNumber"
264
* properties to Error objects automatically. When the feature is off, you
265
* have to explicitly pass them as the second and third argument to the
266
* Error constructor. Note that neither behaviour is fully ECMA 262
267
* compliant (as 262 doesn't specify a three-arg constructor), but keeping
268
* the feature off results in Error objects that don't have
269
* additional non-ECMA properties when constructed using the ECMA-defined
270
* single-arg constructor and is thus desirable if a stricter ECMA
271
* compliance is desired, specifically adherence to the point 15.11.5. of
274
* By default {@link #hasFeature(int)} returns false.
275
* @since 1.6 Release 6
277
public static final int FEATURE_LOCATION_INFORMATION_IN_ERROR = 10;
280
* Controls whether JS 1.5 'strict mode' is enabled.
281
* When the feature is on, Rhino reports more than a dozen different
282
* warnings. When the feature is off, these warnings are not generated.
283
* FEATURE_STRICT_MODE implies FEATURE_STRICT_VARS and FEATURE_STRICT_EVAL.
285
* By default {@link #hasFeature(int)} returns false.
286
* @since 1.6 Release 6
288
public static final int FEATURE_STRICT_MODE = 11;
291
* Controls whether a warning should be treated as an error.
292
* @since 1.6 Release 6
294
public static final int FEATURE_WARNING_AS_ERROR = 12;
297
* Enables enhanced access to Java.
298
* Specifically, controls whether private and protected members can be
299
* accessed, and whether scripts can catch all Java exceptions.
301
* Note that this feature should only be enabled for trusted scripts.
303
* By default {@link #hasFeature(int)} returns false.
304
* @since 1.7 Release 1
306
public static final int FEATURE_ENHANCED_JAVA_ACCESS = 13;
309
public static final String languageVersionProperty = "language version";
310
public static final String errorReporterProperty = "error reporter";
313
* Convenient value to use as zero-length array of objects.
315
public static final Object[] emptyArgs = ScriptRuntime.emptyArgs;
318
* Create a new Context.
320
* Note that the Context must be associated with a thread before
321
* it can be used to execute a script.
322
* @deprecated use {@link ContextFactory#enter()} or
323
* {@link ContextFactory#call(ContextAction)} instead.
327
this(ContextFactory.getGlobal());
330
Context(ContextFactory factory)
332
assert factory != null;
333
this.factory = factory;
334
setLanguageVersion(VERSION_DEFAULT);
335
optimizationLevel = codegenClass != null ? 0 : -1;
336
maximumInterpreterStackDepth = Integer.MAX_VALUE;
340
* Get the current Context.
342
* The current Context is per-thread; this method looks up
343
* the Context associated with the current thread. <p>
345
* @return the Context associated with the current thread, or
346
* null if no context is associated with the current
348
* @see ContextFactory#enterContext()
349
* @see ContextFactory#call(ContextAction)
351
public static Context getCurrentContext()
353
Object helper = VMBridge.instance.getThreadContextHelper();
354
return VMBridge.instance.getContext(helper);
358
* Same as calling {@link ContextFactory#enterContext()} on the global
359
* ContextFactory instance.
360
* @deprecated use {@link ContextFactory#enter()} or
361
* {@link ContextFactory#call(ContextAction)} instead as this method relies
362
* on usage of a static singleton "global" ContextFactory.
363
* @return a Context associated with the current thread
364
* @see #getCurrentContext()
366
* @see #call(ContextAction)
368
public static Context enter()
374
* Get a Context associated with the current thread, using
375
* the given Context if need be.
377
* The same as <code>enter()</code> except that <code>cx</code>
378
* is associated with the current thread and returned if
379
* the current thread has no associated context and <code>cx</code>
380
* is not associated with any other thread.
381
* @param cx a Context to associate with the thread if possible
382
* @return a Context associated with the current thread
383
* @deprecated use {@link ContextFactory#enterContext(Context)} instead as
384
* this method relies on usage of a static singleton "global" ContextFactory.
385
* @see ContextFactory#enterContext(Context)
386
* @see ContextFactory#call(ContextAction)
388
public static Context enter(Context cx)
390
return enter(cx, ContextFactory.getGlobal());
393
static final Context enter(Context cx, ContextFactory factory)
395
Object helper = VMBridge.instance.getThreadContextHelper();
396
Context old = VMBridge.instance.getContext(helper);
401
cx = factory.makeContext();
402
if (cx.enterCount != 0) {
403
throw new IllegalStateException("factory.makeContext() returned Context instance already associated with some thread");
405
factory.onContextCreated(cx);
406
if (factory.isSealed() && !cx.isSealed()) {
410
if (cx.enterCount != 0) {
411
throw new IllegalStateException("can not use Context instance already associated with some thread");
414
VMBridge.instance.setContext(helper, cx);
421
* Exit a block of code requiring a Context.
423
* Calling <code>exit()</code> will remove the association between
424
* the current thread and a Context if the prior call to
425
* {@link ContextFactory#enterContext()} on this thread newly associated a
426
* Context with this thread. Once the current thread no longer has an
427
* associated Context, it cannot be used to execute JavaScript until it is
428
* again associated with a Context.
429
* @see ContextFactory#enterContext()
431
public static void exit()
433
Object helper = VMBridge.instance.getThreadContextHelper();
434
Context cx = VMBridge.instance.getContext(helper);
436
throw new IllegalStateException(
437
"Calling Context.exit without previous Context.enter");
439
if (cx.enterCount < 1) Kit.codeBug();
440
if (--cx.enterCount == 0) {
441
VMBridge.instance.setContext(helper, null);
442
cx.factory.onContextReleased(cx);
447
* Call {@link ContextAction#run(Context cx)}
448
* using the Context instance associated with the current thread.
449
* If no Context is associated with the thread, then
450
* <tt>ContextFactory.getGlobal().makeContext()</tt> will be called to
451
* construct new Context instance. The instance will be temporary
452
* associated with the thread during call to
453
* {@link ContextAction#run(Context)}.
454
* @deprecated use {@link ContextFactory#call(ContextAction)} instead as
455
* this method relies on usage of a static singleton "global"
457
* @return The result of {@link ContextAction#run(Context)}.
459
public static Object call(ContextAction action)
461
return call(ContextFactory.getGlobal(), action);
466
* Callable#call(Context cx, Scriptable scope, Scriptable thisObj,
468
* using the Context instance associated with the current thread.
469
* If no Context is associated with the thread, then
470
* {@link ContextFactory#makeContext()} will be called to construct
471
* new Context instance. The instance will be temporary associated
472
* with the thread during call to {@link ContextAction#run(Context)}.
474
* It is allowed but not advisable to use null for <tt>factory</tt>
475
* argument in which case the global static singleton ContextFactory
476
* instance will be used to create new context instances.
477
* @see ContextFactory#call(ContextAction)
479
public static Object call(ContextFactory factory, final Callable callable,
480
final Scriptable scope, final Scriptable thisObj,
483
if(factory == null) {
484
factory = ContextFactory.getGlobal();
486
return call(factory, new ContextAction() {
487
public Object run(Context cx) {
488
return callable.call(cx, scope, thisObj, args);
494
* The method implements {@links ContextFactory#call(ContextAction)} logic.
496
static Object call(ContextFactory factory, ContextAction action) {
497
Context cx = enter(null, factory);
499
return action.run(cx);
508
* @see ContextFactory#addListener(ContextFactory.Listener)
509
* @see ContextFactory#getGlobal()
511
public static void addContextListener(ContextListener listener)
513
// Special workaround for the debugger
514
String DBG = "org.mozilla.javascript.tools.debugger.Main";
515
if (DBG.equals(listener.getClass().getName())) {
516
Class cl = listener.getClass();
517
Class factoryClass = Kit.classOrNull(
518
"org.mozilla.javascript.ContextFactory");
519
Class[] sig = { factoryClass };
520
Object[] args = { ContextFactory.getGlobal() };
522
Method m = cl.getMethod("attachTo", sig);
523
m.invoke(listener, args);
524
} catch (Exception ex) {
525
RuntimeException rex = new RuntimeException();
526
Kit.initCause(rex, ex);
532
ContextFactory.getGlobal().addListener(listener);
537
* @see ContextFactory#removeListener(ContextFactory.Listener)
538
* @see ContextFactory#getGlobal()
540
public static void removeContextListener(ContextListener listener)
542
ContextFactory.getGlobal().addListener(listener);
546
* Return {@link ContextFactory} instance used to create this Context.
548
public final ContextFactory getFactory()
554
* Checks if this is a sealed Context. A sealed Context instance does not
555
* allow to modify any of its properties and will throw an exception
556
* on any such attempt.
557
* @see #seal(Object sealKey)
559
public final boolean isSealed()
565
* Seal this Context object so any attempt to modify any of its properties
566
* including calling {@link #enter()} and {@link #exit()} methods will
567
* throw an exception.
569
* If <tt>sealKey</tt> is not null, calling
570
* {@link #unseal(Object sealKey)} with the same key unseals
571
* the object. If <tt>sealKey</tt> is null, unsealing is no longer possible.
574
* @see #unseal(Object)
576
public final void seal(Object sealKey)
578
if (sealed) onSealedMutation();
580
this.sealKey = sealKey;
584
* Unseal previously sealed Context object.
585
* The <tt>sealKey</tt> argument should not be null and should match
586
* <tt>sealKey</tt> suplied with the last call to
587
* {@link #seal(Object)} or an exception will be thrown.
590
* @see #seal(Object sealKey)
592
public final void unseal(Object sealKey)
594
if (sealKey == null) throw new IllegalArgumentException();
595
if (this.sealKey != sealKey) throw new IllegalArgumentException();
596
if (!sealed) throw new IllegalStateException();
601
static void onSealedMutation()
603
throw new IllegalStateException();
607
* Get the current language version.
609
* The language version number affects JavaScript semantics as detailed
610
* in the overview documentation.
612
* @return an integer that is one of VERSION_1_0, VERSION_1_1, etc.
614
public final int getLanguageVersion()
620
* Set the language version.
623
* Setting the language version will affect functions and scripts compiled
624
* subsequently. See the overview documentation for version-specific
627
* @param version the version as specified by VERSION_1_0, VERSION_1_1, etc.
629
public void setLanguageVersion(int version)
631
if (sealed) onSealedMutation();
632
checkLanguageVersion(version);
633
Object listeners = propertyListeners;
634
if (listeners != null && version != this.version) {
635
firePropertyChangeImpl(listeners, languageVersionProperty,
636
new Integer(this.version),
637
new Integer(version));
639
this.version = version;
642
public static boolean isValidLanguageVersion(int version)
645
case VERSION_DEFAULT:
659
public static void checkLanguageVersion(int version)
661
if (isValidLanguageVersion(version)) {
664
throw new IllegalArgumentException("Bad language version: "+version);
668
* Get the implementation version.
671
* The implementation version is of the form
673
* "<i>name langVer</i> <code>release</code> <i>relNum date</i>"
675
* where <i>name</i> is the name of the product, <i>langVer</i> is
676
* the language version, <i>relNum</i> is the release number, and
677
* <i>date</i> is the release date for that specific
678
* release in the form "yyyy mm dd".
680
* @return a string that encodes the product, language version, release
683
public final String getImplementationVersion()
685
// XXX Probably it would be better to embed this directly into source
686
// with special build preprocessing but that would require some ant
687
// tweaking and then replacing token in resource files was simpler
688
if (implementationVersion == null) {
689
implementationVersion
690
= ScriptRuntime.getMessage0("implementation.version");
692
return implementationVersion;
696
* Get the current error reporter.
698
* @see org.mozilla.javascript.ErrorReporter
700
public final ErrorReporter getErrorReporter()
702
if (errorReporter == null) {
703
return DefaultErrorReporter.instance;
705
return errorReporter;
709
* Change the current error reporter.
711
* @return the previous error reporter
712
* @see org.mozilla.javascript.ErrorReporter
714
public final ErrorReporter setErrorReporter(ErrorReporter reporter)
716
if (sealed) onSealedMutation();
717
if (reporter == null) throw new IllegalArgumentException();
718
ErrorReporter old = getErrorReporter();
719
if (reporter == old) {
722
Object listeners = propertyListeners;
723
if (listeners != null) {
724
firePropertyChangeImpl(listeners, errorReporterProperty,
727
this.errorReporter = reporter;
732
* Get the current locale. Returns the default locale if none has
735
* @see java.util.Locale
738
public final Locale getLocale()
741
locale = Locale.getDefault();
746
* Set the current locale.
748
* @see java.util.Locale
750
public final Locale setLocale(Locale loc)
752
if (sealed) onSealedMutation();
753
Locale result = locale;
759
* Register an object to receive notifications when a bound property
761
* @see java.beans.PropertyChangeEvent
762
* @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
763
* @param l the listener
765
public final void addPropertyChangeListener(PropertyChangeListener l)
767
if (sealed) onSealedMutation();
768
propertyListeners = Kit.addListener(propertyListeners, l);
772
* Remove an object from the list of objects registered to receive
773
* notification of changes to a bounded property
774
* @see java.beans.PropertyChangeEvent
775
* @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
776
* @param l the listener
778
public final void removePropertyChangeListener(PropertyChangeListener l)
780
if (sealed) onSealedMutation();
781
propertyListeners = Kit.removeListener(propertyListeners, l);
785
* Notify any registered listeners that a bounded property has changed
786
* @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
787
* @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
788
* @see java.beans.PropertyChangeListener
789
* @see java.beans.PropertyChangeEvent
790
* @param property the bound property
791
* @param oldValue the old value
792
* @param newValue the new value
794
final void firePropertyChange(String property, Object oldValue,
797
Object listeners = propertyListeners;
798
if (listeners != null) {
799
firePropertyChangeImpl(listeners, property, oldValue, newValue);
803
private void firePropertyChangeImpl(Object listeners, String property,
804
Object oldValue, Object newValue)
806
for (int i = 0; ; ++i) {
807
Object l = Kit.getListener(listeners, i);
810
if (l instanceof PropertyChangeListener) {
811
PropertyChangeListener pcl = (PropertyChangeListener)l;
812
pcl.propertyChange(new PropertyChangeEvent(
813
this, property, oldValue, newValue));
819
* Report a warning using the error reporter for the current thread.
821
* @param message the warning message to report
822
* @param sourceName a string describing the source, such as a filename
823
* @param lineno the starting line number
824
* @param lineSource the text of the line (may be null)
825
* @param lineOffset the offset into lineSource where problem was detected
826
* @see org.mozilla.javascript.ErrorReporter
828
public static void reportWarning(String message, String sourceName,
829
int lineno, String lineSource,
832
Context cx = Context.getContext();
833
if (cx.hasFeature(FEATURE_WARNING_AS_ERROR))
834
reportError(message, sourceName, lineno, lineSource, lineOffset);
836
cx.getErrorReporter().warning(message, sourceName, lineno,
837
lineSource, lineOffset);
841
* Report a warning using the error reporter for the current thread.
843
* @param message the warning message to report
844
* @see org.mozilla.javascript.ErrorReporter
846
public static void reportWarning(String message)
849
String filename = getSourcePositionFromStack(linep);
850
Context.reportWarning(message, filename, linep[0], null, 0);
853
public static void reportWarning(String message, Throwable t)
856
String filename = getSourcePositionFromStack(linep);
857
Writer sw = new StringWriter();
858
PrintWriter pw = new PrintWriter(sw);
860
t.printStackTrace(pw);
862
Context.reportWarning(sw.toString(), filename, linep[0], null, 0);
866
* Report an error using the error reporter for the current thread.
868
* @param message the error message to report
869
* @param sourceName a string describing the source, such as a filename
870
* @param lineno the starting line number
871
* @param lineSource the text of the line (may be null)
872
* @param lineOffset the offset into lineSource where problem was detected
873
* @see org.mozilla.javascript.ErrorReporter
875
public static void reportError(String message, String sourceName,
876
int lineno, String lineSource,
879
Context cx = getCurrentContext();
881
cx.getErrorReporter().error(message, sourceName, lineno,
882
lineSource, lineOffset);
884
throw new EvaluatorException(message, sourceName, lineno,
885
lineSource, lineOffset);
890
* Report an error using the error reporter for the current thread.
892
* @param message the error message to report
893
* @see org.mozilla.javascript.ErrorReporter
895
public static void reportError(String message)
898
String filename = getSourcePositionFromStack(linep);
899
Context.reportError(message, filename, linep[0], null, 0);
903
* Report a runtime error using the error reporter for the current thread.
905
* @param message the error message to report
906
* @param sourceName a string describing the source, such as a filename
907
* @param lineno the starting line number
908
* @param lineSource the text of the line (may be null)
909
* @param lineOffset the offset into lineSource where problem was detected
910
* @return a runtime exception that will be thrown to terminate the
911
* execution of the script
912
* @see org.mozilla.javascript.ErrorReporter
914
public static EvaluatorException reportRuntimeError(String message,
920
Context cx = getCurrentContext();
922
return cx.getErrorReporter().
923
runtimeError(message, sourceName, lineno,
924
lineSource, lineOffset);
926
throw new EvaluatorException(message, sourceName, lineno,
927
lineSource, lineOffset);
931
static EvaluatorException reportRuntimeError0(String messageId)
933
String msg = ScriptRuntime.getMessage0(messageId);
934
return reportRuntimeError(msg);
937
static EvaluatorException reportRuntimeError1(String messageId,
940
String msg = ScriptRuntime.getMessage1(messageId, arg1);
941
return reportRuntimeError(msg);
944
static EvaluatorException reportRuntimeError2(String messageId,
945
Object arg1, Object arg2)
947
String msg = ScriptRuntime.getMessage2(messageId, arg1, arg2);
948
return reportRuntimeError(msg);
951
static EvaluatorException reportRuntimeError3(String messageId,
952
Object arg1, Object arg2,
955
String msg = ScriptRuntime.getMessage3(messageId, arg1, arg2, arg3);
956
return reportRuntimeError(msg);
959
static EvaluatorException reportRuntimeError4(String messageId,
960
Object arg1, Object arg2,
961
Object arg3, Object arg4)
964
= ScriptRuntime.getMessage4(messageId, arg1, arg2, arg3, arg4);
965
return reportRuntimeError(msg);
969
* Report a runtime error using the error reporter for the current thread.
971
* @param message the error message to report
972
* @see org.mozilla.javascript.ErrorReporter
974
public static EvaluatorException reportRuntimeError(String message)
977
String filename = getSourcePositionFromStack(linep);
978
return Context.reportRuntimeError(message, filename, linep[0], null, 0);
982
* Initialize the standard objects.
984
* Creates instances of the standard objects and their constructors
985
* (Object, String, Number, Date, etc.), setting up 'scope' to act
986
* as a global object as in ECMA 15.1.<p>
988
* This method must be called to initialize a scope before scripts
989
* can be evaluated in that scope.<p>
991
* This method does not affect the Context it is called upon.
993
* @return the initialized scope
995
public final ScriptableObject initStandardObjects()
997
return initStandardObjects(null, false);
1001
* Initialize the standard objects.
1003
* Creates instances of the standard objects and their constructors
1004
* (Object, String, Number, Date, etc.), setting up 'scope' to act
1005
* as a global object as in ECMA 15.1.<p>
1007
* This method must be called to initialize a scope before scripts
1008
* can be evaluated in that scope.<p>
1010
* This method does not affect the Context it is called upon.
1012
* @param scope the scope to initialize, or null, in which case a new
1013
* object will be created to serve as the scope
1014
* @return the initialized scope. The method returns the value of the scope
1015
* argument if it is not null or newly allocated scope object which
1016
* is an instance {@link ScriptableObject}.
1018
public final Scriptable initStandardObjects(ScriptableObject scope)
1020
return initStandardObjects(scope, false);
1024
* Initialize the standard objects.
1026
* Creates instances of the standard objects and their constructors
1027
* (Object, String, Number, Date, etc.), setting up 'scope' to act
1028
* as a global object as in ECMA 15.1.<p>
1030
* This method must be called to initialize a scope before scripts
1031
* can be evaluated in that scope.<p>
1033
* This method does not affect the Context it is called upon.<p>
1035
* This form of the method also allows for creating "sealed" standard
1036
* objects. An object that is sealed cannot have properties added, changed,
1037
* or removed. This is useful to create a "superglobal" that can be shared
1038
* among several top-level objects. Note that sealing is not allowed in
1039
* the current ECMA/ISO language specification, but is likely for
1042
* @param scope the scope to initialize, or null, in which case a new
1043
* object will be created to serve as the scope
1044
* @param sealed whether or not to create sealed standard objects that
1045
* cannot be modified.
1046
* @return the initialized scope. The method returns the value of the scope
1047
* argument if it is not null or newly allocated scope object.
1050
public ScriptableObject initStandardObjects(ScriptableObject scope,
1053
return ScriptRuntime.initStandardObjects(this, scope, sealed);
1057
* Get the singleton object that represents the JavaScript Undefined value.
1059
public static Object getUndefinedValue()
1061
return Undefined.instance;
1065
* Evaluate a JavaScript source string.
1067
* The provided source name and line number are used for error messages
1068
* and for producing debug information.
1070
* @param scope the scope to execute in
1071
* @param source the JavaScript source
1072
* @param sourceName a string describing the source, such as a filename
1073
* @param lineno the starting line number
1074
* @param securityDomain an arbitrary object that specifies security
1075
* information about the origin or owner of the script. For
1076
* implementations that don't care about security, this value
1078
* @return the result of evaluating the string
1079
* @see org.mozilla.javascript.SecurityController
1081
public final Object evaluateString(Scriptable scope, String source,
1082
String sourceName, int lineno,
1083
Object securityDomain)
1085
Script script = compileString(source, sourceName, lineno,
1087
if (script != null) {
1088
return script.exec(this, scope);
1095
* Evaluate a reader as JavaScript source.
1097
* All characters of the reader are consumed.
1099
* @param scope the scope to execute in
1100
* @param in the Reader to get JavaScript source from
1101
* @param sourceName a string describing the source, such as a filename
1102
* @param lineno the starting line number
1103
* @param securityDomain an arbitrary object that specifies security
1104
* information about the origin or owner of the script. For
1105
* implementations that don't care about security, this value
1107
* @return the result of evaluating the source
1109
* @exception IOException if an IOException was generated by the Reader
1111
public final Object evaluateReader(Scriptable scope, Reader in,
1112
String sourceName, int lineno,
1113
Object securityDomain)
1116
Script script = compileReader(scope, in, sourceName, lineno,
1118
if (script != null) {
1119
return script.exec(this, scope);
1126
* Check whether a string is ready to be compiled.
1128
* stringIsCompilableUnit is intended to support interactive compilation of
1129
* javascript. If compiling the string would result in an error
1130
* that might be fixed by appending more source, this method
1131
* returns false. In every other case, it returns true.
1133
* Interactive shells may accumulate source lines, using this
1134
* method after each new line is appended to check whether the
1135
* statement being entered is complete.
1137
* @param source the source buffer to check
1138
* @return whether the source is ready for compilation
1139
* @since 1.4 Release 2
1141
public final boolean stringIsCompilableUnit(String source)
1143
boolean errorseen = false;
1144
CompilerEnvirons compilerEnv = new CompilerEnvirons();
1145
compilerEnv.initFromContext(this);
1146
// no source name or source text manager, because we're just
1147
// going to throw away the result.
1148
compilerEnv.setGeneratingSource(false);
1150
Parser p = InformativeParser.makeParser(compilerEnv,
1151
DefaultErrorReporter.instance);
1153
p.parse(source, null, 1);
1154
} catch (EvaluatorException ee) {
1157
// Return false only if an error occurred as a result of reading past
1158
// the end of the file, i.e. if the source could be fixed by
1159
// appending more source.
1160
if (errorseen && p.eof())
1168
* @see #compileReader(Reader in, String sourceName, int lineno,
1169
* Object securityDomain)
1171
public final Script compileReader(Scriptable scope, Reader in,
1172
String sourceName, int lineno,
1173
Object securityDomain)
1176
return compileReader(in, sourceName, lineno, securityDomain);
1180
* Compiles the source in the given reader.
1182
* Returns a script that may later be executed.
1183
* Will consume all the source in the reader.
1185
* @param in the input reader
1186
* @param sourceName a string describing the source, such as a filename
1187
* @param lineno the starting line number for reporting errors
1188
* @param securityDomain an arbitrary object that specifies security
1189
* information about the origin or owner of the script. For
1190
* implementations that don't care about security, this value
1192
* @return a script that may later be executed
1193
* @exception IOException if an IOException was generated by the Reader
1194
* @see org.mozilla.javascript.Script
1196
public final Script compileReader(Reader in, String sourceName,
1197
int lineno, Object securityDomain)
1201
// For compatibility IllegalArgumentException can not be thrown here
1204
return (Script) compileImpl(null, in, null, sourceName, lineno,
1205
securityDomain, false, null, null);
1209
* Compiles the source in the given string.
1211
* Returns a script that may later be executed.
1213
* @param source the source string
1214
* @param sourceName a string describing the source, such as a filename
1215
* @param lineno the starting line number for reporting errors
1216
* @param securityDomain an arbitrary object that specifies security
1217
* information about the origin or owner of the script. For
1218
* implementations that don't care about security, this value
1220
* @return a script that may later be executed
1221
* @see org.mozilla.javascript.Script
1223
public final Script compileString(String source,
1224
String sourceName, int lineno,
1225
Object securityDomain)
1228
// For compatibility IllegalArgumentException can not be thrown here
1231
return compileString(source, null, null, sourceName, lineno,
1235
final Script compileString(String source,
1237
ErrorReporter compilationErrorReporter,
1238
String sourceName, int lineno,
1239
Object securityDomain)
1242
return (Script) compileImpl(null, null, source, sourceName, lineno,
1243
securityDomain, false,
1244
compiler, compilationErrorReporter);
1245
} catch (IOException ex) {
1246
// Should not happen when dealing with source as string
1247
throw new RuntimeException();
1252
* Compile a JavaScript function.
1254
* The function source must be a function definition as defined by
1255
* ECMA (e.g., "function f(a) { return a; }").
1257
* @param scope the scope to compile relative to
1258
* @param source the function definition source
1259
* @param sourceName a string describing the source, such as a filename
1260
* @param lineno the starting line number
1261
* @param securityDomain an arbitrary object that specifies security
1262
* information about the origin or owner of the script. For
1263
* implementations that don't care about security, this value
1265
* @return a Function that may later be called
1266
* @see org.mozilla.javascript.Function
1268
public final Function compileFunction(Scriptable scope, String source,
1269
String sourceName, int lineno,
1270
Object securityDomain)
1272
return compileFunction(scope, source, null, null, sourceName, lineno,
1276
final Function compileFunction(Scriptable scope, String source,
1278
ErrorReporter compilationErrorReporter,
1279
String sourceName, int lineno,
1280
Object securityDomain)
1283
return (Function) compileImpl(scope, null, source, sourceName,
1284
lineno, securityDomain, true,
1285
compiler, compilationErrorReporter);
1287
catch (IOException ioe) {
1288
// Should never happen because we just made the reader
1290
throw new RuntimeException();
1295
* Decompile the script.
1297
* The canonical source of the script is returned.
1299
* @param script the script to decompile
1300
* @param indent the number of spaces to indent the result
1301
* @return a string representing the script source
1303
public final String decompileScript(Script script, int indent)
1305
NativeFunction scriptImpl = (NativeFunction) script;
1306
return scriptImpl.decompile(indent, 0);
1310
* Decompile a JavaScript Function.
1312
* Decompiles a previously compiled JavaScript function object to
1315
* Returns function body of '[native code]' if no decompilation
1316
* information is available.
1318
* @param fun the JavaScript function to decompile
1319
* @param indent the number of spaces to indent the result
1320
* @return a string representing the function source
1322
public final String decompileFunction(Function fun, int indent)
1324
if (fun instanceof BaseFunction)
1325
return ((BaseFunction)fun).decompile(indent, 0);
1327
return "function " + fun.getClassName() +
1328
"() {\n\t[native code]\n}\n";
1332
* Decompile the body of a JavaScript Function.
1334
* Decompiles the body a previously compiled JavaScript Function
1335
* object to canonical source, omitting the function header and
1338
* Returns '[native code]' if no decompilation information is available.
1340
* @param fun the JavaScript function to decompile
1341
* @param indent the number of spaces to indent the result
1342
* @return a string representing the function body source.
1344
public final String decompileFunctionBody(Function fun, int indent)
1346
if (fun instanceof BaseFunction) {
1347
BaseFunction bf = (BaseFunction)fun;
1348
return bf.decompile(indent, Decompiler.ONLY_BODY_FLAG);
1350
// ALERT: not sure what the right response here is.
1351
return "[native code]\n";
1355
* Create a new JavaScript object.
1357
* Equivalent to evaluating "new Object()".
1358
* @param scope the scope to search for the constructor and to evaluate
1360
* @return the new object
1362
public final Scriptable newObject(Scriptable scope)
1364
return newObject(scope, "Object", ScriptRuntime.emptyArgs);
1368
* Create a new JavaScript object by executing the named constructor.
1370
* The call <code>newObject(scope, "Foo")</code> is equivalent to
1371
* evaluating "new Foo()".
1373
* @param scope the scope to search for the constructor and to evaluate against
1374
* @param constructorName the name of the constructor to call
1375
* @return the new object
1377
public final Scriptable newObject(Scriptable scope, String constructorName)
1379
return newObject(scope, constructorName, ScriptRuntime.emptyArgs);
1383
* Creates a new JavaScript object by executing the named constructor.
1385
* Searches <code>scope</code> for the named constructor, calls it with
1386
* the given arguments, and returns the result.<p>
1390
* Object[] args = { "a", "b" };
1391
* newObject(scope, "Foo", args)</pre>
1392
* is equivalent to evaluating "new Foo('a', 'b')", assuming that the Foo
1393
* constructor has been defined in <code>scope</code>.
1395
* @param scope The scope to search for the constructor and to evaluate
1397
* @param constructorName the name of the constructor to call
1398
* @param args the array of arguments for the constructor
1399
* @return the new object
1401
public final Scriptable newObject(Scriptable scope, String constructorName,
1404
scope = ScriptableObject.getTopLevelScope(scope);
1405
Function ctor = ScriptRuntime.getExistingCtor(this, scope,
1407
if (args == null) { args = ScriptRuntime.emptyArgs; }
1408
return ctor.construct(this, scope, args);
1412
* Create an array with a specified initial length.
1414
* @param scope the scope to create the object in
1415
* @param length the initial length (JavaScript arrays may have
1416
* additional properties added dynamically).
1417
* @return the new array object
1419
public final Scriptable newArray(Scriptable scope, int length)
1421
NativeArray result = new NativeArray(length);
1422
ScriptRuntime.setObjectProtoAndParent(result, scope);
1427
* Create an array with a set of initial elements.
1429
* @param scope the scope to create the object in.
1430
* @param elements the initial elements. Each object in this array
1431
* must be an acceptable JavaScript type and type
1432
* of array should be exactly Object[], not
1433
* SomeObjectSubclass[].
1434
* @return the new array object.
1436
public final Scriptable newArray(Scriptable scope, Object[] elements)
1438
if (elements.getClass().getComponentType() != ScriptRuntime.ObjectClass)
1439
throw new IllegalArgumentException();
1440
NativeArray result = new NativeArray(elements);
1441
ScriptRuntime.setObjectProtoAndParent(result, scope);
1446
* Get the elements of a JavaScript array.
1448
* If the object defines a length property convertible to double number,
1449
* then the number is converted Uint32 value as defined in Ecma 9.6
1450
* and Java array of that size is allocated.
1451
* The array is initialized with the values obtained by
1452
* calling get() on object for each value of i in [0,length-1]. If
1453
* there is not a defined value for a property the Undefined value
1454
* is used to initialize the corresponding element in the array. The
1455
* Java array is then returned.
1456
* If the object doesn't define a length property or it is not a number,
1457
* empty array is returned.
1458
* @param object the JavaScript array or array-like object
1459
* @return a Java array of objects
1460
* @since 1.4 release 2
1462
public final Object[] getElements(Scriptable object)
1464
return ScriptRuntime.getArrayElements(object);
1468
* Convert the value to a JavaScript boolean value.
1472
* @param value a JavaScript value
1473
* @return the corresponding boolean value converted using
1476
public static boolean toBoolean(Object value)
1478
return ScriptRuntime.toBoolean(value);
1482
* Convert the value to a JavaScript Number value.
1484
* Returns a Java double for the JavaScript Number.
1488
* @param value a JavaScript value
1489
* @return the corresponding double value converted using
1492
public static double toNumber(Object value)
1494
return ScriptRuntime.toNumber(value);
1498
* Convert the value to a JavaScript String value.
1502
* @param value a JavaScript value
1503
* @return the corresponding String value converted using
1506
public static String toString(Object value)
1508
return ScriptRuntime.toString(value);
1512
* Convert the value to an JavaScript object value.
1514
* Note that a scope must be provided to look up the constructors
1515
* for Number, Boolean, and String.
1519
* Additionally, arbitrary Java objects and classes will be
1520
* wrapped in a Scriptable object with its Java fields and methods
1521
* reflected as JavaScript properties of the object.
1523
* @param value any Java object
1524
* @param scope global scope containing constructors for Number,
1525
* Boolean, and String
1526
* @return new JavaScript object
1528
public static Scriptable toObject(Object value, Scriptable scope)
1530
return ScriptRuntime.toObject(scope, value);
1535
* @see #toObject(Object, Scriptable)
1537
public static Scriptable toObject(Object value, Scriptable scope,
1540
return ScriptRuntime.toObject(scope, value);
1544
* Convenient method to convert java value to its closest representation
1547
* If value is an instance of String, Number, Boolean, Function or
1548
* Scriptable, it is returned as it and will be treated as the corresponding
1549
* JavaScript type of string, number, boolean, function and object.
1551
* Note that for Number instances during any arithmetic operation in
1552
* JavaScript the engine will always use the result of
1553
* <tt>Number.doubleValue()</tt> resulting in a precision loss if
1554
* the number can not fit into double.
1556
* If value is an instance of Character, it will be converted to string of
1557
* length 1 and its JavaScript type will be string.
1559
* The rest of values will be wrapped as LiveConnect objects
1560
* by calling {@link WrapFactory#wrap(Context cx, Scriptable scope,
1561
* Object obj, Class staticType)} as in:
1563
* Context cx = Context.getCurrentContext();
1564
* return cx.getWrapFactory().wrap(cx, scope, value, null);
1567
* @param value any Java object
1568
* @param scope top scope object
1569
* @return value suitable to pass to any API that takes JavaScript values.
1571
public static Object javaToJS(Object value, Scriptable scope)
1573
if (value instanceof String || value instanceof Number
1574
|| value instanceof Boolean || value instanceof Scriptable)
1577
} else if (value instanceof Character) {
1578
return String.valueOf(((Character)value).charValue());
1580
Context cx = Context.getContext();
1581
return cx.getWrapFactory().wrap(cx, scope, value, null);
1586
* Convert a JavaScript value into the desired type.
1587
* Uses the semantics defined with LiveConnect3 and throws an
1588
* Illegal argument exception if the conversion cannot be performed.
1589
* @param value the JavaScript value to convert
1590
* @param desiredType the Java type to convert to. Primitive Java
1591
* types are represented using the TYPE fields in the corresponding
1592
* wrapper class in java.lang.
1593
* @return the converted value
1594
* @throws EvaluatorException if the conversion cannot be performed
1596
public static Object jsToJava(Object value, Class desiredType)
1597
throws EvaluatorException
1599
return NativeJavaObject.coerceTypeImpl(desiredType, value);
1604
* @see #jsToJava(Object, Class)
1605
* @throws IllegalArgumentException if the conversion cannot be performed.
1606
* Note that {@link #jsToJava(Object, Class)} throws
1607
* {@link EvaluatorException} instead.
1609
public static Object toType(Object value, Class desiredType)
1610
throws IllegalArgumentException
1613
return jsToJava(value, desiredType);
1614
} catch (EvaluatorException ex) {
1615
IllegalArgumentException
1616
ex2 = new IllegalArgumentException(ex.getMessage());
1617
Kit.initCause(ex2, ex);
1623
* Rethrow the exception wrapping it as the script runtime exception.
1624
* Unless the exception is instance of {@link EcmaError} or
1625
* {@link EvaluatorException} it will be wrapped as
1626
* {@link WrappedException}, a subclass of {@link EvaluatorException}.
1627
* The resulting exception object always contains
1628
* source name and line number of script that triggered exception.
1630
* This method always throws an exception, its return value is provided
1631
* only for convenience to allow a usage like:
1633
* throw Context.throwAsScriptRuntimeEx(ex);
1635
* to indicate that code after the method is unreachable.
1636
* @throws EvaluatorException
1639
public static RuntimeException throwAsScriptRuntimeEx(Throwable e)
1641
while ((e instanceof InvocationTargetException)) {
1642
e = ((InvocationTargetException) e).getTargetException();
1644
// special handling of Error so scripts would not catch them
1645
if (e instanceof Error) {
1646
Context cx = getContext();
1648
!cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS))
1653
if (e instanceof RhinoException) {
1654
throw (RhinoException)e;
1656
throw new WrappedException(e);
1660
* Tell whether debug information is being generated.
1663
public final boolean isGeneratingDebug()
1665
return generatingDebug;
1669
* Specify whether or not debug information should be generated.
1671
* Setting the generation of debug information on will set the
1672
* optimization level to zero.
1675
public final void setGeneratingDebug(boolean generatingDebug)
1677
if (sealed) onSealedMutation();
1678
generatingDebugChanged = true;
1679
if (generatingDebug && getOptimizationLevel() > 0)
1680
setOptimizationLevel(0);
1681
this.generatingDebug = generatingDebug;
1685
* Tell whether source information is being generated.
1688
public final boolean isGeneratingSource()
1690
return generatingSource;
1694
* Specify whether or not source information should be generated.
1696
* Without source information, evaluating the "toString" method
1697
* on JavaScript functions produces only "[native code]" for
1698
* the body of the function.
1699
* Note that code generated without source is not fully ECMA
1703
public final void setGeneratingSource(boolean generatingSource)
1705
if (sealed) onSealedMutation();
1706
this.generatingSource = generatingSource;
1710
* Get the current optimization level.
1712
* The optimization level is expressed as an integer between -1 and
1717
public final int getOptimizationLevel()
1719
return optimizationLevel;
1723
* Set the current optimization level.
1725
* The optimization level is expected to be an integer between -1 and
1726
* 9. Any negative values will be interpreted as -1, and any values
1727
* greater than 9 will be interpreted as 9.
1728
* An optimization level of -1 indicates that interpretive mode will
1729
* always be used. Levels 0 through 9 indicate that class files may
1730
* be generated. Higher optimization levels trade off compile time
1731
* performance for runtime performance.
1732
* The optimizer level can't be set greater than -1 if the optimizer
1733
* package doesn't exist at run time.
1734
* @param optimizationLevel an integer indicating the level of
1735
* optimization to perform
1739
public final void setOptimizationLevel(int optimizationLevel)
1741
if (sealed) onSealedMutation();
1742
if (optimizationLevel == -2) {
1743
// To be compatible with Cocoon fork
1744
optimizationLevel = -1;
1746
checkOptimizationLevel(optimizationLevel);
1747
if (codegenClass == null)
1748
optimizationLevel = -1;
1749
this.optimizationLevel = optimizationLevel;
1752
public static boolean isValidOptimizationLevel(int optimizationLevel)
1754
return -1 <= optimizationLevel && optimizationLevel <= 9;
1757
public static void checkOptimizationLevel(int optimizationLevel)
1759
if (isValidOptimizationLevel(optimizationLevel)) {
1762
throw new IllegalArgumentException(
1763
"Optimization level outside [-1..9]: "+optimizationLevel);
1767
* Returns the maximum stack depth (in terms of number of call frames)
1768
* allowed in a single invocation of interpreter. If the set depth would be
1769
* exceeded, the interpreter will throw an EvaluatorException in the script.
1770
* Defaults to Integer.MAX_VALUE. The setting only has effect for
1771
* interpreted functions (those compiled with optimization level set to -1).
1772
* As the interpreter doesn't use the Java stack but rather manages its own
1773
* stack in the heap memory, a runaway recursion in interpreted code would
1774
* eventually consume all available memory and cause OutOfMemoryError
1775
* instead of a StackOverflowError limited to only a single thread. This
1776
* setting helps prevent such situations.
1778
* @return The current maximum interpreter stack depth.
1780
public final int getMaximumInterpreterStackDepth()
1782
return maximumInterpreterStackDepth;
1786
* Sets the maximum stack depth (in terms of number of call frames)
1787
* allowed in a single invocation of interpreter. If the set depth would be
1788
* exceeded, the interpreter will throw an EvaluatorException in the script.
1789
* Defaults to Integer.MAX_VALUE. The setting only has effect for
1790
* interpreted functions (those compiled with optimization level set to -1).
1791
* As the interpreter doesn't use the Java stack but rather manages its own
1792
* stack in the heap memory, a runaway recursion in interpreted code would
1793
* eventually consume all available memory and cause OutOfMemoryError
1794
* instead of a StackOverflowError limited to only a single thread. This
1795
* setting helps prevent such situations.
1797
* @param max the new maximum interpreter stack depth
1798
* @throws IllegalStateException if this context's optimization level is not
1800
* @throws IllegalArgumentException if the new depth is not at least 1
1802
public final void setMaximumInterpreterStackDepth(int max)
1804
if(sealed) onSealedMutation();
1805
if(optimizationLevel != -1) {
1806
throw new IllegalStateException("Cannot set maximumInterpreterStackDepth when optimizationLevel != -1");
1809
throw new IllegalArgumentException("Cannot set maximumInterpreterStackDepth to less than 1");
1811
maximumInterpreterStackDepth = max;
1815
* Set the security controller for this context.
1816
* <p> SecurityController may only be set if it is currently null
1817
* and {@link SecurityController#hasGlobal()} is <tt>false</tt>.
1818
* Otherwise a SecurityException is thrown.
1819
* @param controller a SecurityController object
1820
* @throws SecurityException if there is already a SecurityController
1821
* object for this Context or globally installed.
1822
* @see SecurityController#initGlobal(SecurityController controller)
1823
* @see SecurityController#hasGlobal()
1825
public final void setSecurityController(SecurityController controller)
1827
if (sealed) onSealedMutation();
1828
if (controller == null) throw new IllegalArgumentException();
1829
if (securityController != null) {
1830
throw new SecurityException("Can not overwrite existing SecurityController object");
1832
if (SecurityController.hasGlobal()) {
1833
throw new SecurityException("Can not overwrite existing global SecurityController object");
1835
securityController = controller;
1839
* Set the LiveConnect access filter for this context.
1840
* <p> {@link ClassShutter} may only be set if it is currently null.
1841
* Otherwise a SecurityException is thrown.
1842
* @param shutter a ClassShutter object
1843
* @throws SecurityException if there is already a ClassShutter
1844
* object for this Context
1846
public final void setClassShutter(ClassShutter shutter)
1848
if (sealed) onSealedMutation();
1849
if (shutter == null) throw new IllegalArgumentException();
1850
if (classShutter != null) {
1851
throw new SecurityException("Cannot overwrite existing " +
1852
"ClassShutter object");
1854
classShutter = shutter;
1857
final ClassShutter getClassShutter()
1859
return classShutter;
1863
* Get a value corresponding to a key.
1865
* Since the Context is associated with a thread it can be
1866
* used to maintain values that can be later retrieved using
1867
* the current thread.
1869
* Note that the values are maintained with the Context, so
1870
* if the Context is disassociated from the thread the values
1871
* cannot be retrieved. Also, if private data is to be maintained
1872
* in this manner the key should be a java.lang.Object
1873
* whose reference is not divulged to untrusted code.
1874
* @param key the key used to lookup the value
1875
* @return a value previously stored using putThreadLocal.
1877
public final Object getThreadLocal(Object key)
1879
if (hashtable == null)
1881
return hashtable.get(key);
1885
* Put a value that can later be retrieved using a given key.
1887
* @param key the key used to index the value
1888
* @param value the value to save
1890
public final void putThreadLocal(Object key, Object value)
1892
if (sealed) onSealedMutation();
1893
if (hashtable == null)
1894
hashtable = new Hashtable();
1895
hashtable.put(key, value);
1899
* Remove values from thread-local storage.
1900
* @param key the key for the entry to remove.
1901
* @since 1.5 release 2
1903
public final void removeThreadLocal(Object key)
1905
if (sealed) onSealedMutation();
1906
if (hashtable == null)
1908
hashtable.remove(key);
1913
* @see #FEATURE_DYNAMIC_SCOPE
1914
* @see #hasFeature(int)
1916
public final boolean hasCompileFunctionsWithDynamicScope()
1918
return compileFunctionsWithDynamicScopeFlag;
1923
* @see #FEATURE_DYNAMIC_SCOPE
1924
* @see #hasFeature(int)
1926
public final void setCompileFunctionsWithDynamicScope(boolean flag)
1928
if (sealed) onSealedMutation();
1929
compileFunctionsWithDynamicScopeFlag = flag;
1934
* @see ClassCache#get(Scriptable)
1935
* @see ClassCache#setCachingEnabled(boolean)
1937
public static void setCachingEnabled(boolean cachingEnabled)
1942
* Set a WrapFactory for this Context.
1944
* The WrapFactory allows custom object wrapping behavior for
1945
* Java object manipulated with JavaScript.
1947
* @since 1.5 Release 4
1949
public final void setWrapFactory(WrapFactory wrapFactory)
1951
if (sealed) onSealedMutation();
1952
if (wrapFactory == null) throw new IllegalArgumentException();
1953
this.wrapFactory = wrapFactory;
1957
* Return the current WrapFactory, or null if none is defined.
1959
* @since 1.5 Release 4
1961
public final WrapFactory getWrapFactory()
1963
if (wrapFactory == null) {
1964
wrapFactory = new WrapFactory();
1970
* Return the current debugger.
1971
* @return the debugger, or null if none is attached.
1973
public final Debugger getDebugger()
1979
* Return the debugger context data associated with current context.
1980
* @return the debugger data, or null if debugger is not attached
1982
public final Object getDebuggerContextData()
1984
return debuggerData;
1988
* Set the associated debugger.
1989
* @param debugger the debugger to be used on callbacks from
1991
* @param contextData arbitrary object that debugger can use to store
1994
public final void setDebugger(Debugger debugger, Object contextData)
1996
if (sealed) onSealedMutation();
1997
this.debugger = debugger;
1998
debuggerData = contextData;
2002
* Return DebuggableScript instance if any associated with the script.
2003
* If callable supports DebuggableScript implementation, the method
2004
* returns it. Otherwise null is returned.
2006
public static DebuggableScript getDebuggableView(Script script)
2008
if (script instanceof NativeFunction) {
2009
return ((NativeFunction)script).getDebuggableView();
2015
* Controls certain aspects of script semantics.
2016
* Should be overwritten to alter default behavior.
2018
* The default implementation calls
2019
* {@link ContextFactory#hasFeature(Context cx, int featureIndex)}
2020
* that allows to customize Context behavior without introducing
2021
* Context subclasses. {@link ContextFactory} documentation gives
2022
* an example of hasFeature implementation.
2024
* @param featureIndex feature index to check
2025
* @return true if the <code>featureIndex</code> feature is turned on
2026
* @see #FEATURE_NON_ECMA_GET_YEAR
2027
* @see #FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME
2028
* @see #FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER
2029
* @see #FEATURE_TO_STRING_AS_SOURCE
2030
* @see #FEATURE_PARENT_PROTO_PROPRTIES
2032
* @see #FEATURE_DYNAMIC_SCOPE
2033
* @see #FEATURE_STRICT_VARS
2034
* @see #FEATURE_STRICT_EVAL
2035
* @see #FEATURE_LOCATION_INFORMATION_IN_ERROR
2036
* @see #FEATURE_STRICT_MODE
2037
* @see #FEATURE_WARNING_AS_ERROR
2038
* @see #FEATURE_ENHANCED_JAVA_ACCESS
2040
public boolean hasFeature(int featureIndex)
2042
ContextFactory f = getFactory();
2043
return f.hasFeature(this, featureIndex);
2047
Returns an object which specifies an E4X implementation to use within
2048
this <code>Context</code>. Note
2049
that the XMLLib.Factory interface should be considered experimental.
2051
The default implementation uses the implementation provided by this
2052
<code>Context</code>'s {@link ContextFactory}.
2054
@return An XMLLib.Factory. Should not return <code>null</code> if
2055
{@link #FEATURE_E4X} is enabled. See {@link #hasFeature}.
2057
public XMLLib.Factory getE4xImplementationFactory() {
2058
return getFactory().getE4xImplementationFactory();
2062
* Get threshold of executed instructions counter that triggers call to
2063
* <code>observeInstructionCount()</code>.
2064
* When the threshold is zero, instruction counting is disabled,
2065
* otherwise each time the run-time executes at least the threshold value
2066
* of script instructions, <code>observeInstructionCount()</code> will
2069
public final int getInstructionObserverThreshold()
2071
return instructionThreshold;
2075
* Set threshold of executed instructions counter that triggers call to
2076
* <code>observeInstructionCount()</code>.
2077
* When the threshold is zero, instruction counting is disabled,
2078
* otherwise each time the run-time executes at least the threshold value
2079
* of script instructions, <code>observeInstructionCount()</code> will
2081
* Note that the meaning of "instruction" is not guaranteed to be
2082
* consistent between compiled and interpretive modes: executing a given
2083
* script or function in the different modes will result in different
2084
* instruction counts against the threshold.
2085
* {@link #setGenerateObserverCount} is called with true if
2086
* <code>threshold</code> is greater than zero, false otherwise.
2087
* @param threshold The instruction threshold
2089
public final void setInstructionObserverThreshold(int threshold)
2091
if (sealed) onSealedMutation();
2092
if (threshold < 0) throw new IllegalArgumentException();
2093
instructionThreshold = threshold;
2094
setGenerateObserverCount(threshold > 0);
2098
* Turn on or off generation of code with callbacks to
2099
* track the count of executed instructions.
2100
* Currently only affects JVM byte code generation: this slows down the
2101
* generated code, but code generated without the callbacks will not
2102
* be counted toward instruction thresholds. Rhino's interpretive
2103
* mode does instruction counting without inserting callbacks, so
2104
* there is no requirement to compile code differently.
2105
* @param generateObserverCount if true, generated code will contain
2106
* calls to accumulate an estimate of the instructions executed.
2108
public void setGenerateObserverCount(boolean generateObserverCount) {
2109
this.generateObserverCount = generateObserverCount;
2113
* Allow application to monitor counter of executed script instructions
2114
* in Context subclasses.
2115
* Run-time calls this when instruction counting is enabled and the counter
2116
* reaches limit set by <code>setInstructionObserverThreshold()</code>.
2117
* The method is useful to observe long running scripts and if necessary
2118
* to terminate them.
2120
* The instruction counting support is available only for interpreted
2121
* scripts generated when the optimization level is set to -1.
2123
* The default implementation calls
2124
* {@link ContextFactory#observeInstructionCount(Context cx,
2125
* int instructionCount)}
2126
* that allows to customize Context behavior without introducing
2127
* Context subclasses.
2129
* @param instructionCount amount of script instruction executed since
2130
* last call to <code>observeInstructionCount</code>
2131
* @throws Error to terminate the script
2132
* @see #setOptimizationLevel(int)
2134
protected void observeInstructionCount(int instructionCount)
2136
ContextFactory f = getFactory();
2137
f.observeInstructionCount(this, instructionCount);
2141
* Create class loader for generated classes.
2142
* The method calls {@link ContextFactory#createClassLoader(ClassLoader)}
2143
* using the result of {@link #getFactory()}.
2145
public GeneratedClassLoader createClassLoader(ClassLoader parent)
2147
ContextFactory f = getFactory();
2148
return f.createClassLoader(parent);
2151
public final ClassLoader getApplicationClassLoader()
2153
if (applicationClassLoader == null) {
2154
ContextFactory f = getFactory();
2155
ClassLoader loader = f.getApplicationClassLoader();
2156
if (loader == null) {
2157
ClassLoader threadLoader
2158
= VMBridge.instance.getCurrentThreadClassLoader();
2159
if (threadLoader != null
2160
&& Kit.testIfCanLoadRhinoClasses(threadLoader))
2162
// Thread.getContextClassLoader is not cached since
2163
// its caching prevents it from GC which may lead to
2164
// a memory leak and hides updates to
2165
// Thread.getContextClassLoader
2166
return threadLoader;
2168
// Thread.getContextClassLoader can not load Rhino classes,
2169
// try to use the loader of ContextFactory or Context
2171
Class fClass = f.getClass();
2172
if (fClass != ScriptRuntime.ContextFactoryClass) {
2173
loader = fClass.getClassLoader();
2175
loader = getClass().getClassLoader();
2178
applicationClassLoader = loader;
2180
return applicationClassLoader;
2183
public final void setApplicationClassLoader(ClassLoader loader)
2185
if (sealed) onSealedMutation();
2186
if (loader == null) {
2187
// restore default behaviour
2188
applicationClassLoader = null;
2191
if (!Kit.testIfCanLoadRhinoClasses(loader)) {
2192
throw new IllegalArgumentException(
2193
"Loader can not resolve Rhino classes");
2195
applicationClassLoader = loader;
2198
/********** end of API **********/
2201
* Internal method that reports an error for missing calls to
2204
static Context getContext()
2206
Context cx = getCurrentContext();
2208
throw new RuntimeException(
2209
"No Context associated with current Thread");
2214
private Object compileImpl(Scriptable scope,
2215
Reader sourceReader, String sourceString,
2216
String sourceName, int lineno,
2217
Object securityDomain, boolean returnFunction,
2219
ErrorReporter compilationErrorReporter)
2222
if(sourceName == null) {
2223
sourceName = "unnamed script";
2225
if (securityDomain != null && getSecurityController() == null) {
2226
throw new IllegalArgumentException(
2227
"securityDomain should be null if setSecurityController() was never called");
2230
// One of sourceReader or sourceString has to be null
2231
if (!(sourceReader == null ^ sourceString == null)) Kit.codeBug();
2232
// scope should be given if and only if compiling function
2233
if (!(scope == null ^ returnFunction)) Kit.codeBug();
2235
CompilerEnvirons compilerEnv = new CompilerEnvirons();
2236
compilerEnv.initFromContext(this);
2237
if (compilationErrorReporter == null) {
2238
compilationErrorReporter = compilerEnv.getErrorReporter();
2241
if (debugger != null) {
2242
if (sourceReader != null) {
2243
sourceString = Kit.readReader(sourceReader);
2244
sourceReader = null;
2249
Parser p = InformativeParser.makeParser(compilerEnv,
2250
compilationErrorReporter);
2251
if (returnFunction) {
2252
p.calledByCompileFunction = true;
2254
ScriptOrFnNode tree;
2255
if (sourceString != null) {
2256
tree = p.parse(sourceString, sourceName, lineno);
2258
tree = p.parse(sourceReader, sourceName, lineno);
2260
if (returnFunction) {
2261
if (!(tree.getFunctionCount() == 1
2262
&& tree.getFirstChild() != null
2263
&& tree.getFirstChild().getType() == Token.FUNCTION))
2265
// XXX: the check just look for the first child
2266
// and allows for more nodes after it for compatibility
2267
// with sources like function() {};;;
2268
throw new IllegalArgumentException(
2269
"compileFunction only accepts source with single JS function: "+sourceString);
2273
if (compiler == null) {
2274
compiler = createCompiler();
2277
String encodedSource = p.getEncodedSource();
2279
Object bytecode = compiler.compile(compilerEnv,
2280
tree, encodedSource,
2283
if (debugger != null) {
2284
if (sourceString == null) Kit.codeBug();
2285
if (bytecode instanceof DebuggableScript) {
2286
DebuggableScript dscript = (DebuggableScript)bytecode;
2287
notifyDebugger_r(this, dscript, sourceString);
2289
throw new RuntimeException("NOT SUPPORTED");
2294
if (returnFunction) {
2295
result = compiler.createFunctionObject(this, scope, bytecode, securityDomain);
2297
result = compiler.createScriptObject(bytecode, securityDomain);
2303
private static void notifyDebugger_r(Context cx, DebuggableScript dscript,
2306
cx.debugger.handleCompilationDone(cx, dscript, debugSource);
2307
for (int i = 0; i != dscript.getFunctionCount(); ++i) {
2308
notifyDebugger_r(cx, dscript.getFunction(i), debugSource);
2312
private static Class codegenClass = Kit.classOrNull(
2313
"org.mozilla.javascript.optimizer.Codegen");
2314
private static Class interpreterClass = Kit.classOrNull(
2315
"org.mozilla.javascript.Interpreter");
2317
private Evaluator createCompiler()
2319
Evaluator result = null;
2320
if (optimizationLevel >= 0 && codegenClass != null) {
2321
result = (Evaluator)Kit.newInstanceOrNull(codegenClass);
2323
if (result == null) {
2324
result = createInterpreter();
2329
static Evaluator createInterpreter()
2331
return (Evaluator)Kit.newInstanceOrNull(interpreterClass);
2334
static String getSourcePositionFromStack(int[] linep)
2336
Context cx = getCurrentContext();
2339
if (cx.lastInterpreterFrame != null) {
2340
Evaluator evaluator = createInterpreter();
2341
if (evaluator != null)
2342
return evaluator.getSourcePositionFromStack(cx, linep);
2345
* A bit of a hack, but the only way to get filename and line
2346
* number from an enclosing frame.
2348
CharArrayWriter writer = new CharArrayWriter();
2349
RuntimeException re = new RuntimeException();
2350
re.printStackTrace(new PrintWriter(writer));
2351
String s = writer.toString();
2355
for (int i=0; i < s.length(); i++) {
2356
char c = s.charAt(i);
2363
else if (c == '\n' && open != -1 && close != -1 && colon != -1 &&
2364
open < colon && colon < close)
2366
String fileStr = s.substring(open + 1, colon);
2367
if (!fileStr.endsWith(".java")) {
2368
String lineStr = s.substring(colon + 1, close);
2370
linep[0] = Integer.parseInt(lineStr);
2376
catch (NumberFormatException e) {
2380
open = close = colon = -1;
2387
RegExpProxy getRegExpProxy()
2389
if (regExpProxy == null) {
2390
Class cl = Kit.classOrNull(
2391
"org.mozilla.javascript.regexp.RegExpImpl");
2393
regExpProxy = (RegExpProxy)Kit.newInstanceOrNull(cl);
2399
final boolean isVersionECMA1()
2401
return version == VERSION_DEFAULT || version >= VERSION_1_3;
2404
// The method must NOT be public or protected
2405
SecurityController getSecurityController()
2407
SecurityController global = SecurityController.global();
2408
if (global != null) {
2411
return securityController;
2414
public final boolean isGeneratingDebugChanged()
2416
return generatingDebugChanged;
2420
* Add a name to the list of names forcing the creation of real
2421
* activation objects for functions.
2423
* @param name the name of the object to add to the list
2425
public void addActivationName(String name)
2427
if (sealed) onSealedMutation();
2428
if (activationNames == null)
2429
activationNames = new Hashtable(5);
2430
activationNames.put(name, name);
2434
* Check whether the name is in the list of names of objects
2435
* forcing the creation of activation objects.
2437
* @param name the name of the object to test
2439
* @return true if an function activation object is needed.
2441
public final boolean isActivationNeeded(String name)
2443
return activationNames != null && activationNames.containsKey(name);
2447
* Remove a name from the list of names forcing the creation of real
2448
* activation objects for functions.
2450
* @param name the name of the object to remove from the list
2452
public void removeActivationName(String name)
2454
if (sealed) onSealedMutation();
2455
if (activationNames != null)
2456
activationNames.remove(name);
2459
private static String implementationVersion;
2461
private final ContextFactory factory;
2462
private boolean sealed;
2463
private Object sealKey;
2465
Scriptable topCallScope;
2466
NativeCall currentActivationCall;
2467
XMLLib cachedXMLLib;
2469
// for Objects, Arrays to tag themselves as being printed out,
2470
// so they don't print themselves out recursively.
2471
// Use ObjToIntMap instead of java.util.HashSet for JDK 1.1 compatibility
2472
ObjToIntMap iterating;
2474
Object interpreterSecurityDomain;
2478
private SecurityController securityController;
2479
private ClassShutter classShutter;
2480
private ErrorReporter errorReporter;
2481
RegExpProxy regExpProxy;
2482
private Locale locale;
2483
private boolean generatingDebug;
2484
private boolean generatingDebugChanged;
2485
private boolean generatingSource=true;
2486
boolean compileFunctionsWithDynamicScopeFlag;
2487
boolean useDynamicScope;
2488
private int optimizationLevel;
2489
private int maximumInterpreterStackDepth;
2490
private WrapFactory wrapFactory;
2492
private Object debuggerData;
2493
private int enterCount;
2494
private Object propertyListeners;
2495
private Hashtable hashtable;
2496
private ClassLoader applicationClassLoader;
2499
* This is the list of names of objects forcing the creation of
2500
* function activation records.
2502
Hashtable activationNames;
2504
// For the interpreter to store the last frame for error reports etc.
2505
Object lastInterpreterFrame;
2507
// For the interpreter to store information about previous invocations
2508
// interpreter invocations
2509
ObjArray previousInterpreterInvocations;
2511
// For instruction counting (interpreter only)
2512
int instructionCount;
2513
int instructionThreshold;
2515
// It can be used to return the second index-like result from function
2518
// It can be used to return the second uint32 result from function
2521
// It can be used to return the second Scriptable result from function
2522
Scriptable scratchScriptable;
2524
// Generate an observer count on compiled code
2525
public boolean generateObserverCount = false;