1package goja 2 3import ( 4 "strconv" 5 "testing" 6) 7 8func TestProxy_Object_target_getPrototypeOf(t *testing.T) { 9 const SCRIPT = ` 10 var proto = {}; 11 var obj = Object.create(proto); 12 var proxy = new Proxy(obj, {}); 13 var p = Object.getPrototypeOf(proxy); 14 assert.sameValue(proto, p); 15 ` 16 17 testScript1(TESTLIB+SCRIPT, _undefined, t) 18} 19 20func TestProxy_Object_proxy_getPrototypeOf(t *testing.T) { 21 const SCRIPT = ` 22 var proto = {}; 23 var proto2 = {}; 24 var obj = Object.create(proto); 25 var proxy = new Proxy(obj, { 26 getPrototypeOf: function(target) { 27 return proto2; 28 } 29 }); 30 var p = Object.getPrototypeOf(proxy); 31 assert.sameValue(proto2, p); 32 ` 33 34 testScript1(TESTLIB+SCRIPT, _undefined, t) 35} 36 37func TestProxy_Object_native_proxy_getPrototypeOf(t *testing.T) { 38 const SCRIPT = ` 39 var p = Object.getPrototypeOf(proxy); 40 assert.sameValue(proto, p); 41 ` 42 43 runtime := New() 44 45 prototype := runtime.NewObject() 46 runtime.Set("proto", prototype) 47 48 target := runtime.NewObject() 49 proxy := runtime.NewProxy(target, &ProxyTrapConfig{ 50 GetPrototypeOf: func(target *Object) *Object { 51 return prototype 52 }, 53 }) 54 runtime.Set("proxy", proxy) 55 56 _, err := runtime.RunString(TESTLIB + SCRIPT) 57 if err != nil { 58 t.Fatal(err) 59 } 60} 61 62func TestProxy_Object_target_setPrototypeOf(t *testing.T) { 63 const SCRIPT = ` 64 var proto = {}; 65 var obj = {}; 66 Object.setPrototypeOf(obj, proto); 67 var proxy = new Proxy(obj, {}); 68 var p = Object.getPrototypeOf(proxy); 69 assert.sameValue(proto, p); 70 ` 71 72 testScript1(TESTLIB+SCRIPT, _undefined, t) 73} 74 75func TestProxy_Object_proxy_setPrototypeOf(t *testing.T) { 76 const SCRIPT = ` 77 var proto = {}; 78 var proto2 = {}; 79 var obj = {}; 80 Object.setPrototypeOf(obj, proto); 81 var proxy = new Proxy(obj, { 82 setPrototypeOf: function(target, prototype) { 83 return Object.setPrototypeOf(target, proto2); 84 } 85 }); 86 Object.setPrototypeOf(proxy, null); 87 var p = Object.getPrototypeOf(proxy); 88 assert.sameValue(proto2, p); 89 ` 90 91 testScript1(TESTLIB+SCRIPT, _undefined, t) 92} 93 94func TestProxy_Object_target_isExtensible(t *testing.T) { 95 const SCRIPT = ` 96 var obj = {}; 97 Object.seal(obj); 98 var proxy = new Proxy(obj, {}); 99 Object.isExtensible(proxy); 100 ` 101 102 testScript1(SCRIPT, valueFalse, t) 103} 104 105func TestProxy_proxy_isExtensible(t *testing.T) { 106 const SCRIPT = ` 107 var obj = {}; 108 Object.seal(obj); 109 var proxy = new Proxy(obj, { 110 isExtensible: function(target) { 111 return false; 112 } 113 }); 114 Object.isExtensible(proxy); 115 ` 116 117 testScript1(SCRIPT, valueFalse, t) 118} 119 120func TestProxy_native_proxy_isExtensible(t *testing.T) { 121 const SCRIPT = ` 122 (function() { 123 Object.preventExtensions(target); 124 return Object.isExtensible(proxy); 125 })(); 126 ` 127 128 runtime := New() 129 130 target := runtime.NewObject() 131 runtime.Set("target", target) 132 133 proxy := runtime.NewProxy(target, &ProxyTrapConfig{ 134 IsExtensible: func(target *Object) (success bool) { 135 return false 136 }, 137 }) 138 runtime.Set("proxy", proxy) 139 140 val, err := runtime.RunString(SCRIPT) 141 if err != nil { 142 t.Fatal(err) 143 } 144 if val.ToBoolean() { 145 t.Fatal() 146 } 147} 148 149func TestProxy_Object_target_preventExtensions(t *testing.T) { 150 const SCRIPT = ` 151 var obj = { 152 canEvolve: true 153 }; 154 var proxy = new Proxy(obj, {}); 155 Object.preventExtensions(proxy); 156 proxy.canEvolve 157 ` 158 159 testScript1(SCRIPT, valueTrue, t) 160} 161 162func TestProxy_proxy_preventExtensions(t *testing.T) { 163 const SCRIPT = ` 164 var obj = { 165 canEvolve: true 166 }; 167 var proxy = new Proxy(obj, { 168 preventExtensions: function(target) { 169 target.canEvolve = false; 170 return false; 171 } 172 }); 173 Object.preventExtensions(proxy); 174 proxy.canEvolve; 175 ` 176 177 testScript1(SCRIPT, valueFalse, t) 178} 179 180func TestProxy_native_proxy_preventExtensions(t *testing.T) { 181 const SCRIPT = ` 182 (function() { 183 Object.preventExtensions(proxy); 184 return proxy.canEvolve; 185 })(); 186 ` 187 188 runtime := New() 189 190 target := runtime.NewObject() 191 target.Set("canEvolve", true) 192 runtime.Set("target", target) 193 194 proxy := runtime.NewProxy(target, &ProxyTrapConfig{ 195 PreventExtensions: func(target *Object) (success bool) { 196 target.Set("canEvolve", false) 197 return false 198 }, 199 }) 200 runtime.Set("proxy", proxy) 201 202 val, err := runtime.RunString(SCRIPT) 203 if err != nil { 204 t.Fatal(err) 205 } 206 if val.ToBoolean() { 207 t.Fatal() 208 } 209} 210 211func TestProxy_Object_target_getOwnPropertyDescriptor(t *testing.T) { 212 const SCRIPT = ` 213 var desc = { 214 configurable: false, 215 enumerable: false, 216 value: 42, 217 writable: false 218 }; 219 220 var obj = {}; 221 Object.defineProperty(obj, "foo", desc); 222 223 var proxy = new Proxy(obj, {}); 224 225 var desc2 = Object.getOwnPropertyDescriptor(proxy, "foo"); 226 desc2.value 227 ` 228 229 testScript1(SCRIPT, valueInt(42), t) 230} 231 232func TestProxy_proxy_getOwnPropertyDescriptor(t *testing.T) { 233 const SCRIPT = ` 234 var desc = { 235 configurable: false, 236 enumerable: false, 237 value: 42, 238 writable: false 239 }; 240 var proxy_desc = { 241 configurable: false, 242 enumerable: false, 243 value: 24, 244 writable: false 245 }; 246 247 var obj = {}; 248 Object.defineProperty(obj, "foo", desc); 249 250 var proxy = new Proxy(obj, { 251 getOwnPropertyDescriptor: function(target, property) { 252 return proxy_desc; 253 } 254 }); 255 256 assert.throws(TypeError, function() { 257 Object.getOwnPropertyDescriptor(proxy, "foo"); 258 }); 259 undefined; 260 ` 261 262 testScript1(TESTLIB+SCRIPT, _undefined, t) 263} 264 265func TestProxy_native_proxy_getOwnPropertyDescriptor(t *testing.T) { 266 const SCRIPT = ` 267 (function() { 268 var desc = { 269 configurable: true, 270 enumerable: false, 271 value: 42, 272 writable: false 273 }; 274 var proxy_desc = { 275 configurable: true, 276 enumerable: false, 277 value: 24, 278 writable: false 279 }; 280 281 var obj = {}; 282 Object.defineProperty(obj, "foo", desc); 283 284 return function(constructor) { 285 var proxy = constructor(obj, proxy_desc); 286 287 var desc2 = Object.getOwnPropertyDescriptor(proxy, "foo"); 288 return desc2.value 289 } 290 })(); 291 ` 292 293 runtime := New() 294 295 constructor := func(call FunctionCall) Value { 296 target := call.Argument(0).(*Object) 297 proxyDesc := call.Argument(1).(*Object) 298 299 return runtime.NewProxy(target, &ProxyTrapConfig{ 300 GetOwnPropertyDescriptor: func(target *Object, prop string) PropertyDescriptor { 301 return runtime.toPropertyDescriptor(proxyDesc) 302 }, 303 }).proxy.val 304 } 305 306 val, err := runtime.RunString(SCRIPT) 307 if err != nil { 308 t.Fatal(err) 309 } 310 311 if c, ok := val.(*Object).self.assertCallable(); ok { 312 val := c(FunctionCall{ 313 This: val, 314 Arguments: []Value{runtime.ToValue(constructor)}, 315 }) 316 if i := val.ToInteger(); i != 24 { 317 t.Fatalf("val: %d", i) 318 } 319 } else { 320 t.Fatal("not a function") 321 } 322} 323 324func TestProxy_native_proxy_getOwnPropertyDescriptorIdx(t *testing.T) { 325 vm := New() 326 a := vm.NewArray() 327 proxy1 := vm.NewProxy(a, &ProxyTrapConfig{ 328 GetOwnPropertyDescriptor: func(target *Object, prop string) PropertyDescriptor { 329 panic(vm.NewTypeError("GetOwnPropertyDescriptor was called for %q", prop)) 330 }, 331 GetOwnPropertyDescriptorIdx: func(target *Object, prop int) PropertyDescriptor { 332 if prop >= -1 && prop <= 1 { 333 return PropertyDescriptor{ 334 Value: vm.ToValue(prop), 335 Configurable: FLAG_TRUE, 336 } 337 } 338 return PropertyDescriptor{} 339 }, 340 }) 341 342 proxy2 := vm.NewProxy(a, &ProxyTrapConfig{ 343 GetOwnPropertyDescriptor: func(target *Object, prop string) PropertyDescriptor { 344 switch prop { 345 case "-1", "0", "1": 346 return PropertyDescriptor{ 347 Value: vm.ToValue(prop), 348 Configurable: FLAG_TRUE, 349 } 350 } 351 return PropertyDescriptor{} 352 }, 353 }) 354 355 proxy3 := vm.NewProxy(a, &ProxyTrapConfig{ 356 GetOwnPropertyDescriptor: func(target *Object, prop string) PropertyDescriptor { 357 return PropertyDescriptor{ 358 Value: vm.ToValue(prop), 359 Configurable: FLAG_TRUE, 360 } 361 }, 362 GetOwnPropertyDescriptorIdx: func(target *Object, prop int) PropertyDescriptor { 363 panic(vm.NewTypeError("GetOwnPropertyDescriptorIdx was called for %d", prop)) 364 }, 365 }) 366 367 vm.Set("proxy1", proxy1) 368 vm.Set("proxy2", proxy2) 369 vm.Set("proxy3", proxy3) 370 _, err := vm.RunString(TESTLIBX + ` 371 var desc; 372 for (var i = -1; i <= 1; i++) { 373 desc = Object.getOwnPropertyDescriptor(proxy1, i); 374 assert(deepEqual(desc, {value: i, writable: false, enumerable: false, configurable: true}), "1. int "+i); 375 376 desc = Object.getOwnPropertyDescriptor(proxy1, ""+i); 377 assert(deepEqual(desc, {value: i, writable: false, enumerable: false, configurable: true}), "1. str "+i); 378 379 desc = Object.getOwnPropertyDescriptor(proxy2, i); 380 assert(deepEqual(desc, {value: ""+i, writable: false, enumerable: false, configurable: true}), "2. int "+i); 381 382 desc = Object.getOwnPropertyDescriptor(proxy2, ""+i); 383 assert(deepEqual(desc, {value: ""+i, writable: false, enumerable: false, configurable: true}), "2. str "+i); 384 } 385 386 for (const prop of ["00", " 0", "-0", "01"]) { 387 desc = Object.getOwnPropertyDescriptor(proxy3, prop); 388 assert(deepEqual(desc, {value: prop, writable: false, enumerable: false, configurable: true}), "3. "+prop); 389 } 390 `) 391 if err != nil { 392 t.Fatal(err) 393 } 394} 395 396func TestProxy_native_proxy_getOwnPropertyDescriptorSym(t *testing.T) { 397 vm := New() 398 o := vm.NewObject() 399 sym := NewSymbol("42") 400 vm.Set("sym", sym) 401 proxy := vm.NewProxy(o, &ProxyTrapConfig{ 402 GetOwnPropertyDescriptorSym: func(target *Object, s *Symbol) PropertyDescriptor { 403 if target != o { 404 panic(vm.NewTypeError("Invalid target")) 405 } 406 if s == sym { 407 return PropertyDescriptor{ 408 Value: vm.ToValue("passed"), 409 Writable: FLAG_TRUE, 410 Configurable: FLAG_TRUE, 411 } 412 } 413 return PropertyDescriptor{} 414 }, 415 }) 416 417 vm.Set("proxy", proxy) 418 _, err := vm.RunString(TESTLIBX + ` 419 var desc = Object.getOwnPropertyDescriptor(proxy, sym); 420 assert(deepEqual(desc, {value: "passed", writable: true, enumerable: false, configurable: true})); 421 assert.sameValue(Object.getOwnPropertyDescriptor(proxy, Symbol.iterator), undefined); 422 `) 423 if err != nil { 424 t.Fatal(err) 425 } 426} 427 428func TestProxy_native_proxy_getOwnPropertyDescriptor_non_existing(t *testing.T) { 429 vm := New() 430 proxy := vm.NewProxy(vm.NewObject(), &ProxyTrapConfig{ 431 GetOwnPropertyDescriptor: func(target *Object, prop string) (propertyDescriptor PropertyDescriptor) { 432 return // empty PropertyDescriptor 433 }, 434 }) 435 vm.Set("proxy", proxy) 436 res, err := vm.RunString(`Object.getOwnPropertyDescriptor(proxy, "foo") === undefined`) 437 if err != nil { 438 t.Fatal(err) 439 } 440 if res != valueTrue { 441 t.Fatal(res) 442 } 443} 444 445func TestProxy_Object_target_defineProperty(t *testing.T) { 446 const SCRIPT = ` 447 var obj = {}; 448 var proxy = new Proxy(obj, {}); 449 Object.defineProperty(proxy, "foo", { 450 value: "test123" 451 }); 452 proxy.foo; 453 ` 454 455 testScript1(SCRIPT, asciiString("test123"), t) 456} 457 458func TestProxy_proxy_defineProperty(t *testing.T) { 459 const SCRIPT = ` 460 var obj = {}; 461 var proxy = new Proxy(obj, { 462 defineProperty: function(target, prop, descriptor) { 463 target.foo = "321tset"; 464 return true; 465 } 466 }); 467 Object.defineProperty(proxy, "foo", { 468 value: "test123" 469 }); 470 proxy.foo; 471 ` 472 473 testScript1(SCRIPT, asciiString("321tset"), t) 474} 475 476func TestProxy_native_proxy_defineProperty(t *testing.T) { 477 const SCRIPT = ` 478 Object.defineProperty(proxy, "foo", { 479 value: "teststr" 480 }); 481 Object.defineProperty(proxy, "0", { 482 value: "testidx" 483 }); 484 Object.defineProperty(proxy, Symbol.toStringTag, { 485 value: "testsym" 486 }); 487 assert.sameValue(proxy.foo, "teststr-passed-str"); 488 assert.sameValue(proxy[0], "testidx-passed-idx"); 489 assert.sameValue(proxy[Symbol.toStringTag], "testsym-passed-sym"); 490 ` 491 492 runtime := New() 493 494 target := runtime.NewObject() 495 496 proxy := runtime.NewProxy(target, &ProxyTrapConfig{ 497 DefineProperty: func(target *Object, key string, propertyDescriptor PropertyDescriptor) (success bool) { 498 target.Set(key, propertyDescriptor.Value.String()+"-passed-str") 499 return true 500 }, 501 DefinePropertyIdx: func(target *Object, key int, propertyDescriptor PropertyDescriptor) (success bool) { 502 target.Set(strconv.Itoa(key), propertyDescriptor.Value.String()+"-passed-idx") 503 return true 504 }, 505 DefinePropertySym: func(target *Object, key *Symbol, propertyDescriptor PropertyDescriptor) (success bool) { 506 target.SetSymbol(key, propertyDescriptor.Value.String()+"-passed-sym") 507 return true 508 }, 509 }) 510 runtime.Set("proxy", proxy) 511 512 _, err := runtime.RunString(TESTLIB + SCRIPT) 513 if err != nil { 514 t.Fatal(err) 515 } 516} 517 518func TestProxy_target_has_in(t *testing.T) { 519 const SCRIPT = ` 520 var obj = { 521 secret: true 522 }; 523 var proxy = new Proxy(obj, {}); 524 525 "secret" in proxy 526 ` 527 528 testScript1(SCRIPT, valueTrue, t) 529} 530 531func TestProxy_proxy_has_in(t *testing.T) { 532 const SCRIPT = ` 533 var obj = { 534 secret: true 535 }; 536 var proxy = new Proxy(obj, { 537 has: function(target, key) { 538 return key !== "secret"; 539 } 540 }); 541 542 "secret" in proxy 543 ` 544 545 testScript1(SCRIPT, valueFalse, t) 546} 547 548func TestProxy_target_has_with(t *testing.T) { 549 const SCRIPT = ` 550 var obj = { 551 secret: true 552 }; 553 var proxy = new Proxy(obj, {}); 554 555 with(proxy) { 556 (secret); 557 } 558 ` 559 560 testScript1(SCRIPT, valueTrue, t) 561} 562 563func TestProxy_proxy_has_with(t *testing.T) { 564 const SCRIPT = ` 565 var obj = { 566 secret: true 567 }; 568 var proxy = new Proxy(obj, { 569 has: function(target, key) { 570 return key !== "secret"; 571 } 572 }); 573 574 var thrown = false; 575 try { 576 with(proxy) { 577 (secret); 578 } 579 } catch (e) { 580 if (e instanceof ReferenceError) { 581 thrown = true; 582 } else { 583 throw e; 584 } 585 } 586 thrown; 587 ` 588 589 testScript1(SCRIPT, valueTrue, t) 590} 591 592func TestProxy_target_get(t *testing.T) { 593 const SCRIPT = ` 594 var obj = {}; 595 var proxy = new Proxy(obj, {}); 596 Object.defineProperty(proxy, "foo", { 597 value: "test123" 598 }); 599 proxy.foo; 600 ` 601 602 testScript1(SCRIPT, asciiString("test123"), t) 603} 604 605func TestProxy_proxy_get(t *testing.T) { 606 const SCRIPT = ` 607 var obj = {}; 608 var proxy = new Proxy(obj, { 609 get: function(target, prop, receiver) { 610 return "321tset" 611 } 612 }); 613 Object.defineProperty(proxy, "foo", { 614 value: "test123", 615 configurable: true, 616 }); 617 proxy.foo; 618 ` 619 620 testScript1(SCRIPT, asciiString("321tset"), t) 621} 622 623func TestProxy_proxy_get_json_stringify(t *testing.T) { 624 const SCRIPT = ` 625 var obj = {}; 626 var propValue = "321tset"; 627 var _handler, _target, _prop, _receiver; 628 var proxy = new Proxy(obj, { 629 ownKeys: function() { 630 return ["foo"]; 631 }, 632 getOwnPropertyDescriptor: function(target, prop) { 633 if (prop === "foo") { 634 return { 635 value: propValue, 636 enumerable: true, 637 configurable: true 638 } 639 } 640 }, 641 get: function(target, prop, receiver) { 642 if (prop === "foo") { 643 _prop = prop; 644 _receiver = receiver; 645 return propValue; 646 } 647 return obj[prop]; 648 } 649 }); 650 var res = JSON.stringify(proxy); 651 assert.sameValue(res, '{"foo":"321tset"}'); 652 assert.sameValue(_prop, "foo"); 653 assert.sameValue(_receiver, proxy); 654 ` 655 656 testScript1(TESTLIB+SCRIPT, _undefined, t) 657} 658 659func TestProxy_native_proxy_get(t *testing.T) { 660 vm := New() 661 propValueStr := vm.ToValue("321tset") 662 propValueIdx := vm.ToValue("idx") 663 propValueSym := vm.ToValue("sym") 664 sym := NewSymbol("test") 665 obj := vm.NewObject() 666 proxy := vm.NewProxy(obj, &ProxyTrapConfig{ 667 OwnKeys: func(*Object) *Object { 668 return vm.NewArray("0", "foo") 669 }, 670 GetOwnPropertyDescriptor: func(target *Object, prop string) (propertyDescriptor PropertyDescriptor) { 671 if prop == "foo" { 672 return PropertyDescriptor{ 673 Value: propValueStr, 674 Enumerable: FLAG_TRUE, 675 Configurable: FLAG_TRUE, 676 } 677 } 678 if prop == "0" { 679 panic(vm.NewTypeError("GetOwnPropertyDescriptor(0) was called")) 680 } 681 return 682 }, 683 GetOwnPropertyDescriptorIdx: func(target *Object, prop int) (propertyDescriptor PropertyDescriptor) { 684 if prop == 0 { 685 return PropertyDescriptor{ 686 Value: propValueIdx, 687 Enumerable: FLAG_TRUE, 688 Configurable: FLAG_TRUE, 689 } 690 } 691 return 692 }, 693 Get: func(target *Object, property string, receiver Value) (value Value) { 694 if property == "foo" { 695 return propValueStr 696 } 697 if property == "0" { 698 panic(vm.NewTypeError("Get(0) was called")) 699 } 700 return obj.Get(property) 701 }, 702 GetIdx: func(target *Object, property int, receiver Value) (value Value) { 703 if property == 0 { 704 return propValueIdx 705 } 706 return obj.Get(strconv.Itoa(property)) 707 }, 708 GetSym: func(target *Object, property *Symbol, receiver Value) (value Value) { 709 if property == sym { 710 return propValueSym 711 } 712 return obj.GetSymbol(property) 713 }, 714 }) 715 vm.Set("proxy", proxy) 716 res, err := vm.RunString(`JSON.stringify(proxy)`) 717 if err != nil { 718 t.Fatal(err) 719 } 720 if !res.SameAs(asciiString(`{"0":"idx","foo":"321tset"}`)) { 721 t.Fatalf("res: %v", res) 722 } 723 res, err = vm.RunString(`proxy[Symbol.toPrimitive]`) 724 if err != nil { 725 t.Fatal(err) 726 } 727 if !IsUndefined(res) { 728 t.Fatalf("res: %v", res) 729 } 730 731 res, err = vm.RunString(`proxy.hasOwnProperty(Symbol.toPrimitive)`) 732 if err != nil { 733 t.Fatal(err) 734 } 735 if !res.SameAs(valueFalse) { 736 t.Fatalf("res: %v", res) 737 } 738 739 if val := vm.ToValue(proxy).(*Object).GetSymbol(sym); val == nil || !val.SameAs(propValueSym) { 740 t.Fatalf("Get(symbol): %v", val) 741 } 742 743 res, err = vm.RunString(`proxy.toString()`) 744 if err != nil { 745 t.Fatal(err) 746 } 747 if !res.SameAs(asciiString(`[object Object]`)) { 748 t.Fatalf("res: %v", res) 749 } 750} 751 752func TestProxy_native_proxy_set(t *testing.T) { 753 vm := New() 754 propValueStr := vm.ToValue("321tset") 755 propValueIdx := vm.ToValue("idx") 756 propValueSym := vm.ToValue("sym") 757 sym := NewSymbol("test") 758 obj := vm.NewObject() 759 proxy := vm.NewProxy(obj, &ProxyTrapConfig{ 760 Set: func(target *Object, property string, value Value, receiver Value) (success bool) { 761 if property == "str" { 762 obj.Set(property, propValueStr) 763 return true 764 } 765 panic(vm.NewTypeError("Setter for unexpected property: %q", property)) 766 }, 767 SetIdx: func(target *Object, property int, value Value, receiver Value) (success bool) { 768 if property == 0 { 769 obj.Set(strconv.Itoa(property), propValueIdx) 770 return true 771 } 772 panic(vm.NewTypeError("Setter for unexpected idx property: %d", property)) 773 }, 774 SetSym: func(target *Object, property *Symbol, value Value, receiver Value) (success bool) { 775 if property == sym { 776 obj.SetSymbol(property, propValueSym) 777 return true 778 } 779 panic(vm.NewTypeError("Setter for unexpected sym property: %q", property.String())) 780 }, 781 }) 782 proxyObj := vm.ToValue(proxy).ToObject(vm) 783 err := proxyObj.Set("str", "") 784 if err != nil { 785 t.Fatal(err) 786 } 787 err = proxyObj.Set("0", "") 788 if err != nil { 789 t.Fatal(err) 790 } 791 err = proxyObj.SetSymbol(sym, "") 792 if err != nil { 793 t.Fatal(err) 794 } 795 if v := obj.Get("str"); !propValueStr.SameAs(v) { 796 t.Fatal(v) 797 } 798 if v := obj.Get("0"); !propValueIdx.SameAs(v) { 799 t.Fatal(v) 800 } 801 if v := obj.GetSymbol(sym); !propValueSym.SameAs(v) { 802 t.Fatal(v) 803 } 804} 805 806func TestProxy_target_set_prop(t *testing.T) { 807 const SCRIPT = ` 808 var obj = {}; 809 var proxy = new Proxy(obj, {}); 810 proxy.foo = "test123"; 811 proxy.foo; 812 ` 813 814 testScript1(SCRIPT, asciiString("test123"), t) 815} 816 817func TestProxy_proxy_set_prop(t *testing.T) { 818 const SCRIPT = ` 819 var obj = {}; 820 var proxy = new Proxy(obj, { 821 set: function(target, prop, receiver) { 822 target.foo = "321tset"; 823 return true; 824 } 825 }); 826 proxy.foo = "test123"; 827 proxy.foo; 828 ` 829 830 testScript1(SCRIPT, asciiString("321tset"), t) 831} 832func TestProxy_target_set_associative(t *testing.T) { 833 const SCRIPT = ` 834 var obj = {}; 835 var proxy = new Proxy(obj, {}); 836 proxy["foo"] = "test123"; 837 proxy.foo; 838 ` 839 840 testScript1(SCRIPT, asciiString("test123"), t) 841} 842 843func TestProxy_proxy_set_associative(t *testing.T) { 844 const SCRIPT = ` 845 var obj = {}; 846 var proxy = new Proxy(obj, { 847 set: function(target, property, value, receiver) { 848 target["foo"] = "321tset"; 849 return true; 850 } 851 }); 852 proxy["foo"] = "test123"; 853 proxy.foo; 854 ` 855 856 testScript1(SCRIPT, asciiString("321tset"), t) 857} 858 859func TestProxy_target_delete(t *testing.T) { 860 const SCRIPT = ` 861 var obj = { 862 foo: "test" 863 }; 864 var proxy = new Proxy(obj, {}); 865 delete proxy.foo; 866 867 proxy.foo; 868 ` 869 870 testScript1(SCRIPT, _undefined, t) 871} 872 873func TestProxy_proxy_delete(t *testing.T) { 874 const SCRIPT = ` 875 var obj = { 876 foo: "test" 877 }; 878 var proxy = new Proxy(obj, { 879 deleteProperty: function(target, prop) { 880 return true; 881 } 882 }); 883 delete proxy.foo; 884 885 proxy.foo; 886 ` 887 888 testScript1(SCRIPT, asciiString("test"), t) 889} 890 891func TestProxy_native_delete(t *testing.T) { 892 vm := New() 893 sym := NewSymbol("test") 894 obj := vm.NewObject() 895 var strCalled, idxCalled, symCalled, strNegCalled, idxNegCalled, symNegCalled bool 896 proxy := vm.NewProxy(obj, &ProxyTrapConfig{ 897 DeleteProperty: func(target *Object, property string) (success bool) { 898 if property == "str" { 899 strCalled = true 900 return true 901 } 902 if property == "strNeg" { 903 strNegCalled = true 904 return false 905 } 906 panic(vm.NewTypeError("DeleteProperty for unexpected property: %q", property)) 907 }, 908 DeletePropertyIdx: func(target *Object, property int) (success bool) { 909 if property == 0 { 910 idxCalled = true 911 return true 912 } 913 if property == 1 { 914 idxNegCalled = true 915 return false 916 } 917 panic(vm.NewTypeError("DeletePropertyIdx for unexpected idx property: %d", property)) 918 }, 919 DeletePropertySym: func(target *Object, property *Symbol) (success bool) { 920 if property == sym { 921 symCalled = true 922 return true 923 } 924 if property == SymIterator { 925 symNegCalled = true 926 return false 927 } 928 panic(vm.NewTypeError("DeletePropertySym for unexpected sym property: %q", property.String())) 929 }, 930 }) 931 proxyObj := vm.ToValue(proxy).ToObject(vm) 932 err := proxyObj.Delete("str") 933 if err != nil { 934 t.Fatal(err) 935 } 936 err = proxyObj.Delete("0") 937 if err != nil { 938 t.Fatal(err) 939 } 940 err = proxyObj.DeleteSymbol(sym) 941 if err != nil { 942 t.Fatal(err) 943 } 944 if !strCalled { 945 t.Fatal("str") 946 } 947 if !idxCalled { 948 t.Fatal("idx") 949 } 950 if !symCalled { 951 t.Fatal("sym") 952 } 953 vm.Set("proxy", proxy) 954 _, err = vm.RunString(` 955 if (delete proxy.strNeg) { 956 throw new Error("strNeg"); 957 } 958 if (delete proxy[1]) { 959 throw new Error("idxNeg"); 960 } 961 if (delete proxy[Symbol.iterator]) { 962 throw new Error("symNeg"); 963 } 964 `) 965 if err != nil { 966 t.Fatal(err) 967 } 968 if !strNegCalled { 969 t.Fatal("strNeg") 970 } 971 if !idxNegCalled { 972 t.Fatal("idxNeg") 973 } 974 if !symNegCalled { 975 t.Fatal("symNeg") 976 } 977} 978 979func TestProxy_target_keys(t *testing.T) { 980 const SCRIPT = ` 981 var obj = { 982 foo: "test" 983 }; 984 var proxy = new Proxy(obj, {}); 985 986 var keys = Object.keys(proxy); 987 if (keys.length != 1) { 988 throw new Error("assertion error"); 989 } 990 ` 991 992 testScript1(SCRIPT, _undefined, t) 993} 994 995func TestProxy_proxy_keys(t *testing.T) { 996 const SCRIPT = ` 997 var obj = { 998 foo: "test" 999 }; 1000 var proxy = new Proxy(obj, { 1001 ownKeys: function(target) { 1002 return ["foo", "bar"]; 1003 } 1004 }); 1005 1006 var keys = Object.keys(proxy); 1007 if (keys.length !== 1) { 1008 throw new Error("length is "+keys.length); 1009 } 1010 if (keys[0] !== "foo") { 1011 throw new Error("keys[0] is "+keys[0]); 1012 } 1013 ` 1014 1015 testScript1(SCRIPT, _undefined, t) 1016} 1017 1018func TestProxy_target_call(t *testing.T) { 1019 const SCRIPT = ` 1020 var obj = function() { 1021 return "test" 1022 } 1023 1024 var proxy = new Proxy(obj, {}); 1025 1026 proxy(); 1027 ` 1028 1029 testScript1(SCRIPT, asciiString("test"), t) 1030} 1031 1032func TestProxy_proxy_call(t *testing.T) { 1033 const SCRIPT = ` 1034 var obj = function() { 1035 return "test" 1036 } 1037 1038 var proxy = new Proxy(obj, { 1039 apply: function(target, thisArg, args) { 1040 return "tset" 1041 } 1042 }); 1043 1044 proxy(); 1045 ` 1046 1047 testScript1(SCRIPT, asciiString("tset"), t) 1048} 1049 1050func TestProxy_target_func_apply(t *testing.T) { 1051 const SCRIPT = ` 1052 var obj = function() { 1053 return "test" 1054 } 1055 1056 var proxy = new Proxy(obj, {}); 1057 1058 proxy.apply(); 1059 ` 1060 1061 testScript1(SCRIPT, asciiString("test"), t) 1062} 1063 1064func TestProxy_proxy_func_apply(t *testing.T) { 1065 const SCRIPT = ` 1066 var obj = function() { 1067 return "test" 1068 } 1069 1070 var proxy = new Proxy(obj, { 1071 apply: function(target, thisArg, args) { 1072 return "tset" 1073 } 1074 }); 1075 1076 proxy.apply(); 1077 ` 1078 1079 testScript1(SCRIPT, asciiString("tset"), t) 1080} 1081 1082func TestProxy_target_func_call(t *testing.T) { 1083 const SCRIPT = ` 1084 var obj = function() { 1085 return "test" 1086 } 1087 1088 var proxy = new Proxy(obj, {}); 1089 1090 proxy.call(); 1091 ` 1092 1093 testScript1(SCRIPT, asciiString("test"), t) 1094} 1095 1096func TestProxy_proxy_func_call(t *testing.T) { 1097 const SCRIPT = ` 1098 var obj = function() { 1099 return "test" 1100 } 1101 1102 var proxy = new Proxy(obj, { 1103 apply: function(target, thisArg, args) { 1104 return "tset" 1105 } 1106 }); 1107 1108 proxy.call(); 1109 ` 1110 1111 testScript1(SCRIPT, asciiString("tset"), t) 1112} 1113 1114func TestProxy_target_new(t *testing.T) { 1115 const SCRIPT = ` 1116 var obj = function(word) { 1117 this.foo = function() { 1118 return word; 1119 } 1120 } 1121 1122 var proxy = new Proxy(obj, {}); 1123 1124 var instance = new proxy("test"); 1125 instance.foo(); 1126 ` 1127 1128 testScript1(SCRIPT, asciiString("test"), t) 1129} 1130 1131func TestProxy_proxy_new(t *testing.T) { 1132 const SCRIPT = ` 1133 var obj = function(word) { 1134 this.foo = function() { 1135 return word; 1136 } 1137 } 1138 1139 var proxy = new Proxy(obj, { 1140 construct: function(target, args, newTarget) { 1141 var word = args[0]; 1142 return { 1143 foo: function() { 1144 return "caught-" + word 1145 } 1146 } 1147 } 1148 }); 1149 1150 var instance = new proxy("test"); 1151 instance.foo(); 1152 ` 1153 1154 testScript1(SCRIPT, asciiString("caught-test"), t) 1155} 1156 1157func TestProxy_Object_native_proxy_ownKeys(t *testing.T) { 1158 headers := map[string][]string{ 1159 "k0": {}, 1160 } 1161 vm := New() 1162 proxy := vm.NewProxy(vm.NewObject(), &ProxyTrapConfig{ 1163 OwnKeys: func(target *Object) (object *Object) { 1164 keys := make([]interface{}, 0, len(headers)) 1165 for k := range headers { 1166 keys = append(keys, k) 1167 } 1168 return vm.ToValue(keys).ToObject(vm) 1169 }, 1170 GetOwnPropertyDescriptor: func(target *Object, prop string) PropertyDescriptor { 1171 v, exists := headers[prop] 1172 if exists { 1173 return PropertyDescriptor{ 1174 Value: vm.ToValue(v), 1175 Enumerable: FLAG_TRUE, 1176 Configurable: FLAG_TRUE, 1177 } 1178 } 1179 return PropertyDescriptor{} 1180 }, 1181 }) 1182 vm.Set("headers", proxy) 1183 v, err := vm.RunString(` 1184 var keys = Object.keys(headers); 1185 keys.length === 1 && keys[0] === "k0"; 1186 `) 1187 if err != nil { 1188 t.Fatal(err) 1189 } 1190 if v != valueTrue { 1191 t.Fatal("not true", v) 1192 } 1193} 1194 1195func TestProxy_proxy_forIn(t *testing.T) { 1196 const SCRIPT = ` 1197 var proto = { 1198 a: 2, 1199 protoProp: 1 1200 } 1201 Object.defineProperty(proto, "protoNonEnum", { 1202 value: 2, 1203 writable: true, 1204 configurable: true 1205 }); 1206 var target = Object.create(proto); 1207 var proxy = new Proxy(target, { 1208 ownKeys: function() { 1209 return ["a", "b"]; 1210 }, 1211 getOwnPropertyDescriptor: function(target, p) { 1212 switch (p) { 1213 case "a": 1214 case "b": 1215 return { 1216 value: 42, 1217 enumerable: true, 1218 configurable: true 1219 } 1220 } 1221 }, 1222 }); 1223 1224 var forInResult = []; 1225 for (var key in proxy) { 1226 if (forInResult.indexOf(key) !== -1) { 1227 throw new Error("Duplicate property "+key); 1228 } 1229 forInResult.push(key); 1230 } 1231 forInResult.length === 3 && forInResult[0] === "a" && forInResult[1] === "b" && forInResult[2] === "protoProp"; 1232 ` 1233 1234 testScript1(SCRIPT, valueTrue, t) 1235} 1236 1237func TestProxyExport(t *testing.T) { 1238 vm := New() 1239 v, err := vm.RunString(` 1240 new Proxy({}, {}); 1241 `) 1242 if err != nil { 1243 t.Fatal(err) 1244 } 1245 v1 := v.Export() 1246 if _, ok := v1.(Proxy); !ok { 1247 t.Fatalf("Export returned unexpected type: %T", v1) 1248 } 1249} 1250 1251func TestProxy_proxy_createTargetNotCallable(t *testing.T) { 1252 // from https://github.com/tc39/test262/blob/main/test/built-ins/Proxy/create-target-is-not-callable.js 1253 const SCRIPT = ` 1254 var p = new Proxy({}, {}); 1255 1256 assert.throws(TypeError, function() { 1257 p(); 1258 }); 1259 ` 1260 1261 testScript1(TESTLIB+SCRIPT, _undefined, t) 1262} 1263 1264func TestProxyEnumerableSymbols(t *testing.T) { 1265 const SCRIPT = ` 1266 var getOwnKeys = []; 1267 var ownKeysResult = [Symbol(), "foo", "0"]; 1268 var proxy = new Proxy({}, { 1269 getOwnPropertyDescriptor: function(_target, key) { 1270 getOwnKeys.push(key); 1271 }, 1272 ownKeys: function() { 1273 return ownKeysResult; 1274 }, 1275 }); 1276 1277 let {...$} = proxy; 1278 compareArray(getOwnKeys, ownKeysResult); 1279 ` 1280 1281 testScript1(TESTLIB+SCRIPT, valueTrue, t) 1282} 1283