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

How to debug javascript in trireme? #109

Open
sunchey11 opened this issue Mar 31, 2015 · 7 comments
Open

How to debug javascript in trireme? #109

sunchey11 opened this issue Mar 31, 2015 · 7 comments

Comments

@sunchey11
Copy link

Hi
How to debug javascript source in trireme, including internal js module and normal javascript?

@gbrail
Copy link
Contributor

gbrail commented Mar 31, 2015

For debugging the Java code inside Trireme, or Java code that you add as a
Node module, you can use a regular Java debugger. The "trireme" script
doesn't have a place to plug in arguments, but if you launch it yourself
using "java -jar trireme.jar" or something else then you can easily add
additional Java options to enable debugging.

Unfortunately, we don't have a good way to debug the JavaScript itself.
Rhino has hooks for an interactive debugger, but Trireme does not plug in
to them and I don't think there is a way to attach the Rhino debugger
externally.

Both experiences could use some improvement and they're a great place for
some additional work if someone has time to do some more experiments and
make some changes.

On Mon, Mar 30, 2015 at 5:53 PM, sunchey11 [email protected] wrote:

Hi
How to debug javascript source in trireme, including internal js module
and normal javascript?


Reply to this email directly or view it on GitHub
#109.

greg brail | apigee https://apigee.com/ | twitter @gbrail
http://twitter.com/gbrail

@sunchey11
Copy link
Author

When I read source of trireme, I wrote some code to embed rhino's debugger program into trireme.
The code is ugly and not work in server program, but it help me understand nodejs source and trireme js source.

