github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/object_gomap_test.go (about) 1 package goja 2 3 import "testing" 4 5 func 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 23 func 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 62 func 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 103 func 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 119 func 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 135 func 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 153 func 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 186 func TestGoMapWithProto(t *testing.T) { 187 vm := New() 188 m := map[string]interface{}{ 189 "t": "42", 190 } 191 vm.Set("m", m) 192 vm.testScriptWithTestLib(` 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 `, _undefined, t) 241 } 242 243 func TestGoMapProtoProp(t *testing.T) { 244 const SCRIPT = ` 245 (function() { 246 "use strict"; 247 var proto = {}; 248 Object.defineProperty(proto, "ro", {value: 42}); 249 Object.setPrototypeOf(m, proto); 250 assert.throws(TypeError, function() { 251 m.ro = 43; 252 }); 253 Object.defineProperty(m, "ro", {value: 43}); 254 assert.sameValue(m.ro, 43); 255 })(); 256 ` 257 258 r := New() 259 r.Set("m", map[string]interface{}{}) 260 r.testScriptWithTestLib(SCRIPT, _undefined, t) 261 } 262 263 func TestGoMapProtoPropChain(t *testing.T) { 264 const SCRIPT = ` 265 (function() { 266 "use strict"; 267 var p1 = Object.create(null); 268 m.__proto__ = p1; 269 270 Object.defineProperty(p1, "test", { 271 value: 42 272 }); 273 274 Object.defineProperty(m, "test", { 275 value: 43, 276 writable: true, 277 }); 278 var o = Object.create(m); 279 o.test = 44; 280 assert.sameValue(o.test, 44); 281 282 var sym = Symbol(true); 283 Object.defineProperty(p1, sym, { 284 value: 42 285 }); 286 287 Object.defineProperty(m, sym, { 288 value: 43, 289 writable: true, 290 }); 291 o[sym] = 44; 292 assert.sameValue(o[sym], 44); 293 })(); 294 ` 295 296 r := New() 297 r.Set("m", map[string]interface{}{}) 298 r.testScriptWithTestLib(SCRIPT, _undefined, t) 299 } 300 301 func TestGoMapUnicode(t *testing.T) { 302 const SCRIPT = ` 303 Object.setPrototypeOf(m, s); 304 if (m.Тест !== "passed") { 305 throw new Error("m.Тест: " + m.Тест); 306 } 307 m["é"]; 308 ` 309 type S struct { 310 Тест string 311 } 312 vm := New() 313 m := map[string]interface{}{ 314 "é": 42, 315 } 316 s := S{ 317 Тест: "passed", 318 } 319 vm.Set("m", m) 320 vm.Set("s", &s) 321 res, err := vm.RunString(SCRIPT) 322 if err != nil { 323 t.Fatal(err) 324 } 325 if res == nil || !res.StrictEquals(valueInt(42)) { 326 t.Fatalf("Unexpected value: %v", res) 327 } 328 }