Merge pull request #5802 from luchua-bc/java/rhino-injection

Java: CWE-094 Rhino code injection
This commit is contained in:
Chris Smowton
2021-05-18 19:25:53 +01:00
committed by GitHub
32 changed files with 2249 additions and 133 deletions

View File

@@ -0,0 +1,40 @@
import org.mozilla.javascript.ClassShutter;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
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) {
return className.startsWith("com.example.");
}
});
}
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();
}
}
}

View File

@@ -1,26 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The ScriptEngine API has been available since the release of Java 6.
It allows applications to interact with scripts written in languages such as JavaScript.</p>
</overview>
<recommendation>
<p>Use "Cloudbees Rhino Sandbox" or sandboxing with SecurityManager or use <a href="https://www.graalvm.org/">graalvm</a> instead.</p>
</recommendation>
<example>
<p>The following code could execute random JavaScript code</p>
<sample src="ScriptEngine.java" />
<sample src="NashornScriptEngine.java" />
</example>
<references>
<li>
CERT coding standard: <a href="https://wiki.sei.cmu.edu/confluence/display/java/IDS52-J.+Prevent+code+injection">ScriptEngine code injection</a>
</li>
</references>
</qhelp>

View File

@@ -1,51 +0,0 @@
/**
* @name ScriptEngine evaluation
* @description Malicious Javascript code could cause arbitrary command execution at the OS level
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/unsafe-eval
* @tags security
* external/cwe/cwe-094
*/
import java
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
class ScriptEngineMethod extends Method {
ScriptEngineMethod() {
this.getDeclaringType().getASupertype*().hasQualifiedName("javax.script", "ScriptEngine") and
this.hasName("eval")
}
}
predicate scriptEngine(MethodAccess ma, Expr sink) {
exists(Method m | m = ma.getMethod() |
m instanceof ScriptEngineMethod and
sink = ma.getArgument(0)
)
}
class ScriptEngineSink extends DataFlow::ExprNode {
ScriptEngineSink() { scriptEngine(_, this.getExpr()) }
MethodAccess getMethodAccess() { scriptEngine(result, this.getExpr()) }
}
class ScriptEngineConfiguration extends TaintTracking::Configuration {
ScriptEngineConfiguration() { this = "ScriptEngineConfiguration" }
override predicate isSource(DataFlow::Node source) {
source instanceof RemoteFlowSource
or
source instanceof LocalUserInput
}
override predicate isSink(DataFlow::Node sink) { sink instanceof ScriptEngineSink }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ScriptEngineConfiguration conf
where conf.hasFlowPath(source, sink)
select sink.getNode().(ScriptEngineSink).getMethodAccess(), source, sink, "ScriptEngine eval $@.",
source.getNode(), "user input"

View File

@@ -0,0 +1,52 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The Java Scripting API has been available since the release of Java 6. It allows
applications to interact with scripts written in languages such as JavaScript. 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>
</overview>
<recommendation>
<p>In general, including user input in a Java Script Engine 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. Use "Cloudbees Rhino Sandbox" or
sandboxing with SecurityManager, which will be deprecated in a future release, or use
<a href="https://www.graalvm.org/">GraalVM</a> instead.</p>
</recommendation>
<example>
<p>The following code could execute user-supplied JavaScript code in <code>ScriptEngine</code></p>
<sample src="ScriptEngine.java" />
<sample src="NashornScriptEngine.java" />
<p>The following example shows two ways of using Rhino expression. In the 'BAD' case,
an unsafe context is initialized with <code>initStandardObjects</code> that allows arbitrary
Java code to be executed. 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>
CERT coding standard: <a href="https://wiki.sei.cmu.edu/confluence/display/java/IDS52-J.+Prevent+code+injection">ScriptEngine code injection</a>
</li>
<li>
GraalVM: <a href="https://www.graalvm.org/reference-manual/js/NashornMigrationGuide/#secure-by-default">Secure by Default</a>
</li>
<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">Code Injection</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,146 @@
/**
* @name Injection in Java Script Engine
* @description Evaluation of user-controlled data using the Java Script Engine may
* lead to remote code execution.
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/unsafe-eval
* @tags security
* external/cwe/cwe-094
*/
import java
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
/** A method of ScriptEngine that allows code injection. */
class ScriptEngineMethod extends Method {
ScriptEngineMethod() {
this.getDeclaringType().getASupertype*().hasQualifiedName("javax.script", "ScriptEngine") and
this.hasName("eval")
or
this.getDeclaringType().getASupertype*().hasQualifiedName("javax.script", "Compilable") and
this.hasName("compile")
or
this.getDeclaringType().getASupertype*().hasQualifiedName("javax.script", "ScriptEngineFactory") and
this.hasName(["getProgram", "getMethodCallSyntax"])
}
}
/** The context class `org.mozilla.javascript.Context` of Rhino Java Script Engine. */
class RhinoContext extends RefType {
RhinoContext() { this.hasQualifiedName("org.mozilla.javascript", "Context") }
}
/** A method that evaluates a Rhino expression with `org.mozilla.javascript.Context`. */
class RhinoEvaluateExpressionMethod extends Method {
RhinoEvaluateExpressionMethod() {
this.getDeclaringType().getAnAncestor*() instanceof RhinoContext and
this.hasName([
"evaluateString", "evaluateReader", "compileFunction", "compileReader", "compileString"
])
}
}
/**
* A method that compiles a Rhino expression with
* `org.mozilla.javascript.optimizer.ClassCompiler`.
*/
class RhinoCompileClassMethod extends Method {
RhinoCompileClassMethod() {
this.getDeclaringType()
.getASupertype*()
.hasQualifiedName("org.mozilla.javascript.optimizer", "ClassCompiler") and
this.hasName("compileToClassFiles")
}
}
/**
* A method that defines a Java class from a Rhino expression with
* `org.mozilla.javascript.GeneratedClassLoader`.
*/
class RhinoDefineClassMethod extends Method {
RhinoDefineClassMethod() {
this.getDeclaringType()
.getASupertype*()
.hasQualifiedName("org.mozilla.javascript", "GeneratedClassLoader") and
this.hasName("defineClass")
}
}
/**
* Holds if `ma` is a call to a `ScriptEngineMethod` and `sink` is an argument that
* will be executed.
*/
predicate isScriptArgument(MethodAccess ma, Expr sink) {
exists(ScriptEngineMethod m |
m = ma.getMethod() and
if m.getDeclaringType().getASupertype*().hasQualifiedName("javax.script", "ScriptEngineFactory")
then sink = ma.getArgument(_) // all arguments allow script injection
else sink = ma.getArgument(0)
)
}
/**
* Holds if a Rhino expression evaluation method is vulnerable to code injection.
*/
predicate evaluatesRhinoExpression(MethodAccess ma, Expr sink) {
exists(RhinoEvaluateExpressionMethod m | m = ma.getMethod() |
(
if ma.getMethod().getName() = "compileReader"
then sink = ma.getArgument(0) // The first argument is the input reader
else sink = ma.getArgument(1) // The second argument is the JavaScript or Java input
) and
not exists(MethodAccess ca |
ca.getMethod().hasName(["initSafeStandardObjects", "setClassShutter"]) and // safe mode or `ClassShutter` constraint is enforced
ma.getQualifier() = ca.getQualifier().(VarAccess).getVariable().getAnAccess()
)
)
}
/**
* Holds if a Rhino expression compilation method is vulnerable to code injection.
*/
predicate compilesScript(MethodAccess ma, Expr sink) {
exists(RhinoCompileClassMethod m | m = ma.getMethod() | sink = ma.getArgument(0))
}
/**
* Holds if a Rhino class loading method is vulnerable to code injection.
*/
predicate definesRhinoClass(MethodAccess ma, Expr sink) {
exists(RhinoDefineClassMethod m | m = ma.getMethod() | sink = ma.getArgument(1))
}
/** A script injection sink. */
class ScriptInjectionSink extends DataFlow::ExprNode {
MethodAccess methodAccess;
ScriptInjectionSink() {
isScriptArgument(methodAccess, this.getExpr()) or
evaluatesRhinoExpression(methodAccess, this.getExpr()) or
compilesScript(methodAccess, this.getExpr()) or
definesRhinoClass(methodAccess, this.getExpr())
}
/** An access to the method associated with this sink. */
MethodAccess getMethodAccess() { result = methodAccess }
}
/**
* A taint tracking configuration that tracks flow from `RemoteFlowSource` to an argument
* of a method call that executes injected script.
*/
class ScriptInjectionConfiguration extends TaintTracking::Configuration {
ScriptInjectionConfiguration() { this = "ScriptInjectionConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof ScriptInjectionSink }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ScriptInjectionConfiguration conf
where conf.hasFlowPath(source, sink)
select sink.getNode().(ScriptInjectionSink).getMethodAccess(), source, sink,
"Java Script Engine evaluate $@.", source.getNode(), "user input"

View File

@@ -0,0 +1,91 @@
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.CompilerEnvirons;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.DefiningClassLoader;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.optimizer.ClassCompiler;
/**
* 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) {
return className.startsWith("com.example.");
}
});
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();
}
}
// BAD: allow arbitrary code to be compiled for subsequent execution
protected void doGet2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String code = request.getParameter("code");
ClassCompiler compiler = new ClassCompiler(new CompilerEnvirons());
Object[] objs = compiler.compileToClassFiles(code, "/sourceLocation", 1, "mainClassName");
}
// BAD: allow arbitrary code to be loaded for subsequent execution
protected void doPost2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String code = request.getParameter("code");
Class clazz = new DefiningClassLoader().defineClass("Powerfunc", code.getBytes());
}
}

View File

@@ -1,32 +0,0 @@
edges
| ScriptEngineTest.java:8:44:8:55 | input : String | ScriptEngineTest.java:12:37:12:41 | input |
| ScriptEngineTest.java:15:51:15:62 | input : String | ScriptEngineTest.java:19:31:19:35 | input |
| ScriptEngineTest.java:23:58:23:69 | input : String | ScriptEngineTest.java:27:31:27:35 | input |
| ScriptEngineTest.java:30:46:30:57 | input : String | ScriptEngineTest.java:34:31:34:35 | input |
| ScriptEngineTest.java:37:26:37:38 | args : String[] | ScriptEngineTest.java:38:56:38:62 | ...[...] : String |
| ScriptEngineTest.java:37:26:37:38 | args : String[] | ScriptEngineTest.java:39:63:39:69 | ...[...] : String |
| ScriptEngineTest.java:37:26:37:38 | args : String[] | ScriptEngineTest.java:40:70:40:76 | ...[...] : String |
| ScriptEngineTest.java:37:26:37:38 | args : String[] | ScriptEngineTest.java:41:58:41:64 | ...[...] : String |
| ScriptEngineTest.java:38:56:38:62 | ...[...] : String | ScriptEngineTest.java:8:44:8:55 | input : String |
| ScriptEngineTest.java:39:63:39:69 | ...[...] : String | ScriptEngineTest.java:15:51:15:62 | input : String |
| ScriptEngineTest.java:40:70:40:76 | ...[...] : String | ScriptEngineTest.java:23:58:23:69 | input : String |
| ScriptEngineTest.java:41:58:41:64 | ...[...] : String | ScriptEngineTest.java:30:46:30:57 | input : String |
nodes
| ScriptEngineTest.java:8:44:8:55 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:12:37:12:41 | input | semmle.label | input |
| ScriptEngineTest.java:15:51:15:62 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:19:31:19:35 | input | semmle.label | input |
| ScriptEngineTest.java:23:58:23:69 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:27:31:27:35 | input | semmle.label | input |
| ScriptEngineTest.java:30:46:30:57 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:34:31:34:35 | input | semmle.label | input |
| ScriptEngineTest.java:37:26:37:38 | args : String[] | semmle.label | args : String[] |
| ScriptEngineTest.java:38:56:38:62 | ...[...] : String | semmle.label | ...[...] : String |
| ScriptEngineTest.java:39:63:39:69 | ...[...] : String | semmle.label | ...[...] : String |
| ScriptEngineTest.java:40:70:40:76 | ...[...] : String | semmle.label | ...[...] : String |
| ScriptEngineTest.java:41:58:41:64 | ...[...] : String | semmle.label | ...[...] : String |
#select
| ScriptEngineTest.java:12:19:12:42 | eval(...) | ScriptEngineTest.java:37:26:37:38 | args : String[] | ScriptEngineTest.java:12:37:12:41 | input | ScriptEngine eval $@. | ScriptEngineTest.java:37:26:37:38 | args | user input |
| ScriptEngineTest.java:19:19:19:36 | eval(...) | ScriptEngineTest.java:37:26:37:38 | args : String[] | ScriptEngineTest.java:19:31:19:35 | input | ScriptEngine eval $@. | ScriptEngineTest.java:37:26:37:38 | args | user input |
| ScriptEngineTest.java:27:19:27:36 | eval(...) | ScriptEngineTest.java:37:26:37:38 | args : String[] | ScriptEngineTest.java:27:31:27:35 | input | ScriptEngine eval $@. | ScriptEngineTest.java:37:26:37:38 | args | user input |
| ScriptEngineTest.java:34:19:34:36 | eval(...) | ScriptEngineTest.java:37:26:37:38 | args : String[] | ScriptEngineTest.java:34:31:34:35 | input | ScriptEngine eval $@. | ScriptEngineTest.java:37:26:37:38 | args | user input |

View File

@@ -1 +0,0 @@
experimental/Security/CWE/CWE-094/ScriptEngine.ql

View File

@@ -1,9 +1,21 @@
import javax.script.AbstractScriptEngine;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
import javax.script.*;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ScriptEngineTest {
public class ScriptEngineTest extends HttpServlet {
public void testWithScriptEngineReference(String input) throws ScriptException {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
@@ -33,26 +45,59 @@ public class ScriptEngineTest {
MyCustomScriptEngine engine = (MyCustomScriptEngine) factory.getScriptEngine(new String[] { "-scripting" });
Object result = engine.eval(input);
}
public static void main(String[] args) throws ScriptException {
new ScriptEngineTest().testWithScriptEngineReference(args[0]);
new ScriptEngineTest().testNashornWithScriptEngineReference(args[0]);
new ScriptEngineTest().testNashornWithNashornScriptEngineReference(args[0]);
new ScriptEngineTest().testCustomScriptEngineReference(args[0]);
public void testScriptEngineCompilable(String input) throws ScriptException {
NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
Compilable engine = (Compilable) factory.getScriptEngine(new String[] { "-scripting" });
CompiledScript script = engine.compile(input);
Object result = script.eval();
}
public void testScriptEngineGetProgram(String input) throws ScriptException {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine engine = scriptEngineManager.getEngineByName("nashorn");
String program = engine.getFactory().getProgram(input);
Object result = engine.eval(program);
}
private static class MyCustomScriptEngine extends AbstractScriptEngine {
public Object eval(String var1) throws ScriptException {
return null;
}
public Object eval(String var1) throws ScriptException { return null; }
@Override
public ScriptEngineFactory getFactory() { return null; }
}
private static class MyCustomFactory implements ScriptEngineFactory {
public MyCustomFactory() {
}
public ScriptEngine getScriptEngine() { return null; }
}
@Override
public ScriptEngine getScriptEngine() { return null; }
public ScriptEngine getScriptEngine(String... args) { return null; }
@Override
public String getEngineName() { return null; }
@Override
public String getMethodCallSyntax(final String obj, final String method, final String... args) { return null; }
@Override
public String getProgram(final String... statements) { return null; }
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String code = request.getParameter("code");
new ScriptEngineTest().testWithScriptEngineReference(code);
new ScriptEngineTest().testNashornWithScriptEngineReference(code);
new ScriptEngineTest().testNashornWithNashornScriptEngineReference(code);
new ScriptEngineTest().testCustomScriptEngineReference(code);
new ScriptEngineTest().testScriptEngineCompilable(code);
new ScriptEngineTest().testScriptEngineGetProgram(code);
} catch (ScriptException se) {
throw new IOException(se.getMessage());
}
}
}

View File

@@ -0,0 +1,58 @@
edges
| RhinoServlet.java:28:23:28:50 | getParameter(...) : String | RhinoServlet.java:32:55:32:58 | code |
| RhinoServlet.java:81:23:81:50 | getParameter(...) : String | RhinoServlet.java:83:54:83:57 | code |
| RhinoServlet.java:88:23:88:50 | getParameter(...) : String | RhinoServlet.java:89:74:89:88 | getBytes(...) |
| ScriptEngineTest.java:20:44:20:55 | input : String | ScriptEngineTest.java:24:37:24:41 | input |
| ScriptEngineTest.java:27:51:27:62 | input : String | ScriptEngineTest.java:31:31:31:35 | input |
| ScriptEngineTest.java:35:58:35:69 | input : String | ScriptEngineTest.java:39:31:39:35 | input |
| ScriptEngineTest.java:42:46:42:57 | input : String | ScriptEngineTest.java:46:31:46:35 | input |
| ScriptEngineTest.java:49:41:49:52 | input : String | ScriptEngineTest.java:52:42:52:46 | input |
| ScriptEngineTest.java:56:41:56:52 | input : String | ScriptEngineTest.java:59:51:59:55 | input |
| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:93:57:93:60 | code : String |
| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:94:64:94:67 | code : String |
| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:95:71:95:74 | code : String |
| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:96:59:96:62 | code : String |
| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:97:54:97:57 | code : String |
| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:98:54:98:57 | code : String |
| ScriptEngineTest.java:93:57:93:60 | code : String | ScriptEngineTest.java:20:44:20:55 | input : String |
| ScriptEngineTest.java:94:64:94:67 | code : String | ScriptEngineTest.java:27:51:27:62 | input : String |
| ScriptEngineTest.java:95:71:95:74 | code : String | ScriptEngineTest.java:35:58:35:69 | input : String |
| ScriptEngineTest.java:96:59:96:62 | code : String | ScriptEngineTest.java:42:46:42:57 | input : String |
| ScriptEngineTest.java:97:54:97:57 | code : String | ScriptEngineTest.java:49:41:49:52 | input : String |
| ScriptEngineTest.java:98:54:98:57 | code : String | ScriptEngineTest.java:56:41:56:52 | input : String |
nodes
| RhinoServlet.java:28:23:28:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| RhinoServlet.java:32:55:32:58 | code | semmle.label | code |
| RhinoServlet.java:81:23:81:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| RhinoServlet.java:83:54:83:57 | code | semmle.label | code |
| RhinoServlet.java:88:23:88:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| RhinoServlet.java:89:74:89:88 | getBytes(...) | semmle.label | getBytes(...) |
| ScriptEngineTest.java:20:44:20:55 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:24:37:24:41 | input | semmle.label | input |
| ScriptEngineTest.java:27:51:27:62 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:31:31:31:35 | input | semmle.label | input |
| ScriptEngineTest.java:35:58:35:69 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:39:31:39:35 | input | semmle.label | input |
| ScriptEngineTest.java:42:46:42:57 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:46:31:46:35 | input | semmle.label | input |
| ScriptEngineTest.java:49:41:49:52 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:52:42:52:46 | input | semmle.label | input |
| ScriptEngineTest.java:56:41:56:52 | input : String | semmle.label | input : String |
| ScriptEngineTest.java:59:51:59:55 | input | semmle.label | input |
| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| ScriptEngineTest.java:93:57:93:60 | code : String | semmle.label | code : String |
| ScriptEngineTest.java:94:64:94:67 | code : String | semmle.label | code : String |
| ScriptEngineTest.java:95:71:95:74 | code : String | semmle.label | code : String |
| ScriptEngineTest.java:96:59:96:62 | code : String | semmle.label | code : String |
| ScriptEngineTest.java:97:54:97:57 | code : String | semmle.label | code : String |
| ScriptEngineTest.java:98:54:98:57 | code : String | semmle.label | code : String |
#select
| RhinoServlet.java:32:29:32:78 | evaluateString(...) | RhinoServlet.java:28:23:28:50 | getParameter(...) : String | RhinoServlet.java:32:55:32:58 | code | Java Script Engine evaluate $@. | RhinoServlet.java:28:23:28:50 | getParameter(...) | user input |
| RhinoServlet.java:83:25:83:97 | compileToClassFiles(...) | RhinoServlet.java:81:23:81:50 | getParameter(...) : String | RhinoServlet.java:83:54:83:57 | code | Java Script Engine evaluate $@. | RhinoServlet.java:81:23:81:50 | getParameter(...) | user input |
| RhinoServlet.java:89:23:89:89 | defineClass(...) | RhinoServlet.java:88:23:88:50 | getParameter(...) : String | RhinoServlet.java:89:74:89:88 | getBytes(...) | Java Script Engine evaluate $@. | RhinoServlet.java:88:23:88:50 | getParameter(...) | user input |
| ScriptEngineTest.java:24:19:24:42 | eval(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:24:37:24:41 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
| ScriptEngineTest.java:31:19:31:36 | eval(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:31:31:31:35 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
| ScriptEngineTest.java:39:19:39:36 | eval(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:39:31:39:35 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
| ScriptEngineTest.java:46:19:46:36 | eval(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:46:31:46:35 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
| ScriptEngineTest.java:52:27:52:47 | compile(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:52:42:52:46 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
| ScriptEngineTest.java:59:20:59:56 | getProgram(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:59:51:59:55 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-094/ScriptInjection.ql

View File

@@ -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

View File

@@ -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);
}

View File

@@ -0,0 +1,12 @@
/* -*- 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;
public class CompilerEnvirons {
public CompilerEnvirons() {
}
}

View File

@@ -0,0 +1,695 @@
/* -*- 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;
}
/**
* @deprecated
* @see #compileReader(Reader in, String sourceName, int lineno, Object securityDomain)
*/
@Deprecated
public final Script compileReader(
Scriptable scope, Reader in, String sourceName, int lineno, Object securityDomain)
throws IOException {
return null;
}
/**
* Compiles the source in the given reader.
*
* <p>Returns a script that may later be executed. Will consume all the source in the reader.
*
* @param in the input reader
* @param sourceName a string describing the source, such as a filename
* @param lineno the starting line number for reporting errors
* @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 a script that may later be executed
* @exception IOException if an IOException was generated by the Reader
* @see org.mozilla.javascript.Script
*/
public final Script compileReader(
Reader in, String sourceName, int lineno, Object securityDomain) throws IOException {
return null;
}
/**
* Compiles the source in the given string.
*
* <p>Returns a script that may later be executed.
*
* @param source the source string
* @param sourceName a string describing the source, such as a filename
* @param lineno the starting line number for reporting errors. Use 0 if the line number is
* unknown.
* @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 a script that may later be executed
* @see org.mozilla.javascript.Script
*/
public final Script compileString(
String source, String sourceName, int lineno, Object securityDomain) {
return null;
}
/**
* Compile a JavaScript function.
*
* <p>The function source must be a function definition as defined by ECMA (e.g., "function f(a)
* { return a; }").
*
* @param scope the scope to compile relative to
* @param source the function definition 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 a Function that may later be called
* @see org.mozilla.javascript.Function
*/
public final Function compileFunction(
Scriptable scope, String source, String sourceName, int lineno, Object securityDomain) {
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;
}
}

View File

@@ -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 &gt; 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;
}
}

