feat(rtl): nodebridge decodes JS arrays/objects to native PRG values

jsValToValue now recursively converts JS arrays/objects (the "json" wire
type) into native hbrt arrays/hashes, so PRG can Len()/index/hb_HGetDef the
results of npm methods (e.g. os.cpus()[1]:model). Strings/numbers/booleans/
buffers unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
CharlesKWON
2026-06-15 21:42:00 +09:00
parent 1e80c89414
commit 76853d4beb

View File

@@ -370,7 +370,13 @@ func jsValToValue(val map[string]interface{}) hbrt.Value {
t := str(val["t"])
v := str(val["v"])
switch t {
case "string", "buffer", "json":
case "string", "buffer":
return hbrt.MakeString(v)
case "json": // JS array/object → 네이티브 PRG 배열/해시로 디코드
var parsed interface{}
if err := json.Unmarshal([]byte(v), &parsed); err == nil {
return jsonToValue(parsed)
}
return hbrt.MakeString(v)
case "number":
if f, err := strconv.ParseFloat(v, 64); err == nil {
@@ -384,6 +390,34 @@ func jsValToValue(val map[string]interface{}) hbrt.Value {
}
}
// jsonToValue: 디코드된 JSON 값을 네이티브 hbrt.Value(배열/해시/스칼라)로.
func jsonToValue(x interface{}) hbrt.Value {
switch v := x.(type) {
case nil:
return hbrt.MakeNil()
case bool:
return hbrt.MakeBool(v)
case float64:
return hbrt.MakeDoubleAuto(v)
case string:
return hbrt.MakeString(v)
case []interface{}:
items := make([]hbrt.Value, len(v))
for i, e := range v {
items[i] = jsonToValue(e)
}
return hbrt.MakeArrayFrom(items)
case map[string]interface{}:
pairs := make([]hbrt.Value, 0, len(v)*2)
for k, e := range v {
pairs = append(pairs, hbrt.MakeString(k), jsonToValue(e))
}
return hbrt.MakeHashFrom(hbrt.HashFromPairs(pairs))
default:
return hbrt.MakeNil()
}
}
func str(v interface{}) string {
if s, ok := v.(string); ok {
return s