Source Code Cross Referenced for Context.java in  » Scripting » rhino » org » mozilla » javascript » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » rhino » org.mozilla.javascript 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002:         *
0003:         * ***** BEGIN LICENSE BLOCK *****
0004:         * Version: MPL 1.1/GPL 2.0
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version
0007:         * 1.1 (the "License"); you may not use this file except in compliance with
0008:         * the License. You may obtain a copy of the License at
0009:         * http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the
0014:         * License.
0015:         *
0016:         * The Original Code is Rhino code, released
0017:         * May 6, 1999.
0018:         *
0019:         * The Initial Developer of the Original Code is
0020:         * Netscape Communications Corporation.
0021:         * Portions created by the Initial Developer are Copyright (C) 1997-2000
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *    Bob Jervis
0026:         *
0027:         * Alternatively, the contents of this file may be used under the terms of
0028:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0029:         * case the provisions of the GPL are applicable instead of those above. If
0030:         * you wish to allow use of your version of this file only under the terms of
0031:         * the GPL and not to allow others to use your version of this file under the
0032:         * MPL, indicate your decision by deleting the provisions above and replacing
0033:         * them with the notice and other provisions required by the GPL. If you do
0034:         * not delete the provisions above, a recipient may use your version of this
0035:         * file under either the MPL or the GPL.
0036:         *
0037:         * ***** END LICENSE BLOCK ***** */
0038:
0039:        // API class
0040:        package org.mozilla.javascript;
0041:
0042:        import java.beans.PropertyChangeEvent;
0043:        import java.beans.PropertyChangeListener;
0044:        import java.io.CharArrayWriter;
0045:        import java.io.IOException;
0046:        import java.io.PrintWriter;
0047:        import java.io.Reader;
0048:        import java.io.StringWriter;
0049:        import java.io.Writer;
0050:        import java.lang.reflect.InvocationTargetException;
0051:        import java.lang.reflect.Method;
0052:        import java.util.Hashtable;
0053:        import java.util.Locale;
0054:
0055:        import org.mozilla.javascript.debug.DebuggableScript;
0056:        import org.mozilla.javascript.debug.Debugger;
0057:        import org.mozilla.javascript.xml.XMLLib;
0058:
0059:        /**
0060:         * This class represents the runtime context of an executing script.
0061:         *
0062:         * Before executing a script, an instance of Context must be created
0063:         * and associated with the thread that will be executing the script.
0064:         * The Context will be used to store information about the executing
0065:         * of the script such as the call stack. Contexts are associated with
0066:         * the current thread  using the {@link #call(ContextAction)}
0067:         * or {@link #enter()} methods.<p>
0068:         *
0069:         * Different forms of script execution are supported. Scripts may be
0070:         * evaluated from the source directly, or first compiled and then later
0071:         * executed. Interactive execution is also supported.<p>
0072:         *
0073:         * Some aspects of script execution, such as type conversions and
0074:         * object creation, may be accessed directly through methods of
0075:         * Context.
0076:         *
0077:         * @see Scriptable
0078:         * @author Norris Boyd
0079:         * @author Brendan Eich
0080:         */
0081:
0082:        public class Context {
0083:            /**
0084:             * Language versions.
0085:             *
0086:             * All integral values are reserved for future version numbers.
0087:             */
0088:
0089:            /**
0090:             * The unknown version.
0091:             */
0092:            public static final int VERSION_UNKNOWN = -1;
0093:
0094:            /**
0095:             * The default version.
0096:             */
0097:            public static final int VERSION_DEFAULT = 0;
0098:
0099:            /**
0100:             * JavaScript 1.0
0101:             */
0102:            public static final int VERSION_1_0 = 100;
0103:
0104:            /**
0105:             * JavaScript 1.1
0106:             */
0107:            public static final int VERSION_1_1 = 110;
0108:
0109:            /**
0110:             * JavaScript 1.2
0111:             */
0112:            public static final int VERSION_1_2 = 120;
0113:
0114:            /**
0115:             * JavaScript 1.3
0116:             */
0117:            public static final int VERSION_1_3 = 130;
0118:
0119:            /**
0120:             * JavaScript 1.4
0121:             */
0122:            public static final int VERSION_1_4 = 140;
0123:
0124:            /**
0125:             * JavaScript 1.5
0126:             */
0127:            public static final int VERSION_1_5 = 150;
0128:
0129:            /**
0130:             * JavaScript 1.6
0131:             */
0132:            public static final int VERSION_1_6 = 160;
0133:
0134:            /**
0135:             * JavaScript 1.7
0136:             */
0137:            public static final int VERSION_1_7 = 170;
0138:
0139:            /**
0140:             * Controls behaviour of <tt>Date.prototype.getYear()</tt>.
0141:             * If <tt>hasFeature(FEATURE_NON_ECMA_GET_YEAR)</tt> returns true,
0142:             * Date.prototype.getYear subtructs 1900 only if 1900 <= date < 2000.
0143:             * The default behavior of {@link #hasFeature(int)} is always to subtruct
0144:             * 1900 as rquired by ECMAScript B.2.4.
0145:             */
0146:            public static final int FEATURE_NON_ECMA_GET_YEAR = 1;
0147:
0148:            /**
0149:             * Control if member expression as function name extension is available.
0150:             * If <tt>hasFeature(FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)</tt> returns
0151:             * true, allow <tt>function memberExpression(args) { body }</tt> to be
0152:             * syntax sugar for <tt>memberExpression = function(args) { body }</tt>,
0153:             * when memberExpression is not a simple identifier.
0154:             * See ECMAScript-262, section 11.2 for definition of memberExpression.
0155:             * By default {@link #hasFeature(int)} returns false.
0156:             */
0157:            public static final int FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME = 2;
0158:
0159:            /**
0160:             * Control if reserved keywords are treated as identifiers.
0161:             * If <tt>hasFeature(RESERVED_KEYWORD_AS_IDENTIFIER)</tt> returns true,
0162:             * treat future reserved keyword (see  Ecma-262, section 7.5.3) as ordinary
0163:             * identifiers but warn about this usage.
0164:             *
0165:             * By default {@link #hasFeature(int)} returns false.
0166:             */
0167:            public static final int FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER = 3;
0168:
0169:            /**
0170:             * Control if <tt>toString()</tt> should returns the same result
0171:             * as  <tt>toSource()</tt> when applied to objects and arrays.
0172:             * If <tt>hasFeature(FEATURE_TO_STRING_AS_SOURCE)</tt> returns true,
0173:             * calling <tt>toString()</tt> on JS objects gives the same result as
0174:             * calling <tt>toSource()</tt>. That is it returns JS source with code
0175:             * to create an object with all enumeratable fields of the original object
0176:             * instead of printing <tt>[object <i>result of
0177:             * {@link Scriptable#getClassName()}</i>]</tt>.
0178:             * <p>
0179:             * By default {@link #hasFeature(int)} returns true only if
0180:             * the current JS version is set to {@link #VERSION_1_2}.
0181:             */
0182:            public static final int FEATURE_TO_STRING_AS_SOURCE = 4;
0183:
0184:            /**
0185:             * Control if properties <tt>__proto__</tt> and <tt>__parent__</tt>
0186:             * are treated specially.
0187:             * If <tt>hasFeature(FEATURE_PARENT_PROTO_PROPERTIES)</tt> returns true,
0188:             * treat <tt>__parent__</tt> and <tt>__proto__</tt> as special properties.
0189:             * <p>
0190:             * The properties allow to query and set scope and prototype chains for the
0191:             * objects. The special meaning of the properties is available
0192:             * only when they are used as the right hand side of the dot operator.
0193:             * For example, while <tt>x.__proto__ = y</tt> changes the prototype
0194:             * chain of the object <tt>x</tt> to point to <tt>y</tt>,
0195:             * <tt>x["__proto__"] = y</tt> simply assigns a new value to the property
0196:             * <tt>__proto__</tt> in <tt>x</tt> even when the feature is on.
0197:             *
0198:             * By default {@link #hasFeature(int)} returns true.
0199:             */
0200:            public static final int FEATURE_PARENT_PROTO_PROPERTIES = 5;
0201:
0202:            /**
0203:             * @deprecated In previous releases, this name was given to
0204:             * FEATURE_PARENT_PROTO_PROPERTIES.
0205:             */
0206:            public static final int FEATURE_PARENT_PROTO_PROPRTIES = 5;
0207:
0208:            /**
0209:             * Control if support for E4X(ECMAScript for XML) extension is available.
0210:             * If hasFeature(FEATURE_E4X) returns true, the XML syntax is available.
0211:             * <p>
0212:             * By default {@link #hasFeature(int)} returns true if
0213:             * the current JS version is set to {@link #VERSION_DEFAULT}
0214:             * or is at least {@link #VERSION_1_6}.
0215:             * @since 1.6 Release 1
0216:             */
0217:            public static final int FEATURE_E4X = 6;
0218:
0219:            /**
0220:             * Control if dynamic scope should be used for name access.
0221:             * If hasFeature(FEATURE_DYNAMIC_SCOPE) returns true, then the name lookup
0222:             * during name resolution will use the top scope of the script or function
0223:             * which is at the top of JS execution stack instead of the top scope of the
0224:             * script or function from the current stack frame if the top scope of
0225:             * the top stack frame contains the top scope of the current stack frame
0226:             * on its prototype chain.
0227:             * <p>
0228:             * This is useful to define shared scope containing functions that can
0229:             * be called from scripts and functions using private scopes.
0230:             * <p>
0231:             * By default {@link #hasFeature(int)} returns false.
0232:             * @since 1.6 Release 1
0233:             */
0234:            public static final int FEATURE_DYNAMIC_SCOPE = 7;
0235:
0236:            /**
0237:             * Control if strict variable mode is enabled.
0238:             * When the feature is on Rhino reports runtime errors if assignment
0239:             * to a global variable that does not exist is executed. When the feature
0240:             * is off such assignments creates new variable in the global scope  as
0241:             * required by ECMA 262.
0242:             * <p>
0243:             * By default {@link #hasFeature(int)} returns false.
0244:             * @since 1.6 Release 1
0245:             */
0246:            public static final int FEATURE_STRICT_VARS = 8;
0247:
0248:            /**
0249:             * Control if strict eval mode is enabled.
0250:             * When the feature is on Rhino reports runtime errors if non-string
0251:             * argument is passed to the eval function. When the feature is off
0252:             * eval simply return non-string argument as is without performing any
0253:             * evaluation as required by ECMA 262.
0254:             * <p>
0255:             * By default {@link #hasFeature(int)} returns false.
0256:             * @since 1.6 Release 1
0257:             */
0258:            public static final int FEATURE_STRICT_EVAL = 9;
0259:
0260:            /**
0261:             * When the feature is on Rhino will add a "fileName" and "lineNumber"
0262:             * properties to Error objects automatically. When the feature is off, you
0263:             * have to explicitly pass them as the second and third argument to the
0264:             * Error constructor. Note that neither behaviour is fully ECMA 262 
0265:             * compliant (as 262 doesn't specify a three-arg constructor), but keeping 
0266:             * the feature off results in Error objects that don't have
0267:             * additional non-ECMA properties when constructed using the ECMA-defined
0268:             * single-arg constructor and is thus desirable if a stricter ECMA 
0269:             * compliance is desired, specifically adherence to the point 15.11.5. of
0270:             * the standard.
0271:             * <p>
0272:             * By default {@link #hasFeature(int)} returns false.
0273:             * @since 1.6 Release 6
0274:             */
0275:            public static final int FEATURE_LOCATION_INFORMATION_IN_ERROR = 10;
0276:
0277:            /**
0278:             * Controls whether JS 1.5 'strict mode' is enabled.
0279:             * When the feature is on, Rhino reports more than a dozen different
0280:             * warnings.  When the feature is off, these warnings are not generated.
0281:             * FEATURE_STRICT_MODE implies FEATURE_STRICT_VARS and FEATURE_STRICT_EVAL.
0282:             * <p>
0283:             * By default {@link #hasFeature(int)} returns false.
0284:             * @since 1.6 Release 6
0285:             */
0286:            public static final int FEATURE_STRICT_MODE = 11;
0287:
0288:            /**
0289:             * Controls whether a warning should be treated as an error.
0290:             * @since 1.6 Release 6
0291:             */
0292:            public static final int FEATURE_WARNING_AS_ERROR = 12;
0293:
0294:            /**
0295:             * Enables enhanced access to Java. 
0296:             * Specifically, controls whether private and protected members can be
0297:             * accessed, and whether scripts can catch all Java exceptions.
0298:             * <p>
0299:             * Note that this feature should only be enabled for trusted scripts.
0300:             * <p>
0301:             * By default {@link #hasFeature(int)} returns false.
0302:             * @since 1.7 Release 1
0303:             */
0304:            public static final int FEATURE_ENHANCED_JAVA_ACCESS = 13;
0305:
0306:            public static final String languageVersionProperty = "language version";
0307:            public static final String errorReporterProperty = "error reporter";
0308:
0309:            /**
0310:             * Convenient value to use as zero-length array of objects.
0311:             */
0312:            public static final Object[] emptyArgs = ScriptRuntime.emptyArgs;
0313:
0314:            /**
0315:             * Create a new Context.
0316:             *
0317:             * Note that the Context must be associated with a thread before
0318:             * it can be used to execute a script.
0319:             * @deprecated use {@link ContextFactory#enter()} or 
0320:             * {@link ContextFactory#call(ContextAction)} instead.
0321:             */
0322:            public Context() {
0323:                this (ContextFactory.getGlobal());
0324:            }
0325:
0326:            Context(ContextFactory factory) {
0327:                assert factory != null;
0328:                this .factory = factory;
0329:                setLanguageVersion(VERSION_DEFAULT);
0330:                optimizationLevel = codegenClass != null ? 0 : -1;
0331:                maximumInterpreterStackDepth = Integer.MAX_VALUE;
0332:            }
0333:
0334:            /**
0335:             * Get the current Context.
0336:             *
0337:             * The current Context is per-thread; this method looks up
0338:             * the Context associated with the current thread. <p>
0339:             *
0340:             * @return the Context associated with the current thread, or
0341:             *         null if no context is associated with the current
0342:             *         thread.
0343:             * @see ContextFactory#enterContext()
0344:             * @see ContextFactory#call(ContextAction)
0345:             */
0346:            public static Context getCurrentContext() {
0347:                Object helper = VMBridge.instance.getThreadContextHelper();
0348:                return VMBridge.instance.getContext(helper);
0349:            }
0350:
0351:            /**
0352:             * Same as calling {@link ContextFactory#enterContext()} on the global
0353:             * ContextFactory instance.
0354:             * @deprecated use {@link ContextFactory#enter()} or 
0355:             * {@link ContextFactory#call(ContextAction)} instead as this method relies
0356:             * on usage of a static singleton "global" ContextFactory.
0357:             * @return a Context associated with the current thread
0358:             * @see #getCurrentContext()
0359:             * @see #exit()
0360:             * @see #call(ContextAction)
0361:             */
0362:            public static Context enter() {
0363:                return enter(null);
0364:            }
0365:
0366:            /**
0367:             * Get a Context associated with the current thread, using
0368:             * the given Context if need be.
0369:             * <p>
0370:             * The same as <code>enter()</code> except that <code>cx</code>
0371:             * is associated with the current thread and returned if
0372:             * the current thread has no associated context and <code>cx</code>
0373:             * is not associated with any other thread.
0374:             * @param cx a Context to associate with the thread if possible
0375:             * @return a Context associated with the current thread
0376:             * @deprecated use {@link ContextFactory#enterContext(Context)} instead as 
0377:             * this method relies on usage of a static singleton "global" ContextFactory.
0378:             * @see ContextFactory#enterContext(Context)
0379:             * @see ContextFactory#call(ContextAction)
0380:             */
0381:            public static Context enter(Context cx) {
0382:                return enter(cx, ContextFactory.getGlobal());
0383:            }
0384:
0385:            static final Context enter(Context cx, ContextFactory factory) {
0386:                Object helper = VMBridge.instance.getThreadContextHelper();
0387:                Context old = VMBridge.instance.getContext(helper);
0388:                if (old != null) {
0389:                    cx = old;
0390:                } else {
0391:                    if (cx == null) {
0392:                        cx = factory.makeContext();
0393:                        if (cx.enterCount != 0) {
0394:                            throw new IllegalStateException(
0395:                                    "factory.makeContext() returned Context instance already associated with some thread");
0396:                        }
0397:                        factory.onContextCreated(cx);
0398:                        if (factory.isSealed() && !cx.isSealed()) {
0399:                            cx.seal(null);
0400:                        }
0401:                    } else {
0402:                        if (cx.enterCount != 0) {
0403:                            throw new IllegalStateException(
0404:                                    "can not use Context instance already associated with some thread");
0405:                        }
0406:                    }
0407:                    VMBridge.instance.setContext(helper, cx);
0408:                }
0409:                ++cx.enterCount;
0410:                return cx;
0411:            }
0412:
0413:            /**
0414:             * Exit a block of code requiring a Context.
0415:             *
0416:             * Calling <code>exit()</code> will remove the association between
0417:             * the current thread and a Context if the prior call to
0418:             * {@link ContextFactory#enterContext()} on this thread newly associated a 
0419:             * Context with this thread. Once the current thread no longer has an 
0420:             * associated Context, it cannot be used to execute JavaScript until it is 
0421:             * again associated with a Context.
0422:             * @see ContextFactory#enterContext()
0423:             */
0424:            public static void exit() {
0425:                Object helper = VMBridge.instance.getThreadContextHelper();
0426:                Context cx = VMBridge.instance.getContext(helper);
0427:                if (cx == null) {
0428:                    throw new IllegalStateException(
0429:                            "Calling Context.exit without previous Context.enter");
0430:                }
0431:                if (cx.enterCount < 1)
0432:                    Kit.codeBug();
0433:                if (--cx.enterCount == 0) {
0434:                    VMBridge.instance.setContext(helper, null);
0435:                    cx.factory.onContextReleased(cx);
0436:                }
0437:            }
0438:
0439:            /**
0440:             * Call {@link ContextAction#run(Context cx)}
0441:             * using the Context instance associated with the current thread.
0442:             * If no Context is associated with the thread, then
0443:             * <tt>ContextFactory.getGlobal().makeContext()</tt> will be called to
0444:             * construct new Context instance. The instance will be temporary
0445:             * associated with the thread during call to
0446:             * {@link ContextAction#run(Context)}.
0447:             * @deprecated use {@link ContextFactory#call(ContextAction)} instead as 
0448:             * this method relies on usage of a static singleton "global" 
0449:             * ContextFactory.
0450:             * @return The result of {@link ContextAction#run(Context)}.
0451:             */
0452:            public static Object call(ContextAction action) {
0453:                return call(ContextFactory.getGlobal(), action);
0454:            }
0455:
0456:            /**
0457:             * Call {@link
0458:             * Callable#call(Context cx, Scriptable scope, Scriptable thisObj,
0459:             *               Object[] args)}
0460:             * using the Context instance associated with the current thread.
0461:             * If no Context is associated with the thread, then
0462:             * {@link ContextFactory#makeContext()} will be called to construct
0463:             * new Context instance. The instance will be temporary associated
0464:             * with the thread during call to {@link ContextAction#run(Context)}.
0465:             * <p>
0466:             * It is allowed but not advisable to use null for <tt>factory</tt> 
0467:             * argument in which case the global static singleton ContextFactory 
0468:             * instance will be used to create new context instances.
0469:             * @see ContextFactory#call(ContextAction)
0470:             */
0471:            public static Object call(ContextFactory factory,
0472:                    final Callable callable, final Scriptable scope,
0473:                    final Scriptable this Obj, final Object[] args) {
0474:                if (factory == null) {
0475:                    factory = ContextFactory.getGlobal();
0476:                }
0477:                return call(factory, new ContextAction() {
0478:                    public Object run(Context cx) {
0479:                        return callable.call(cx, scope, this Obj, args);
0480:                    }
0481:                });
0482:            }
0483:
0484:            /**
0485:             * The method implements {@links ContextFactory#call(ContextAction)} logic.
0486:             */
0487:            static Object call(ContextFactory factory, ContextAction action) {
0488:                Context cx = enter(null, factory);
0489:                try {
0490:                    return action.run(cx);
0491:                } finally {
0492:                    exit();
0493:                }
0494:            }
0495:
0496:            /**
0497:             * @deprecated
0498:             * @see ContextFactory#addListener(ContextFactory.Listener)
0499:             * @see ContextFactory#getGlobal()
0500:             */
0501:            public static void addContextListener(ContextListener listener) {
0502:                // Special workaround for the debugger
0503:                String DBG = "org.mozilla.javascript.tools.debugger.Main";
0504:                if (DBG.equals(listener.getClass().getName())) {
0505:                    Class cl = listener.getClass();
0506:                    Class factoryClass = Kit
0507:                            .classOrNull("org.mozilla.javascript.ContextFactory");
0508:                    Class[] sig = { factoryClass };
0509:                    Object[] args = { ContextFactory.getGlobal() };
0510:                    try {
0511:                        Method m = cl.getMethod("attachTo", sig);
0512:                        m.invoke(listener, args);
0513:                    } catch (Exception ex) {
0514:                        RuntimeException rex = new RuntimeException();
0515:                        Kit.initCause(rex, ex);
0516:                        throw rex;
0517:                    }
0518:                    return;
0519:                }
0520:
0521:                ContextFactory.getGlobal().addListener(listener);
0522:            }
0523:
0524:            /**
0525:             * @deprecated
0526:             * @see ContextFactory#removeListener(ContextFactory.Listener)
0527:             * @see ContextFactory#getGlobal()
0528:             */
0529:            public static void removeContextListener(ContextListener listener) {
0530:                ContextFactory.getGlobal().addListener(listener);
0531:            }
0532:
0533:            /**
0534:             * Return {@link ContextFactory} instance used to create this Context.
0535:             */
0536:            public final ContextFactory getFactory() {
0537:                return factory;
0538:            }
0539:
0540:            /**
0541:             * Checks if this is a sealed Context. A sealed Context instance does not
0542:             * allow to modify any of its properties and will throw an exception
0543:             * on any such attempt.
0544:             * @see #seal(Object sealKey)
0545:             */
0546:            public final boolean isSealed() {
0547:                return sealed;
0548:            }
0549:
0550:            /**
0551:             * Seal this Context object so any attempt to modify any of its properties
0552:             * including calling {@link #enter()} and {@link #exit()} methods will
0553:             * throw an exception.
0554:             * <p>
0555:             * If <tt>sealKey</tt> is not null, calling
0556:             * {@link #unseal(Object sealKey)} with the same key unseals
0557:             * the object. If <tt>sealKey</tt> is null, unsealing is no longer possible.
0558:             *
0559:             * @see #isSealed()
0560:             * @see #unseal(Object)
0561:             */
0562:            public final void seal(Object sealKey) {
0563:                if (sealed)
0564:                    onSealedMutation();
0565:                sealed = true;
0566:                this .sealKey = sealKey;
0567:            }
0568:
0569:            /**
0570:             * Unseal previously sealed Context object.
0571:             * The <tt>sealKey</tt> argument should not be null and should match
0572:             * <tt>sealKey</tt> suplied with the last call to
0573:             * {@link #seal(Object)} or an exception will be thrown.
0574:             *
0575:             * @see #isSealed()
0576:             * @see #seal(Object sealKey)
0577:             */
0578:            public final void unseal(Object sealKey) {
0579:                if (sealKey == null)
0580:                    throw new IllegalArgumentException();
0581:                if (this .sealKey != sealKey)
0582:                    throw new IllegalArgumentException();
0583:                if (!sealed)
0584:                    throw new IllegalStateException();
0585:                sealed = false;
0586:                this .sealKey = null;
0587:            }
0588:
0589:            static void onSealedMutation() {
0590:                throw new IllegalStateException();
0591:            }
0592:
0593:            /**
0594:             * Get the current language version.
0595:             * <p>
0596:             * The language version number affects JavaScript semantics as detailed
0597:             * in the overview documentation.
0598:             *
0599:             * @return an integer that is one of VERSION_1_0, VERSION_1_1, etc.
0600:             */
0601:            public final int getLanguageVersion() {
0602:                return version;
0603:            }
0604:
0605:            /**
0606:             * Set the language version.
0607:             *
0608:             * <p>
0609:             * Setting the language version will affect functions and scripts compiled
0610:             * subsequently. See the overview documentation for version-specific
0611:             * behavior.
0612:             *
0613:             * @param version the version as specified by VERSION_1_0, VERSION_1_1, etc.
0614:             */
0615:            public void setLanguageVersion(int version) {
0616:                if (sealed)
0617:                    onSealedMutation();
0618:                checkLanguageVersion(version);
0619:                Object listeners = propertyListeners;
0620:                if (listeners != null && version != this .version) {
0621:                    firePropertyChangeImpl(listeners, languageVersionProperty,
0622:                            new Integer(this .version), new Integer(version));
0623:                }
0624:                this .version = version;
0625:            }
0626:
0627:            public static boolean isValidLanguageVersion(int version) {
0628:                switch (version) {
0629:                case VERSION_DEFAULT:
0630:                case VERSION_1_0:
0631:                case VERSION_1_1:
0632:                case VERSION_1_2:
0633:                case VERSION_1_3:
0634:                case VERSION_1_4:
0635:                case VERSION_1_5:
0636:                case VERSION_1_6:
0637:                case VERSION_1_7:
0638:                    return true;
0639:                }
0640:                return false;
0641:            }
0642:
0643:            public static void checkLanguageVersion(int version) {
0644:                if (isValidLanguageVersion(version)) {
0645:                    return;
0646:                }
0647:                throw new IllegalArgumentException("Bad language version: "
0648:                        + version);
0649:            }
0650:
0651:            /**
0652:             * Get the implementation version.
0653:             *
0654:             * <p>
0655:             * The implementation version is of the form
0656:             * <pre>
0657:             *    "<i>name langVer</i> <code>release</code> <i>relNum date</i>"
0658:             * </pre>
0659:             * where <i>name</i> is the name of the product, <i>langVer</i> is
0660:             * the language version, <i>relNum</i> is the release number, and
0661:             * <i>date</i> is the release date for that specific
0662:             * release in the form "yyyy mm dd".
0663:             *
0664:             * @return a string that encodes the product, language version, release
0665:             *         number, and date.
0666:             */
0667:            public final String getImplementationVersion() {
0668:                // XXX Probably it would be better to embed this directly into source
0669:                // with special build preprocessing but that would require some ant
0670:                // tweaking and then replacing token in resource files was simpler
0671:                if (implementationVersion == null) {
0672:                    implementationVersion = ScriptRuntime
0673:                            .getMessage0("implementation.version");
0674:                }
0675:                return implementationVersion;
0676:            }
0677:
0678:            /**
0679:             * Get the current error reporter.
0680:             *
0681:             * @see org.mozilla.javascript.ErrorReporter
0682:             */
0683:            public final ErrorReporter getErrorReporter() {
0684:                if (errorReporter == null) {
0685:                    return DefaultErrorReporter.instance;
0686:                }
0687:                return errorReporter;
0688:            }
0689:
0690:            /**
0691:             * Change the current error reporter.
0692:             *
0693:             * @return the previous error reporter
0694:             * @see org.mozilla.javascript.ErrorReporter
0695:             */
0696:            public final ErrorReporter setErrorReporter(ErrorReporter reporter) {
0697:                if (sealed)
0698:                    onSealedMutation();
0699:                if (reporter == null)
0700:                    throw new IllegalArgumentException();
0701:                ErrorReporter old = getErrorReporter();
0702:                if (reporter == old) {
0703:                    return old;
0704:                }
0705:                Object listeners = propertyListeners;
0706:                if (listeners != null) {
0707:                    firePropertyChangeImpl(listeners, errorReporterProperty,
0708:                            old, reporter);
0709:                }
0710:                this .errorReporter = reporter;
0711:                return old;
0712:            }
0713:
0714:            /**
0715:             * Get the current locale.  Returns the default locale if none has
0716:             * been set.
0717:             *
0718:             * @see java.util.Locale
0719:             */
0720:
0721:            public final Locale getLocale() {
0722:                if (locale == null)
0723:                    locale = Locale.getDefault();
0724:                return locale;
0725:            }
0726:
0727:            /**
0728:             * Set the current locale.
0729:             *
0730:             * @see java.util.Locale
0731:             */
0732:            public final Locale setLocale(Locale loc) {
0733:                if (sealed)
0734:                    onSealedMutation();
0735:                Locale result = locale;
0736:                locale = loc;
0737:                return result;
0738:            }
0739:
0740:            /**
0741:             * Register an object to receive notifications when a bound property
0742:             * has changed
0743:             * @see java.beans.PropertyChangeEvent
0744:             * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
0745:             * @param l the listener
0746:             */
0747:            public final void addPropertyChangeListener(PropertyChangeListener l) {
0748:                if (sealed)
0749:                    onSealedMutation();
0750:                propertyListeners = Kit.addListener(propertyListeners, l);
0751:            }
0752:
0753:            /**
0754:             * Remove an object from the list of objects registered to receive
0755:             * notification of changes to a bounded property
0756:             * @see java.beans.PropertyChangeEvent
0757:             * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
0758:             * @param l the listener
0759:             */
0760:            public final void removePropertyChangeListener(
0761:                    PropertyChangeListener l) {
0762:                if (sealed)
0763:                    onSealedMutation();
0764:                propertyListeners = Kit.removeListener(propertyListeners, l);
0765:            }
0766:
0767:            /**
0768:             * Notify any registered listeners that a bounded property has changed
0769:             * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
0770:             * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
0771:             * @see java.beans.PropertyChangeListener
0772:             * @see java.beans.PropertyChangeEvent
0773:             * @param  property  the bound property
0774:             * @param  oldValue  the old value
0775:             * @param  newValue   the new value
0776:             */
0777:            final void firePropertyChange(String property, Object oldValue,
0778:                    Object newValue) {
0779:                Object listeners = propertyListeners;
0780:                if (listeners != null) {
0781:                    firePropertyChangeImpl(listeners, property, oldValue,
0782:                            newValue);
0783:                }
0784:            }
0785:
0786:            private void firePropertyChangeImpl(Object listeners,
0787:                    String property, Object oldValue, Object newValue) {
0788:                for (int i = 0;; ++i) {
0789:                    Object l = Kit.getListener(listeners, i);
0790:                    if (l == null)
0791:                        break;
0792:                    if (l instanceof  PropertyChangeListener) {
0793:                        PropertyChangeListener pcl = (PropertyChangeListener) l;
0794:                        pcl.propertyChange(new PropertyChangeEvent(this ,
0795:                                property, oldValue, newValue));
0796:                    }
0797:                }
0798:            }
0799:
0800:            /**
0801:             * Report a warning using the error reporter for the current thread.
0802:             *
0803:             * @param message the warning message to report
0804:             * @param sourceName a string describing the source, such as a filename
0805:             * @param lineno the starting line number
0806:             * @param lineSource the text of the line (may be null)
0807:             * @param lineOffset the offset into lineSource where problem was detected
0808:             * @see org.mozilla.javascript.ErrorReporter
0809:             */
0810:            public static void reportWarning(String message, String sourceName,
0811:                    int lineno, String lineSource, int lineOffset) {
0812:                Context cx = Context.getContext();
0813:                if (cx.hasFeature(FEATURE_WARNING_AS_ERROR))
0814:                    reportError(message, sourceName, lineno, lineSource,
0815:                            lineOffset);
0816:                else
0817:                    cx.getErrorReporter().warning(message, sourceName, lineno,
0818:                            lineSource, lineOffset);
0819:            }
0820:
0821:            /**
0822:             * Report a warning using the error reporter for the current thread.
0823:             *
0824:             * @param message the warning message to report
0825:             * @see org.mozilla.javascript.ErrorReporter
0826:             */
0827:            public static void reportWarning(String message) {
0828:                int[] linep = { 0 };
0829:                String filename = getSourcePositionFromStack(linep);
0830:                Context.reportWarning(message, filename, linep[0], null, 0);
0831:            }
0832:
0833:            public static void reportWarning(String message, Throwable t) {
0834:                int[] linep = { 0 };
0835:                String filename = getSourcePositionFromStack(linep);
0836:                Writer sw = new StringWriter();
0837:                PrintWriter pw = new PrintWriter(sw);
0838:                pw.println(message);
0839:                t.printStackTrace(pw);
0840:                pw.flush();
0841:                Context.reportWarning(sw.toString(), filename, linep[0], null,
0842:                        0);
0843:            }
0844:
0845:            /**
0846:             * Report an error using the error reporter for the current thread.
0847:             *
0848:             * @param message the error message to report
0849:             * @param sourceName a string describing the source, such as a filename
0850:             * @param lineno the starting line number
0851:             * @param lineSource the text of the line (may be null)
0852:             * @param lineOffset the offset into lineSource where problem was detected
0853:             * @see org.mozilla.javascript.ErrorReporter
0854:             */
0855:            public static void reportError(String message, String sourceName,
0856:                    int lineno, String lineSource, int lineOffset) {
0857:                Context cx = getCurrentContext();
0858:                if (cx != null) {
0859:                    cx.getErrorReporter().error(message, sourceName, lineno,
0860:                            lineSource, lineOffset);
0861:                } else {
0862:                    throw new EvaluatorException(message, sourceName, lineno,
0863:                            lineSource, lineOffset);
0864:                }
0865:            }
0866:
0867:            /**
0868:             * Report an error using the error reporter for the current thread.
0869:             *
0870:             * @param message the error message to report
0871:             * @see org.mozilla.javascript.ErrorReporter
0872:             */
0873:            public static void reportError(String message) {
0874:                int[] linep = { 0 };
0875:                String filename = getSourcePositionFromStack(linep);
0876:                Context.reportError(message, filename, linep[0], null, 0);
0877:            }
0878:
0879:            /**
0880:             * Report a runtime error using the error reporter for the current thread.
0881:             *
0882:             * @param message the error message to report
0883:             * @param sourceName a string describing the source, such as a filename
0884:             * @param lineno the starting line number
0885:             * @param lineSource the text of the line (may be null)
0886:             * @param lineOffset the offset into lineSource where problem was detected
0887:             * @return a runtime exception that will be thrown to terminate the
0888:             *         execution of the script
0889:             * @see org.mozilla.javascript.ErrorReporter
0890:             */
0891:            public static EvaluatorException reportRuntimeError(String message,
0892:                    String sourceName, int lineno, String lineSource,
0893:                    int lineOffset) {
0894:                Context cx = getCurrentContext();
0895:                if (cx != null) {
0896:                    return cx.getErrorReporter().runtimeError(message,
0897:                            sourceName, lineno, lineSource, lineOffset);
0898:                } else {
0899:                    throw new EvaluatorException(message, sourceName, lineno,
0900:                            lineSource, lineOffset);
0901:                }
0902:            }
0903:
0904:            static EvaluatorException reportRuntimeError0(String messageId) {
0905:                String msg = ScriptRuntime.getMessage0(messageId);
0906:                return reportRuntimeError(msg);
0907:            }
0908:
0909:            static EvaluatorException reportRuntimeError1(String messageId,
0910:                    Object arg1) {
0911:                String msg = ScriptRuntime.getMessage1(messageId, arg1);
0912:                return reportRuntimeError(msg);
0913:            }
0914:
0915:            static EvaluatorException reportRuntimeError2(String messageId,
0916:                    Object arg1, Object arg2) {
0917:                String msg = ScriptRuntime.getMessage2(messageId, arg1, arg2);
0918:                return reportRuntimeError(msg);
0919:            }
0920:
0921:            static EvaluatorException reportRuntimeError3(String messageId,
0922:                    Object arg1, Object arg2, Object arg3) {
0923:                String msg = ScriptRuntime.getMessage3(messageId, arg1, arg2,
0924:                        arg3);
0925:                return reportRuntimeError(msg);
0926:            }
0927:
0928:            static EvaluatorException reportRuntimeError4(String messageId,
0929:                    Object arg1, Object arg2, Object arg3, Object arg4) {
0930:                String msg = ScriptRuntime.getMessage4(messageId, arg1, arg2,
0931:                        arg3, arg4);
0932:                return reportRuntimeError(msg);
0933:            }
0934:
0935:            /**
0936:             * Report a runtime error using the error reporter for the current thread.
0937:             *
0938:             * @param message the error message to report
0939:             * @see org.mozilla.javascript.ErrorReporter
0940:             */
0941:            public static EvaluatorException reportRuntimeError(String message) {
0942:                int[] linep = { 0 };
0943:                String filename = getSourcePositionFromStack(linep);
0944:                return Context.reportRuntimeError(message, filename, linep[0],
0945:                        null, 0);
0946:            }
0947:
0948:            /**
0949:             * Initialize the standard objects.
0950:             *
0951:             * Creates instances of the standard objects and their constructors
0952:             * (Object, String, Number, Date, etc.), setting up 'scope' to act
0953:             * as a global object as in ECMA 15.1.<p>
0954:             *
0955:             * This method must be called to initialize a scope before scripts
0956:             * can be evaluated in that scope.<p>
0957:             *
0958:             * This method does not affect the Context it is called upon.
0959:             *
0960:             * @return the initialized scope
0961:             */
0962:            public final ScriptableObject initStandardObjects() {
0963:                return initStandardObjects(null, false);
0964:            }
0965:
0966:            /**
0967:             * Initialize the standard objects.
0968:             *
0969:             * Creates instances of the standard objects and their constructors
0970:             * (Object, String, Number, Date, etc.), setting up 'scope' to act
0971:             * as a global object as in ECMA 15.1.<p>
0972:             *
0973:             * This method must be called to initialize a scope before scripts
0974:             * can be evaluated in that scope.<p>
0975:             *
0976:             * This method does not affect the Context it is called upon.
0977:             *
0978:             * @param scope the scope to initialize, or null, in which case a new
0979:             *        object will be created to serve as the scope
0980:             * @return the initialized scope. The method returns the value of the scope
0981:             *         argument if it is not null or newly allocated scope object which
0982:             *         is an instance {@link ScriptableObject}.
0983:             */
0984:            public final Scriptable initStandardObjects(ScriptableObject scope) {
0985:                return initStandardObjects(scope, false);
0986:            }
0987:
0988:            /**
0989:             * Initialize the standard objects.
0990:             *
0991:             * Creates instances of the standard objects and their constructors
0992:             * (Object, String, Number, Date, etc.), setting up 'scope' to act
0993:             * as a global object as in ECMA 15.1.<p>
0994:             *
0995:             * This method must be called to initialize a scope before scripts
0996:             * can be evaluated in that scope.<p>
0997:             *
0998:             * This method does not affect the Context it is called upon.<p>
0999:             *
1000:             * This form of the method also allows for creating "sealed" standard
1001:             * objects. An object that is sealed cannot have properties added, changed,
1002:             * or removed. This is useful to create a "superglobal" that can be shared
1003:             * among several top-level objects. Note that sealing is not allowed in
1004:             * the current ECMA/ISO language specification, but is likely for
1005:             * the next version.
1006:             *
1007:             * @param scope the scope to initialize, or null, in which case a new
1008:             *        object will be created to serve as the scope
1009:             * @param sealed whether or not to create sealed standard objects that
1010:             *        cannot be modified.
1011:             * @return the initialized scope. The method returns the value of the scope
1012:             *         argument if it is not null or newly allocated scope object.
1013:             * @since 1.4R3
1014:             */
1015:            public ScriptableObject initStandardObjects(ScriptableObject scope,
1016:                    boolean sealed) {
1017:                return ScriptRuntime.initStandardObjects(this , scope, sealed);
1018:            }
1019:
1020:            /**
1021:             * Get the singleton object that represents the JavaScript Undefined value.
1022:             */
1023:            public static Object getUndefinedValue() {
1024:                return Undefined.instance;
1025:            }
1026:
1027:            /**
1028:             * Evaluate a JavaScript source string.
1029:             *
1030:             * The provided source name and line number are used for error messages
1031:             * and for producing debug information.
1032:             *
1033:             * @param scope the scope to execute in
1034:             * @param source the JavaScript source
1035:             * @param sourceName a string describing the source, such as a filename
1036:             * @param lineno the starting line number
1037:             * @param securityDomain an arbitrary object that specifies security
1038:             *        information about the origin or owner of the script. For
1039:             *        implementations that don't care about security, this value
1040:             *        may be null.
1041:             * @return the result of evaluating the string
1042:             * @see org.mozilla.javascript.SecurityController
1043:             */
1044:            public final Object evaluateString(Scriptable scope, String source,
1045:                    String sourceName, int lineno, Object securityDomain) {
1046:                Script script = compileString(source, sourceName, lineno,
1047:                        securityDomain);
1048:                if (script != null) {
1049:                    return script.exec(this , scope);
1050:                } else {
1051:                    return null;
1052:                }
1053:            }
1054:
1055:            /**
1056:             * Evaluate a reader as JavaScript source.
1057:             *
1058:             * All characters of the reader are consumed.
1059:             *
1060:             * @param scope the scope to execute in
1061:             * @param in the Reader to get JavaScript source from
1062:             * @param sourceName a string describing the source, such as a filename
1063:             * @param lineno the starting line number
1064:             * @param securityDomain an arbitrary object that specifies security
1065:             *        information about the origin or owner of the script. For
1066:             *        implementations that don't care about security, this value
1067:             *        may be null.
1068:             * @return the result of evaluating the source
1069:             *
1070:             * @exception IOException if an IOException was generated by the Reader
1071:             */
1072:            public final Object evaluateReader(Scriptable scope, Reader in,
1073:                    String sourceName, int lineno, Object securityDomain)
1074:                    throws IOException {
1075:                Script script = compileReader(scope, in, sourceName, lineno,
1076:                        securityDomain);
1077:                if (script != null) {
1078:                    return script.exec(this , scope);
1079:                } else {
1080:                    return null;
1081:                }
1082:            }
1083:
1084:            /**
1085:             * Check whether a string is ready to be compiled.
1086:             * <p>
1087:             * stringIsCompilableUnit is intended to support interactive compilation of
1088:             * javascript.  If compiling the string would result in an error
1089:             * that might be fixed by appending more source, this method
1090:             * returns false.  In every other case, it returns true.
1091:             * <p>
1092:             * Interactive shells may accumulate source lines, using this
1093:             * method after each new line is appended to check whether the
1094:             * statement being entered is complete.
1095:             *
1096:             * @param source the source buffer to check
1097:             * @return whether the source is ready for compilation
1098:             * @since 1.4 Release 2
1099:             */
1100:            public final boolean stringIsCompilableUnit(String source) {
1101:                boolean errorseen = false;
1102:                CompilerEnvirons compilerEnv = new CompilerEnvirons();
1103:                compilerEnv.initFromContext(this );
1104:                // no source name or source text manager, because we're just
1105:                // going to throw away the result.
1106:                compilerEnv.setGeneratingSource(false);
1107:                Parser p = new Parser(compilerEnv,
1108:                        DefaultErrorReporter.instance);
1109:                try {
1110:                    p.parse(source, null, 1);
1111:                } catch (EvaluatorException ee) {
1112:                    errorseen = true;
1113:                }
1114:                // Return false only if an error occurred as a result of reading past
1115:                // the end of the file, i.e. if the source could be fixed by
1116:                // appending more source.
1117:                if (errorseen && p.eof())
1118:                    return false;
1119:                else
1120:                    return true;
1121:            }
1122:
1123:            /**
1124:             * @deprecated
1125:             * @see #compileReader(Reader in, String sourceName, int lineno,
1126:             *                     Object securityDomain)
1127:             */
1128:            public final Script compileReader(Scriptable scope, Reader in,
1129:                    String sourceName, int lineno, Object securityDomain)
1130:                    throws IOException {
1131:                return compileReader(in, sourceName, lineno, securityDomain);
1132:            }
1133:
1134:            /**
1135:             * Compiles the source in the given reader.
1136:             * <p>
1137:             * Returns a script that may later be executed.
1138:             * Will consume all the source in the reader.
1139:             *
1140:             * @param in the input reader
1141:             * @param sourceName a string describing the source, such as a filename
1142:             * @param lineno the starting line number for reporting errors
1143:             * @param securityDomain an arbitrary object that specifies security
1144:             *        information about the origin or owner of the script. For
1145:             *        implementations that don't care about security, this value
1146:             *        may be null.
1147:             * @return a script that may later be executed
1148:             * @exception IOException if an IOException was generated by the Reader
1149:             * @see org.mozilla.javascript.Script
1150:             */
1151:            public final Script compileReader(Reader in, String sourceName,
1152:                    int lineno, Object securityDomain) throws IOException {
1153:                if (lineno < 0) {
1154:                    // For compatibility IllegalArgumentException can not be thrown here
1155:                    lineno = 0;
1156:                }
1157:                return (Script) compileImpl(null, in, null, sourceName, lineno,
1158:                        securityDomain, false, null, null);
1159:            }
1160:
1161:            /**
1162:             * Compiles the source in the given string.
1163:             * <p>
1164:             * Returns a script that may later be executed.
1165:             *
1166:             * @param source the source string
1167:             * @param sourceName a string describing the source, such as a filename
1168:             * @param lineno the starting line number for reporting errors
1169:             * @param securityDomain an arbitrary object that specifies security
1170:             *        information about the origin or owner of the script. For
1171:             *        implementations that don't care about security, this value
1172:             *        may be null.
1173:             * @return a script that may later be executed
1174:             * @see org.mozilla.javascript.Script
1175:             */
1176:            public final Script compileString(String source, String sourceName,
1177:                    int lineno, Object securityDomain) {
1178:                if (lineno < 0) {
1179:                    // For compatibility IllegalArgumentException can not be thrown here
1180:                    lineno = 0;
1181:                }
1182:                return compileString(source, null, null, sourceName, lineno,
1183:                        securityDomain);
1184:            }
1185:
1186:            final Script compileString(String source, Evaluator compiler,
1187:                    ErrorReporter compilationErrorReporter, String sourceName,
1188:                    int lineno, Object securityDomain) {
1189:                try {
1190:                    return (Script) compileImpl(null, null, source, sourceName,
1191:                            lineno, securityDomain, false, compiler,
1192:                            compilationErrorReporter);
1193:                } catch (IOException ex) {
1194:                    // Should not happen when dealing with source as string
1195:                    throw new RuntimeException();
1196:                }
1197:            }
1198:
1199:            /**
1200:             * Compile a JavaScript function.
1201:             * <p>
1202:             * The function source must be a function definition as defined by
1203:             * ECMA (e.g., "function f(a) { return a; }").
1204:             *
1205:             * @param scope the scope to compile relative to
1206:             * @param source the function definition source
1207:             * @param sourceName a string describing the source, such as a filename
1208:             * @param lineno the starting line number
1209:             * @param securityDomain an arbitrary object that specifies security
1210:             *        information about the origin or owner of the script. For
1211:             *        implementations that don't care about security, this value
1212:             *        may be null.
1213:             * @return a Function that may later be called
1214:             * @see org.mozilla.javascript.Function
1215:             */
1216:            public final Function compileFunction(Scriptable scope,
1217:                    String source, String sourceName, int lineno,
1218:                    Object securityDomain) {
1219:                return compileFunction(scope, source, null, null, sourceName,
1220:                        lineno, securityDomain);
1221:            }
1222:
1223:            final Function compileFunction(Scriptable scope, String source,
1224:                    Evaluator compiler, ErrorReporter compilationErrorReporter,
1225:                    String sourceName, int lineno, Object securityDomain) {
1226:                try {
1227:                    return (Function) compileImpl(scope, null, source,
1228:                            sourceName, lineno, securityDomain, true, compiler,
1229:                            compilationErrorReporter);
1230:                } catch (IOException ioe) {
1231:                    // Should never happen because we just made the reader
1232:                    // from a String
1233:                    throw new RuntimeException();
1234:                }
1235:            }
1236:
1237:            /**
1238:             * Decompile the script.
1239:             * <p>
1240:             * The canonical source of the script is returned.
1241:             *
1242:             * @param script the script to decompile
1243:             * @param indent the number of spaces to indent the result
1244:             * @return a string representing the script source
1245:             */
1246:            public final String decompileScript(Script script, int indent) {
1247:                NativeFunction scriptImpl = (NativeFunction) script;
1248:                return scriptImpl.decompile(indent, 0);
1249:            }
1250:
1251:            /**
1252:             * Decompile a JavaScript Function.
1253:             * <p>
1254:             * Decompiles a previously compiled JavaScript function object to
1255:             * canonical source.
1256:             * <p>
1257:             * Returns function body of '[native code]' if no decompilation
1258:             * information is available.
1259:             *
1260:             * @param fun the JavaScript function to decompile
1261:             * @param indent the number of spaces to indent the result
1262:             * @return a string representing the function source
1263:             */
1264:            public final String decompileFunction(Function fun, int indent) {
1265:                if (fun instanceof  BaseFunction)
1266:                    return ((BaseFunction) fun).decompile(indent, 0);
1267:                else
1268:                    return "function " + fun.getClassName()
1269:                            + "() {\n\t[native code]\n}\n";
1270:            }
1271:
1272:            /**
1273:             * Decompile the body of a JavaScript Function.
1274:             * <p>
1275:             * Decompiles the body a previously compiled JavaScript Function
1276:             * object to canonical source, omitting the function header and
1277:             * trailing brace.
1278:             *
1279:             * Returns '[native code]' if no decompilation information is available.
1280:             *
1281:             * @param fun the JavaScript function to decompile
1282:             * @param indent the number of spaces to indent the result
1283:             * @return a string representing the function body source.
1284:             */
1285:            public final String decompileFunctionBody(Function fun, int indent) {
1286:                if (fun instanceof  BaseFunction) {
1287:                    BaseFunction bf = (BaseFunction) fun;
1288:                    return bf.decompile(indent, Decompiler.ONLY_BODY_FLAG);
1289:                }
1290:                // ALERT: not sure what the right response here is.
1291:                return "[native code]\n";
1292:            }
1293:
1294:            /**
1295:             * Create a new JavaScript object.
1296:             *
1297:             * Equivalent to evaluating "new Object()".
1298:             * @param scope the scope to search for the constructor and to evaluate
1299:             *              against
1300:             * @return the new object
1301:             */
1302:            public final Scriptable newObject(Scriptable scope) {
1303:                return newObject(scope, "Object", ScriptRuntime.emptyArgs);
1304:            }
1305:
1306:            /**
1307:             * Create a new JavaScript object by executing the named constructor.
1308:             *
1309:             * The call <code>newObject(scope, "Foo")</code> is equivalent to
1310:             * evaluating "new Foo()".
1311:             *
1312:             * @param scope the scope to search for the constructor and to evaluate against
1313:             * @param constructorName the name of the constructor to call
1314:             * @return the new object
1315:             */
1316:            public final Scriptable newObject(Scriptable scope,
1317:                    String constructorName) {
1318:                return newObject(scope, constructorName,
1319:                        ScriptRuntime.emptyArgs);
1320:            }
1321:
1322:            /**
1323:             * Creates a new JavaScript object by executing the named constructor.
1324:             *
1325:             * Searches <code>scope</code> for the named constructor, calls it with
1326:             * the given arguments, and returns the result.<p>
1327:             *
1328:             * The code
1329:             * <pre>
1330:             * Object[] args = { "a", "b" };
1331:             * newObject(scope, "Foo", args)</pre>
1332:             * is equivalent to evaluating "new Foo('a', 'b')", assuming that the Foo
1333:             * constructor has been defined in <code>scope</code>.
1334:             *
1335:             * @param scope The scope to search for the constructor and to evaluate
1336:             *              against
1337:             * @param constructorName the name of the constructor to call
1338:             * @param args the array of arguments for the constructor
1339:             * @return the new object
1340:             */
1341:            public final Scriptable newObject(Scriptable scope,
1342:                    String constructorName, Object[] args) {
1343:                scope = ScriptableObject.getTopLevelScope(scope);
1344:                Function ctor = ScriptRuntime.getExistingCtor(this , scope,
1345:                        constructorName);
1346:                if (args == null) {
1347:                    args = ScriptRuntime.emptyArgs;
1348:                }
1349:                return ctor.construct(this , scope, args);
1350:            }
1351:
1352:            /**
1353:             * Create an array with a specified initial length.
1354:             * <p>
1355:             * @param scope the scope to create the object in
1356:             * @param length the initial length (JavaScript arrays may have
1357:             *               additional properties added dynamically).
1358:             * @return the new array object
1359:             */
1360:            public final Scriptable newArray(Scriptable scope, int length) {
1361:                NativeArray result = new NativeArray(length);
1362:                ScriptRuntime.setObjectProtoAndParent(result, scope);
1363:                return result;
1364:            }
1365:
1366:            /**
1367:             * Create an array with a set of initial elements.
1368:             *
1369:             * @param scope the scope to create the object in.
1370:             * @param elements the initial elements. Each object in this array
1371:             *                 must be an acceptable JavaScript type and type
1372:             *                 of array should be exactly Object[], not
1373:             *                 SomeObjectSubclass[].
1374:             * @return the new array object.
1375:             */
1376:            public final Scriptable newArray(Scriptable scope, Object[] elements) {
1377:                if (elements.getClass().getComponentType() != ScriptRuntime.ObjectClass)
1378:                    throw new IllegalArgumentException();
1379:                NativeArray result = new NativeArray(elements);
1380:                ScriptRuntime.setObjectProtoAndParent(result, scope);
1381:                return result;
1382:            }
1383:
1384:            /**
1385:             * Get the elements of a JavaScript array.
1386:             * <p>
1387:             * If the object defines a length property convertible to double number,
1388:             * then the number is converted Uint32 value as defined in Ecma 9.6
1389:             * and Java array of that size is allocated.
1390:             * The array is initialized with the values obtained by
1391:             * calling get() on object for each value of i in [0,length-1]. If
1392:             * there is not a defined value for a property the Undefined value
1393:             * is used to initialize the corresponding element in the array. The
1394:             * Java array is then returned.
1395:             * If the object doesn't define a length property or it is not a number,
1396:             * empty array is returned.
1397:             * @param object the JavaScript array or array-like object
1398:             * @return a Java array of objects
1399:             * @since 1.4 release 2
1400:             */
1401:            public final Object[] getElements(Scriptable object) {
1402:                return ScriptRuntime.getArrayElements(object);
1403:            }
1404:
1405:            /**
1406:             * Convert the value to a JavaScript boolean value.
1407:             * <p>
1408:             * See ECMA 9.2.
1409:             *
1410:             * @param value a JavaScript value
1411:             * @return the corresponding boolean value converted using
1412:             *         the ECMA rules
1413:             */
1414:            public static boolean toBoolean(Object value) {
1415:                return ScriptRuntime.toBoolean(value);
1416:            }
1417:
1418:            /**
1419:             * Convert the value to a JavaScript Number value.
1420:             * <p>
1421:             * Returns a Java double for the JavaScript Number.
1422:             * <p>
1423:             * See ECMA 9.3.
1424:             *
1425:             * @param value a JavaScript value
1426:             * @return the corresponding double value converted using
1427:             *         the ECMA rules
1428:             */
1429:            public static double toNumber(Object value) {
1430:                return ScriptRuntime.toNumber(value);
1431:            }
1432:
1433:            /**
1434:             * Convert the value to a JavaScript String value.
1435:             * <p>
1436:             * See ECMA 9.8.
1437:             * <p>
1438:             * @param value a JavaScript value
1439:             * @return the corresponding String value converted using
1440:             *         the ECMA rules
1441:             */
1442:            public static String toString(Object value) {
1443:                return ScriptRuntime.toString(value);
1444:            }
1445:
1446:            /**
1447:             * Convert the value to an JavaScript object value.
1448:             * <p>
1449:             * Note that a scope must be provided to look up the constructors
1450:             * for Number, Boolean, and String.
1451:             * <p>
1452:             * See ECMA 9.9.
1453:             * <p>
1454:             * Additionally, arbitrary Java objects and classes will be
1455:             * wrapped in a Scriptable object with its Java fields and methods
1456:             * reflected as JavaScript properties of the object.
1457:             *
1458:             * @param value any Java object
1459:             * @param scope global scope containing constructors for Number,
1460:             *              Boolean, and String
1461:             * @return new JavaScript object
1462:             */
1463:            public static Scriptable toObject(Object value, Scriptable scope) {
1464:                return ScriptRuntime.toObject(scope, value);
1465:            }
1466:
1467:            /**
1468:             * @deprecated
1469:             * @see #toObject(Object, Scriptable)
1470:             */
1471:            public static Scriptable toObject(Object value, Scriptable scope,
1472:                    Class staticType) {
1473:                return ScriptRuntime.toObject(scope, value);
1474:            }
1475:
1476:            /**
1477:             * Convenient method to convert java value to its closest representation
1478:             * in JavaScript.
1479:             * <p>
1480:             * If value is an instance of String, Number, Boolean, Function or
1481:             * Scriptable, it is returned as it and will be treated as the corresponding
1482:             * JavaScript type of string, number, boolean, function and object.
1483:             * <p>
1484:             * Note that for Number instances during any arithmetic operation in
1485:             * JavaScript the engine will always use the result of
1486:             * <tt>Number.doubleValue()</tt> resulting in a precision loss if
1487:             * the number can not fit into double.
1488:             * <p>
1489:             * If value is an instance of Character, it will be converted to string of
1490:             * length 1 and its JavaScript type will be string.
1491:             * <p>
1492:             * The rest of values will be wrapped as LiveConnect objects
1493:             * by calling {@link WrapFactory#wrap(Context cx, Scriptable scope,
1494:             * Object obj, Class staticType)} as in:
1495:             * <pre>
1496:             *    Context cx = Context.getCurrentContext();
1497:             *    return cx.getWrapFactory().wrap(cx, scope, value, null);
1498:             * </pre>
1499:             *
1500:             * @param value any Java object
1501:             * @param scope top scope object
1502:             * @return value suitable to pass to any API that takes JavaScript values.
1503:             */
1504:            public static Object javaToJS(Object value, Scriptable scope) {
1505:                if (value instanceof  String || value instanceof  Number
1506:                        || value instanceof  Boolean
1507:                        || value instanceof  Scriptable) {
1508:                    return value;
1509:                } else if (value instanceof  Character) {
1510:                    return String.valueOf(((Character) value).charValue());
1511:                } else {
1512:                    Context cx = Context.getContext();
1513:                    return cx.getWrapFactory().wrap(cx, scope, value, null);
1514:                }
1515:            }
1516:
1517:            /**
1518:             * Convert a JavaScript value into the desired type.
1519:             * Uses the semantics defined with LiveConnect3 and throws an
1520:             * Illegal argument exception if the conversion cannot be performed.
1521:             * @param value the JavaScript value to convert
1522:             * @param desiredType the Java type to convert to. Primitive Java
1523:             *        types are represented using the TYPE fields in the corresponding
1524:             *        wrapper class in java.lang.
1525:             * @return the converted value
1526:             * @throws EvaluatorException if the conversion cannot be performed
1527:             */
1528:            public static Object jsToJava(Object value, Class desiredType)
1529:                    throws EvaluatorException {
1530:                return NativeJavaObject.coerceTypeImpl(desiredType, value);
1531:            }
1532:
1533:            /**
1534:             * @deprecated
1535:             * @see #jsToJava(Object, Class)
1536:             * @throws IllegalArgumentException if the conversion cannot be performed.
1537:             *         Note that {@link #jsToJava(Object, Class)} throws
1538:             *         {@link EvaluatorException} instead.
1539:             */
1540:            public static Object toType(Object value, Class desiredType)
1541:                    throws IllegalArgumentException {
1542:                try {
1543:                    return jsToJava(value, desiredType);
1544:                } catch (EvaluatorException ex) {
1545:                    IllegalArgumentException ex2 = new IllegalArgumentException(
1546:                            ex.getMessage());
1547:                    Kit.initCause(ex2, ex);
1548:                    throw ex2;
1549:                }
1550:            }
1551:
1552:            /**
1553:             * Rethrow the exception wrapping it as the script runtime exception.
1554:             * Unless the exception is instance of {@link EcmaError} or
1555:             * {@link EvaluatorException} it will be wrapped as
1556:             * {@link WrappedException}, a subclass of {@link EvaluatorException}.
1557:             * The resulting exception object always contains
1558:             * source name and line number of script that triggered exception.
1559:             * <p>
1560:             * This method always throws an exception, its return value is provided
1561:             * only for convenience to allow a usage like:
1562:             * <pre>
1563:             * throw Context.throwAsScriptRuntimeEx(ex);
1564:             * </pre>
1565:             * to indicate that code after the method is unreachable.
1566:             * @throws EvaluatorException
1567:             * @throws EcmaError
1568:             */
1569:            public static RuntimeException throwAsScriptRuntimeEx(Throwable e) {
1570:                while ((e instanceof  InvocationTargetException)) {
1571:                    e = ((InvocationTargetException) e).getTargetException();
1572:                }
1573:                // special handling of Error so scripts would not catch them
1574:                if (e instanceof  Error) {
1575:                    Context cx = getContext();
1576:                    if (cx == null
1577:                            || !cx
1578:                                    .hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)) {
1579:                        throw (Error) e;
1580:                    }
1581:                }
1582:                if (e instanceof  RhinoException) {
1583:                    throw (RhinoException) e;
1584:                }
1585:                throw new WrappedException(e);
1586:            }
1587:
1588:            /**
1589:             * Tell whether debug information is being generated.
1590:             * @since 1.3
1591:             */
1592:            public final boolean isGeneratingDebug() {
1593:                return generatingDebug;
1594:            }
1595:
1596:            /**
1597:             * Specify whether or not debug information should be generated.
1598:             * <p>
1599:             * Setting the generation of debug information on will set the
1600:             * optimization level to zero.
1601:             * @since 1.3
1602:             */
1603:            public final void setGeneratingDebug(boolean generatingDebug) {
1604:                if (sealed)
1605:                    onSealedMutation();
1606:                generatingDebugChanged = true;
1607:                if (generatingDebug && getOptimizationLevel() > 0)
1608:                    setOptimizationLevel(0);
1609:                this .generatingDebug = generatingDebug;
1610:            }
1611:
1612:            /**
1613:             * Tell whether source information is being generated.
1614:             * @since 1.3
1615:             */
1616:            public final boolean isGeneratingSource() {
1617:                return generatingSource;
1618:            }
1619:
1620:            /**
1621:             * Specify whether or not source information should be generated.
1622:             * <p>
1623:             * Without source information, evaluating the "toString" method
1624:             * on JavaScript functions produces only "[native code]" for
1625:             * the body of the function.
1626:             * Note that code generated without source is not fully ECMA
1627:             * conformant.
1628:             * @since 1.3
1629:             */
1630:            public final void setGeneratingSource(boolean generatingSource) {
1631:                if (sealed)
1632:                    onSealedMutation();
1633:                this .generatingSource = generatingSource;
1634:            }
1635:
1636:            /**
1637:             * Get the current optimization level.
1638:             * <p>
1639:             * The optimization level is expressed as an integer between -1 and
1640:             * 9.
1641:             * @since 1.3
1642:             *
1643:             */
1644:            public final int getOptimizationLevel() {
1645:                return optimizationLevel;
1646:            }
1647:
1648:            /**
1649:             * Set the current optimization level.
1650:             * <p>
1651:             * The optimization level is expected to be an integer between -1 and
1652:             * 9. Any negative values will be interpreted as -1, and any values
1653:             * greater than 9 will be interpreted as 9.
1654:             * An optimization level of -1 indicates that interpretive mode will
1655:             * always be used. Levels 0 through 9 indicate that class files may
1656:             * be generated. Higher optimization levels trade off compile time
1657:             * performance for runtime performance.
1658:             * The optimizer level can't be set greater than -1 if the optimizer
1659:             * package doesn't exist at run time.
1660:             * @param optimizationLevel an integer indicating the level of
1661:             *        optimization to perform
1662:             * @since 1.3
1663:             *
1664:             */
1665:            public final void setOptimizationLevel(int optimizationLevel) {
1666:                if (sealed)
1667:                    onSealedMutation();
1668:                if (optimizationLevel == -2) {
1669:                    // To be compatible with Cocoon fork
1670:                    optimizationLevel = -1;
1671:                }
1672:                checkOptimizationLevel(optimizationLevel);
1673:                if (codegenClass == null)
1674:                    optimizationLevel = -1;
1675:                this .optimizationLevel = optimizationLevel;
1676:            }
1677:
1678:            public static boolean isValidOptimizationLevel(int optimizationLevel) {
1679:                return -1 <= optimizationLevel && optimizationLevel <= 9;
1680:            }
1681:
1682:            public static void checkOptimizationLevel(int optimizationLevel) {
1683:                if (isValidOptimizationLevel(optimizationLevel)) {
1684:                    return;
1685:                }
1686:                throw new IllegalArgumentException(
1687:                        "Optimization level outside [-1..9]: "
1688:                                + optimizationLevel);
1689:            }
1690:
1691:            /**
1692:             * Returns the maximum stack depth (in terms of number of call frames) 
1693:             * allowed in a single invocation of interpreter. If the set depth would be
1694:             * exceeded, the interpreter will throw an EvaluatorException in the script.
1695:             * Defaults to Integer.MAX_VALUE. The setting only has effect for 
1696:             * interpreted functions (those compiled with optimization level set to -1).
1697:             * As the interpreter doesn't use the Java stack but rather manages its own
1698:             * stack in the heap memory, a runaway recursion in interpreted code would 
1699:             * eventually consume all available memory and cause OutOfMemoryError 
1700:             * instead of a StackOverflowError limited to only a single thread. This
1701:             * setting helps prevent such situations.
1702:             *  
1703:             * @return The current maximum interpreter stack depth.
1704:             */
1705:            public final int getMaximumInterpreterStackDepth() {
1706:                return maximumInterpreterStackDepth;
1707:            }
1708:
1709:            /**
1710:             * Sets the maximum stack depth (in terms of number of call frames) 
1711:             * allowed in a single invocation of interpreter. If the set depth would be
1712:             * exceeded, the interpreter will throw an EvaluatorException in the script.
1713:             * Defaults to Integer.MAX_VALUE. The setting only has effect for 
1714:             * interpreted functions (those compiled with optimization level set to -1).
1715:             * As the interpreter doesn't use the Java stack but rather manages its own
1716:             * stack in the heap memory, a runaway recursion in interpreted code would 
1717:             * eventually consume all available memory and cause OutOfMemoryError 
1718:             * instead of a StackOverflowError limited to only a single thread. This
1719:             * setting helps prevent such situations.
1720:             * 
1721:             * @param max the new maximum interpreter stack depth
1722:             * @throws IllegalStateException if this context's optimization level is not
1723:             * -1
1724:             * @throws IllegalArgumentException if the new depth is not at least 1 
1725:             */
1726:            public final void setMaximumInterpreterStackDepth(int max) {
1727:                if (sealed)
1728:                    onSealedMutation();
1729:                if (optimizationLevel != -1) {
1730:                    throw new IllegalStateException(
1731:                            "Cannot set maximumInterpreterStackDepth when optimizationLevel != -1");
1732:                }
1733:                if (max < 1) {
1734:                    throw new IllegalArgumentException(
1735:                            "Cannot set maximumInterpreterStackDepth to less than 1");
1736:                }
1737:                maximumInterpreterStackDepth = max;
1738:            }
1739:
1740:            /**
1741:             * Set the security controller for this context.
1742:             * <p> SecurityController may only be set if it is currently null
1743:             * and {@link SecurityController#hasGlobal()} is <tt>false</tt>.
1744:             * Otherwise a SecurityException is thrown.
1745:             * @param controller a SecurityController object
1746:             * @throws SecurityException if there is already a SecurityController
1747:             *         object for this Context or globally installed.
1748:             * @see SecurityController#initGlobal(SecurityController controller)
1749:             * @see SecurityController#hasGlobal()
1750:             */
1751:            public final void setSecurityController(
1752:                    SecurityController controller) {
1753:                if (sealed)
1754:                    onSealedMutation();
1755:                if (controller == null)
1756:                    throw new IllegalArgumentException();
1757:                if (securityController != null) {
1758:                    throw new SecurityException(
1759:                            "Can not overwrite existing SecurityController object");
1760:                }
1761:                if (SecurityController.hasGlobal()) {
1762:                    throw new SecurityException(
1763:                            "Can not overwrite existing global SecurityController object");
1764:                }
1765:                securityController = controller;
1766:            }
1767:
1768:            /**
1769:             * Set the LiveConnect access filter for this context.
1770:             * <p> {@link ClassShutter} may only be set if it is currently null.
1771:             * Otherwise a SecurityException is thrown.
1772:             * @param shutter a ClassShutter object
1773:             * @throws SecurityException if there is already a ClassShutter
1774:             *         object for this Context
1775:             */
1776:            public final void setClassShutter(ClassShutter shutter) {
1777:                if (sealed)
1778:                    onSealedMutation();
1779:                if (shutter == null)
1780:                    throw new IllegalArgumentException();
1781:                if (classShutter != null) {
1782:                    throw new SecurityException("Cannot overwrite existing "
1783:                            + "ClassShutter object");
1784:                }
1785:                classShutter = shutter;
1786:            }
1787:
1788:            final ClassShutter getClassShutter() {
1789:                return classShutter;
1790:            }
1791:
1792:            /**
1793:             * Get a value corresponding to a key.
1794:             * <p>
1795:             * Since the Context is associated with a thread it can be
1796:             * used to maintain values that can be later retrieved using
1797:             * the current thread.
1798:             * <p>
1799:             * Note that the values are maintained with the Context, so
1800:             * if the Context is disassociated from the thread the values
1801:             * cannot be retrieved. Also, if private data is to be maintained
1802:             * in this manner the key should be a java.lang.Object
1803:             * whose reference is not divulged to untrusted code.
1804:             * @param key the key used to lookup the value
1805:             * @return a value previously stored using putThreadLocal.
1806:             */
1807:            public final Object getThreadLocal(Object key) {
1808:                if (hashtable == null)
1809:                    return null;
1810:                return hashtable.get(key);
1811:            }
1812:
1813:            /**
1814:             * Put a value that can later be retrieved using a given key.
1815:             * <p>
1816:             * @param key the key used to index the value
1817:             * @param value the value to save
1818:             */
1819:            public final void putThreadLocal(Object key, Object value) {
1820:                if (sealed)
1821:                    onSealedMutation();
1822:                if (hashtable == null)
1823:                    hashtable = new Hashtable();
1824:                hashtable.put(key, value);
1825:            }
1826:
1827:            /**
1828:             * Remove values from thread-local storage.
1829:             * @param key the key for the entry to remove.
1830:             * @since 1.5 release 2
1831:             */
1832:            public final void removeThreadLocal(Object key) {
1833:                if (sealed)
1834:                    onSealedMutation();
1835:                if (hashtable == null)
1836:                    return;
1837:                hashtable.remove(key);
1838:            }
1839:
1840:            /**
1841:             * @deprecated
1842:             * @see #FEATURE_DYNAMIC_SCOPE
1843:             * @see #hasFeature(int)
1844:             */
1845:            public final boolean hasCompileFunctionsWithDynamicScope() {
1846:                return compileFunctionsWithDynamicScopeFlag;
1847:            }
1848:
1849:            /**
1850:             * @deprecated
1851:             * @see #FEATURE_DYNAMIC_SCOPE
1852:             * @see #hasFeature(int)
1853:             */
1854:            public final void setCompileFunctionsWithDynamicScope(boolean flag) {
1855:                if (sealed)
1856:                    onSealedMutation();
1857:                compileFunctionsWithDynamicScopeFlag = flag;
1858:            }
1859:
1860:            /**
1861:             * @deprecated
1862:             * @see ClassCache#get(Scriptable)
1863:             * @see ClassCache#setCachingEnabled(boolean)
1864:             */
1865:            public static void setCachingEnabled(boolean cachingEnabled) {
1866:            }
1867:
1868:            /**
1869:             * Set a WrapFactory for this Context.
1870:             * <p>
1871:             * The WrapFactory allows custom object wrapping behavior for
1872:             * Java object manipulated with JavaScript.
1873:             * @see WrapFactory
1874:             * @since 1.5 Release 4
1875:             */
1876:            public final void setWrapFactory(WrapFactory wrapFactory) {
1877:                if (sealed)
1878:                    onSealedMutation();
1879:                if (wrapFactory == null)
1880:                    throw new IllegalArgumentException();
1881:                this .wrapFactory = wrapFactory;
1882:            }
1883:
1884:            /**
1885:             * Return the current WrapFactory, or null if none is defined.
1886:             * @see WrapFactory
1887:             * @since 1.5 Release 4
1888:             */
1889:            public final WrapFactory getWrapFactory() {
1890:                if (wrapFactory == null) {
1891:                    wrapFactory = new WrapFactory();
1892:                }
1893:                return wrapFactory;
1894:            }
1895:
1896:            /**
1897:             * Return the current debugger.
1898:             * @return the debugger, or null if none is attached.
1899:             */
1900:            public final Debugger getDebugger() {
1901:                return debugger;
1902:            }
1903:
1904:            /**
1905:             * Return the debugger context data associated with current context.
1906:             * @return the debugger data, or null if debugger is not attached
1907:             */
1908:            public final Object getDebuggerContextData() {
1909:                return debuggerData;
1910:            }
1911:
1912:            /**
1913:             * Set the associated debugger.
1914:             * @param debugger the debugger to be used on callbacks from
1915:             * the engine.
1916:             * @param contextData arbitrary object that debugger can use to store
1917:             *        per Context data.
1918:             */
1919:            public final void setDebugger(Debugger debugger, Object contextData) {
1920:                if (sealed)
1921:                    onSealedMutation();
1922:                this .debugger = debugger;
1923:                debuggerData = contextData;
1924:            }
1925:
1926:            /**
1927:             * Return DebuggableScript instance if any associated with the script.
1928:             * If callable supports DebuggableScript implementation, the method
1929:             * returns it. Otherwise null is returned.
1930:             */
1931:            public static DebuggableScript getDebuggableView(Script script) {
1932:                if (script instanceof  NativeFunction) {
1933:                    return ((NativeFunction) script).getDebuggableView();
1934:                }
1935:                return null;
1936:            }
1937:
1938:            /**
1939:             * Controls certain aspects of script semantics.
1940:             * Should be overwritten to alter default behavior.
1941:             * <p>
1942:             * The default implementation calls
1943:             * {@link ContextFactory#hasFeature(Context cx, int featureIndex)}
1944:             * that allows to customize Context behavior without introducing
1945:             * Context subclasses.  {@link ContextFactory} documentation gives
1946:             * an example of hasFeature implementation.
1947:             *
1948:             * @param featureIndex feature index to check
1949:             * @return true if the <code>featureIndex</code> feature is turned on
1950:             * @see #FEATURE_NON_ECMA_GET_YEAR
1951:             * @see #FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME
1952:             * @see #FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER
1953:             * @see #FEATURE_TO_STRING_AS_SOURCE
1954:             * @see #FEATURE_PARENT_PROTO_PROPRTIES
1955:             * @see #FEATURE_E4X
1956:             * @see #FEATURE_DYNAMIC_SCOPE
1957:             * @see #FEATURE_STRICT_VARS
1958:             * @see #FEATURE_STRICT_EVAL
1959:             * @see #FEATURE_LOCATION_INFORMATION_IN_ERROR
1960:             * @see #FEATURE_STRICT_MODE
1961:             * @see #FEATURE_WARNING_AS_ERROR
1962:             * @see #FEATURE_ENHANCED_JAVA_ACCESS
1963:             */
1964:            public boolean hasFeature(int featureIndex) {
1965:                ContextFactory f = getFactory();
1966:                return f.hasFeature(this , featureIndex);
1967:            }
1968:
1969:            /**
1970:            	Returns an object which specifies an E4X implementation to use within
1971:            	this <code>Context</code>.  Note
1972:            	that the XMLLib.Factory interface should be considered experimental.
1973:             
1974:            	The default implementation uses the implementation provided by this
1975:            	<code>Context</code>'s {@link ContextFactory}.
1976:             
1977:            	@return An XMLLib.Factory.  Should not return <code>null</code> if
1978:            		{@link #FEATURE_E4X} is enabled.  See {@link #hasFeature}.
1979:             */
1980:            public XMLLib.Factory getE4xImplementationFactory() {
1981:                return getFactory().getE4xImplementationFactory();
1982:            }
1983:
1984:            /**
1985:             * Get threshold of executed instructions counter that triggers call to
1986:             * <code>observeInstructionCount()</code>.
1987:             * When the threshold is zero, instruction counting is disabled,
1988:             * otherwise each time the run-time executes at least the threshold value
1989:             * of script instructions, <code>observeInstructionCount()</code> will
1990:             * be called.
1991:             */
1992:            public final int getInstructionObserverThreshold() {
1993:                return instructionThreshold;
1994:            }
1995:
1996:            /**
1997:             * Set threshold of executed instructions counter that triggers call to
1998:             * <code>observeInstructionCount()</code>.
1999:             * When the threshold is zero, instruction counting is disabled,
2000:             * otherwise each time the run-time executes at least the threshold value
2001:             * of script instructions, <code>observeInstructionCount()</code> will
2002:             * be called.<p/>
2003:             * Note that the meaning of "instruction" is not guaranteed to be
2004:             * consistent between compiled and interpretive modes: executing a given
2005:             * script or function in the different modes will result in different
2006:             * instruction counts against the threshold.
2007:             * {@link #setGenerateObserverCount} is called with true if
2008:             * <code>threshold</code> is greater than zero, false otherwise.
2009:             * @param threshold The instruction threshold
2010:             */
2011:            public final void setInstructionObserverThreshold(int threshold) {
2012:                if (sealed)
2013:                    onSealedMutation();
2014:                if (threshold < 0)
2015:                    throw new IllegalArgumentException();
2016:                instructionThreshold = threshold;
2017:                setGenerateObserverCount(threshold > 0);
2018:            }
2019:
2020:            /**
2021:             * Turn on or off generation of code with callbacks to
2022:             * track the count of executed instructions.
2023:             * Currently only affects JVM byte code generation: this slows down the
2024:             * generated code, but code generated without the callbacks will not
2025:             * be counted toward instruction thresholds. Rhino's interpretive
2026:             * mode does instruction counting without inserting callbacks, so
2027:             * there is no requirement to compile code differently.
2028:             * @param generateObserverCount if true, generated code will contain
2029:             * calls to accumulate an estimate of the instructions executed.
2030:             */
2031:            public void setGenerateObserverCount(boolean generateObserverCount) {
2032:                this .generateObserverCount = generateObserverCount;
2033:            }
2034:
2035:            /**
2036:             * Allow application to monitor counter of executed script instructions
2037:             * in Context subclasses.
2038:             * Run-time calls this when instruction counting is enabled and the counter
2039:             * reaches limit set by <code>setInstructionObserverThreshold()</code>.
2040:             * The method is useful to observe long running scripts and if necessary
2041:             * to terminate them.
2042:             * <p>
2043:             * The instruction counting support is available only for interpreted
2044:             * scripts generated when the optimization level is set to -1.
2045:             * <p>
2046:             * The default implementation calls
2047:             * {@link ContextFactory#observeInstructionCount(Context cx,
2048:             *                                               int instructionCount)}
2049:             * that allows to customize Context behavior without introducing
2050:             * Context subclasses.
2051:             *
2052:             * @param instructionCount amount of script instruction executed since
2053:             * last call to <code>observeInstructionCount</code>
2054:             * @throws Error to terminate the script
2055:             * @see #setOptimizationLevel(int)
2056:             */
2057:            protected void observeInstructionCount(int instructionCount) {
2058:                ContextFactory f = getFactory();
2059:                f.observeInstructionCount(this , instructionCount);
2060:            }
2061:
2062:            /**
2063:             * Create class loader for generated classes.
2064:             * The method calls {@link ContextFactory#createClassLoader(ClassLoader)}
2065:             * using the result of {@link #getFactory()}.
2066:             */
2067:            public GeneratedClassLoader createClassLoader(ClassLoader parent) {
2068:                ContextFactory f = getFactory();
2069:                return f.createClassLoader(parent);
2070:            }
2071:
2072:            public final ClassLoader getApplicationClassLoader() {
2073:                if (applicationClassLoader == null) {
2074:                    ContextFactory f = getFactory();
2075:                    ClassLoader loader = f.getApplicationClassLoader();
2076:                    if (loader == null) {
2077:                        ClassLoader threadLoader = VMBridge.instance
2078:                                .getCurrentThreadClassLoader();
2079:                        if (threadLoader != null
2080:                                && Kit.testIfCanLoadRhinoClasses(threadLoader)) {
2081:                            // Thread.getContextClassLoader is not cached since
2082:                            // its caching prevents it from GC which may lead to
2083:                            // a memory leak and hides updates to
2084:                            // Thread.getContextClassLoader
2085:                            return threadLoader;
2086:                        }
2087:                        // Thread.getContextClassLoader can not load Rhino classes,
2088:                        // try to use the loader of ContextFactory or Context
2089:                        // subclasses.
2090:                        Class fClass = f.getClass();
2091:                        if (fClass != ScriptRuntime.ContextFactoryClass) {
2092:                            loader = fClass.getClassLoader();
2093:                        } else {
2094:                            loader = getClass().getClassLoader();
2095:                        }
2096:                    }
2097:                    applicationClassLoader = loader;
2098:                }
2099:                return applicationClassLoader;
2100:            }
2101:
2102:            public final void setApplicationClassLoader(ClassLoader loader) {
2103:                if (sealed)
2104:                    onSealedMutation();
2105:                if (loader == null) {
2106:                    // restore default behaviour
2107:                    applicationClassLoader = null;
2108:                    return;
2109:                }
2110:                if (!Kit.testIfCanLoadRhinoClasses(loader)) {
2111:                    throw new IllegalArgumentException(
2112:                            "Loader can not resolve Rhino classes");
2113:                }
2114:                applicationClassLoader = loader;
2115:            }
2116:
2117:            /********** end of API **********/
2118:
2119:            /**
2120:             * Internal method that reports an error for missing calls to
2121:             * enter().
2122:             */
2123:            static Context getContext() {
2124:                Context cx = getCurrentContext();
2125:                if (cx == null) {
2126:                    throw new RuntimeException(
2127:                            "No Context associated with current Thread");
2128:                }
2129:                return cx;
2130:            }
2131:
2132:            private Object compileImpl(Scriptable scope, Reader sourceReader,
2133:                    String sourceString, String sourceName, int lineno,
2134:                    Object securityDomain, boolean returnFunction,
2135:                    Evaluator compiler, ErrorReporter compilationErrorReporter)
2136:                    throws IOException {
2137:                if (sourceName == null) {
2138:                    sourceName = "unnamed script";
2139:                }
2140:                if (securityDomain != null && getSecurityController() == null) {
2141:                    throw new IllegalArgumentException(
2142:                            "securityDomain should be null if setSecurityController() was never called");
2143:                }
2144:
2145:                // One of sourceReader or sourceString has to be null
2146:                if (!(sourceReader == null ^ sourceString == null))
2147:                    Kit.codeBug();
2148:                // scope should be given if and only if compiling function
2149:                if (!(scope == null ^ returnFunction))
2150:                    Kit.codeBug();
2151:
2152:                CompilerEnvirons compilerEnv = new CompilerEnvirons();
2153:                compilerEnv.initFromContext(this );
2154:                if (compilationErrorReporter == null) {
2155:                    compilationErrorReporter = compilerEnv.getErrorReporter();
2156:                }
2157:
2158:                if (debugger != null) {
2159:                    if (sourceReader != null) {
2160:                        sourceString = Kit.readReader(sourceReader);
2161:                        sourceReader = null;
2162:                    }
2163:                }
2164:
2165:                Parser p = new Parser(compilerEnv, compilationErrorReporter);
2166:                if (returnFunction) {
2167:                    p.calledByCompileFunction = true;
2168:                }
2169:                ScriptOrFnNode tree;
2170:                if (sourceString != null) {
2171:                    tree = p.parse(sourceString, sourceName, lineno);
2172:                } else {
2173:                    tree = p.parse(sourceReader, sourceName, lineno);
2174:                }
2175:                if (returnFunction) {
2176:                    if (!(tree.getFunctionCount() == 1
2177:                            && tree.getFirstChild() != null && tree
2178:                            .getFirstChild().getType() == Token.FUNCTION)) {
2179:                        // XXX: the check just look for the first child
2180:                        // and allows for more nodes after it for compatibility
2181:                        // with sources like function() {};;;
2182:                        throw new IllegalArgumentException(
2183:                                "compileFunction only accepts source with single JS function: "
2184:                                        + sourceString);
2185:                    }
2186:                }
2187:
2188:                if (compiler == null) {
2189:                    compiler = createCompiler();
2190:                }
2191:
2192:                String encodedSource = p.getEncodedSource();
2193:
2194:                Object bytecode = compiler.compile(compilerEnv, tree,
2195:                        encodedSource, returnFunction);
2196:
2197:                if (debugger != null) {
2198:                    if (sourceString == null)
2199:                        Kit.codeBug();
2200:                    if (bytecode instanceof  DebuggableScript) {
2201:                        DebuggableScript dscript = (DebuggableScript) bytecode;
2202:                        notifyDebugger_r(this , dscript, sourceString);
2203:                    } else {
2204:                        throw new RuntimeException("NOT SUPPORTED");
2205:                    }
2206:                }
2207:
2208:                Object result;
2209:                if (returnFunction) {
2210:                    result = compiler.createFunctionObject(this , scope,
2211:                            bytecode, securityDomain);
2212:                } else {
2213:                    result = compiler.createScriptObject(bytecode,
2214:                            securityDomain);
2215:                }
2216:
2217:                return result;
2218:            }
2219:
2220:            private static void notifyDebugger_r(Context cx,
2221:                    DebuggableScript dscript, String debugSource) {
2222:                cx.debugger.handleCompilationDone(cx, dscript, debugSource);
2223:                for (int i = 0; i != dscript.getFunctionCount(); ++i) {
2224:                    notifyDebugger_r(cx, dscript.getFunction(i), debugSource);
2225:                }
2226:            }
2227:
2228:            private static Class codegenClass = Kit
2229:                    .classOrNull("org.mozilla.javascript.optimizer.Codegen");
2230:            private static Class interpreterClass = Kit
2231:                    .classOrNull("org.mozilla.javascript.Interpreter");
2232:
2233:            private Evaluator createCompiler() {
2234:                Evaluator result = null;
2235:                if (optimizationLevel >= 0 && codegenClass != null) {
2236:                    result = (Evaluator) Kit.newInstanceOrNull(codegenClass);
2237:                }
2238:                if (result == null) {
2239:                    result = createInterpreter();
2240:                }
2241:                return result;
2242:            }
2243:
2244:            static Evaluator createInterpreter() {
2245:                return (Evaluator) Kit.newInstanceOrNull(interpreterClass);
2246:            }
2247:
2248:            static String getSourcePositionFromStack(int[] linep) {
2249:                Context cx = getCurrentContext();
2250:                if (cx == null)
2251:                    return null;
2252:                if (cx.lastInterpreterFrame != null) {
2253:                    Evaluator evaluator = createInterpreter();
2254:                    if (evaluator != null)
2255:                        return evaluator.getSourcePositionFromStack(cx, linep);
2256:                }
2257:                /**
2258:                 * A bit of a hack, but the only way to get filename and line
2259:                 * number from an enclosing frame.
2260:                 */
2261:                CharArrayWriter writer = new CharArrayWriter();
2262:                RuntimeException re = new RuntimeException();
2263:                re.printStackTrace(new PrintWriter(writer));
2264:                String s = writer.toString();
2265:                int open = -1;
2266:                int close = -1;
2267:                int colon = -1;
2268:                for (int i = 0; i < s.length(); i++) {
2269:                    char c = s.charAt(i);
2270:                    if (c == ':')
2271:                        colon = i;
2272:                    else if (c == '(')
2273:                        open = i;
2274:                    else if (c == ')')
2275:                        close = i;
2276:                    else if (c == '\n' && open != -1 && close != -1
2277:                            && colon != -1 && open < colon && colon < close) {
2278:                        String fileStr = s.substring(open + 1, colon);
2279:                        if (!fileStr.endsWith(".java")) {
2280:                            String lineStr = s.substring(colon + 1, close);
2281:                            try {
2282:                                linep[0] = Integer.parseInt(lineStr);
2283:                                if (linep[0] < 0) {
2284:                                    linep[0] = 0;
2285:                                }
2286:                                return fileStr;
2287:                            } catch (NumberFormatException e) {
2288:                                // fall through
2289:                            }
2290:                        }
2291:                        open = close = colon = -1;
2292:                    }
2293:                }
2294:
2295:                return null;
2296:            }
2297:
2298:            RegExpProxy getRegExpProxy() {
2299:                if (regExpProxy == null) {
2300:                    Class cl = Kit
2301:                            .classOrNull("org.mozilla.javascript.regexp.RegExpImpl");
2302:                    if (cl != null) {
2303:                        regExpProxy = (RegExpProxy) Kit.newInstanceOrNull(cl);
2304:                    }
2305:                }
2306:                return regExpProxy;
2307:            }
2308:
2309:            final boolean isVersionECMA1() {
2310:                return version == VERSION_DEFAULT || version >= VERSION_1_3;
2311:            }
2312:
2313:            // The method must NOT be public or protected
2314:            SecurityController getSecurityController() {
2315:                SecurityController global = SecurityController.global();
2316:                if (global != null) {
2317:                    return global;
2318:                }
2319:                return securityController;
2320:            }
2321:
2322:            public final boolean isGeneratingDebugChanged() {
2323:                return generatingDebugChanged;
2324:            }
2325:
2326:            /**
2327:             * Add a name to the list of names forcing the creation of real
2328:             * activation objects for functions.
2329:             *
2330:             * @param name the name of the object to add to the list
2331:             */
2332:            public void addActivationName(String name) {
2333:                if (sealed)
2334:                    onSealedMutation();
2335:                if (activationNames == null)
2336:                    activationNames = new Hashtable(5);
2337:                activationNames.put(name, name);
2338:            }
2339:
2340:            /**
2341:             * Check whether the name is in the list of names of objects
2342:             * forcing the creation of activation objects.
2343:             *
2344:             * @param name the name of the object to test
2345:             *
2346:             * @return true if an function activation object is needed.
2347:             */
2348:            public final boolean isActivationNeeded(String name) {
2349:                return activationNames != null
2350:                        && activationNames.containsKey(name);
2351:            }
2352:
2353:            /**
2354:             * Remove a name from the list of names forcing the creation of real
2355:             * activation objects for functions.
2356:             *
2357:             * @param name the name of the object to remove from the list
2358:             */
2359:            public void removeActivationName(String name) {
2360:                if (sealed)
2361:                    onSealedMutation();
2362:                if (activationNames != null)
2363:                    activationNames.remove(name);
2364:            }
2365:
2366:            private static String implementationVersion;
2367:
2368:            private final ContextFactory factory;
2369:            private boolean sealed;
2370:            private Object sealKey;
2371:
2372:            Scriptable topCallScope;
2373:            NativeCall currentActivationCall;
2374:            XMLLib cachedXMLLib;
2375:
2376:            // for Objects, Arrays to tag themselves as being printed out,
2377:            // so they don't print themselves out recursively.
2378:            // Use ObjToIntMap instead of java.util.HashSet for JDK 1.1 compatibility
2379:            ObjToIntMap iterating;
2380:
2381:            Object interpreterSecurityDomain;
2382:
2383:            int version;
2384:
2385:            private SecurityController securityController;
2386:            private ClassShutter classShutter;
2387:            private ErrorReporter errorReporter;
2388:            RegExpProxy regExpProxy;
2389:            private Locale locale;
2390:            private boolean generatingDebug;
2391:            private boolean generatingDebugChanged;
2392:            private boolean generatingSource = true;
2393:            boolean compileFunctionsWithDynamicScopeFlag;
2394:            boolean useDynamicScope;
2395:            private int optimizationLevel;
2396:            private int maximumInterpreterStackDepth;
2397:            private WrapFactory wrapFactory;
2398:            Debugger debugger;
2399:            private Object debuggerData;
2400:            private int enterCount;
2401:            private Object propertyListeners;
2402:            private Hashtable hashtable;
2403:            private ClassLoader applicationClassLoader;
2404:
2405:            /**
2406:             * This is the list of names of objects forcing the creation of
2407:             * function activation records.
2408:             */
2409:            Hashtable activationNames;
2410:
2411:            // For the interpreter to store the last frame for error reports etc.
2412:            Object lastInterpreterFrame;
2413:
2414:            // For the interpreter to store information about previous invocations
2415:            // interpreter invocations
2416:            ObjArray previousInterpreterInvocations;
2417:
2418:            // For instruction counting (interpreter only)
2419:            int instructionCount;
2420:            int instructionThreshold;
2421:
2422:            // It can be used to return the second index-like result from function
2423:            int scratchIndex;
2424:
2425:            // It can be used to return the second uint32 result from function
2426:            long scratchUint32;
2427:
2428:            // It can be used to return the second Scriptable result from function
2429:            Scriptable scratchScriptable;
2430:
2431:            // Generate an observer count on compiled code
2432:            public boolean generateObserverCount = false;
2433:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.