View File

@@ -0,0 +1,36 @@
/* 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;
/**
* Load generated classes.
*
* @author Norris Boyd
*/
public class DefiningClassLoader extends ClassLoader
implements GeneratedClassLoader
{
public DefiningClassLoader() {
}
public DefiningClassLoader(ClassLoader parentLoader) {
}
@Override
public Class<?> defineClass(String name, byte[] data) {
return null;
}
@Override
public void linkClass(Class<?> cl) {
}
@Override
public Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
return null;
}
}

View File

@@ -0,0 +1,46 @@
/* -*- 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 functions in JavaScript must implement. The interface provides for
* calling functions and constructors.
*
* @see org.mozilla.javascript.Scriptable
* @author Norris Boyd
*/
public interface Function extends Scriptable {
/**
* Call the function.
*
* <p>Note that the array of arguments is not guaranteed to have length greater than 0.
*
* @param cx the current Context for this thread
* @param scope the scope to execute the function relative to. This is set to the value returned
* by getParentScope() except when the function is called from a closure.
* @param thisObj the JavaScript <code>this</code> object
* @param args the array of arguments
* @return the result of the call
*/
Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args);
/**
* Call the function as a constructor.
*
* <p>This method is invoked by the runtime in order to satisfy a use of the JavaScript <code>
* new</code> operator. This method is expected to create a new object and return it.
*
* @param cx the current Context for this thread
* @param scope an enclosing scope of the caller except when the function is called from a
* closure.
* @param args the array of arguments
* @return the allocated object
*/
Scriptable construct(Context cx, Scriptable scope, Object[] args);
}

