1package goja 2 3import "testing" 4 5func TestGomapProp(t *testing.T) { 6 const SCRIPT = ` 7 o.a + o.b; 8 ` 9 r := New() 10 r.Set("o", map[string]interface{}{ 11 "a": 40, 12 "b": 2, 13 }) 14 v, err := r.RunString(SCRIPT) 15 if err != nil { 16 t.Fatal(err) 17 } 18 if i := v.ToInteger(); i != 42 { 19 t.Fatalf("Expected 42, got: %d", i) 20 } 21} 22 23func TestGomapEnumerate(t *testing.T) { 24 const SCRIPT = ` 25 var hasX = false; 26 var hasY = false; 27 for (var key in o) { 28 switch (key) { 29 case "x": 30 if (hasX) { 31 throw "Already have x"; 32 } 33 hasX = true; 34 break; 35 case "y": 36 if (hasY) { 37 throw "Already have y"; 38 } 39 hasY = true; 40 break; 41 default: 42 throw "Unexpected property: " + key; 43 } 44 } 45 hasX && hasY; 46 ` 47 r := New() 48 r.Set("o", map[string]interface{}{ 49 "x": 40, 50 "y": 2, 51 }) 52 v, err := r.RunString(SCRIPT) 53 if err != nil { 54 t.Fatal(err) 55 } 56 57 if !v.StrictEquals(valueTrue) { 58 t.Fatalf("Expected true, got %v", v) 59 } 60} 61 62func TestGomapDeleteWhileEnumerate(t *testing.T) { 63 const SCRIPT = ` 64 var hasX = false; 65 var hasY = false; 66 for (var key in o) { 67 switch (key) { 68 case "x": 69 if (hasX) { 70 throw "Already have x"; 71 } 72 hasX = true; 73 delete o.y; 74 break; 75 case "y": 76 if (hasY) { 77 throw "Already have y"; 78 } 79 hasY = true; 80 delete o.x; 81 break; 82 default: 83 throw "Unexpected property: " + key; 84 } 85 } 86 hasX && !hasY || hasY && !hasX; 87 ` 88 r := New() 89 r.Set("o", map[string]interface{}{ 90 "x": 40, 91 "y": 2, 92 }) 93 v, err := r.RunString(SCRIPT) 94 if err != nil { 95 t.Fatal(err) 96 } 97 98 if !v.StrictEquals(valueTrue) { 99 t.Fatalf("Expected true, got %v", v) 100 } 101} 102 103func TestGomapInstanceOf(t *testing.T) { 104 const SCRIPT = ` 105 (o instanceof Object) && !(o instanceof Error); 106 ` 107 r := New() 108 r.Set("o", map[string]interface{}{}) 109 v, err := r.RunString(SCRIPT) 110 if err != nil { 111 t.Fatal(err) 112 } 113 114 if !v.StrictEquals(valueTrue) { 115 t.Fatalf("Expected true, got %v", v) 116 } 117} 118 119func TestGomapTypeOf(t *testing.T) { 120 const SCRIPT = ` 121 typeof o; 122 ` 123 r := New() 124 r.Set("o", map[string]interface{}{}) 125 v, err := r.RunString(SCRIPT) 126 if err != nil { 127 t.Fatal(err) 128 } 129 130 if !v.StrictEquals(asciiString("object")) { 131 t.Fatalf("Expected object, got %v", v) 132 } 133} 134 135func TestGomapProto(t *testing.T) { 136 const SCRIPT = ` 137 o.hasOwnProperty("test"); 138 ` 139 r := New() 140 r.Set("o", map[string]interface{}{ 141 "test": 42, 142 }) 143 v, err := r.RunString(SCRIPT) 144 if err != nil { 145 t.Fatal(err) 146 } 147 148 if !v.StrictEquals(valueTrue) { 149 t.Fatalf("Expected true, got %v", v) 150 } 151} 152 153func TestGoMapExtensibility(t *testing.T) { 154 const SCRIPT = ` 155 "use strict"; 156 o.test = 42; 157 Object.preventExtensions(o); 158 o.test = 43; 159 try { 160 o.test1 = 42; 161 } catch (e) { 162 if (!(e instanceof TypeError)) { 163 throw e; 164 } 165 } 166 o.test === 43 && o.test1 === undefined; 167 ` 168 169 r := New() 170 r.Set("o", map[string]interface{}{}) 171 v, err := r.RunString(SCRIPT) 172 if err != nil { 173 if ex, ok := err.(*Exception); ok { 174 t.Fatal(ex.String()) 175 } else { 176 t.Fatal(err) 177 } 178 } 179 180 if !v.StrictEquals(valueTrue) { 181 t.Fatalf("Expected true, got %v", v) 182 } 183 184} 185 186func TestGoMapWithProto(t *testing.T) { 187 vm := New() 188 m := map[string]interface{}{ 189 "t": "42", 190 } 191 vm.Set("m", m) 192 _, err := vm.RunString(TESTLIB + ` 193 (function() { 194 'use strict'; 195 var proto = {}; 196 var getterAllowed = false; 197 var setterAllowed = false; 198 var tHolder = "proto t"; 199 Object.defineProperty(proto, "t", { 200 get: function() { 201 if (!getterAllowed) throw new Error("getter is called"); 202 return tHolder; 203 }, 204 set: function(v) { 205 if (!setterAllowed) throw new Error("setter is called"); 206 tHolder = v; 207 } 208 }); 209 var t1Holder; 210 Object.defineProperty(proto, "t1", { 211 get: function() { 212 return t1Holder; 213 }, 214 set: function(v) { 215 t1Holder = v; 216 } 217 }); 218 Object.setPrototypeOf(m, proto); 219 assert.sameValue(m.t, "42"); 220 m.t = 43; 221 assert.sameValue(m.t, 43); 222 t1Holder = "test"; 223 assert.sameValue(m.t1, "test"); 224 m.t1 = "test1"; 225 assert.sameValue(m.t1, "test1"); 226 delete m.t; 227 getterAllowed = true; 228 assert.sameValue(m.t, "proto t", "after delete"); 229 setterAllowed = true; 230 m.t = true; 231 assert.sameValue(m.t, true); 232 assert.sameValue(tHolder, true); 233 Object.preventExtensions(m); 234 assert.throws(TypeError, function() { 235 m.t2 = 1; 236 }); 237 m.t1 = "test2"; 238 assert.sameValue(m.t1, "test2"); 239 })(); 240 `) 241 if err != nil { 242 t.Fatal(err) 243 } 244} 245 246func TestGoMapProtoProp(t *testing.T) { 247 const SCRIPT = ` 248 (function() { 249 "use strict"; 250 var proto = {}; 251 Object.defineProperty(proto, "ro", {value: 42}); 252 Object.setPrototypeOf(m, proto); 253 assert.throws(TypeError, function() { 254 m.ro = 43; 255 }); 256 Object.defineProperty(m, "ro", {value: 43}); 257 assert.sameValue(m.ro, 43); 258 })(); 259 ` 260 261 r := New() 262 r.Set("m", map[string]interface{}{}) 263 _, err := r.RunString(TESTLIB + SCRIPT) 264 if err != nil { 265 t.Fatal(err) 266 } 267} 268 269func TestGoMapProtoPropChain(t *testing.T) { 270 const SCRIPT = ` 271 (function() { 272 "use strict"; 273 var p1 = Object.create(null); 274 m.__proto__ = p1; 275 276 Object.defineProperty(p1, "test", { 277 value: 42 278 }); 279 280 Object.defineProperty(m, "test", { 281 value: 43, 282 writable: true, 283 }); 284 var o = Object.create(m); 285 o.test = 44; 286 assert.sameValue(o.test, 44); 287 288 var sym = Symbol(true); 289 Object.defineProperty(p1, sym, { 290 value: 42 291 }); 292 293 Object.defineProperty(m, sym, { 294 value: 43, 295 writable: true, 296 }); 297 o[sym] = 44; 298 assert.sameValue(o[sym], 44); 299 })(); 300 ` 301 302 r := New() 303 r.Set("m", map[string]interface{}{}) 304 _, err := r.RunString(TESTLIB + SCRIPT) 305 if err != nil { 306 t.Fatal(err) 307 } 308} 309 310func TestGoMapUnicode(t *testing.T) { 311 const SCRIPT = ` 312 Object.setPrototypeOf(m, s); 313 if (m.Тест !== "passed") { 314 throw new Error("m.Тест: " + m.Тест); 315 } 316 m["é"]; 317 ` 318 type S struct { 319 Тест string 320 } 321 vm := New() 322 m := map[string]interface{}{ 323 "é": 42, 324 } 325 s := S{ 326 Тест: "passed", 327 } 328 vm.Set("m", m) 329 vm.Set("s", &s) 330 res, err := vm.RunString(SCRIPT) 331 if err != nil { 332 t.Fatal(err) 333 } 334 if res == nil || !res.StrictEquals(valueInt(42)) { 335 t.Fatalf("Unexpected value: %v", res) 336 } 337} 338