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

329 lines
5.7 KiB
Go

package goja
import "testing"
func TestGomapProp(t *testing.T) {
const SCRIPT = `
o.a + o.b;
`
r := New()
r.Set("o", map[string]interface{}{
"a": 40,
"b": 2,
})
v, err := r.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if i := v.ToInteger(); i != 42 {
t.Fatalf("Expected 42, got: %d", i)
}
}
func TestGomapEnumerate(t *testing.T) {
const SCRIPT = `
var hasX = false;
var hasY = false;
for (var key in o) {
switch (key) {
case "x":
if (hasX) {
throw "Already have x";
}
hasX = true;
break;
case "y":
if (hasY) {
throw "Already have y";
}
hasY = true;
break;
default:
throw "Unexpected property: " + key;
}
}
hasX && hasY;
`
r := New()
r.Set("o", map[string]interface{}{
"x": 40,
"y": 2,
})
v, err := r.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(valueTrue) {
t.Fatalf("Expected true, got %v", v)
}
}
func TestGomapDeleteWhileEnumerate(t *testing.T) {
const SCRIPT = `
var hasX = false;
var hasY = false;
for (var key in o) {
switch (key) {
case "x":
if (hasX) {
throw "Already have x";
}
hasX = true;
delete o.y;
break;
case "y":
if (hasY) {
throw "Already have y";
}
hasY = true;
delete o.x;
break;
default:
throw "Unexpected property: " + key;
}
}
hasX && !hasY || hasY && !hasX;
`
r := New()
r.Set("o", map[string]interface{}{
"x": 40,
"y": 2,
})
v, err := r.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(valueTrue) {
t.Fatalf("Expected true, got %v", v)
}
}
func TestGomapInstanceOf(t *testing.T) {
const SCRIPT = `
(o instanceof Object) && !(o instanceof Error);
`
r := New()
r.Set("o", map[string]interface{}{})
v, err := r.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(valueTrue) {
t.Fatalf("Expected true, got %v", v)
}
}
func TestGomapTypeOf(t *testing.T) {
const SCRIPT = `
typeof o;
`
r := New()
r.Set("o", map[string]interface{}{})
v, err := r.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(asciiString("object")) {
t.Fatalf("Expected object, got %v", v)
}
}
func TestGomapProto(t *testing.T) {
const SCRIPT = `
o.hasOwnProperty("test");
`
r := New()
r.Set("o", map[string]interface{}{
"test": 42,
})
v, err := r.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(valueTrue) {
t.Fatalf("Expected true, got %v", v)
}
}
func TestGoMapExtensibility(t *testing.T) {
const SCRIPT = `
"use strict";
o.test = 42;
Object.preventExtensions(o);
o.test = 43;
try {
o.test1 = 42;
} catch (e) {
if (!(e instanceof TypeError)) {
throw e;
}
}
o.test === 43 && o.test1 === undefined;
`
r := New()
r.Set("o", map[string]interface{}{})
v, err := r.RunString(SCRIPT)
if err != nil {
if ex, ok := err.(*Exception); ok {
t.Fatal(ex.String())
} else {
t.Fatal(err)
}
}
if !v.StrictEquals(valueTrue) {
t.Fatalf("Expected true, got %v", v)
}
}
func TestGoMapWithProto(t *testing.T) {
vm := New()
m := map[string]interface{}{
"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);
assert.sameValue(tHolder, true);
Object.preventExtensions(m);
assert.throws(TypeError, function() {
m.t2 = 1;
});
m.t1 = "test2";
assert.sameValue(m.t1, "test2");
})();
`, _undefined, t)
}
func TestGoMapProtoProp(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]interface{}{})
r.testScriptWithTestLib(SCRIPT, _undefined, t)
}
func TestGoMapProtoPropChain(t *testing.T) {
const SCRIPT = `
(function() {
"use strict";
var p1 = Object.create(null);
m.__proto__ = p1;
Object.defineProperty(p1, "test", {
value: 42
});
Object.defineProperty(m, "test", {
value: 43,
writable: true,
});
var o = Object.create(m);
o.test = 44;
assert.sameValue(o.test, 44);
var sym = Symbol(true);
Object.defineProperty(p1, sym, {
value: 42
});
Object.defineProperty(m, sym, {
value: 43,
writable: true,
});
o[sym] = 44;
assert.sameValue(o[sym], 44);
})();
`
r := New()
r.Set("m", map[string]interface{}{})
r.testScriptWithTestLib(SCRIPT, _undefined, t)
}
func TestGoMapUnicode(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]interface{}{
"é": 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)
}
}