1package goja 2 3import ( 4 "testing" 5) 6 7func TestGoMapReflectGetSet(t *testing.T) { 8 const SCRIPT = ` 9 m.c = m.a + m.b; 10 ` 11 12 vm := New() 13 m := map[string]string{ 14 "a": "4", 15 "b": "2", 16 } 17 vm.Set("m", m) 18 19 _, err := vm.RunString(SCRIPT) 20 if err != nil { 21 t.Fatal(err) 22 } 23 24 if c := m["c"]; c != "42" { 25 t.Fatalf("Unexpected value: '%s'", c) 26 } 27} 28 29func TestGoMapReflectIntKey(t *testing.T) { 30 const SCRIPT = ` 31 m[2] = m[0] + m[1]; 32 ` 33 34 vm := New() 35 m := map[int]int{ 36 0: 40, 37 1: 2, 38 } 39 vm.Set("m", m) 40 41 _, err := vm.RunString(SCRIPT) 42 if err != nil { 43 t.Fatal(err) 44 } 45 46 if c := m[2]; c != 42 { 47 t.Fatalf("Unexpected value: '%d'", c) 48 } 49} 50 51func TestGoMapReflectDelete(t *testing.T) { 52 const SCRIPT = ` 53 delete m.a; 54 ` 55 56 vm := New() 57 m := map[string]string{ 58 "a": "4", 59 "b": "2", 60 } 61 vm.Set("m", m) 62 63 _, err := vm.RunString(SCRIPT) 64 if err != nil { 65 t.Fatal(err) 66 } 67 68 if _, exists := m["a"]; exists { 69 t.Fatal("a still exists") 70 } 71 72 if b := m["b"]; b != "2" { 73 t.Fatalf("Unexpected b: '%s'", b) 74 } 75} 76 77func TestGoMapReflectJSON(t *testing.T) { 78 const SCRIPT = ` 79 function f(m) { 80 return JSON.stringify(m); 81 } 82 ` 83 84 vm := New() 85 m := map[string]string{ 86 "t": "42", 87 } 88 _, err := vm.RunString(SCRIPT) 89 if err != nil { 90 t.Fatal(err) 91 } 92 f := vm.Get("f") 93 if call, ok := AssertFunction(f); ok { 94 v, err := call(nil, ([]Value{vm.ToValue(m)})...) 95 if err != nil { 96 t.Fatal(err) 97 } 98 if !v.StrictEquals(asciiString(`{"t":"42"}`)) { 99 t.Fatalf("Unexpected value: %v", v) 100 } 101 } else { 102 t.Fatalf("Not a function: %v", f) 103 } 104} 105 106func TestGoMapReflectProto(t *testing.T) { 107 const SCRIPT = ` 108 m.hasOwnProperty("t"); 109 ` 110 111 vm := New() 112 m := map[string]string{ 113 "t": "42", 114 } 115 vm.Set("m", m) 116 v, err := vm.RunString(SCRIPT) 117 if err != nil { 118 t.Fatal(err) 119 } 120 if !v.StrictEquals(valueTrue) { 121 t.Fatalf("Expected true, got %v", v) 122 } 123} 124 125type gomapReflect_noMethods map[string]interface{} 126type gomapReflect_withMethods map[string]interface{} 127 128func (m gomapReflect_withMethods) Method() bool { 129 return true 130} 131 132func TestGoMapReflectNoMethods(t *testing.T) { 133 const SCRIPT = ` 134 typeof m === "object" && m.hasOwnProperty("t") && m.t === 42; 135 ` 136 137 vm := New() 138 m := make(gomapReflect_noMethods) 139 m["t"] = 42 140 vm.Set("m", m) 141 v, err := vm.RunString(SCRIPT) 142 if err != nil { 143 t.Fatal(err) 144 } 145 if !v.StrictEquals(valueTrue) { 146 t.Fatalf("Expected true, got %v", v) 147 } 148 149} 150 151func TestGoMapReflectWithMethods(t *testing.T) { 152 const SCRIPT = ` 153 typeof m === "object" && !m.hasOwnProperty("t") && m.hasOwnProperty("Method") && m.Method(); 154 ` 155 156 vm := New() 157 m := make(gomapReflect_withMethods) 158 m["t"] = 42 159 vm.Set("m", m) 160 v, err := vm.RunString(SCRIPT) 161 if err != nil { 162 t.Fatal(err) 163 } 164 if !v.StrictEquals(valueTrue) { 165 t.Fatalf("Expected true, got %v", v) 166 } 167 168} 169 170func TestGoMapReflectWithProto(t *testing.T) { 171 vm := New() 172 m := map[string]string{ 173 "t": "42", 174 } 175 vm.Set("m", m) 176 _, err := vm.RunString(TESTLIB + ` 177 (function() { 178 'use strict'; 179 var proto = {}; 180 var getterAllowed = false; 181 var setterAllowed = false; 182 var tHolder = "proto t"; 183 Object.defineProperty(proto, "t", { 184 get: function() { 185 if (!getterAllowed) throw new Error("getter is called"); 186 return tHolder; 187 }, 188 set: function(v) { 189 if (!setterAllowed) throw new Error("setter is called"); 190 tHolder = v; 191 } 192 }); 193 var t1Holder; 194 Object.defineProperty(proto, "t1", { 195 get: function() { 196 return t1Holder; 197 }, 198 set: function(v) { 199 t1Holder = v; 200 } 201 }); 202 Object.setPrototypeOf(m, proto); 203 assert.sameValue(m.t, "42"); 204 m.t = 43; 205 assert.sameValue(m.t, "43"); 206 t1Holder = "test"; 207 assert.sameValue(m.t1, "test"); 208 m.t1 = "test1"; 209 assert.sameValue(m.t1, "test1"); 210 delete m.t; 211 getterAllowed = true; 212 assert.sameValue(m.t, "proto t", "after delete"); 213 setterAllowed = true; 214 m.t = true; 215 assert.sameValue(m.t, true, "m.t === true"); 216 assert.sameValue(tHolder, true, "tHolder === true"); 217 Object.preventExtensions(m); 218 assert.throws(TypeError, function() { 219 m.t2 = 1; 220 }); 221 m.t1 = "test2"; 222 assert.sameValue(m.t1, "test2"); 223 })(); 224 `) 225 if err != nil { 226 t.Fatal(err) 227 } 228} 229 230func TestGoMapReflectProtoProp(t *testing.T) { 231 const SCRIPT = ` 232 (function() { 233 "use strict"; 234 var proto = {}; 235 Object.defineProperty(proto, "ro", {value: 42}); 236 Object.setPrototypeOf(m, proto); 237 assert.throws(TypeError, function() { 238 m.ro = 43; 239 }); 240 Object.defineProperty(m, "ro", {value: 43}); 241 assert.sameValue(m.ro, "43"); 242 })(); 243 ` 244 245 r := New() 246 r.Set("m", map[string]string{}) 247 _, err := r.RunString(TESTLIB + SCRIPT) 248 if err != nil { 249 t.Fatal(err) 250 } 251} 252 253func TestGoMapReflectUnicode(t *testing.T) { 254 const SCRIPT = ` 255 Object.setPrototypeOf(m, s); 256 if (m.Тест !== "passed") { 257 throw new Error("m.Тест: " + m.Тест); 258 } 259 m["é"]; 260 ` 261 type S struct { 262 Тест string 263 } 264 vm := New() 265 m := map[string]int{ 266 "é": 42, 267 } 268 s := S{ 269 Тест: "passed", 270 } 271 vm.Set("m", m) 272 vm.Set("s", &s) 273 res, err := vm.RunString(SCRIPT) 274 if err != nil { 275 t.Fatal(err) 276 } 277 if res == nil || !res.StrictEquals(valueInt(42)) { 278 t.Fatalf("Unexpected value: %v", res) 279 } 280} 281