2009/12/9 Charles Oliver Nutter <[email protected]>: > On Wed, Dec 9, 2009 at 12:06 PM, Hannes Wallnoefer <[email protected]> wrote: >>> Rhino, in interpreted mode, will inject script stack elements into the Java >>> stack elements, so above every >>> org.mozilla.javascript.Interpreter.interpret() element, you'll have all the >>> JS frames the interpreter created, with an appropriate syntax (function >>> name + source code name + line number; obviously the class name doesn't >>> apply...). >> >> Not to forget the getScriptStackTrace() method in RhinoException. This >> works in both compiled and interpreted mode, and returns a (synthetic) >> stack trace including only the script sources. In Helma NG the >> developer is usually presented two dedicated stack traces as shown >> below. I think this is much preferable to messing with the actual >> stack trace which diminishes its usefulness for the language >> implementor. >> >> ReferenceError: "foo" is not defined. >> Script Stack >> at actions.js:67 >> at helma/webapp.js:97 >> at helma/webapp.js:47 >> at helma/middleware/notfound.js:10 >> at helma/middleware/error.js:13 >> at helma/middleware/responselog.js:26 >> at helma/middleware/etag.js:15 >> at helma/middleware/gzip.js:15 >> at helma/jsgi.js:31 > > Can one of you describe how this is done internally in Rhino? We > obviously have the same challenge in JRuby (and probably in Jython > too) but you may have a simpler or more efficient way to do it.
It's really rather a low-tech approach. RhinoException.getScriptStackTrace() loops through the exception's stack trace and tries to pick only those elements that represent a script source. It returns a String with the rendered stack trace, not an array of stack trace elements, so its only purpose is to be shown to a human being. The hardest part is merging compiled and interpreted code, which can be on the stack at the same time. For compiled code, it's easy - we just check the StackTraceElement's fileName against a file name pattern, which is *.js by default but you can define your own java.io.FilenameFilter if you want. For interpreted code it's a bit harder. The interpreter keeps its own call frame stack and when a RhinoException is initialized the interpreter fills in its current stack. Now when walking the java stack in getScriptStackTrace(), we simply look for frames that represent the interpreter loop (method "interpretLoop" in class "org.mozilla.javascript.Interpreter"). If there is a matching interpreter stack frame as there should be, we fill in its file name and line number. As I said, the approach is simple and pragmatical, but it works well for what it is supposed to do. Hannes -- You received this message because you are subscribed to the Google Groups "JVM Languages" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/jvm-languages?hl=en.
