有没有办法从java获取当前源位置(SourceSection)?
例如通过 context.eval() 执行的 js 脚本调用 java 方法,java 方法记录当前 js 脚本名称+行
PolyglotException 有一个提供此信息的 getSourceLocation()。来自 polyglot 的堆栈跟踪似乎包含有关源位置的信息,例如:program(Unnamed:2:23-53)
有没有办法从java获取当前源位置(SourceSection)?
例如通过 context.eval() 执行的 js 脚本调用 java 方法,java 方法记录当前 js 脚本名称+行
PolyglotException 有一个提供此信息的 getSourceLocation()。来自 polyglot 的堆栈跟踪似乎包含有关源位置的信息,例如:program(Unnamed:2:23-53)
我知道你很久以前就问过这个问题,但我只是第一次看到它。
这是一种轻松到达当前位置的方法:
static StackFrame getCurrentLocation() {
PolyglotException e = Context.getCurrent().asValue(new RuntimeException()).as(PolyglotException.class);
for (StackFrame frame: e.getPolyglotStackTrace()) {
if (frame.isGuestFrame()) {
return frame;
}
}
return null;
}
这是一个完整的可运行示例:
public class Test {
public static void main(String[] args) {
try (Context context = Context.newBuilder().allowHostAccess(HostAccess.ALL).build()) {
context.getBindings("js").putMember("test", new Test());
Source source = Source.newBuilder("js", "test.callback()", "mysource.js").buildLiteral();
context.eval(source);
}
}
public void callback() {
System.out.println(getCurrentLocation());
}
static StackFrame getCurrentLocation() {
PolyglotException e = Context.getCurrent().asValue(new RuntimeException()).as(PolyglotException.class);
for (StackFrame frame: e.getPolyglotStackTrace()) {
if (frame.isGuestFrame()) {
return frame;
}
}
return null;
}
}
这打印:
<js> :program(mysource.js:1:0-14)
哈克解决方案:您可以将new Error().stack
作为参数传递给您的 java 函数以获取堆栈跟踪。给定
public class A {
public A() {}
public void foo(String x) {
System.out.println("MY ARGUMENT IS: " + x);
}
}
你可以
$GRAALVM_HOME/bin/js --jvm --vm.cp=.
> function bar() { var x = new (Java.type("A"))(); x.foo(new Error().stack) }
> bar()
MY ARGUMENT IS: Error
at bar (<shell>:6:1:56)
at <shell>:7:1:1
我找到了一个解决方案,但我仍然不确定它是好还是坏。但目前它是唯一一个似乎有效的方法。
基本上,我需要在 java args 中添加一堆 --add-opens:
--add-opens org.graalvm.truffle/com.oracle.truffle.api=ALL-UNNAMED
--add-opens org.graalvm.truffle/com.oracle.truffle.api.frame=ALL-UNNAMED
--add-opens org.graalvm.truffle/com.oracle.truffle.api.nodes=ALL-UNNAMED
--add-opens org.graalvm.truffle/com.oracle.truffle.api.source=ALL-UNNAMED
然后使用 Truffle 运行时,我可以获得调用者框架和 SourceSelection
Truffle.getRuntime().getCallerFrame().getCallNode().getEncapsulatingSourceSection()