View File

@@ -0,0 +1,34 @@
/* -*- 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;
/**
* Interface to define classes from generated byte code.
*/
public interface GeneratedClassLoader {
/**
* Define a new Java class.
* Classes created via this method should have the same class loader.
*
* @param name fully qualified class name
* @param data class byte code
* @return new class object
*/
public Class<?> defineClass(String name, byte[] data);
/**
* Link the given class.
*
* @param cl Class instance returned from the previous call to
* {@link #defineClass(String, byte[])}
* @see java.lang.ClassLoader
*/
public void linkClass(Class<?> cl);
}

View File

@@ -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
{
}

View File

@@ -0,0 +1,41 @@
/* -*- 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;
/**
* All compiled scripts implement this interface.
* <p>
* This class encapsulates script execution relative to an
* object scope.
* @since 1.3
* @author Norris Boyd
*/
public interface Script {
/**
* Execute the script.
* <p>
* The script is executed in a particular runtime Context, which
* must be associated with the current thread.
* The script is executed relative to a scope--definitions and
* uses of global top-level variables and functions will access
* properties of the scope object. For compliant ECMA
* programs, the scope must be an object that has been initialized
* as a global object using <code>Context.initStandardObjects</code>.
* <p>
*
* @param cx the Context associated with the current thread
* @param scope the scope to execute relative to
* @return the result of executing the script
* @see org.mozilla.javascript.Context#initStandardObjects()
*/
public Object exec(Context cx, Scriptable scope);
}