public static void main(String[] theArgs) throws NodeException {
NodeEnvironment env = new NodeEnvironment();
final String pathname = "hellotest.js";
File file = new File(pathname);
String[] args = new String[] { "2000" };
NodeScript script = env.createScript(pathname, file, args);
final AbstractModuleRegistry registry = (AbstractModuleRegistry) callMethod(
NodeScript.class, script, "getRegistry", new Object[] {});
final ScriptRunner runner = new ScriptRunner(script, env, null, file,
args);

    runner.setRegistry(registry);

    runner.setParentProcess(null);

    ContextFactory contextFactory = env.getContextFactory();
    final ScriptableObject scope = (ScriptableObject) contextFactory
            .call(new ContextAction() {

                public Object run(Context cx) {

                    ScriptableObject scope = cx.initStandardObjects();
                    setField(ScriptRunner.class, "scope", runner, scope);
                    // Lazy first-time init of the node version.
                    registry.loadRoot(cx);
                    callMethod(ScriptRunner.class, runner, "initGlobals",
                            new Object[] { cx });

                    callMethod(ScriptRunner.class, runner, "setArgv",
                            new Object[] { pathname });
                    return scope;
                }

            });
    org.mozilla.javascript.tools.debugger.Main.mainEmbedded(contextFactory,
            scope, "my test");
    Object result = contextFactory.call(new ContextAction() {

        public Object run(Context cx) {
            cx.putThreadLocal(ScriptRunner.RUNNER, runner);

            Script mainScript = registry.getMainScript();

            try {
                String string = IOUtils.toString(trireme.class
                        .getResourceAsStream("trireme.js"));
                Function main = (Function) cx.evaluateString(scope, string,
                        "<cmd>", 1, null);
                // Function main = (Function) mainScript.exec(cx, scope);
                ProcessImpl process = runner.getProcess();
                Object r = main.call(cx, scope, scope,
                        new Object[] { process });
                return r;
            } catch (RhinoException re) {
                throw new RuntimeException(re);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }

    });
    System.out.println(result);
}

public static Method findMethod(Class<?> c, String name) {
    Method[] ms = c.getDeclaredMethods();
    for (Method each : ms) {
        String methodName = each.getName();
        if (name.equals(methodName)) {
            return each;
        }
    }
    return null;
}

public static Object callMethod(Class<?> c, Object instance,
        String methodName, Object[] args) {

    Method method = findMethod(c, methodName);
    method.setAccessible(true);
    try {
        if (Modifier.isStatic(method.getModifiers())) {
            return method.invoke(c, args);
        } else {
            return method.invoke(instance, args);
        }
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    } catch (IllegalArgumentException e) {
        throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
    }
}

public static void setField(Class<?> cls, String name, Object instance,
        Object value) {
    try {
        Field f = cls.getDeclaredField(name);
        f.setAccessible(true);
        f.set(instance, value);
    } catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    } catch (SecurityException e) {
        throw new RuntimeException(e);
    } catch (IllegalArgumentException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

}

What I need is a contextFactory and a scope object to call the code
org.mozilla.javascript.tools.debugger.Main.mainEmbedded(contextFactory,
scope, "my test");
is there any way to expose contextFactory and scope object in trireme, so i don't need to write so many code to embed debugger.

Thanks.

@gbrail
Copy link
Contributor

gbrail commented Apr 1, 2015

I would have no problem with having this capability built in to Trireme --
the debugger is currently part of the standard Rhino JAR, and at any rate
it is not very big.

Do you want to have a try modifying Trireme and submitting a pull request?

The place to put this code would be in the "ScriptRunner" class. The "call"
method is where it uses the ContextFactory to start up the script.

We could enable this functionality by adding another flag to the NodeScript
class -- if the flag is true, then ScriptRunner would launch the script
under the debugger rather than the usual way.

We also might want to modify the startup logic to accept a "--debug"
argument like regular Node does, but let's get it working first and then I
can mess around with the startup parameters.

On Tue, Mar 31, 2015 at 6:41 PM, sunchey11 [email protected] wrote:

When I read source of trireme, I wrote some code to embed rhino's debugger
program into trireme.
The code is ugly and not work in server program, but it help me understand
nodejs source and trireme js source.

public static void main(String[] theArgs) throws NodeException {
NodeEnvironment env = new NodeEnvironment();
final String pathname = "hellotest.js";
File file = new File(pathname);
String[] args = new String[] { "2000" };
NodeScript script = env.createScript(pathname, file, args);
final AbstractModuleRegistry registry = (AbstractModuleRegistry)
callMethod(
NodeScript.class, script, "getRegistry", new Object[] {});
final ScriptRunner runner = new ScriptRunner(script, env, null, file,
args);

runner.setRegistry(registry);

runner.setParentProcess(null);

ContextFactory contextFactory = env.getContextFactory();
final ScriptableObject scope = (ScriptableObject) contextFactory
        .call(new ContextAction() {

            public Object run(Context cx) {

                ScriptableObject scope = cx.initStandardObjects();
                setField(ScriptRunner.class, "scope", runner, scope);
                // Lazy first-time init of the node version.
                registry.loadRoot(cx);
                callMethod(ScriptRunner.class, runner, "initGlobals",
                        new Object[] { cx });

                callMethod(ScriptRunner.class, runner, "setArgv",
                        new Object[] { pathname });
                return scope;
            }

        });
org.mozilla.javascript.tools.debugger.Main.mainEmbedded(contextFactory,
        scope, "my test");
Object result = contextFactory.call(new ContextAction() {

    public Object run(Context cx) {
        cx.putThreadLocal(ScriptRunner.RUNNER, runner);

        Script mainScript = registry.getMainScript();

        try {
            String string = IOUtils.toString(trireme.class
                    .getResourceAsStream("trireme.js"));
            Function main = (Function) cx.evaluateString(scope, string,
                    "<cmd>", 1, null);
            // Function main = (Function) mainScript.exec(cx, scope);
            ProcessImpl process = runner.getProcess();
            Object r = main.call(cx, scope, scope,
                    new Object[] { process });
            return r;
        } catch (RhinoException re) {
            throw new RuntimeException(re);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

});
System.out.println(result);

}

public static Method findMethod(Class<?> c, String name) {
Method[] ms = c.getDeclaredMethods();
for (Method each : ms) {
String methodName = each.getName();
if (name.equals(methodName)) {
return each;
}
}
return null;
}

public static Object callMethod(Class<?> c, Object instance,
String methodName, Object[] args) {

Method method = findMethod(c, methodName);
method.setAccessible(true);
try {
    if (Modifier.isStatic(method.getModifiers())) {
        return method.invoke(c, args);
    } else {
        return method.invoke(instance, args);
    }
} catch (IllegalAccessException e) {
    throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
    throw new RuntimeException(e);
} catch (InvocationTargetException e) {
    throw new RuntimeException(e);
}

}

public static void setField(Class<?> cls, String name, Object instance,
Object value) {
try {
Field f = cls.getDeclaredField(name);
f.setAccessible(true);
f.set(instance, value);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}

}

What I need is a contextFactory and a scope object to call the code
org.mozilla.javascript.tools.debugger.Main.mainEmbedded(contextFactory,
scope, "my test");
is there any way to expose contextFactory and scope object in trireme, so
i don't need to write so many code to embed debugger.

Thanks.


Reply to this email directly or view it on GitHub
#109 (comment).

greg brail | apigee https://apigee.com/ | twitter @gbrail
http://twitter.com/gbrail

@sunchey11
Copy link
Author

I submitted a pull request.
I changed 4 file.
NativeModule.java
NodeScript.java
ScriptRunner.java
Utils.java

Using these code to show a debugger.
NodeEnvironment env = new NodeEnvironment();
NodeScript script = env.createScript("hellotest.js", new File(
"hellotest.js"), new String[] { "2000" });
script.setDebugging(true);
ScriptStatus status = script.execute().get();

I am not familiar with github and this is my first time submitting a pull request.
So please check if these file are completely committed.
Thanks.

@gbrail
Copy link
Contributor

gbrail commented Apr 3, 2015

Thanks!

I am traveling next week but I will look when I get back.

On Thursday, April 2, 2015, sunchey11 [email protected] wrote:

I submitted a pull request.
I changed 4 file.
NativeModule.java
NodeScript.java
ScriptRunner.java
Utils.java

I am not familiar with github and this is my first time submiting a pull
request.
So please check if these file are completely committed.
Thanks.


Reply to this email directly or view it on GitHub
#109 (comment).

greg brail | apigee https://apigee.com/ | twitter @gbrail
http://twitter.com/gbrail

@sunchey11
Copy link
Author

I had sent the last request to the wrong spot as I’m not familiar with the operation of the github.
I re-sent a pull request, you may check it in: #110
By the way, could you please advice when the trireme 0.8.6 will be released.
Thanks.

@gbrail
Copy link
Contributor

gbrail commented May 8, 2015

Yes, it's been a little while. I should have some time next week to do a
release.

I need a little time to understand and test the debug changes that you made
-- thanks for sending them, but they impact the product in a pretty
fundamental way and I need to see what other effects they have on the code
base. It probably makes sense to do that before doing a release, although
with the new Rhino version I could do a release with what's in master now
and it'd still have value.

On Thu, May 7, 2015 at 6:04 PM, sunchey11 [email protected] wrote:

I had sent the last request to the wrong spot as I’m not familiar with the
operation of the github.
I re-sent a pull request, you may check it in: #110
#110
By the way, could you please advice when the trireme 0.8.6 will be
released.
Thanks.


Reply to this email directly or view it on GitHub
#109 (comment).

greg brail | apigee https://apigee.com/ | twitter @gbrail
http://twitter.com/gbrail

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants