You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GraalVM Polyglot获取JS方法内变量为空的问题求助

如何在GraalVM ExecutionListener中获取JS方法内的局部变量?

问题描述

我在使用GraalVM Polyglot API调用JS模块时,尝试在ExecutionListener.onEnter中获取JS方法执行时的局部变量,但始终得到空集合。目前只能拿到export default中的成员,无法获取test方法内部的深层变量。

修正后的代码

package com.fbi.fvite;

import org.graalvm.polyglot.*;
import org.graalvm.polyglot.management.ExecutionListener;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Test {
    private static Map<String, String> options = new HashMap<>();

    public static void main(String[] args) {

        System.setProperty("polyglot.engine.WarnInterpreterOnly", "false");

        // Enable CommonJS experimental support.
        options.put("js.commonjs-require", "true");
        options.put("js.esm-eval-returns-exports", "true");
        options.put("js.commonjs-require-cwd", "projects/" + CommAttr.projectId + "/src/modules");
        // 开启JS调试支持
        options.put("js.debug", "true");

        Source js = null;
        try {
            js = Source.newBuilder("js","""
                    export default {
                                        
                        /**
                         * test method
                         */
                        test(params) {
                            const { hello, world } = params;
                            var aaa = '123';
                                        
                            return {
                                hello,
                                world
                            }
                        }
                    }
                    
                    
                    """,
                    "test.mjs"
            ).mimeType("application/javascript+module").build();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try(Context context = Context.newBuilder()
                .allowAllAccess(true)
                .options(options)
                .allowExperimentalOptions(true)
                .allowIO(true)
                .allowDebugging(true) // 允许访问调试API
                .build()){
            Value fun = context.eval(js).getMember("default").getMember("test");

            ExecutionListener listener = ExecutionListener.newBuilder()
                    .onEnter((e) -> {
                        // 获取当前执行栈帧
                        Frame frame = e.getFrame();
                        if (frame != null) {
                            Map<String, Object> variables = new HashMap<>();
                            // 遍历栈帧中的局部变量
                            for (String varName : frame.getVariableNames()) {
                                Value varValue = frame.getVariable(varName);
                                // 区分宿主对象和JS原生值,按需转换
                                variables.put(varName, varValue.isHostObject() ? varValue.asHostObject() : varValue.toString());
                            }

                            SourceSection section = e.getLocation();
                            System.out.println("line: " + section.getStartLine() + ", code: " + section.getCharacters() + ", variables: " + variables);
                        }
                    })
                    .statements(true)
                    .collectInputValues(true)
                    .attach(context.getEngine());
            Value value = fun.execute(Map.of("hello", "world"));
            System.out.println("完毕,返回值:" + value);
            listener.close();
        }
    }
}

关键修正说明

  1. 启用调试配置

    • 添加js.debug=true选项开启JS调试支持
    • 构建Context时调用.allowDebugging(true),允许访问栈帧等调试相关API
  2. 正确获取局部变量

    • 不再从JS函数对象fun中取成员,而是通过ExecutionEvent.getFrame()获取当前执行的栈帧
    • 利用Frame.getVariableNames()遍历局部变量名,再通过Frame.getVariable(varName)获取对应变量值
  3. 变量值处理

    • 区分宿主对象和JS原生值,按需转换为Java对象或字符串,方便查看输出

内容的提问来源于stack exchange,提问作者shengkai guo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 23:00:57