View File

@@ -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);
}

View File

@@ -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
{
}

View File

@@ -0,0 +1,112 @@
/* -*- 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.optimizer;
import org.mozilla.javascript.CompilerEnvirons;
/**
* Generates class files from script sources.
*
* since 1.5 Release 5
* @author Igor Bukanov
*/
public class ClassCompiler
{
/**
* Construct ClassCompiler that uses the specified compiler environment
* when generating classes.
*/
public ClassCompiler(CompilerEnvirons compilerEnv)
{
}
/**
* Set the class name to use for main method implementation.
* The class must have a method matching
* <code>public static void main(Script sc, String[] args)</code>, it will be
* called when <code>main(String[] args)</code> is called in the generated
* class. The class name should be fully qulified name and include the
* package name like in <code>org.foo.Bar</code>.
*/
public void setMainMethodClass(String className)
{
}
/**
* Get the name of the class for main method implementation.
* @see #setMainMethodClass(String)
*/
public String getMainMethodClass()
{
return null;
}
/**
* Get the compiler environment the compiler uses.
*/
public CompilerEnvirons getCompilerEnv()
{
return null;
}
/**
* Get the class that the generated target will extend.
*/
public Class<?> getTargetExtends()
{
return null;
}
/**
* Set the class that the generated target will extend.
*
* @param extendsClass the class it extends
*/
public void setTargetExtends(Class<?> extendsClass)
{
}
/**
* Get the interfaces that the generated target will implement.
*/
public Class<?>[] getTargetImplements()
{
return null;
}
/**
* Set the interfaces that the generated target will implement.
*
* @param implementsClasses an array of Class objects, one for each
* interface the target will extend
*/
public void setTargetImplements(Class<?>[] implementsClasses)
{
}
/**
* Compile JavaScript source into one or more Java class files.
* The first compiled class will have name mainClassName.
* If the results of {@link #getTargetExtends()} or
* {@link #getTargetImplements()} are not null, then the first compiled
* class will extend the specified super class and implement
* specified interfaces.
*
* @return array where elements with even indexes specifies class name
* and the following odd index gives class file body as byte[]
* array. The initial element of the array always holds
* mainClassName and array[1] holds its byte code.
*/
public Object[] compileToClassFiles(String source,
String sourceLocation,
int lineno,
String mainClassName)
{
return null;
}
}

