mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
Rhino code injection
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
public class RhinoInjection extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setContentType("text/plain");
|
||||
String code = request.getParameter("code");
|
||||
Context ctx = Context.enter();
|
||||
try {
|
||||
{
|
||||
// BAD: allow arbitrary Java and JavaScript code to be executed
|
||||
Scriptable scope = ctx.initStandardObjects();
|
||||
}
|
||||
|
||||
{
|
||||
// GOOD: enable the safe mode
|
||||
Scriptable scope = ctx.initSafeStandardObjects();
|
||||
}
|
||||
|
||||
{
|
||||
// GOOD: enforce a constraint on allowed classes
|
||||
Scriptable scope = ctx.initStandardObjects();
|
||||
ctx.setClassShutter(new ClassShutter() {
|
||||
public boolean visibleToScripts(String className) {
|
||||
if(className.startsWith("com.example.")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Object result = ctx.evaluateString(scope, code, "<code>", 1, null);
|
||||
response.getWriter().print(Context.toString(result));
|
||||
} catch(RhinoException ex) {
|
||||
response.getWriter().println(ex.getMessage());
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Rhino is a JavaScript engine written fully in Java and managed by the Mozilla Foundation.
|
||||
It serves as an embedded scripting engine inside Java applications which allows
|
||||
Java-to-JavaScript interoperability and provides a seamless integration between the two
|
||||
languages. If an expression is built using attacker-controlled data, and then evaluated in
|
||||
a powerful context, it may allow the attacker to run arbitrary code.
|
||||
</p>
|
||||
<p>
|
||||
Typically an expression is evaluated in the powerful context initialized with
|
||||
<code>initStandardObjects</code> that allows an expression of arbitrary Java code to
|
||||
execute in the JVM.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
In general, including user input in a Rhino expression should be avoided.
|
||||
If user input must be included in the expression, it should be then evaluated in a safe
|
||||
context that doesn't allow arbitrary code invocation.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows two ways of using Rhino expression. In the 'BAD' case,
|
||||
an unsafe context is initialized with <code>initStandardObjects</code>. In the 'GOOD' case,
|
||||
a safe context is initialized with <code>initSafeStandardObjects</code> or
|
||||
<code>setClassShutter</code>.
|
||||
</p>
|
||||
<sample src="RhinoInjection.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Mozilla Rhino:
|
||||
<a href="https://github.com/mozilla/rhino">Rhino: JavaScript in Java</a>
|
||||
</li>
|
||||
<li>
|
||||
Rhino Sandbox:
|
||||
<a href="https://github.com/javadelight/delight-rhino-sandbox">A sandbox to execute JavaScript code with Rhino in Java.</a>
|
||||
</li>
|
||||
<li>
|
||||
GuardRails:
|
||||
<a href="https://docs.guardrails.io/docs/en/vulnerabilities/java/insecure_use_of_dangerous_function">Code Injection</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @name Injection in Mozilla Rhino JavaScript Engine
|
||||
* @description Evaluation of a user-controlled JavaScript or Java expression in Rhino
|
||||
* JavaScript Engine may lead to remote code execution.
|
||||
* @kind path-problem
|
||||
* @id java/rhino-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-094
|
||||
*/
|
||||
|
||||
import java
|
||||
import RhinoInjection
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, RhinoInjectionConfig conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "Rhino injection from $@.", source.getNode(), " user input"
|
||||
@@ -0,0 +1,56 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
|
||||
/** The class `org.mozilla.javascript.Context`. */
|
||||
class Context extends RefType {
|
||||
Context() { this.hasQualifiedName("org.mozilla.javascript", "Context") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A method that evaluates a Rhino expression.
|
||||
*/
|
||||
class EvaluateExpressionMethod extends Method {
|
||||
EvaluateExpressionMethod() {
|
||||
this.getDeclaringType().getAnAncestor*() instanceof Context and
|
||||
(
|
||||
hasName("evaluateString") or
|
||||
hasName("evaluateReader")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for unsafe user input that is used to evaluate
|
||||
* a Rhino expression.
|
||||
*/
|
||||
class RhinoInjectionConfig extends TaintTracking::Configuration {
|
||||
RhinoInjectionConfig() { this = "RhinoInjectionConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source instanceof RemoteFlowSource
|
||||
or
|
||||
source instanceof LocalUserInput
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof EvaluateExpressionSink }
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink for Rhino code injection vulnerabilities.
|
||||
*/
|
||||
class EvaluateExpressionSink extends DataFlow::ExprNode {
|
||||
EvaluateExpressionSink() {
|
||||
exists(MethodAccess ea, EvaluateExpressionMethod m | m = ea.getMethod() |
|
||||
this.asExpr() = ea.getArgument(1) and // The second argument is the JavaScript or Java input
|
||||
not exists(MethodAccess ca |
|
||||
(
|
||||
ca.getMethod().hasName("initSafeStandardObjects") // safe mode
|
||||
or
|
||||
ca.getMethod().hasName("setClassShutter") // `ClassShutter` constraint is enforced
|
||||
) and
|
||||
ea.getQualifier() = ca.getQualifier().(VarAccess).getVariable().getAnAccess()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
edges
|
||||
| RhinoServlet.java:25:23:25:50 | getParameter(...) : String | RhinoServlet.java:29:55:29:58 | code |
|
||||
nodes
|
||||
| RhinoServlet.java:25:23:25:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| RhinoServlet.java:29:55:29:58 | code | semmle.label | code |
|
||||
#select
|
||||
| RhinoServlet.java:29:55:29:58 | code | RhinoServlet.java:25:23:25:50 | getParameter(...) : String | RhinoServlet.java:29:55:29:58 | code | Rhino injection from $@. | RhinoServlet.java:25:23:25:50 | getParameter(...) | user input |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-094/RhinoInjection.ql
|
||||
@@ -0,0 +1,78 @@
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.mozilla.javascript.ClassShutter;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.RhinoException;
|
||||
|
||||
/**
|
||||
* Servlet implementation class RhinoServlet
|
||||
*/
|
||||
public class RhinoServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RhinoServlet() {
|
||||
super();
|
||||
}
|
||||
|
||||
// BAD: allow arbitrary Java and JavaScript code to be executed
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setContentType("text/plain");
|
||||
String code = request.getParameter("code");
|
||||
Context ctx = Context.enter();
|
||||
try {
|
||||
Scriptable scope = ctx.initStandardObjects();
|
||||
Object result = ctx.evaluateString(scope, code, "<code>", 1, null);
|
||||
response.getWriter().print(Context.toString(result));
|
||||
} catch(RhinoException ex) {
|
||||
response.getWriter().println(ex.getMessage());
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: enable the safe mode
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setContentType("text/plain");
|
||||
String code = request.getParameter("code");
|
||||
Context ctx = Context.enter();
|
||||
try {
|
||||
Scriptable scope = ctx.initSafeStandardObjects();
|
||||
Object result = ctx.evaluateString(scope, code, "<code>", 1, null);
|
||||
response.getWriter().print(Context.toString(result));
|
||||
} catch(RhinoException ex) {
|
||||
response.getWriter().println(ex.getMessage());
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: enforce a constraint on allowed classes
|
||||
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setContentType("text/plain");
|
||||
String code = request.getParameter("code");
|
||||
Context ctx = Context.enter();
|
||||
try {
|
||||
Scriptable scope = ctx.initStandardObjects();
|
||||
ctx.setClassShutter(new ClassShutter() {
|
||||
public boolean visibleToScripts(String className) {
|
||||
if(className.startsWith("com.example.")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Object result = ctx.evaluateString(scope, code, "<code>", 1, null);
|
||||
response.getWriter().print(Context.toString(result));
|
||||
} catch(RhinoException ex) {
|
||||
response.getWriter().println(ex.getMessage());
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2:${testdir}/../../../../experimental/stubs/rhino-1.7.13
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
Embeddings that wish to filter Java classes that are visible to scripts
|
||||
through the LiveConnect, should implement this interface.
|
||||
|
||||
@see Context#setClassShutter(ClassShutter)
|
||||
@since 1.5 Release 4
|
||||
@author Norris Boyd
|
||||
*/
|
||||
|
||||
public interface ClassShutter {
|
||||
|
||||
/**
|
||||
* Return true iff the Java class with the given name should be exposed
|
||||
* to scripts.
|
||||
* <p>
|
||||
* An embedding may filter which Java classes are exposed through
|
||||
* LiveConnect to JavaScript scripts.
|
||||
* <p>
|
||||
* Due to the fact that there is no package reflection in Java,
|
||||
* this method will also be called with package names. There
|
||||
* is no way for Rhino to tell if "Packages.a.b" is a package name
|
||||
* or a class that doesn't exist. What Rhino does is attempt
|
||||
* to load each segment of "Packages.a.b.c": It first attempts to
|
||||
* load class "a", then attempts to load class "a.b", then
|
||||
* finally attempts to load class "a.b.c". On a Rhino installation
|
||||
* without any ClassShutter set, and without any of the
|
||||
* above classes, the expression "Packages.a.b.c" will result in
|
||||
* a [JavaPackage a.b.c] and not an error.
|
||||
* <p>
|
||||
* With ClassShutter supplied, Rhino will first call
|
||||
* visibleToScripts before attempting to look up the class name. If
|
||||
* visibleToScripts returns false, the class name lookup is not
|
||||
* performed and subsequent Rhino execution assumes the class is
|
||||
* not present. So for "java.lang.System.out.println" the lookup
|
||||
* of "java.lang.System" is skipped and thus Rhino assumes that
|
||||
* "java.lang.System" doesn't exist. So then for "java.lang.System.out",
|
||||
* Rhino attempts to load the class "java.lang.System.out" because
|
||||
* it assumes that "java.lang.System" is a package name.
|
||||
* <p>
|
||||
* @param fullClassName the full name of the class (including the package
|
||||
* name, with '.' as a delimiter). For example the
|
||||
* standard string class is "java.lang.String"
|
||||
* @return whether or not to reveal this class to scripts
|
||||
*/
|
||||
public boolean visibleToScripts(String fullClassName);
|
||||
}
|
||||
@@ -0,0 +1,623 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* This class represents the runtime context of an executing script.
|
||||
*
|
||||
* Before executing a script, an instance of Context must be created
|
||||
* and associated with the thread that will be executing the script.
|
||||
* The Context will be used to store information about the executing
|
||||
* of the script such as the call stack. Contexts are associated with
|
||||
* the current thread using the {@link #call(ContextAction)}
|
||||
* or {@link #enter()} methods.<p>
|
||||
*
|
||||
* Different forms of script execution are supported. Scripts may be
|
||||
* evaluated from the source directly, or first compiled and then later
|
||||
* executed. Interactive execution is also supported.<p>
|
||||
*
|
||||
* Some aspects of script execution, such as type conversions and
|
||||
* object creation, may be accessed directly through methods of
|
||||
* Context.
|
||||
*
|
||||
* @see Scriptable
|
||||
* @author Norris Boyd
|
||||
* @author Brendan Eich
|
||||
*/
|
||||
|
||||
public class Context
|
||||
implements Closeable
|
||||
{
|
||||
/**
|
||||
* Creates a new Context. The context will be associated with the {@link
|
||||
* ContextFactory#getGlobal() global context factory}.
|
||||
*
|
||||
* Note that the Context must be associated with a thread before
|
||||
* it can be used to execute a script.
|
||||
* @deprecated this constructor is deprecated because it creates a
|
||||
* dependency on a static singleton context factory. Use
|
||||
* {@link ContextFactory#enter()} or
|
||||
* {@link ContextFactory#call(ContextAction)} instead. If you subclass
|
||||
* this class, consider using {@link #Context(ContextFactory)} constructor
|
||||
* instead in the subclasses' constructors.
|
||||
*/
|
||||
@Deprecated
|
||||
public Context()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new context. Provided as a preferred super constructor for
|
||||
* subclasses in place of the deprecated default public constructor.
|
||||
* @param factory the context factory associated with this context (most
|
||||
* likely, the one that created the context). Can not be null. The context
|
||||
* features are inherited from the factory, and the context will also
|
||||
* otherwise use its factory's services.
|
||||
* @throws IllegalArgumentException if factory parameter is null.
|
||||
*/
|
||||
protected Context(ContextFactory factory)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current Context.
|
||||
*
|
||||
* The current Context is per-thread; this method looks up
|
||||
* the Context associated with the current thread. <p>
|
||||
*
|
||||
* @return the Context associated with the current thread, or
|
||||
* null if no context is associated with the current
|
||||
* thread.
|
||||
* @see ContextFactory#enterContext()
|
||||
* @see ContextFactory#call(ContextAction)
|
||||
*/
|
||||
public static Context getCurrentContext()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as calling {@link ContextFactory#enterContext()} on the global
|
||||
* ContextFactory instance.
|
||||
* @return a Context associated with the current thread
|
||||
* @see #getCurrentContext()
|
||||
* @see #exit()
|
||||
* @see #call(ContextAction)
|
||||
*/
|
||||
public static Context enter()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Context associated with the current thread, using
|
||||
* the given Context if need be.
|
||||
* <p>
|
||||
* The same as <code>enter()</code> except that <code>cx</code>
|
||||
* is associated with the current thread and returned if
|
||||
* the current thread has no associated context and <code>cx</code>
|
||||
* is not associated with any other thread.
|
||||
* @param cx a Context to associate with the thread if possible
|
||||
* @return a Context associated with the current thread
|
||||
* @deprecated use {@link ContextFactory#enterContext(Context)} instead as
|
||||
* this method relies on usage of a static singleton "global" ContextFactory.
|
||||
* @see ContextFactory#enterContext(Context)
|
||||
* @see ContextFactory#call(ContextAction)
|
||||
*/
|
||||
@Deprecated
|
||||
public static Context enter(Context cx)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
static final Context enter(Context cx, ContextFactory factory)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit a block of code requiring a Context.
|
||||
*
|
||||
* Calling <code>exit()</code> will remove the association between
|
||||
* the current thread and a Context if the prior call to
|
||||
* {@link ContextFactory#enterContext()} on this thread newly associated a
|
||||
* Context with this thread. Once the current thread no longer has an
|
||||
* associated Context, it cannot be used to execute JavaScript until it is
|
||||
* again associated with a Context.
|
||||
* @see ContextFactory#enterContext()
|
||||
*/
|
||||
public static void exit()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link ContextFactory} instance used to create this Context.
|
||||
*/
|
||||
public final ContextFactory getFactory()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this is a sealed Context. A sealed Context instance does not
|
||||
* allow to modify any of its properties and will throw an exception
|
||||
* on any such attempt.
|
||||
* @see #seal(Object sealKey)
|
||||
*/
|
||||
public final boolean isSealed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seal this Context object so any attempt to modify any of its properties
|
||||
* including calling {@link #enter()} and {@link #exit()} methods will
|
||||
* throw an exception.
|
||||
* <p>
|
||||
* If <code>sealKey</code> is not null, calling
|
||||
* {@link #unseal(Object sealKey)} with the same key unseals
|
||||
* the object. If <code>sealKey</code> is null, unsealing is no longer possible.
|
||||
*
|
||||
* @see #isSealed()
|
||||
* @see #unseal(Object)
|
||||
*/
|
||||
public final void seal(Object sealKey)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Unseal previously sealed Context object.
|
||||
* The <code>sealKey</code> argument should not be null and should match
|
||||
* <code>sealKey</code> suplied with the last call to
|
||||
* {@link #seal(Object)} or an exception will be thrown.
|
||||
*
|
||||
* @see #isSealed()
|
||||
* @see #seal(Object sealKey)
|
||||
*/
|
||||
public final void unseal(Object sealKey)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current language version.
|
||||
* <p>
|
||||
* The language version number affects JavaScript semantics as detailed
|
||||
* in the overview documentation.
|
||||
*
|
||||
* @return an integer that is one of VERSION_1_0, VERSION_1_1, etc.
|
||||
*/
|
||||
public final int getLanguageVersion()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the language version.
|
||||
*
|
||||
* <p>
|
||||
* Setting the language version will affect functions and scripts compiled
|
||||
* subsequently. See the overview documentation for version-specific
|
||||
* behavior.
|
||||
*
|
||||
* @param version the version as specified by VERSION_1_0, VERSION_1_1, etc.
|
||||
*/
|
||||
public void setLanguageVersion(int version)
|
||||
{
|
||||
}
|
||||
|
||||
public static boolean isValidLanguageVersion(int version)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void checkLanguageVersion(int version)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the implementation version.
|
||||
*
|
||||
* <p>
|
||||
* The implementation version is of the form
|
||||
* <pre>
|
||||
* "<i>name langVer</i> <code>release</code> <i>relNum date</i>"
|
||||
* </pre>
|
||||
* where <i>name</i> is the name of the product, <i>langVer</i> is
|
||||
* the language version, <i>relNum</i> is the release number, and
|
||||
* <i>date</i> is the release date for that specific
|
||||
* release in the form "yyyy mm dd".
|
||||
*
|
||||
* @return a string that encodes the product, language version, release
|
||||
* number, and date.
|
||||
*/
|
||||
public final String getImplementationVersion() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the standard objects.
|
||||
*
|
||||
* Creates instances of the standard objects and their constructors
|
||||
* (Object, String, Number, Date, etc.), setting up 'scope' to act
|
||||
* as a global object as in ECMA 15.1.<p>
|
||||
*
|
||||
* This method must be called to initialize a scope before scripts
|
||||
* can be evaluated in that scope.<p>
|
||||
*
|
||||
* This method does not affect the Context it is called upon.
|
||||
*
|
||||
* @return the initialized scope
|
||||
*/
|
||||
public final ScriptableObject initStandardObjects()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the standard objects, leaving out those that offer access directly
|
||||
* to Java classes. This sets up "scope" to have access to all the standard
|
||||
* JavaScript classes, but does not create global objects for any top-level
|
||||
* Java packages. In addition, the "Packages," "JavaAdapter," and
|
||||
* "JavaImporter" classes, and the "getClass" function, are not
|
||||
* initialized.
|
||||
*
|
||||
* The result of this function is a scope that may be safely used in a "sandbox"
|
||||
* environment where it is not desirable to give access to Java code from JavaScript.
|
||||
*
|
||||
* Creates instances of the standard objects and their constructors
|
||||
* (Object, String, Number, Date, etc.), setting up 'scope' to act
|
||||
* as a global object as in ECMA 15.1.<p>
|
||||
*
|
||||
* This method must be called to initialize a scope before scripts
|
||||
* can be evaluated in that scope.<p>
|
||||
*
|
||||
* This method does not affect the Context it is called upon.
|
||||
*
|
||||
* @return the initialized scope
|
||||
*/
|
||||
public final ScriptableObject initSafeStandardObjects()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the standard objects.
|
||||
*
|
||||
* Creates instances of the standard objects and their constructors
|
||||
* (Object, String, Number, Date, etc.), setting up 'scope' to act
|
||||
* as a global object as in ECMA 15.1.<p>
|
||||
*
|
||||
* This method must be called to initialize a scope before scripts
|
||||
* can be evaluated in that scope.<p>
|
||||
*
|
||||
* This method does not affect the Context it is called upon.
|
||||
*
|
||||
* @param scope the scope to initialize, or null, in which case a new
|
||||
* object will be created to serve as the scope
|
||||
* @return the initialized scope. The method returns the value of the scope
|
||||
* argument if it is not null or newly allocated scope object which
|
||||
* is an instance {@link ScriptableObject}.
|
||||
*/
|
||||
public final Scriptable initStandardObjects(ScriptableObject scope)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the standard objects, leaving out those that offer access directly
|
||||
* to Java classes. This sets up "scope" to have access to all the standard
|
||||
* JavaScript classes, but does not create global objects for any top-level
|
||||
* Java packages. In addition, the "Packages," "JavaAdapter," and
|
||||
* "JavaImporter" classes, and the "getClass" function, are not
|
||||
* initialized.
|
||||
*
|
||||
* The result of this function is a scope that may be safely used in a "sandbox"
|
||||
* environment where it is not desirable to give access to Java code from JavaScript.
|
||||
*
|
||||
* Creates instances of the standard objects and their constructors
|
||||
* (Object, String, Number, Date, etc.), setting up 'scope' to act
|
||||
* as a global object as in ECMA 15.1.<p>
|
||||
*
|
||||
* This method must be called to initialize a scope before scripts
|
||||
* can be evaluated in that scope.<p>
|
||||
*
|
||||
* This method does not affect the Context it is called upon.
|
||||
*
|
||||
* @param scope the scope to initialize, or null, in which case a new
|
||||
* object will be created to serve as the scope
|
||||
* @return the initialized scope. The method returns the value of the scope
|
||||
* argument if it is not null or newly allocated scope object which
|
||||
* is an instance {@link ScriptableObject}.
|
||||
*/
|
||||
public final Scriptable initSafeStandardObjects(ScriptableObject scope)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the standard objects.
|
||||
*
|
||||
* Creates instances of the standard objects and their constructors
|
||||
* (Object, String, Number, Date, etc.), setting up 'scope' to act
|
||||
* as a global object as in ECMA 15.1.<p>
|
||||
*
|
||||
* This method must be called to initialize a scope before scripts
|
||||
* can be evaluated in that scope.<p>
|
||||
*
|
||||
* This method does not affect the Context it is called upon.<p>
|
||||
*
|
||||
* This form of the method also allows for creating "sealed" standard
|
||||
* objects. An object that is sealed cannot have properties added, changed,
|
||||
* or removed. This is useful to create a "superglobal" that can be shared
|
||||
* among several top-level objects. Note that sealing is not allowed in
|
||||
* the current ECMA/ISO language specification, but is likely for
|
||||
* the next version.
|
||||
*
|
||||
* @param scope the scope to initialize, or null, in which case a new
|
||||
* object will be created to serve as the scope
|
||||
* @param sealed whether or not to create sealed standard objects that
|
||||
* cannot be modified.
|
||||
* @return the initialized scope. The method returns the value of the scope
|
||||
* argument if it is not null or newly allocated scope object.
|
||||
* @since 1.4R3
|
||||
*/
|
||||
public ScriptableObject initStandardObjects(ScriptableObject scope,
|
||||
boolean sealed)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the standard objects, leaving out those that offer access directly
|
||||
* to Java classes. This sets up "scope" to have access to all the standard
|
||||
* JavaScript classes, but does not create global objects for any top-level
|
||||
* Java packages. In addition, the "Packages," "JavaAdapter," and
|
||||
* "JavaImporter" classes, and the "getClass" function, are not
|
||||
* initialized.
|
||||
*
|
||||
* The result of this function is a scope that may be safely used in a "sandbox"
|
||||
* environment where it is not desirable to give access to Java code from JavaScript.
|
||||
*
|
||||
* Creates instances of the standard objects and their constructors
|
||||
* (Object, String, Number, Date, etc.), setting up 'scope' to act
|
||||
* as a global object as in ECMA 15.1.<p>
|
||||
*
|
||||
* This method must be called to initialize a scope before scripts
|
||||
* can be evaluated in that scope.<p>
|
||||
*
|
||||
* This method does not affect the Context it is called upon.<p>
|
||||
*
|
||||
* This form of the method also allows for creating "sealed" standard
|
||||
* objects. An object that is sealed cannot have properties added, changed,
|
||||
* or removed. This is useful to create a "superglobal" that can be shared
|
||||
* among several top-level objects. Note that sealing is not allowed in
|
||||
* the current ECMA/ISO language specification, but is likely for
|
||||
* the next version.
|
||||
*
|
||||
* @param scope the scope to initialize, or null, in which case a new
|
||||
* object will be created to serve as the scope
|
||||
* @param sealed whether or not to create sealed standard objects that
|
||||
* cannot be modified.
|
||||
* @return the initialized scope. The method returns the value of the scope
|
||||
* argument if it is not null or newly allocated scope object.
|
||||
* @since 1.7.6
|
||||
*/
|
||||
public ScriptableObject initSafeStandardObjects(ScriptableObject scope,
|
||||
boolean sealed)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton object that represents the JavaScript Undefined value.
|
||||
*/
|
||||
public static Object getUndefinedValue()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a JavaScript source string.
|
||||
*
|
||||
* The provided source name and line number are used for error messages
|
||||
* and for producing debug information.
|
||||
*
|
||||
* @param scope the scope to execute in
|
||||
* @param source the JavaScript source
|
||||
* @param sourceName a string describing the source, such as a filename
|
||||
* @param lineno the starting line number
|
||||
* @param securityDomain an arbitrary object that specifies security
|
||||
* information about the origin or owner of the script. For
|
||||
* implementations that don't care about security, this value
|
||||
* may be null.
|
||||
* @return the result of evaluating the string
|
||||
* @see org.mozilla.javascript.SecurityController
|
||||
*/
|
||||
public final Object evaluateString(Scriptable scope, String source,
|
||||
String sourceName, int lineno,
|
||||
Object securityDomain)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a reader as JavaScript source.
|
||||
*
|
||||
* All characters of the reader are consumed.
|
||||
*
|
||||
* @param scope the scope to execute in
|
||||
* @param in the Reader to get JavaScript source from
|
||||
* @param sourceName a string describing the source, such as a filename
|
||||
* @param lineno the starting line number
|
||||
* @param securityDomain an arbitrary object that specifies security
|
||||
* information about the origin or owner of the script. For
|
||||
* implementations that don't care about security, this value
|
||||
* may be null.
|
||||
* @return the result of evaluating the source
|
||||
*
|
||||
* @exception IOException if an IOException was generated by the Reader
|
||||
*/
|
||||
public final Object evaluateReader(Scriptable scope, Reader in,
|
||||
String sourceName, int lineno,
|
||||
Object securityDomain)
|
||||
throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to a JavaScript boolean value.
|
||||
* <p>
|
||||
* See ECMA 9.2.
|
||||
*
|
||||
* @param value a JavaScript value
|
||||
* @return the corresponding boolean value converted using
|
||||
* the ECMA rules
|
||||
*/
|
||||
public static boolean toBoolean(Object value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to a JavaScript Number value.
|
||||
* <p>
|
||||
* Returns a Java double for the JavaScript Number.
|
||||
* <p>
|
||||
* See ECMA 9.3.
|
||||
*
|
||||
* @param value a JavaScript value
|
||||
* @return the corresponding double value converted using
|
||||
* the ECMA rules
|
||||
*/
|
||||
public static double toNumber(Object value)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to a JavaScript String value.
|
||||
* <p>
|
||||
* See ECMA 9.8.
|
||||
* <p>
|
||||
* @param value a JavaScript value
|
||||
* @return the corresponding String value converted using
|
||||
* the ECMA rules
|
||||
*/
|
||||
public static String toString(Object value)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to an JavaScript object value.
|
||||
* <p>
|
||||
* Note that a scope must be provided to look up the constructors
|
||||
* for Number, Boolean, and String.
|
||||
* <p>
|
||||
* See ECMA 9.9.
|
||||
* <p>
|
||||
* Additionally, arbitrary Java objects and classes will be
|
||||
* wrapped in a Scriptable object with its Java fields and methods
|
||||
* reflected as JavaScript properties of the object.
|
||||
*
|
||||
* @param value any Java object
|
||||
* @param scope global scope containing constructors for Number,
|
||||
* Boolean, and String
|
||||
* @return new JavaScript object
|
||||
*/
|
||||
public static Scriptable toObject(Object value, Scriptable scope)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient method to convert java value to its closest representation
|
||||
* in JavaScript.
|
||||
* <p>
|
||||
* If value is an instance of String, Number, Boolean, Function or
|
||||
* Scriptable, it is returned as it and will be treated as the corresponding
|
||||
* JavaScript type of string, number, boolean, function and object.
|
||||
* <p>
|
||||
* Note that for Number instances during any arithmetic operation in
|
||||
* JavaScript the engine will always use the result of
|
||||
* <code>Number.doubleValue()</code> resulting in a precision loss if
|
||||
* the number can not fit into double.
|
||||
* <p>
|
||||
* If value is an instance of Character, it will be converted to string of
|
||||
* length 1 and its JavaScript type will be string.
|
||||
* <p>
|
||||
* The rest of values will be wrapped as LiveConnect objects
|
||||
* by calling {@link WrapFactory#wrap(Context cx, Scriptable scope,
|
||||
* Object obj, Class staticType)} as in:
|
||||
* <pre>
|
||||
* Context cx = Context.getCurrentContext();
|
||||
* return cx.getWrapFactory().wrap(cx, scope, value, null);
|
||||
* </pre>
|
||||
*
|
||||
* @param value any Java object
|
||||
* @param scope top scope object
|
||||
* @return value suitable to pass to any API that takes JavaScript values.
|
||||
*/
|
||||
public static Object javaToJS(Object value, Scriptable scope)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JavaScript value into the desired type.
|
||||
* Uses the semantics defined with LiveConnect3 and throws an
|
||||
* Illegal argument exception if the conversion cannot be performed.
|
||||
* @param value the JavaScript value to convert
|
||||
* @param desiredType the Java type to convert to. Primitive Java
|
||||
* types are represented using the TYPE fields in the corresponding
|
||||
* wrapper class in java.lang.
|
||||
* @return the converted value
|
||||
* @throws EvaluatorException if the conversion cannot be performed
|
||||
*/
|
||||
public static Object jsToJava(Object value, Class<?> desiredType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the LiveConnect access filter for this context.
|
||||
* <p> {@link ClassShutter} may only be set if it is currently null.
|
||||
* Otherwise a SecurityException is thrown.
|
||||
* @param shutter a ClassShutter object
|
||||
* @throws SecurityException if there is already a ClassShutter
|
||||
* object for this Context
|
||||
*/
|
||||
public synchronized final void setClassShutter(ClassShutter shutter)
|
||||
{
|
||||
}
|
||||
|
||||
final synchronized ClassShutter getClassShutter()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public interface ClassShutterSetter {
|
||||
public void setClassShutter(ClassShutter shutter);
|
||||
public ClassShutter getClassShutter();
|
||||
}
|
||||
|
||||
public final synchronized ClassShutterSetter getClassShutterSetter() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* Factory class that Rhino runtime uses to create new {@link Context}
|
||||
* instances. A <code>ContextFactory</code> can also notify listeners
|
||||
* about context creation and release.
|
||||
* <p>
|
||||
* When the Rhino runtime needs to create new {@link Context} instance during
|
||||
* execution of {@link Context#enter()} or {@link Context}, it will call
|
||||
* {@link #makeContext()} of the current global ContextFactory.
|
||||
* See {@link #getGlobal()} and {@link #initGlobal(ContextFactory)}.
|
||||
* <p>
|
||||
* It is also possible to use explicit ContextFactory instances for Context
|
||||
* creation. This is useful to have a set of independent Rhino runtime
|
||||
* instances under single JVM. See {@link #call(ContextAction)}.
|
||||
* <p>
|
||||
* The following example demonstrates Context customization to terminate
|
||||
* scripts running more then 10 seconds and to provide better compatibility
|
||||
* with JavaScript code using MSIE-specific features.
|
||||
* <pre>
|
||||
* import org.mozilla.javascript.*;
|
||||
*
|
||||
* class MyFactory extends ContextFactory
|
||||
* {
|
||||
*
|
||||
* // Custom {@link Context} to store execution time.
|
||||
* private static class MyContext extends Context
|
||||
* {
|
||||
* long startTime;
|
||||
* }
|
||||
*
|
||||
* static {
|
||||
* // Initialize GlobalFactory with custom factory
|
||||
* ContextFactory.initGlobal(new MyFactory());
|
||||
* }
|
||||
*
|
||||
* // Override {@link #makeContext()}
|
||||
* protected Context makeContext()
|
||||
* {
|
||||
* MyContext cx = new MyContext();
|
||||
* // Make Rhino runtime to call observeInstructionCount
|
||||
* // each 10000 bytecode instructions
|
||||
* cx.setInstructionObserverThreshold(10000);
|
||||
* return cx;
|
||||
* }
|
||||
*
|
||||
* // Override {@link #hasFeature(Context, int)}
|
||||
* public boolean hasFeature(Context cx, int featureIndex)
|
||||
* {
|
||||
* // Turn on maximum compatibility with MSIE scripts
|
||||
* switch (featureIndex) {
|
||||
* case {@link Context#FEATURE_NON_ECMA_GET_YEAR}:
|
||||
* return true;
|
||||
*
|
||||
* case {@link Context#FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME}:
|
||||
* return true;
|
||||
*
|
||||
* case {@link Context#FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER}:
|
||||
* return true;
|
||||
*
|
||||
* case {@link Context#FEATURE_PARENT_PROTO_PROPERTIES}:
|
||||
* return false;
|
||||
* }
|
||||
* return super.hasFeature(cx, featureIndex);
|
||||
* }
|
||||
*
|
||||
* // Override {@link #observeInstructionCount(Context, int)}
|
||||
* protected void observeInstructionCount(Context cx, int instructionCount)
|
||||
* {
|
||||
* MyContext mcx = (MyContext)cx;
|
||||
* long currentTime = System.currentTimeMillis();
|
||||
* if (currentTime - mcx.startTime > 10*1000) {
|
||||
* // More then 10 seconds from Context creation time:
|
||||
* // it is time to stop the script.
|
||||
* // Throw Error instance to ensure that script will never
|
||||
* // get control back through catch or finally.
|
||||
* throw new Error();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // Override {@link #doTopCall(Callable,
|
||||
Context, Scriptable,
|
||||
Scriptable, Object[])}
|
||||
* protected Object doTopCall(Callable callable,
|
||||
* Context cx, Scriptable scope,
|
||||
* Scriptable thisObj, Object[] args)
|
||||
* {
|
||||
* MyContext mcx = (MyContext)cx;
|
||||
* mcx.startTime = System.currentTimeMillis();
|
||||
*
|
||||
* return super.doTopCall(callable, cx, scope, thisObj, args);
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
public class ContextFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* Listener of {@link Context} creation and release events.
|
||||
*/
|
||||
public interface Listener
|
||||
{
|
||||
/**
|
||||
* Notify about newly created {@link Context} object.
|
||||
*/
|
||||
public void contextCreated(Context cx);
|
||||
|
||||
/**
|
||||
* Notify that the specified {@link Context} instance is no longer
|
||||
* associated with the current thread.
|
||||
*/
|
||||
public void contextReleased(Context cx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get global ContextFactory.
|
||||
*
|
||||
* @see #hasExplicitGlobal()
|
||||
* @see #initGlobal(ContextFactory)
|
||||
*/
|
||||
public static ContextFactory getGlobal()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if global factory was set.
|
||||
* Return true to indicate that {@link #initGlobal(ContextFactory)} was
|
||||
* already called and false to indicate that the global factory was not
|
||||
* explicitly set.
|
||||
*
|
||||
* @see #getGlobal()
|
||||
* @see #initGlobal(ContextFactory)
|
||||
*/
|
||||
public static boolean hasExplicitGlobal()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set global ContextFactory.
|
||||
* The method can only be called once.
|
||||
*
|
||||
* @see #getGlobal()
|
||||
* @see #hasExplicitGlobal()
|
||||
*/
|
||||
public synchronized static void initGlobal(ContextFactory factory)
|
||||
{
|
||||
}
|
||||
|
||||
public interface GlobalSetter {
|
||||
public void setContextFactoryGlobal(ContextFactory factory);
|
||||
public ContextFactory getContextFactoryGlobal();
|
||||
}
|
||||
|
||||
public synchronized static GlobalSetter getGlobalSetter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new {@link Context} instance to be associated with the current
|
||||
* thread.
|
||||
* This is a callback method used by Rhino to create {@link Context}
|
||||
* instance when it is necessary to associate one with the current
|
||||
* execution thread. <code>makeContext()</code> is allowed to call
|
||||
* {@link Context#seal(Object)} on the result to prevent
|
||||
* {@link Context} changes by hostile scripts or applets.
|
||||
*/
|
||||
protected Context makeContext()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of {@link Context#hasFeature(int featureIndex)}.
|
||||
* This can be used to customize {@link Context} without introducing
|
||||
* additional subclasses.
|
||||
*/
|
||||
protected boolean hasFeature(Context cx, int featureIndex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ClassLoader to use when searching for Java classes.
|
||||
* Unless it was explicitly initialized with
|
||||
* {@link #initApplicationClassLoader(ClassLoader)} the method returns
|
||||
* null to indicate that Thread.getContextClassLoader() should be used.
|
||||
*/
|
||||
public final ClassLoader getApplicationClassLoader()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set explicit class loader to use when searching for Java classes.
|
||||
*
|
||||
* @see #getApplicationClassLoader()
|
||||
*/
|
||||
public final void initApplicationClassLoader(ClassLoader loader)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this is a sealed ContextFactory.
|
||||
* @see #seal()
|
||||
*/
|
||||
public final boolean isSealed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seal this ContextFactory so any attempt to modify it like to add or
|
||||
* remove its listeners will throw an exception.
|
||||
* @see #isSealed()
|
||||
*/
|
||||
public final void seal()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a context associated with the current thread, creating one if need
|
||||
* be. The Context stores the execution state of the JavaScript engine, so
|
||||
* it is required that the context be entered before execution may begin.
|
||||
* Once a thread has entered a Context, then getCurrentContext() may be
|
||||
* called to find the context that is associated with the current thread.
|
||||
* <p>
|
||||
* Calling <code>enterContext()</code> will return either the Context
|
||||
* currently associated with the thread, or will create a new context and
|
||||
* associate it with the current thread. Each call to
|
||||
* <code>enterContext()</code> must have a matching call to
|
||||
* {@link Context#exit()}.
|
||||
* <pre>
|
||||
* Context cx = contextFactory.enterContext();
|
||||
* try {
|
||||
* ...
|
||||
* cx.evaluateString(...);
|
||||
* } finally {
|
||||
* Context.exit();
|
||||
* }
|
||||
* </pre>
|
||||
* Instead of using <code>enterContext()</code>, <code>exit()</code> pair consider
|
||||
* using {@link #call(ContextAction)} which guarantees proper association
|
||||
* of Context instances with the current thread.
|
||||
* With this method the above example becomes:
|
||||
* <pre>
|
||||
* ContextFactory.call(new ContextAction() {
|
||||
* public Object run(Context cx) {
|
||||
* ...
|
||||
* cx.evaluateString(...);
|
||||
* return null;
|
||||
* }
|
||||
* });
|
||||
* </pre>
|
||||
* @return a Context associated with the current thread
|
||||
* @see Context#getCurrentContext()
|
||||
* @see Context#exit()
|
||||
* @see #call(ContextAction)
|
||||
*/
|
||||
public Context enterContext()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #enterContext()} instead
|
||||
* @return a Context associated with the current thread
|
||||
*/
|
||||
@Deprecated
|
||||
public final Context enter()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link Context#exit()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final void exit()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Context associated with the current thread, using the given
|
||||
* Context if need be.
|
||||
* <p>
|
||||
* The same as <code>enterContext()</code> except that <code>cx</code>
|
||||
* is associated with the current thread and returned if the current thread
|
||||
* has no associated context and <code>cx</code> is not associated with any
|
||||
* other thread.
|
||||
* @param cx a Context to associate with the thread if possible
|
||||
* @return a Context associated with the current thread
|
||||
* @see #enterContext()
|
||||
* @see #call(ContextAction)
|
||||
* @throws IllegalStateException if <code>cx</code> is already associated
|
||||
* with a different thread
|
||||
*/
|
||||
public final Context enterContext(Context cx)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* The class of exceptions thrown by the JavaScript engine.
|
||||
*/
|
||||
public abstract class RhinoException extends RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* This is interface that all objects in JavaScript must implement.
|
||||
* The interface provides for the management of properties and for
|
||||
* performing conversions.
|
||||
* <p>
|
||||
* Host system implementors may find it easier to extend the ScriptableObject
|
||||
* class rather than implementing Scriptable when writing host objects.
|
||||
* <p>
|
||||
* There are many static methods defined in ScriptableObject that perform
|
||||
* the multiple calls to the Scriptable interface needed in order to
|
||||
* manipulate properties in prototype chains.
|
||||
* <p>
|
||||
*
|
||||
* @see org.mozilla.javascript.ScriptableObject
|
||||
* @author Norris Boyd
|
||||
* @author Nick Thompson
|
||||
* @author Brendan Eich
|
||||
*/
|
||||
|
||||
public interface Scriptable {
|
||||
|
||||
/**
|
||||
* Get the name of the set of objects implemented by this Java class.
|
||||
* This corresponds to the [[Class]] operation in ECMA and is used
|
||||
* by Object.prototype.toString() in ECMA.<p>
|
||||
* See ECMA 8.6.2 and 15.2.4.2.
|
||||
*/
|
||||
public String getClassName();
|
||||
|
||||
/**
|
||||
* Get a named property from the object.
|
||||
*
|
||||
* Looks property up in this object and returns the associated value
|
||||
* if found. Returns NOT_FOUND if not found.
|
||||
* Note that this method is not expected to traverse the prototype
|
||||
* chain. This is different from the ECMA [[Get]] operation.
|
||||
*
|
||||
* Depending on the property selector, the runtime will call
|
||||
* this method or the form of <code>get</code> that takes an
|
||||
* integer:
|
||||
* <table>
|
||||
* <tr><th>JavaScript code</th><th>Java code</th></tr>
|
||||
* <tr><td>a.b </td><td>a.get("b", a)</td></tr>
|
||||
* <tr><td>a["foo"] </td><td>a.get("foo", a)</td></tr>
|
||||
* <tr><td>a[3] </td><td>a.get(3, a)</td></tr>
|
||||
* <tr><td>a["3"] </td><td>a.get(3, a)</td></tr>
|
||||
* <tr><td>a[3.0] </td><td>a.get(3, a)</td></tr>
|
||||
* <tr><td>a["3.0"] </td><td>a.get("3.0", a)</td></tr>
|
||||
* <tr><td>a[1.1] </td><td>a.get("1.1", a)</td></tr>
|
||||
* <tr><td>a[-4] </td><td>a.get(-4, a)</td></tr>
|
||||
* </table>
|
||||
* <p>
|
||||
* The values that may be returned are limited to the following:
|
||||
* <UL>
|
||||
* <LI>java.lang.Boolean objects</LI>
|
||||
* <LI>java.lang.String objects</LI>
|
||||
* <LI>java.lang.Number objects</LI>
|
||||
* <LI>org.mozilla.javascript.Scriptable objects</LI>
|
||||
* <LI>null</LI>
|
||||
* <LI>The value returned by Context.getUndefinedValue()</LI>
|
||||
* <LI>NOT_FOUND</LI>
|
||||
* </UL>
|
||||
* @param name the name of the property
|
||||
* @param start the object in which the lookup began
|
||||
* @return the value of the property (may be null), or NOT_FOUND
|
||||
* @see org.mozilla.javascript.Context#getUndefinedValue
|
||||
*/
|
||||
public Object get(String name, Scriptable start);
|
||||
|
||||
/**
|
||||
* Get a property from the object selected by an integral index.
|
||||
*
|
||||
* Identical to <code>get(String, Scriptable)</code> except that
|
||||
* an integral index is used to select the property.
|
||||
*
|
||||
* @param index the numeric index for the property
|
||||
* @param start the object in which the lookup began
|
||||
* @return the value of the property (may be null), or NOT_FOUND
|
||||
* @see org.mozilla.javascript.Scriptable#get(String,Scriptable)
|
||||
*/
|
||||
public Object get(int index, Scriptable start);
|
||||
|
||||
/**
|
||||
* Indicates whether or not a named property is defined in an object.
|
||||
*
|
||||
* Does not traverse the prototype chain.<p>
|
||||
*
|
||||
* The property is specified by a String name
|
||||
* as defined for the <code>get</code> method.<p>
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @param start the object in which the lookup began
|
||||
* @return true if and only if the named property is found in the object
|
||||
* @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
|
||||
* @see org.mozilla.javascript.ScriptableObject#getProperty(Scriptable, String)
|
||||
*/
|
||||
public boolean has(String name, Scriptable start);
|
||||
|
||||
/**
|
||||
* Indicates whether or not an indexed property is defined in an object.
|
||||
*
|
||||
* Does not traverse the prototype chain.<p>
|
||||
*
|
||||
* The property is specified by an integral index
|
||||
* as defined for the <code>get</code> method.<p>
|
||||
*
|
||||
* @param index the numeric index for the property
|
||||
* @param start the object in which the lookup began
|
||||
* @return true if and only if the indexed property is found in the object
|
||||
* @see org.mozilla.javascript.Scriptable#get(int, Scriptable)
|
||||
* @see org.mozilla.javascript.ScriptableObject#getProperty(Scriptable, int)
|
||||
*/
|
||||
public boolean has(int index, Scriptable start);
|
||||
|
||||
/**
|
||||
* Sets a named property in this object.
|
||||
* <p>
|
||||
* The property is specified by a string name
|
||||
* as defined for <code>get</code>.
|
||||
* <p>
|
||||
* The possible values that may be passed in are as defined for
|
||||
* <code>get</code>. A class that implements this method may choose
|
||||
* to ignore calls to set certain properties, in which case those
|
||||
* properties are effectively read-only.<p>
|
||||
* For properties defined in a prototype chain,
|
||||
* use <code>putProperty</code> in ScriptableObject. <p>
|
||||
* Note that if a property <i>a</i> is defined in the prototype <i>p</i>
|
||||
* of an object <i>o</i>, then evaluating <code>o.a = 23</code> will cause
|
||||
* <code>set</code> to be called on the prototype <i>p</i> with
|
||||
* <i>o</i> as the <i>start</i> parameter.
|
||||
* To preserve JavaScript semantics, it is the Scriptable
|
||||
* object's responsibility to modify <i>o</i>. <p>
|
||||
* This design allows properties to be defined in prototypes and implemented
|
||||
* in terms of getters and setters of Java values without consuming slots
|
||||
* in each instance.
|
||||
* <p>
|
||||
* The values that may be set are limited to the following:
|
||||
* <UL>
|
||||
* <LI>java.lang.Boolean objects</LI>
|
||||
* <LI>java.lang.String objects</LI>
|
||||
* <LI>java.lang.Number objects</LI>
|
||||
* <LI>org.mozilla.javascript.Scriptable objects</LI>
|
||||
* <LI>null</LI>
|
||||
* <LI>The value returned by Context.getUndefinedValue()</LI>
|
||||
* </UL><p>
|
||||
* Arbitrary Java objects may be wrapped in a Scriptable by first calling
|
||||
* <code>Context.toObject</code>. This allows the property of a JavaScript
|
||||
* object to contain an arbitrary Java object as a value.<p>
|
||||
* Note that <code>has</code> will be called by the runtime first before
|
||||
* <code>set</code> is called to determine in which object the
|
||||
* property is defined.
|
||||
* Note that this method is not expected to traverse the prototype chain,
|
||||
* which is different from the ECMA [[Put]] operation.
|
||||
* @param name the name of the property
|
||||
* @param start the object whose property is being set
|
||||
* @param value value to set the property to
|
||||
* @see org.mozilla.javascript.Scriptable#has(String, Scriptable)
|
||||
* @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
|
||||
* @see org.mozilla.javascript.ScriptableObject#putProperty(Scriptable, String, Object)
|
||||
* @see org.mozilla.javascript.Context#toObject(Object, Scriptable)
|
||||
*/
|
||||
public void put(String name, Scriptable start, Object value);
|
||||
|
||||
/**
|
||||
* Sets an indexed property in this object.
|
||||
* <p>
|
||||
* The property is specified by an integral index
|
||||
* as defined for <code>get</code>.<p>
|
||||
*
|
||||
* Identical to <code>put(String, Scriptable, Object)</code> except that
|
||||
* an integral index is used to select the property.
|
||||
*
|
||||
* @param index the numeric index for the property
|
||||
* @param start the object whose property is being set
|
||||
* @param value value to set the property to
|
||||
* @see org.mozilla.javascript.Scriptable#has(int, Scriptable)
|
||||
* @see org.mozilla.javascript.Scriptable#get(int, Scriptable)
|
||||
* @see org.mozilla.javascript.ScriptableObject#putProperty(Scriptable, int, Object)
|
||||
* @see org.mozilla.javascript.Context#toObject(Object, Scriptable)
|
||||
*/
|
||||
public void put(int index, Scriptable start, Object value);
|
||||
|
||||
/**
|
||||
* Removes a property from this object.
|
||||
* This operation corresponds to the ECMA [[Delete]] except that
|
||||
* the no result is returned. The runtime will guarantee that this
|
||||
* method is called only if the property exists. After this method
|
||||
* is called, the runtime will call Scriptable.has to see if the
|
||||
* property has been removed in order to determine the boolean
|
||||
* result of the delete operator as defined by ECMA 11.4.1.
|
||||
* <p>
|
||||
* A property can be made permanent by ignoring calls to remove
|
||||
* it.<p>
|
||||
* The property is specified by a String name
|
||||
* as defined for <code>get</code>.
|
||||
* <p>
|
||||
* To delete properties defined in a prototype chain,
|
||||
* see deleteProperty in ScriptableObject.
|
||||
* @param name the identifier for the property
|
||||
* @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
|
||||
* @see org.mozilla.javascript.ScriptableObject#deleteProperty(Scriptable, String)
|
||||
*/
|
||||
public void delete(String name);
|
||||
|
||||
/**
|
||||
* Removes a property from this object.
|
||||
*
|
||||
* The property is specified by an integral index
|
||||
* as defined for <code>get</code>.
|
||||
* <p>
|
||||
* To delete properties defined in a prototype chain,
|
||||
* see deleteProperty in ScriptableObject.
|
||||
*
|
||||
* Identical to <code>delete(String)</code> except that
|
||||
* an integral index is used to select the property.
|
||||
*
|
||||
* @param index the numeric index for the property
|
||||
* @see org.mozilla.javascript.Scriptable#get(int, Scriptable)
|
||||
* @see org.mozilla.javascript.ScriptableObject#deleteProperty(Scriptable, int)
|
||||
*/
|
||||
public void delete(int index);
|
||||
|
||||
/**
|
||||
* Get the prototype of the object.
|
||||
* @return the prototype
|
||||
*/
|
||||
public Scriptable getPrototype();
|
||||
|
||||
/**
|
||||
* Set the prototype of the object.
|
||||
* @param prototype the prototype to set
|
||||
*/
|
||||
public void setPrototype(Scriptable prototype);
|
||||
|
||||
/**
|
||||
* Get the parent scope of the object.
|
||||
* @return the parent scope
|
||||
*/
|
||||
public Scriptable getParentScope();
|
||||
|
||||
/**
|
||||
* Set the parent scope of the object.
|
||||
* @param parent the parent scope to set
|
||||
*/
|
||||
public void setParentScope(Scriptable parent);
|
||||
|
||||
/**
|
||||
* Get an array of property ids.
|
||||
*
|
||||
* Not all property ids need be returned. Those properties
|
||||
* whose ids are not returned are considered non-enumerable.
|
||||
*
|
||||
* @return an array of Objects. Each entry in the array is either
|
||||
* a java.lang.String or a java.lang.Number
|
||||
*/
|
||||
public Object[] getIds();
|
||||
|
||||
/**
|
||||
* Get the default value of the object with a given hint.
|
||||
* The hints are String.class for type String, Number.class for type
|
||||
* Number, Scriptable.class for type Object, and Boolean.class for
|
||||
* type Boolean. <p>
|
||||
*
|
||||
* A <code>hint</code> of null means "no hint".
|
||||
*
|
||||
* See ECMA 8.6.2.6.
|
||||
*
|
||||
* @param hint the type hint
|
||||
* @return the default value
|
||||
*/
|
||||
public Object getDefaultValue(Class<?> hint);
|
||||
|
||||
/**
|
||||
* The instanceof operator.
|
||||
*
|
||||
* <p>
|
||||
* The JavaScript code "lhs instanceof rhs" causes rhs.hasInstance(lhs) to
|
||||
* be called.
|
||||
*
|
||||
* <p>
|
||||
* The return value is implementation dependent so that embedded host objects can
|
||||
* return an appropriate value. See the JS 1.3 language documentation for more
|
||||
* detail.
|
||||
*
|
||||
* <p>This operator corresponds to the proposed EMCA [[HasInstance]] operator.
|
||||
*
|
||||
* @param instance The value that appeared on the LHS of the instanceof
|
||||
* operator
|
||||
*
|
||||
* @return an implementation dependent value
|
||||
*/
|
||||
public boolean hasInstance(Scriptable instance);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* This is the default implementation of the Scriptable interface. This
|
||||
* class provides convenient default behavior that makes it easier to
|
||||
* define host objects.
|
||||
* <p>
|
||||
* Various properties and methods of JavaScript objects can be conveniently
|
||||
* defined using methods of ScriptableObject.
|
||||
* <p>
|
||||
* Classes extending ScriptableObject must define the getClassName method.
|
||||
*
|
||||
* @see org.mozilla.javascript.Scriptable
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
|
||||
public abstract class ScriptableObject implements Scriptable
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user