123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- 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)
- })
- }
|