Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add rhino debugger #110

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion core/src/main/java/io/apigee/trireme/core/NodeScript.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public class NodeScript
private String workingDir;
private Map<String, String> environment;
private String nodeVersion = NodeEnvironment.DEFAULT_NODE_VERSION;
private boolean debugging = false;

NodeScript(NodeEnvironment env, String scriptName, File script, String[] args)
{
Expand All @@ -83,8 +84,15 @@ public class NodeScript
this.env = env;
this.forceRepl = forceRepl;
this.sandbox = env.getSandbox();
}
}

public boolean isDebugging() {
return debugging;
}

public void setDebugging(boolean debugging) {
this.debugging = debugging;
}
/**
* Run the script and return a Future denoting its status. The script is treated exactly as any other
* Node.js program -- that is, it runs in a separate thread, and the returned future may be used to
Expand Down
79 changes: 67 additions & 12 deletions core/src/main/java/io/apigee/trireme/core/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,11 @@
*/
package io.apigee.trireme.core;

import io.apigee.trireme.kernel.Charsets;
import io.apigee.trireme.core.internal.NodeOSException;
import io.apigee.trireme.kernel.Charsets;
import io.apigee.trireme.kernel.ErrorCodes;
import io.apigee.trireme.kernel.util.BufferUtils;
import io.apigee.trireme.kernel.util.StringUtils;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.Scriptable;

import java.io.File;
import java.io.FileInputStream;
Expand All @@ -43,6 +39,12 @@
import java.util.ArrayList;
import java.util.List;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.Scriptable;

/**
* A few utility functions, mainly for Rhino, that are useful when writing Node modules in Java.
*/
Expand Down Expand Up @@ -293,11 +295,64 @@ public static ByteBuffer duplicateBuffer(ByteBuffer b)
return BufferUtils.duplicateBuffer(b);
}

/**
* Remove leading and trailing strings from a quoted string that has both leading and trailing quotes on it.
*/
public static String unquote(String s)
{
return StringUtils.unquote(s);
}
/**
* Remove leading and trailing strings from a quoted string that has both
* leading and trailing quotes on it.
*/
public static String unquote(String s) {
return StringUtils.unquote(s);
}

/**
*

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's really a lot of blank lines being added here...

* Find script source by the fullname of script class. the script source
*
* must ended with '.js' extension.
*
*
*
* @param script
*
* script instance
*
* @return if found script source, return source string. if not found,
*
* return null.
*/

