package jscriptx_test import ( "context" "testing" "git.fsdpf.net/go/jscriptx" ) // Go 的切片和 map 进到脚本里长什么样。 // // 这不是 jscriptx 的行为,是 goja 的——但脚本作者是照着这个写代码的,一旦变了, // 业务脚本会**静默**走错分支(比如查出来的记录突然 Array.isArray 为 false, // 整段列表被当成空的),所以在这里钉住。 // // 之所以走 jscriptx 而不是直接用 goja:注入前还经过一层 freeze,得连那层一起验。 func TestGo值到脚本里的形状(t *testing.T) { e, err := jscriptx.New(jscriptx.WithLogger(nil)) if err != nil { t.Fatal(err) } defer e.Close() // 照着资源查询的返回长的:[]map[string]any,里面混着切片、字符串和 nil records := func() []map[string]any { return []map[string]any{{ "role": "user", "content": "你好", "attempts": []any{map[string]any{"name": "a.pdf"}, map[string]any{"url": "http://x"}}, "tool_calls": `[{"id":"1"}]`, // 列里存的是 JSON 字符串 "reasoning": nil, }} } s, err := e.Compile("shape.ts", ` export default class C { Run() { const rows = getRecords() const r = rows[0] return { // 切片是真数组:length / for-of / map 都能用 rowsIsArray: Array.isArray(rows), rowsLen: rows.length, attemptsIsArray: Array.isArray(r.attempts), attemptsLen: r.attempts.length, mapped: r.attempts.map(a => a.name || a.url).join(","), // map[string]any 的值按 Go 的类型各自转换,不会统一成字符串 contentType: typeof r.content, toolCallsType: typeof r.tool_calls, // Go 的 nil 是 null,不是 undefined——判空要用 == null 或 === null reasoningIsNull: r.reasoning === null, reasoningIsUndef: r.reasoning === undefined, // 没有的列是 undefined,不会报错 missingIsUndef: r.nope === undefined, } } }`) if err != nil { t.Fatal(err) } ctx := jscriptx.WithScope(context.Background(), jscriptx.ScopeGlobals(map[string]any{"getRecords": records})) obj, err := s.New(ctx) if err != nil { t.Fatal(err) } defer obj.Close() var got map[string]any if err := obj.CallInto(ctx, "Run", &got); err != nil { t.Fatal(err) } want := map[string]any{ "rowsIsArray": true, "rowsLen": int64(1), "attemptsIsArray": true, "attemptsLen": int64(2), "mapped": "a.pdf,http://x", "contentType": "string", "toolCallsType": "string", "reasoningIsNull": true, "reasoningIsUndef": false, "missingIsUndef": true, } for k, w := range want { if got[k] != w { t.Errorf("%s = %#v,该是 %#v", k, got[k], w) } } }