ai_old/goja/object_gomap_reflect_test.go
2024-09-20 16:50:35 +08:00

351 lines
6.2 KiB
Go

package goja
import (
"sort"
"strings"
"testing"
)
func TestGoMapReflectGetSet(t *testing.T) {
const SCRIPT = `
m.c = m.a + m.b;
`
vm := New()
m := map[string]string{
"a": "4",
"b": "2",
}
vm.Set("m", m)
_, err := vm.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if c := m["c"]; c != "42" {
t.Fatalf("Unexpected value: '%s'", c)
}
}
func TestGoMapReflectIntKey(t *testing.T) {
const SCRIPT = `
m[2] = m[0] + m[1];
`
vm := New()
m := map[int]int{
0: 40,
1: 2,
}
vm.Set("m", m)
_, err := vm.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if c := m[2]; c != 42 {
t.Fatalf("Unexpected value: '%d'", c)
}
}
func TestGoMapReflectDelete(t *testing.T) {
const SCRIPT = `
delete m.a;
`
vm := New()
m := map[string]string{
"a": "4",
"b": "2",
}
vm.Set("m", m)
_, err := vm.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if _, exists := m["a"]; exists {
t.Fatal("a still exists")
}
if b := m["b"]; b != "2" {
t.Fatalf("Unexpected b: '%s'", b)
}
}
func TestGoMapReflectJSON(t *testing.T) {
const SCRIPT = `
function f(m) {
return JSON.stringify(m);
}
`
vm := New()
m := map[string]string{
"t": "42",
}
_, err := vm.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
f := vm.Get("f")
if call, ok := AssertFunction(f); ok {
v, err := call(nil, ([]Value{vm.ToValue(m)})...)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(asciiString(`{"t":"42"}`)) {
t.Fatalf("Unexpected value: %v", v)
}
} else {
t.Fatalf("Not a function: %v", f)
}
}
func TestGoMapReflectProto(t *testing.T) {
const SCRIPT = `
m.hasOwnProperty("t");
`
vm := New()
m := map[string]string{
"t": "42",
}
vm.Set("m", m)
v, err := vm.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(valueTrue) {
t.Fatalf("Expected true, got %v", v)
}
}
type gomapReflect_noMethods map[string]interface{}
type gomapReflect_withMethods map[string]interface{}
func (m gomapReflect_withMethods) Method() bool {
return true
}
func TestGoMapReflectNoMethods(t *testing.T) {
const SCRIPT = `
typeof m === "object" && m.hasOwnProperty("t") && m.t === 42;
`
vm := New()
m := make(gomapReflect_noMethods)
m["t"] = 42
vm.Set("m", m)
v, err := vm.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(valueTrue) {
t.Fatalf("Expected true, got %v", v)
}
}
func TestGoMapReflectWithMethods(t *testing.T) {
const SCRIPT = `
typeof m === "object" && !m.hasOwnProperty("t") && m.hasOwnProperty("Method") && m.Method();
`
vm := New()
m := make(gomapReflect_withMethods)
m["t"] = 42
vm.Set("m", m)
v, err := vm.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(valueTrue) {
t.Fatalf("Expected true, got %v", v)
}
}
func TestGoMapReflectWithProto(t *testing.T) {
vm := New()
m := map[string]string{
"t": "42",
}
vm.Set("m", m)
vm.testScriptWithTestLib(`
(function() {
'use strict';
var proto = {};
var getterAllowed = false;
var setterAllowed = false;
var tHolder = "proto t";
Object.defineProperty(proto, "t", {
get: function() {
if (!getterAllowed) throw new Error("getter is called");
return tHolder;
},
set: function(v) {
if (!setterAllowed) throw new Error("setter is called");
tHolder = v;
}
});
var t1Holder;
Object.defineProperty(proto, "t1", {
get: function() {
return t1Holder;
},
set: function(v) {
t1Holder = v;
}
});
Object.setPrototypeOf(m, proto);
assert.sameValue(m.t, "42");
m.t = 43;
assert.sameValue(m.t, "43");
t1Holder = "test";
assert.sameValue(m.t1, "test");
m.t1 = "test1";
assert.sameValue(m.t1, "test1");
delete m.t;
getterAllowed = true;
assert.sameValue(m.t, "proto t", "after delete");
setterAllowed = true;
m.t = true;
assert.sameValue(m.t, true, "m.t === true");
assert.sameValue(tHolder, true, "tHolder === true");
Object.preventExtensions(m);
assert.throws(TypeError, function() {
m.t2 = 1;
});
m.t1 = "test2";
assert.sameValue(m.t1, "test2");
})();
`, _undefined, t)
}
func TestGoMapReflectProtoProp(t *testing.T) {
const SCRIPT = `
(function() {
"use strict";
var proto = {};
Object.defineProperty(proto, "ro", {value: 42});
Object.setPrototypeOf(m, proto);
assert.throws(TypeError, function() {
m.ro = 43;
});
Object.defineProperty(m, "ro", {value: 43});
assert.sameValue(m.ro, "43");
})();
`
r := New()
r.Set("m", map[string]string{})
r.testScriptWithTestLib(SCRIPT, _undefined, t)
}
func TestGoMapReflectUnicode(t *testing.T) {
const SCRIPT = `
Object.setPrototypeOf(m, s);
if (m.Тест !== "passed") {
throw new Error("m.Тест: " + m.Тест);
}
m["é"];
`
type S struct {
Тест string
}
vm := New()
m := map[string]int{
"é": 42,
}
s := S{
Тест: "passed",
}
vm.Set("m", m)
vm.Set("s", &s)
res, err := vm.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if res == nil || !res.StrictEquals(valueInt(42)) {
t.Fatalf("Unexpected value: %v", res)
}
}
func TestGoMapReflectStruct(t *testing.T) {
type S struct {
Test int
}
m := map[string]S{
"1": {Test: 1},
}
vm := New()
vm.Set("m", m)
res, err := vm.RunString("m[1].Test = 2; m[1].Test")
if err != nil {
t.Fatal(err)
}
if res.Export() != int64(1) {
t.Fatal(res)
}
}
func TestGoMapReflectElt(t *testing.T) {
type mapping map[string]interface{}
const SCRIPT = `a.s() && a.t === null && a.t1 === undefined;`
r := New()
r.Set("a", mapping{
"s": func() bool { return true },
"t": nil,
})
r.testScript(SCRIPT, valueTrue, t)
}
func TestGoMapReflectKeyToString(t *testing.T) {
vm := New()
test := func(v any, t *testing.T) {
o1 := vm.ToValue(v).ToObject(vm)
keys := o1.Keys()
sort.Strings(keys)
if len(keys) != 2 || keys[0] != "1" || keys[1] != "2" {
t.Fatal(keys)
}
keys1 := o1.self.stringKeys(true, nil)
sort.Slice(keys1, func(a, b int) bool {
return strings.Compare(keys1[a].String(), keys1[b].String()) < 0
})
if len(keys1) != 2 || keys1[0] != asciiString("1") || keys1[1] != asciiString("2") {
t.Fatal(keys1)
}
}
t.Run("int", func(t *testing.T) {
m1 := map[int]any{
1: 2,
2: 3,
}
test(m1, t)
})
t.Run("CustomString", func(t *testing.T) {
type CustomString string
m2 := map[CustomString]any{
"1": 2,
"2": 3,
}
test(m2, t)
})
}