public static String getScriptSource(Script script) {

Class<? extends Script> clazz = script.getClass();

String name = clazz.getSimpleName();

InputStream is = clazz.getResourceAsStream(name + ".js");

try {

if (is != null) {

String src = Utils.readStream(is);

return src;

}

} catch (IOException e) {

} finally {

try {

is.close();

} catch (IOException ignore) {

}

}

return null;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,6 @@
import io.apigee.trireme.kernel.PathTranslator;
import io.apigee.trireme.kernel.net.NetworkPolicy;
import io.apigee.trireme.kernel.net.SelectorHandler;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextAction;
import org.mozilla.javascript.EcmaError;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Undefined;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.File;
Expand All @@ -79,6 +65,23 @@
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextAction;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.EcmaError;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Undefined;
import org.mozilla.javascript.tools.debugger.Main;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This class actually runs the script.
*/
Expand Down Expand Up @@ -662,19 +665,36 @@ private void closeCloseables(Context cx)
* Execute the script.
*/
@Override
public ScriptStatus call()
throws NodeException
{
Object ret = env.getContextFactory().call(new ContextAction()
{
@Override
public Object run(Context cx)
{
return runScript(cx);
}
});
return (ScriptStatus)ret;
}
public ScriptStatus call() throws NodeException {
ContextFactory contextFactory = env.getContextFactory();
contextFactory.call(new ContextAction() {
@Override
public Object run(Context cx) {
// All scripts get their own global scope. This is a lot safer
// than sharing them in case a script wants
// to add to the prototype of String or Date or whatever (as
// they often do)
// This uses a bit more memory and in theory slows down script
// startup but in practice it is
// a drop in the bucket.
scope = cx.initStandardObjects();
return null;
}
});
// debugger does not work when Main.mainEmbedded(...) is put in to
// contextFactory.call(...).
// I don't know why.
if (getScriptObject().isDebugging()) {
Main.mainEmbedded(env.getContextFactory(), scope, "trireme debug");
}

Object ret = contextFactory.call(new ContextAction() {
public Object run(Context cx) {
return runScript(cx);
}
});
return (ScriptStatus) ret;
}

protected ScriptStatus runScript(Context cx)
{
Expand All @@ -691,11 +711,7 @@ protected ScriptStatus runScript(Context cx)
now = System.currentTimeMillis();

try {
// All scripts get their own global scope. This is a lot safer than sharing them in case a script wants
// to add to the prototype of String or Date or whatever (as they often do)
// This uses a bit more memory and in theory slows down script startup but in practice it is
// a drop in the bucket.
scope = cx.initStandardObjects();


// Lazy first-time init of the node version.
registry.loadRoot(cx);
Expand Down Expand Up @@ -726,7 +742,20 @@ protected ScriptStatus runScript(Context cx)
// Run "trireme.js," which is our equivalent of "node.js". It returns a function that takes
// "process". When done, we may have ticks to execute.
Script mainScript = registry.getMainScript();
Function main = (Function)mainScript.exec(cx, scope);
Function main = null;
if (getScriptObject().isDebugging()) {
// try to find script source
String src = Utils.getScriptSource(mainScript);
if (src != null) {
Object ret = cx.evaluateString(scope, src, mainScript
.getClass().getName(), 1, null);

main = (Function) ret;
}
}
if (main == null) {
main = (Function) mainScript.exec(cx, scope);
}

boolean timing = startTiming(cx);
try {
Expand Down
60 changes: 44 additions & 16 deletions core/src/main/java/io/apigee/trireme/core/modules/NativeModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -198,22 +198,50 @@ public Scriptable internalRequire(String name, Context cx)
return null;
}

private void runCompiledModule(Script compiled, Context cx, ModuleImpl mod)
{
Function requireFunc = new FunctionObject("require",
Utils.findMethod(NativeImpl.class, "require"),
this);

// The script code found in src/main/javascript is wrapped with a function by the Rhino compiler
// (see the pom.xml for the wrapper code). What we actually
// need to do here is to invoke the wrapper function after running the script.

Object ret = compiled.exec(cx, runner.getScriptScope());
Function fn = (Function)ret;
fn.call(cx, runner.getScriptScope(), null, new Object[] { mod.getExports(), requireFunc,
mod, mod.getFileName() });
mod.setLoaded(true);
}
private void runCompiledModule(Script compiled, Context cx,
ModuleImpl mod) {

Function requireFunc = new FunctionObject("require",
Utils.findMethod(NativeImpl.class, "require"), this);

Function fn = null;

if (runner.getScriptObject().isDebugging()) {
// try to find script source
String src = Utils.getScriptSource(compiled);
if (src != null) {
String finalSource = NativeImpl.WRAP_PREFIX + src
+ NativeImpl.WRAP_POSTFIX;
Object ret = cx
.evaluateString(runner.getScriptScope(),
finalSource, compiled.getClass().getName(),
1, null);

fn = (Function) ret;
} else {
// TODO how to find module script source defined by
// NodeScriptModule
}

}
if (fn == null) {
// The script code found in src/main/javascript is wrapped with
// a function by the Rhino compiler
// (see the pom.xml for the wrapper code). What we actually
// need to do here is to invoke the wrapper function after
// running the script.

Object ret = compiled.exec(cx, runner.getScriptScope());
fn = (Function) ret;
}
fn.call(cx,
runner.getScriptScope(),
null,
new Object[] { mod.getExports(), requireFunc, mod,
mod.getFileName() });

mod.setLoaded(true);
}

@JSFunction
public static Object getCached(Context cx, Scriptable thisObj, Object[] args, Function func)
Expand Down