View File

@@ -0,0 +1,14 @@
package javax.script;
import java.util.Map;
public interface Bindings extends Map<String, Object> {
public Object put(String name, Object value);
public void putAll(Map<? extends String, ? extends Object> toMerge);
public boolean containsKey(Object key);
public Object get(Object key);
public Object remove(Object key);
}

View File

@@ -0,0 +1,9 @@
package javax.script;
import java.io.Reader;
public interface Compilable {
public CompiledScript compile(String script) throws ScriptException;
public CompiledScript compile(Reader script) throws ScriptException;
}

View File

@@ -0,0 +1,17 @@
package javax.script;
public abstract class CompiledScript {
public abstract Object eval(ScriptContext context) throws ScriptException;
public Object eval(Bindings bindings) throws ScriptException {
return null;
}
public Object eval() throws ScriptException {
return null;
}
public abstract ScriptEngine getEngine();
}

View File

@@ -2,5 +2,7 @@ package javax.script;
public interface ScriptEngine {
Object eval(String var1) throws ScriptException;
public ScriptEngineFactory getFactory();
}

View File

@@ -1,6 +1,11 @@
package javax.script;
public interface ScriptEngineFactory {
public String getEngineName();
public String getMethodCallSyntax(String obj, String m, String... args);
public String getProgram(String... statements);
ScriptEngine getScriptEngine();
}

View File

@@ -0,0 +1,5 @@
package jdk.nashorn.api.scripting;
public interface ClassFilter {
public boolean exposeToScripts(String className);
}

View File

@@ -1,10 +1,31 @@
package jdk.nashorn.api.scripting;
import javax.script.*;
import java.io.Reader;
public final class NashornScriptEngine extends AbstractScriptEngine {
import javax.script.AbstractScriptEngine;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
public final class NashornScriptEngine extends AbstractScriptEngine implements Compilable {
public Object eval(String var1) throws ScriptException {
return null;
}
}
@Override
public ScriptEngineFactory getFactory() {
return null;
}
@Override
public CompiledScript compile(final Reader reader) throws ScriptException {
return null;
}
@Override
public CompiledScript compile(final String str) throws ScriptException {
return null;
}
}

View File

@@ -3,20 +3,48 @@ package jdk.nashorn.api.scripting;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
public final class NashornScriptEngineFactory implements ScriptEngineFactory {
public NashornScriptEngineFactory() {
}
@Override
public String getEngineName() {
return null;
}
@Override
public String getMethodCallSyntax(final String obj, final String method, final String... args) {
return null;
}
@Override
public String getProgram(final String... statements) {
return null;
}
@Override
public ScriptEngine getScriptEngine() {
return null;
}
public ScriptEngine getScriptEngine(final ClassLoader appLoader) {
return null;
}
public ScriptEngine getScriptEngine(String... args) {
public ScriptEngine getScriptEngine(final ClassFilter classFilter) {
return null;
}
public ScriptEngine getScriptEngine(final String... args) {
return null;
}
public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) {
return null;
}
public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
return null;
}
}