1// Copyright 2011 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// We change the stack size for the ARM64 simulator because at one point this 29// test enters an infinite recursion which goes through the runtime and we 30// overflow the system stack before the simulator stack. 31 32// Flags: --harmony-proxies --sim-stack-size=500 --allow-natives-syntax 33 34 35// Helper. 36 37function TestWithProxies(test, x, y, z) { 38 // Separate function for nicer stack traces. 39 TestWithObjectProxy(test, x, y, z); 40 TestWithFunctionProxy(test, x, y, z); 41} 42 43function TestWithObjectProxy(test, x, y, z) { 44 test((handler) => { return new Proxy({}, handler) }, x, y, z) 45 46} 47 48function TestWithFunctionProxy(test, x, y, z) { 49 test((handler) => { return new Proxy(() => {}, handler) }, x, y, z) 50} 51 52// --------------------------------------------------------------------------- 53// Getting property descriptors (Object.getOwnPropertyDescriptor). 54 55var key 56 57function TestGetOwnProperty(handler) { 58 TestWithProxies(TestGetOwnProperty2, handler) 59} 60 61function TestGetOwnProperty2(create, handler) { 62 var p = create(handler) 63 assertEquals(42, Object.getOwnPropertyDescriptor(p, "a").value) 64 assertEquals("a", key) 65 assertEquals(42, Object.getOwnPropertyDescriptor(p, 99).value) 66 assertEquals("99", key) 67} 68 69TestGetOwnProperty({ 70 getOwnPropertyDescriptor(target, k) { 71 key = k 72 return {value: 42, configurable: true} 73 } 74}) 75 76TestGetOwnProperty({ 77 getOwnPropertyDescriptor(target, k) { 78 return this.getOwnPropertyDescriptor2(k) 79 }, 80 getOwnPropertyDescriptor2(k) { 81 key = k 82 return {value: 42, configurable: true} 83 } 84}) 85 86TestGetOwnProperty({ 87 getOwnPropertyDescriptor(target, k) { 88 key = k 89 return {get value() { return 42 }, get configurable() { return true }} 90 } 91}) 92 93TestGetOwnProperty(new Proxy({}, { 94 get(target, pk, receiver) { 95 return function(t, k) { key = k; return {value: 42, configurable: true} } 96 } 97})) 98 99 100// --------------------------------------------------------------------------- 101function TestGetOwnPropertyThrow(handler) { 102 TestWithProxies(TestGetOwnPropertyThrow2, handler) 103} 104 105function TestGetOwnPropertyThrow2(create, handler) { 106 var p = create(handler) 107 assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn") 108 assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, 77), "myexn") 109} 110 111TestGetOwnPropertyThrow({ 112 getOwnPropertyDescriptor: function(k) { throw "myexn" } 113}) 114 115TestGetOwnPropertyThrow({ 116 getOwnPropertyDescriptor: function(k) { 117 return this.getOwnPropertyDescriptor2(k) 118 }, 119 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 120}) 121 122TestGetOwnPropertyThrow({ 123 getOwnPropertyDescriptor: function(k) { 124 return {get value() { throw "myexn" }} 125 } 126}) 127 128TestGetOwnPropertyThrow(new Proxy({}, { 129 get: function(pr, pk) { 130 return function(k) { throw "myexn" } 131 } 132})) 133 134 135// --------------------------------------------------------------------------- 136// Getters (dot, brackets). 137 138var key 139 140function TestGet(handler) { 141 TestWithProxies(TestGet2, handler) 142} 143 144function TestGet2(create, handler) { 145 var p = create(handler) 146 assertEquals(42, p.a) 147 assertEquals("a", key) 148 assertEquals(42, p["b"]) 149 assertEquals("b", key) 150 assertEquals(42, p[99]) 151 assertEquals("99", key) 152 assertEquals(42, (function(n) { return p[n] })("c")) 153 assertEquals("c", key) 154 assertEquals(42, (function(n) { return p[n] })(101)) 155 assertEquals("101", key) 156 157 var o = Object.create(p, {x: {value: 88}}) 158 assertEquals(42, o.a) 159 assertEquals("a", key) 160 assertEquals(42, o["b"]) 161 assertEquals("b", key) 162 assertEquals(42, o[99]) 163 assertEquals("99", key) 164 assertEquals(88, o.x) 165 assertEquals(88, o["x"]) 166 assertEquals(42, (function(n) { return o[n] })("c")) 167 assertEquals("c", key) 168 assertEquals(42, (function(n) { return o[n] })(101)) 169 assertEquals("101", key) 170 assertEquals(88, (function(n) { return o[n] })("x")) 171} 172 173TestGet({ 174 get(t, k, r) { key = k; return 42 } 175}) 176 177TestGet({ 178 get(t, k, r) { return this.get2(r, k) }, 179 get2(r, k) { key = k; return 42 } 180}) 181 182TestGet(new Proxy({}, { 183 get(pt, pk, pr) { 184 return function(t, k, r) { key = k; return 42 } 185 } 186})) 187 188 189// --------------------------------------------------------------------------- 190function TestGetCall(handler) { 191 TestWithProxies(TestGetCall2, handler) 192} 193 194function TestGetCall2(create, handler) { 195 var p = create(handler) 196 assertEquals(55, p.f()) 197 assertEquals(55, p["f"]()) 198 assertEquals(55, p.f("unused", "arguments")) 199 assertEquals(55, p.f.call(p)) 200 assertEquals(55, p["f"].call(p)) 201 assertEquals(55, p[101].call(p)) 202 assertEquals(55, p.withargs(45, 5)) 203 assertEquals(55, p.withargs.call(p, 11, 22)) 204 assertEquals(55, (function(n) { return p[n]() })("f")) 205 assertEquals(55, (function(n) { return p[n].call(p) })("f")) 206 assertEquals(55, (function(n) { return p[n](15, 20) })("withargs")) 207 assertEquals(55, (function(n) { return p[n].call(p, 13, 21) })("withargs")) 208 assertEquals("6655", "66" + p) // calls p.toString 209 210 var o = Object.create(p, {g: {value: function(x) { return x + 88 }}}) 211 assertEquals(55, o.f()) 212 assertEquals(55, o["f"]()) 213 assertEquals(55, o.f("unused", "arguments")) 214 assertEquals(55, o.f.call(o)) 215 assertEquals(55, o.f.call(p)) 216 assertEquals(55, o["f"].call(p)) 217 assertEquals(55, o[101].call(p)) 218 assertEquals(55, o.withargs(45, 5)) 219 assertEquals(55, o.withargs.call(p, 11, 22)) 220 assertEquals(90, o.g(2)) 221 assertEquals(91, o.g.call(o, 3)) 222 assertEquals(92, o.g.call(p, 4)) 223 assertEquals(55, (function(n) { return o[n]() })("f")) 224 assertEquals(55, (function(n) { return o[n].call(o) })("f")) 225 assertEquals(55, (function(n) { return o[n](15, 20) })("withargs")) 226 assertEquals(55, (function(n) { return o[n].call(o, 13, 21) })("withargs")) 227 assertEquals(93, (function(n) { return o[n](5) })("g")) 228 assertEquals(94, (function(n) { return o[n].call(o, 6) })("g")) 229 assertEquals(95, (function(n) { return o[n].call(p, 7) })("g")) 230 assertEquals("6655", "66" + o) // calls o.toString 231} 232 233TestGetCall({ 234 get(t, k, r) { return () => { return 55 } } 235}) 236 237TestGetCall({ 238 get(t, k, r) { return this.get2(t, k, r) }, 239 get2(t, k, r) { return () => { return 55 } } 240}) 241 242TestGetCall({ 243 get(t, k, r) { 244 if (k == "gg") { 245 return () => { return 55 } 246 } else if (k == "withargs") { 247 return (n, m) => { return n + m * 2 } 248 } else { 249 return () => { return r.gg() } 250 } 251 } 252}) 253 254TestGetCall(new Proxy({}, { 255 get(pt, pk, pr) { 256 return (t, k, r) => { return () => { return 55 } } 257 } 258})) 259 260 261// --------------------------------------------------------------------------- 262function TestGetThrow(handler) { 263 TestWithProxies(TestGetThrow2, handler) 264} 265 266function TestGetThrow2(create, handler) { 267 var p = create(handler) 268 assertThrowsEquals(function(){ p.a }, "myexn") 269 assertThrowsEquals(function(){ p["b"] }, "myexn") 270 assertThrowsEquals(function(){ p[3] }, "myexn") 271 assertThrowsEquals(function(){ (function(n) { p[n] })("c") }, "myexn") 272 assertThrowsEquals(function(){ (function(n) { p[n] })(99) }, "myexn") 273 274 var o = Object.create(p, {x: {value: 88}, '4': {value: 89}}) 275 assertThrowsEquals(function(){ o.a }, "myexn") 276 assertThrowsEquals(function(){ o["b"] }, "myexn") 277 assertThrowsEquals(function(){ o[3] }, "myexn") 278 assertThrowsEquals(function(){ (function(n) { o[n] })("c") }, "myexn") 279 assertThrowsEquals(function(){ (function(n) { o[n] })(99) }, "myexn") 280} 281 282TestGetThrow({ 283 get(r, k) { throw "myexn" } 284}) 285 286TestGetThrow({ 287 get(r, k) { return this.get2(r, k) }, 288 get2(r, k) { throw "myexn" } 289}) 290 291TestGetThrow(new Proxy({}, { 292 get(pr, pk) { throw "myexn" } 293})) 294 295TestGetThrow(new Proxy({}, { 296 get(pr, pk) { 297 return function(r, k) { throw "myexn" } 298 } 299})) 300 301 302// --------------------------------------------------------------------------- 303// Setters. 304 305var key 306var val 307 308function TestSet(handler) { 309 TestWithProxies(TestSet2, handler) 310} 311 312function TestSet2(create, handler) { 313 var p = create(handler) 314 assertEquals(42, p.a = 42) 315 assertEquals("a", key) 316 assertEquals(42, val) 317 assertEquals(43, p["b"] = 43) 318 assertEquals("b", key) 319 assertEquals(43, val) 320 assertEquals(44, p[77] = 44) 321 assertEquals("77", key) 322 assertEquals(44, val) 323 324 assertEquals(45, (function(n) { return p[n] = 45 })("c")) 325 assertEquals("c", key) 326 assertEquals(45, val) 327 assertEquals(46, (function(n) { return p[n] = 46 })(99)) 328 assertEquals("99", key) 329 assertEquals(46, val) 330 331 assertEquals(47, p["0"] = 47) 332 assertEquals("0", key) 333 assertEquals(47, val) 334} 335 336TestSet({ 337 set: function(r, k, v) { key = k; val = v; return true } 338}) 339 340TestSet({ 341 set: function(r, k, v) { return this.set2(r, k, v) }, 342 set2: function(r, k, v) { key = k; val = v; return true } 343}) 344 345TestSet(new Proxy({}, { 346 get(pk, pr) { 347 return (r, k, v) => { key = k; val = v; return true } 348 } 349})) 350 351 352// --------------------------------------------------------------------------- 353function TestSetThrow(handler) { 354 TestWithProxies(TestSetThrow2, handler) 355} 356 357function TestSetThrow2(create, handler) { 358 var p = create(handler) 359 assertThrowsEquals(function(){ p.a = 42 }, "myexn") 360 assertThrowsEquals(function(){ p["b"] = 42 }, "myexn") 361 assertThrowsEquals(function(){ p[22] = 42 }, "myexn") 362 assertThrowsEquals(function(){ (function(n) { p[n] = 45 })("c") }, "myexn") 363 assertThrowsEquals(function(){ (function(n) { p[n] = 46 })(99) }, "myexn") 364} 365 366TestSetThrow({ 367 set: function(r, k, v) { throw "myexn" } 368}) 369 370TestSetThrow({ 371 set: function(r, k, v) { return this.set2(r, k, v) }, 372 set2: function(r, k, v) { throw "myexn" } 373}) 374 375TestSetThrow({ 376 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 377 defineProperty: function(k, desc) { key = k; val = desc.value } 378}) 379 380TestSetThrow({ 381 getOwnPropertyDescriptor: function(k) { 382 return {configurable: true, writable: true} 383 }, 384 defineProperty: function(k, desc) { throw "myexn" } 385}) 386 387TestSetThrow({ 388 getOwnPropertyDescriptor: function(k) { 389 return this.getOwnPropertyDescriptor2(k) 390 }, 391 getOwnPropertyDescriptor2: function(k) { throw "myexn" }, 392 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, 393 defineProperty2: function(k, desc) { key = k; val = desc.value } 394}) 395 396TestSetThrow({ 397 getOwnPropertyDescriptor: function(k) { 398 return this.getOwnPropertyDescriptor2(k) 399 }, 400 getOwnPropertyDescriptor2: function(k) { 401 return {configurable: true, writable: true} 402 }, 403 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, 404 defineProperty2: function(k, desc) { throw "myexn" } 405}) 406 407TestSetThrow({ 408 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 409 defineProperty: function(k, desc) { key = k; val = desc.value } 410}) 411 412TestSetThrow({ 413 getOwnPropertyDescriptor: function(k) { 414 return { 415 get configurable() { return true }, 416 get writable() { return true } 417 } 418 }, 419 defineProperty: function(k, desc) { throw "myexn" } 420}) 421 422TestSetThrow({ 423 getOwnPropertyDescriptor: function(k) { throw "myexn" } 424}) 425 426TestSetThrow({ 427 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 428 defineProperty: function(k, desc) { key = k; val = desc.value } 429}) 430 431TestSetThrow(new Proxy({}, { 432 get: function(pr, pk) { throw "myexn" } 433})) 434 435TestSetThrow(new Proxy({}, { 436 get: function(pr, pk) { 437 return function(r, k, v) { throw "myexn" } 438 } 439})) 440 441// --------------------------------------------------------------------------- 442 443// Evil proxy-induced side-effects shouldn't crash. 444TestWithProxies(function(create) { 445 var calls = 0 446 var handler = { 447 getPropertyDescriptor: function() { 448 ++calls 449 return (calls % 2 == 1) 450 ? {get: function() { return 5 }, configurable: true} 451 : {set: function() { return false }, configurable: true} 452 } 453 } 454 var p = create(handler) 455 var o = Object.create(p) 456 // Make proxy prototype property read-only after CanPut check. 457 try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } 458}) 459 460TestWithProxies(function(create) { 461 var handler = { 462 getPropertyDescriptor: function() { 463 Object.defineProperty(o, "x", {get: function() { return 5 }}); 464 return {set: function() {}} 465 } 466 } 467 var p = create(handler) 468 var o = Object.create(p) 469 // Make object property read-only after CanPut check. 470 try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } 471}) 472 473 474// --------------------------------------------------------------------------- 475// Property definition (Object.defineProperty and Object.defineProperties). 476 477var key 478var desc 479 480function TestDefine(handler) { 481 TestWithProxies(TestDefine2, handler) 482} 483 484function TestDefine2(create, handler) { 485 var p = create(handler) 486 assertEquals(p, Object.defineProperty(p, "a", {value: 44})) 487 assertEquals("a", key) 488 assertEquals(1, Object.getOwnPropertyNames(desc).length) 489 assertEquals(44, desc.value) 490 491 assertEquals(p, Object.defineProperty(p, "b", {value: 45, writable: false})) 492 assertEquals("b", key) 493 assertEquals(2, Object.getOwnPropertyNames(desc).length) 494 assertEquals(45, desc.value) 495 assertEquals(false, desc.writable) 496 497 assertEquals(p, Object.defineProperty(p, "c", {value: 46, enumerable: false})) 498 assertEquals("c", key) 499 assertEquals(2, Object.getOwnPropertyNames(desc).length) 500 assertEquals(46, desc.value) 501 assertEquals(false, desc.enumerable) 502 503 assertEquals(p, Object.defineProperty(p, 101, {value: 47, enumerable: false})) 504 assertEquals("101", key) 505 assertEquals(2, Object.getOwnPropertyNames(desc).length) 506 assertEquals(47, desc.value) 507 assertEquals(false, desc.enumerable) 508 509 var attributes = {configurable: true, mine: 66, minetoo: 23} 510 assertEquals(p, Object.defineProperty(p, "d", attributes)) 511 assertEquals("d", key); 512 // Modifying the attributes object after the fact should have no effect. 513 attributes.configurable = false 514 attributes.mine = 77 515 delete attributes.minetoo; 516 assertEquals(1, Object.getOwnPropertyNames(desc).length) 517 assertEquals(true, desc.configurable) 518 assertEquals(undefined, desc.mine) 519 assertEquals(undefined, desc.minetoo) 520 521 assertEquals(p, Object.defineProperty(p, "e", {get: function(){ return 5 }})) 522 assertEquals("e", key) 523 assertEquals(1, Object.getOwnPropertyNames(desc).length) 524 assertEquals(5, desc.get()) 525 526 assertEquals(p, Object.defineProperty(p, "zzz", {})) 527 assertEquals("zzz", key) 528 assertEquals(0, Object.getOwnPropertyNames(desc).length) 529 530 var props = { 531 '11': {}, 532 blub: {get: function() { return true }}, 533 '': {get value() { return 20 }}, 534 last: {value: 21, configurable: true, mine: "eyes"} 535 } 536 Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false}) 537 assertEquals(p, Object.defineProperties(p, props)) 538 assertEquals("last", key) 539 assertEquals(2, Object.getOwnPropertyNames(desc).length) 540 assertEquals(21, desc.value) 541 assertEquals(true, desc.configurable) 542 assertEquals(undefined, desc.mine) // Arguably a bug in the spec... 543 544 var props = {bla: {get value() { throw "myexn" }}} 545 assertThrowsEquals(function(){ Object.defineProperties(p, props) }, "myexn") 546} 547 548TestDefine({ 549 defineProperty(t, k, d) { key = k; desc = d; return true } 550}) 551 552TestDefine({ 553 defineProperty(t, k, d) { return this.defineProperty2(k, d) }, 554 defineProperty2(k, d) { key = k; desc = d; return true } 555}) 556 557 558// --------------------------------------------------------------------------- 559function TestDefineThrow(handler) { 560 TestWithProxies(TestDefineThrow2, handler) 561} 562 563function TestDefineThrow2(create, handler) { 564 var p = create(handler) 565 assertThrowsEquals(() => Object.defineProperty(p, "a", {value: 44}), "myexn") 566 assertThrowsEquals(() => Object.defineProperty(p, 0, {value: 44}), "myexn") 567 568 var d1 = create({ 569 get: function(r, k) { throw "myexn" }, 570 getOwnPropertyNames: function() { return ["value"] } 571 }) 572 assertThrowsEquals(function(){ Object.defineProperty(p, "p", d1) }, "myexn") 573 var d2 = create({ 574 get: function(r, k) { return 77 }, 575 getOwnPropertyNames: function() { throw "myexn" } 576 }) 577 assertThrowsEquals(function(){ Object.defineProperty(p, "p", d2) }, "myexn") 578 579 var props = {bla: {get value() { throw "otherexn" }}} 580 assertThrowsEquals(() => Object.defineProperties(p, props), "otherexn") 581} 582 583TestDefineThrow({ 584 defineProperty: function(k, d) { throw "myexn" } 585}) 586 587TestDefineThrow({ 588 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, 589 defineProperty2: function(k, d) { throw "myexn" } 590}) 591 592TestDefineThrow(new Proxy({}, { 593 get: function(pr, pk) { throw "myexn" } 594})) 595 596TestDefineThrow(new Proxy({}, { 597 get: function(pr, pk) { 598 return function(k, d) { throw "myexn" } 599 } 600})) 601 602 603 604// --------------------------------------------------------------------------- 605// Property deletion (delete). 606 607var key 608 609function TestDelete(handler) { 610 TestWithProxies(TestDelete2, handler) 611} 612 613function TestDelete2(create, handler) { 614 var p = create(handler) 615 assertEquals(true, delete p.a) 616 assertEquals("a", key) 617 assertEquals(true, delete p["b"]) 618 assertEquals("b", key) 619 assertEquals(true, delete p[1]) 620 assertEquals("1", key) 621 622 assertEquals(false, delete p.z1) 623 assertEquals("z1", key) 624 assertEquals(false, delete p["z2"]) 625 assertEquals("z2", key); 626 627 (function() { 628 "use strict" 629 assertEquals(true, delete p.c) 630 assertEquals("c", key) 631 assertEquals(true, delete p["d"]) 632 assertEquals("d", key) 633 assertEquals(true, delete p[2]) 634 assertEquals("2", key) 635 636 assertThrows(function(){ delete p.z3 }, TypeError) 637 assertEquals("z3", key) 638 assertThrows(function(){ delete p["z4"] }, TypeError) 639 assertEquals("z4", key) 640 })() 641} 642 643TestDelete({ 644 deleteProperty(target, k) { key = k; return k < "z" } 645}) 646 647TestDelete({ 648 deleteProperty(target, k) { return this.delete2(k) }, 649 delete2: function(k) { key = k; return k < "z" } 650}) 651 652TestDelete(new Proxy({}, { 653 get(pt, pk, pr) { 654 return (target, k) => { key = k; return k < "z" } 655 } 656})) 657 658 659// --------------------------------------------------------------------------- 660function TestDeleteThrow(handler) { 661 TestWithProxies(TestDeleteThrow2, handler) 662} 663 664function TestDeleteThrow2(create, handler) { 665 var p = create(handler) 666 assertThrowsEquals(function(){ delete p.a }, "myexn") 667 assertThrowsEquals(function(){ delete p["b"] }, "myexn"); 668 assertThrowsEquals(function(){ delete p[3] }, "myexn"); 669 670 (function() { 671 "use strict" 672 assertThrowsEquals(function(){ delete p.c }, "myexn") 673 assertThrowsEquals(function(){ delete p["d"] }, "myexn") 674 assertThrowsEquals(function(){ delete p[4] }, "myexn"); 675 })() 676} 677 678TestDeleteThrow({ 679 deleteProperty(t, k) { throw "myexn" } 680}) 681 682TestDeleteThrow({ 683 deleteProperty(t, k) { return this.delete2(k) }, 684 delete2(k) { throw "myexn" } 685}) 686 687TestDeleteThrow(new Proxy({}, { 688 get(pt, pk, pr) { throw "myexn" } 689})) 690 691TestDeleteThrow(new Proxy({}, { 692 get(pt, pk, pr) { 693 return (k) => { throw "myexn" } 694 } 695})) 696 697 698// --------------------------------------------------------------------------- 699// Property descriptors (Object.getOwnPropertyDescriptor). 700 701function TestDescriptor(handler) { 702 TestWithProxies(TestDescriptor2, handler) 703} 704 705function TestDescriptor2(create, handler) { 706 var p = create(handler) 707 var descs = [ 708 {configurable: true}, 709 {value: 34, enumerable: true, configurable: true}, 710 {value: 3, writable: false, mine: "eyes", configurable: true}, 711 {get value() { return 20 }, get configurable() { return true }}, 712 {get: function() { "get" }, set: function() { "set" }, configurable: true} 713 ] 714 for (var i = 0; i < descs.length; ++i) { 715 assertEquals(p, Object.defineProperty(p, i, descs[i])) 716 var desc = Object.getOwnPropertyDescriptor(p, i) 717 for (prop in descs[i]) { 718 // TODO(rossberg): Ignore user attributes as long as the spec isn't 719 // fixed suitably. 720 if (prop != "mine") assertEquals(descs[i][prop], desc[prop]) 721 } 722 assertEquals(undefined, Object.getOwnPropertyDescriptor(p, "absent")) 723 } 724} 725 726TestDescriptor({ 727 defineProperty(t, k, d) { this["__" + k] = d; return true }, 728 getOwnPropertyDescriptor(t, k) { return this["__" + k] } 729}) 730 731TestDescriptor({ 732 defineProperty(t, k, d) { this["__" + k] = d; return true }, 733 getOwnPropertyDescriptor(t, k) { 734 return this.getOwnPropertyDescriptor2(k) 735 }, 736 getOwnPropertyDescriptor2: function(k) { return this["__" + k] } 737}) 738 739 740// --------------------------------------------------------------------------- 741function TestDescriptorThrow(handler) { 742 TestWithProxies(TestDescriptorThrow2, handler) 743} 744 745function TestDescriptorThrow2(create, handler) { 746 var p = create(handler) 747 assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn") 748} 749 750TestDescriptorThrow({ 751 getOwnPropertyDescriptor: function(k) { throw "myexn" } 752}) 753 754TestDescriptorThrow({ 755 getOwnPropertyDescriptor: function(k) { 756 return this.getOwnPropertyDescriptor2(k) 757 }, 758 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 759}) 760 761 762 763// --------------------------------------------------------------------------- 764// Comparison. 765 766function TestComparison(eq) { 767 TestWithProxies(TestComparison2, eq) 768} 769 770function TestComparison2(create, eq) { 771 var p1 = create({}) 772 var p2 = create({}) 773 774 assertTrue(eq(p1, p1)) 775 assertTrue(eq(p2, p2)) 776 assertTrue(!eq(p1, p2)) 777 assertTrue(!eq(p1, {})) 778 assertTrue(!eq({}, p2)) 779 assertTrue(!eq({}, {})) 780} 781 782TestComparison(function(o1, o2) { return o1 == o2 }) 783TestComparison(function(o1, o2) { return o1 === o2 }) 784TestComparison(function(o1, o2) { return !(o1 != o2) }) 785TestComparison(function(o1, o2) { return !(o1 !== o2) }) 786 787 788 789// Type (typeof). 790 791function TestTypeof() { 792 assertEquals("object", typeof new Proxy({},{})) 793 assertTrue(typeof new Proxy({}, {}) == "object") 794 assertTrue("object" == typeof new Proxy({},{})) 795 796 assertEquals("function", typeof new Proxy(function() {}, {})) 797 assertTrue(typeof new Proxy(function() {}, {}) == "function") 798 assertTrue("function" == typeof new Proxy(function() {},{})) 799} 800 801TestTypeof() 802 803 804 805// --------------------------------------------------------------------------- 806// Membership test (in). 807 808var key 809 810function TestIn(handler) { 811 TestWithProxies(TestIn2, handler) 812} 813 814function TestIn2(create, handler) { 815 var p = create(handler) 816 assertTrue("a" in p) 817 assertEquals("a", key) 818 assertTrue(99 in p) 819 assertEquals("99", key) 820 assertFalse("z" in p) 821 assertEquals("z", key) 822 823 assertEquals(2, ("a" in p) ? 2 : 0) 824 assertEquals(0, !("a" in p) ? 2 : 0) 825 assertEquals(0, ("zzz" in p) ? 2 : 0) 826 assertEquals(2, !("zzz" in p) ? 2 : 0) 827 828 // Test compilation in conditionals. 829 if ("b" in p) { 830 } else { 831 assertTrue(false) 832 } 833 assertEquals("b", key) 834 835 if ("zz" in p) { 836 assertTrue(false) 837 } 838 assertEquals("zz", key) 839 840 if (!("c" in p)) { 841 assertTrue(false) 842 } 843 assertEquals("c", key) 844 845 if (!("zzz" in p)) { 846 } else { 847 assertTrue(false) 848 } 849 assertEquals("zzz", key) 850} 851 852TestIn({ 853 has(t, k) { key = k; return k < "z" } 854}) 855 856TestIn({ 857 has(t, k) { return this.has2(k) }, 858 has2(k) { key = k; return k < "z" } 859}) 860 861TestIn(new Proxy({},{ 862 get(pt, pk, pr) { 863 return (t, k) => { key = k; return k < "z" } 864 } 865})) 866 867 868// --------------------------------------------------------------------------- 869function TestInThrow(handler) { 870 TestWithProxies(TestInThrow2, handler) 871} 872 873function TestInThrow2(create, handler) { 874 var p = create(handler) 875 assertThrowsEquals(function(){ return "a" in p }, "myexn") 876 assertThrowsEquals(function(){ return 99 in p }, "myexn") 877 assertThrowsEquals(function(){ return !("a" in p) }, "myexn") 878 assertThrowsEquals(function(){ return ("a" in p) ? 2 : 3 }, "myexn") 879 assertThrowsEquals(function(){ if ("b" in p) {} }, "myexn") 880 assertThrowsEquals(function(){ if (!("b" in p)) {} }, "myexn") 881 assertThrowsEquals(function(){ if ("zzz" in p) {} }, "myexn") 882} 883 884TestInThrow({ 885 has: function(k) { throw "myexn" } 886}) 887 888TestInThrow({ 889 has: function(k) { return this.has2(k) }, 890 has2: function(k) { throw "myexn" } 891}) 892 893TestInThrow(new Proxy({},{ 894 get: function(pr, pk) { throw "myexn" } 895})) 896 897TestInThrow(new Proxy({},{ 898 get: function(pr, pk) { 899 return function(k) { throw "myexn" } 900 } 901})) 902 903 904 905// --------------------------------------------------------------------------- 906// Own Properties (Object.prototype.hasOwnProperty). 907 908var key 909 910function TestHasOwn(handler) { 911 TestWithProxies(TestHasOwn2, handler) 912} 913 914function TestHasOwn2(create, handler) { 915 var p = create(handler) 916 assertTrue(Object.prototype.hasOwnProperty.call(p, "a")) 917 assertEquals("a", key) 918 assertTrue(Object.prototype.hasOwnProperty.call(p, 99)) 919 assertEquals("99", key) 920 assertFalse(Object.prototype.hasOwnProperty.call(p, "z")) 921 assertEquals("z", key) 922} 923 924TestHasOwn({ 925 getOwnPropertyDescriptor(t, k) { 926 key = k; if (k < "z") return {configurable: true} 927 }, 928 has() { assertUnreachable() } 929}) 930 931TestHasOwn({ 932 getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) }, 933 getOwnPropertyDescriptor2(k) { 934 key = k; if (k < "z") return {configurable: true} 935 } 936}) 937 938 939 940// --------------------------------------------------------------------------- 941function TestHasOwnThrow(handler) { 942 TestWithProxies(TestHasOwnThrow2, handler) 943} 944 945function TestHasOwnThrow2(create, handler) { 946 var p = create(handler) 947 assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, "a")}, 948 "myexn") 949 assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, 99)}, 950 "myexn") 951} 952 953TestHasOwnThrow({ 954 getOwnPropertyDescriptor(t, k) { throw "myexn" } 955}) 956 957TestHasOwnThrow({ 958 getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) }, 959 getOwnPropertyDescriptor2(k) { throw "myexn" } 960}); 961 962 963// --------------------------------------------------------------------------- 964// Instanceof (instanceof) 965 966(function TestProxyInstanceof() { 967 var o1 = {} 968 var p1 = new Proxy({}, {}) 969 var p2 = new Proxy(o1, {}) 970 var p3 = new Proxy(p2, {}) 971 var o2 = Object.create(p2) 972 973 var f0 = function() {} 974 f0.prototype = o1 975 var f1 = function() {} 976 f1.prototype = p1 977 var f2 = function() {} 978 f2.prototype = p2 979 var f3 = function() {} 980 f3.prototype = o2 981 982 assertTrue(o1 instanceof Object) 983 assertFalse(o1 instanceof f0) 984 assertFalse(o1 instanceof f1) 985 assertFalse(o1 instanceof f2) 986 assertFalse(o1 instanceof f3) 987 assertTrue(p1 instanceof Object) 988 assertFalse(p1 instanceof f0) 989 assertFalse(p1 instanceof f1) 990 assertFalse(p1 instanceof f2) 991 assertFalse(p1 instanceof f3) 992 assertTrue(p2 instanceof Object) 993 assertFalse(p2 instanceof f0) 994 assertFalse(p2 instanceof f1) 995 assertFalse(p2 instanceof f2) 996 assertFalse(p2 instanceof f3) 997 assertTrue(p3 instanceof Object) 998 assertFalse(p3 instanceof f0) 999 assertFalse(p3 instanceof f1) 1000 assertFalse(p3 instanceof f2) 1001 assertFalse(p3 instanceof f3) 1002 assertTrue(o2 instanceof Object) 1003 assertFalse(o2 instanceof f0) 1004 assertFalse(o2 instanceof f1) 1005 assertTrue(o2 instanceof f2) 1006 assertFalse(o2 instanceof f3) 1007 1008 var f = new Proxy(function() {}, {}) 1009 assertTrue(f instanceof Function) 1010})(); 1011 1012 1013(function TestInstanceofProxy() { 1014 var o0 = Object.create(null) 1015 var o1 = {} 1016 var o2 = Object.create(o0) 1017 var o3 = Object.create(o1) 1018 var o4 = Object.create(o2) 1019 var o5 = Object.create(o3) 1020 1021 function handler(o) { return {get: function() { return o } } } 1022 var f0 = new Proxy(function() {}, handler(o0)) 1023 var f1 = new Proxy(function() {}, handler(o1)) 1024 var f2 = new Proxy(function() {}, handler(o2)) 1025 var f3 = new Proxy(function() {}, handler(o3)) 1026 var f4 = new Proxy(function() {}, handler(o4)) 1027 var f5 = new Proxy(function() {}, handler(o4)) 1028 1029 assertFalse(null instanceof f0) 1030 assertFalse(o0 instanceof f0) 1031 assertFalse(o0 instanceof f1) 1032 assertFalse(o0 instanceof f2) 1033 assertFalse(o0 instanceof f3) 1034 assertFalse(o0 instanceof f4) 1035 assertFalse(o0 instanceof f5) 1036 assertFalse(o1 instanceof f0) 1037 assertFalse(o1 instanceof f1) 1038 assertFalse(o1 instanceof f2) 1039 assertFalse(o1 instanceof f3) 1040 assertFalse(o1 instanceof f4) 1041 assertFalse(o1 instanceof f5) 1042 assertTrue(o2 instanceof f0) 1043 assertFalse(o2 instanceof f1) 1044 assertFalse(o2 instanceof f2) 1045 assertFalse(o2 instanceof f3) 1046 assertFalse(o2 instanceof f4) 1047 assertFalse(o2 instanceof f5) 1048 assertFalse(o3 instanceof f0) 1049 assertTrue(o3 instanceof f1) 1050 assertFalse(o3 instanceof f2) 1051 assertFalse(o3 instanceof f3) 1052 assertFalse(o3 instanceof f4) 1053 assertFalse(o3 instanceof f5) 1054 assertTrue(o4 instanceof f0) 1055 assertFalse(o4 instanceof f1) 1056 assertTrue(o4 instanceof f2) 1057 assertFalse(o4 instanceof f3) 1058 assertFalse(o4 instanceof f4) 1059 assertFalse(o4 instanceof f5) 1060 assertFalse(o5 instanceof f0) 1061 assertTrue(o5 instanceof f1) 1062 assertFalse(o5 instanceof f2) 1063 assertTrue(o5 instanceof f3) 1064 assertFalse(o5 instanceof f4) 1065 assertFalse(o5 instanceof f5) 1066 1067 var f = new Proxy(function() {}, {}) 1068 var ff = new Proxy(function() {}, handler(Function)) 1069 assertTrue(f instanceof Function) 1070 assertFalse(f instanceof ff) 1071})(); 1072 1073 1074// --------------------------------------------------------------------------- 1075// Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf). 1076 1077(function TestPrototype() { 1078 var o1 = {} 1079 var p1 = new Proxy({}, {}) 1080 var p2 = new Proxy(o1, {}) 1081 var p3 = new Proxy(p2, {}) 1082 var o2 = Object.create(p3) 1083 1084 assertSame(Object.getPrototypeOf(o1), Object.prototype) 1085 assertSame(Object.getPrototypeOf(p1), Object.prototype) 1086 assertSame(Object.getPrototypeOf(p2), Object.prototype) 1087 assertSame(Object.getPrototypeOf(p3), Object.prototype) 1088 assertSame(Object.getPrototypeOf(o2), p3) 1089 1090 assertTrue(Object.prototype.isPrototypeOf(o1)) 1091 assertTrue(Object.prototype.isPrototypeOf(p1)) 1092 assertTrue(Object.prototype.isPrototypeOf(p2)) 1093 assertTrue(Object.prototype.isPrototypeOf(p3)) 1094 assertTrue(Object.prototype.isPrototypeOf(o2)) 1095 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1)) 1096 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p1)) 1097 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2)) 1098 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3)) 1099 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2)) 1100 assertFalse(Object.prototype.isPrototypeOf.call(o1, o1)) 1101 assertFalse(Object.prototype.isPrototypeOf.call(o1, p1)) 1102 assertFalse(Object.prototype.isPrototypeOf.call(o1, p2)) 1103 assertFalse(Object.prototype.isPrototypeOf.call(o1, p3)) 1104 assertFalse(Object.prototype.isPrototypeOf.call(o1, o2)) 1105 assertFalse(Object.prototype.isPrototypeOf.call(p1, p1)) 1106 assertFalse(Object.prototype.isPrototypeOf.call(p1, o1)) 1107 assertFalse(Object.prototype.isPrototypeOf.call(p1, p2)) 1108 assertFalse(Object.prototype.isPrototypeOf.call(p1, p3)) 1109 assertFalse(Object.prototype.isPrototypeOf.call(p1, o2)) 1110 assertFalse(Object.prototype.isPrototypeOf.call(p2, p1)) 1111 assertFalse(Object.prototype.isPrototypeOf.call(p2, p2)) 1112 assertFalse(Object.prototype.isPrototypeOf.call(p2, p3)) 1113 assertFalse(Object.prototype.isPrototypeOf.call(p2, o2)) 1114 assertFalse(Object.prototype.isPrototypeOf.call(p3, p2)) 1115 assertTrue(Object.prototype.isPrototypeOf.call(p3, o2)) 1116 assertFalse(Object.prototype.isPrototypeOf.call(o2, o1)) 1117 assertFalse(Object.prototype.isPrototypeOf.call(o2, p1)) 1118 assertFalse(Object.prototype.isPrototypeOf.call(o2, p2)) 1119 assertFalse(Object.prototype.isPrototypeOf.call(o2, p3)) 1120 assertFalse(Object.prototype.isPrototypeOf.call(o2, o2)) 1121 1122 var f = new Proxy(function() {}, {}) 1123 assertSame(Object.getPrototypeOf(f), Function.prototype) 1124 assertTrue(Object.prototype.isPrototypeOf(f)) 1125 assertTrue(Object.prototype.isPrototypeOf.call(Function.prototype, f)) 1126})(); 1127 1128 1129// --------------------------------------------------------------------------- 1130function TestPropertyNamesThrow(handler) { 1131 TestWithProxies(TestPropertyNamesThrow2, handler) 1132} 1133 1134function TestPropertyNamesThrow2(create, handler) { 1135 var p = create(handler) 1136 assertThrowsEquals(function(){ Object.getOwnPropertyNames(p) }, "myexn") 1137} 1138 1139TestPropertyNamesThrow({ 1140 ownKeys() { throw "myexn" } 1141}) 1142 1143TestPropertyNamesThrow({ 1144 ownKeys() { return this.getOwnPropertyNames2() }, 1145 getOwnPropertyNames2() { throw "myexn" } 1146}) 1147 1148// --------------------------------------------------------------------------- 1149 1150function TestKeys(names, handler) { 1151 var p = new Proxy({}, handler); 1152 assertArrayEquals(names, Object.keys(p)) 1153} 1154 1155TestKeys([], { 1156 ownKeys() { return [] } 1157}) 1158 1159TestKeys([], { 1160 ownKeys() { return ["a", "zz", " ", "0", "toString"] } 1161}) 1162 1163TestKeys(["a", "zz", " ", "0", "toString"], { 1164 ownKeys() { return ["a", "zz", " ", "0", "toString"] }, 1165 getOwnPropertyDescriptor(t, p) { 1166 return {configurable: true, enumerable: true} 1167 } 1168}) 1169 1170TestKeys([], { 1171 ownKeys() { return this.keys2() }, 1172 keys2() { return ["throw", "function "] } 1173}) 1174 1175TestKeys(["throw", "function "], { 1176 ownKeys() { return this.keys2() }, 1177 keys2() { return ["throw", "function "] }, 1178 getOwnPropertyDescriptor(t, p) { 1179 return {configurable: true, enumerable: true} 1180 } 1181}) 1182 1183TestKeys(["a", "0"], { 1184 ownKeys() { return ["a", "23", "zz", "", "0"] }, 1185 getOwnPropertyDescriptor(t, k) { 1186 return k == "" ? 1187 undefined : 1188 { configurable: true, enumerable: k.length == 1} 1189 } 1190}) 1191 1192TestKeys(["23", "zz", ""], { 1193 ownKeys() { return this.getOwnPropertyNames2() }, 1194 getOwnPropertyNames2() { return ["a", "23", "zz", "", "0"] }, 1195 getOwnPropertyDescriptor(t, k) { 1196 return this.getOwnPropertyDescriptor2(k) 1197 }, 1198 getOwnPropertyDescriptor2(k) { 1199 return {configurable: true, enumerable: k.length != 1 } 1200 } 1201}) 1202 1203TestKeys([], { 1204 get ownKeys() { 1205 return function() { return ["a", "b", "c"] } 1206 }, 1207 getOwnPropertyDescriptor: function(k) { return {configurable: true} } 1208}) 1209 1210 1211// --------------------------------------------------------------------------- 1212function TestKeysThrow(handler) { 1213 TestWithProxies(TestKeysThrow2, handler) 1214} 1215 1216function TestKeysThrow2(create, handler) { 1217 var p = create(handler); 1218 assertThrowsEquals(function(){ Object.keys(p) }, "myexn"); 1219} 1220 1221TestKeysThrow({ 1222 ownKeys() { throw "myexn" } 1223}) 1224 1225TestKeysThrow({ 1226 ownKeys() { return this.keys2() }, 1227 keys2() { throw "myexn" } 1228}) 1229 1230TestKeysThrow({ 1231 ownKeys() { return ['1'] }, 1232 getOwnPropertyDescriptor: function() { throw "myexn" }, 1233}) 1234 1235TestKeysThrow({ 1236 ownKeys() { return this.getOwnPropertyNames2() }, 1237 getOwnPropertyNames2() { return ['1', '2'] }, 1238 getOwnPropertyDescriptor(k) { 1239 return this.getOwnPropertyDescriptor2(k) 1240 }, 1241 getOwnPropertyDescriptor2(k) { throw "myexn" } 1242}) 1243 1244TestKeysThrow({ 1245 get ownKeys() { throw "myexn" } 1246}) 1247 1248TestKeysThrow({ 1249 get ownKeys() { 1250 return function() { throw "myexn" } 1251 }, 1252}) 1253 1254TestKeysThrow({ 1255 get ownKeys() { 1256 return function() { return ['1', '2'] } 1257 }, 1258 getOwnPropertyDescriptor(k) { throw "myexn" } 1259}) 1260 1261 1262 1263// --------------------------------------------------------------------------- 1264// String conversion (Object.prototype.toString, 1265// Object.prototype.toLocaleString, 1266// Function.prototype.toString) 1267 1268var key 1269 1270function TestToString(handler) { 1271 var p = new Proxy({}, handler) 1272 key = "" 1273 assertEquals("[object Object]", Object.prototype.toString.call(p)) 1274 assertEquals(Symbol.toStringTag, key) 1275 assertEquals("my_proxy", Object.prototype.toLocaleString.call(p)) 1276 assertEquals("toString", key) 1277 1278 var f = new Proxy(function() {}, handler) 1279 key = "" 1280 assertEquals("[object Function]", Object.prototype.toString.call(f)) 1281 assertEquals(Symbol.toStringTag, key) 1282 assertEquals("my_proxy", Object.prototype.toLocaleString.call(f)) 1283 assertEquals("toString", key) 1284 assertThrows(function(){ Function.prototype.toString.call(f) }) 1285 1286 var o = Object.create(p) 1287 key = "" 1288 assertEquals("[object Object]", Object.prototype.toString.call(o)) 1289 assertEquals(Symbol.toStringTag, key) 1290 assertEquals("my_proxy", Object.prototype.toLocaleString.call(o)) 1291 assertEquals("toString", key) 1292} 1293 1294TestToString({ 1295 get: function(r, k) { key = k; return function() { return "my_proxy" } } 1296}) 1297 1298TestToString({ 1299 get: function(r, k) { return this.get2(r, k) }, 1300 get2: function(r, k) { key = k; return function() { return "my_proxy" } } 1301}) 1302 1303TestToString(new Proxy({}, { 1304 get: function(pr, pk) { 1305 return function(r, k) { key = k; return function() { return "my_proxy" } } 1306 } 1307})) 1308 1309 1310function TestToStringThrow(handler) { 1311 var p = new Proxy({}, handler) 1312 assertThrowsEquals(() => Object.prototype.toString.call(p), "myexn") 1313 assertThrowsEquals(() => Object.prototype.toLocaleString.call(p), "myexn") 1314 1315 var f = new Proxy(function(){}, handler) 1316 assertThrowsEquals(() => Object.prototype.toString.call(f), "myexn") 1317 assertThrowsEquals(() => Object.prototype.toLocaleString.call(f), "myexn") 1318 1319 var o = Object.create(p) 1320 assertThrowsEquals(() => Object.prototype.toString.call(o), "myexn") 1321 assertThrowsEquals(() => Object.prototype.toLocaleString.call(o), "myexn") 1322} 1323 1324TestToStringThrow({ 1325 get: function(r, k) { throw "myexn" } 1326}) 1327 1328TestToStringThrow({ 1329 get: function(r, k) { return this.get2(r, k) }, 1330 get2: function(r, k) { throw "myexn" } 1331}) 1332 1333TestToStringThrow(new Proxy({}, { 1334 get: function(pr, pk) { throw "myexn" } 1335})) 1336 1337TestToStringThrow(new Proxy({}, { 1338 get: function(pr, pk) { 1339 return function(r, k) { throw "myexn" } 1340 } 1341})) 1342 1343 1344// --------------------------------------------------------------------------- 1345// Value conversion (Object.prototype.toValue) 1346 1347function TestValueOf(handler) { 1348 TestWithProxies(TestValueOf2, handler) 1349} 1350 1351function TestValueOf2(create, handler) { 1352 var p = create(handler) 1353 assertSame(p, Object.prototype.valueOf.call(p)) 1354} 1355 1356TestValueOf({}) 1357 1358 1359 1360// --------------------------------------------------------------------------- 1361// Enumerability (Object.prototype.propertyIsEnumerable) 1362 1363var key 1364 1365function TestIsEnumerable(handler) { 1366 TestWithProxies(TestIsEnumerable2, handler) 1367} 1368 1369function TestIsEnumerable2(create, handler) { 1370 var p = create(handler) 1371 assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a")) 1372 assertEquals("a", key) 1373 assertTrue(Object.prototype.propertyIsEnumerable.call(p, 2)) 1374 assertEquals("2", key) 1375 assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z")) 1376 assertEquals("z", key) 1377 1378 var o = Object.create(p) 1379 key = "" 1380 assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a")) 1381 assertEquals("", key) // trap not invoked 1382} 1383 1384TestIsEnumerable({ 1385 getOwnPropertyDescriptor(t, k) { 1386 key = k; 1387 return {enumerable: k < "z", configurable: true} 1388 }, 1389}) 1390 1391TestIsEnumerable({ 1392 getOwnPropertyDescriptor: function(t, k) { 1393 return this.getOwnPropertyDescriptor2(k) 1394 }, 1395 getOwnPropertyDescriptor2: function(k) { 1396 key = k; 1397 return {enumerable: k < "z", configurable: true} 1398 }, 1399}) 1400 1401TestIsEnumerable({ 1402 getOwnPropertyDescriptor: function(t, k) { 1403 key = k; 1404 return {get enumerable() { return k < "z" }, configurable: true} 1405 }, 1406}) 1407 1408TestIsEnumerable(new Proxy({}, { 1409 get: function(pt, pk, pr) { 1410 return function(t, k) { 1411 key = k; 1412 return {enumerable: k < "z", configurable: true} 1413 } 1414 } 1415})) 1416 1417 1418// --------------------------------------------------------------------------- 1419function TestIsEnumerableThrow(handler) { 1420 TestWithProxies(TestIsEnumerableThrow2, handler) 1421} 1422 1423function TestIsEnumerableThrow2(create, handler) { 1424 var p = create(handler) 1425 assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, "a"), 1426 "myexn") 1427 assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, 11), 1428 "myexn") 1429} 1430 1431TestIsEnumerableThrow({ 1432 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1433}) 1434 1435TestIsEnumerableThrow({ 1436 getOwnPropertyDescriptor: function(k) { 1437 return this.getOwnPropertyDescriptor2(k) 1438 }, 1439 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 1440}) 1441 1442TestIsEnumerableThrow({ 1443 getOwnPropertyDescriptor: function(k) { 1444 return {get enumerable() { throw "myexn" }, configurable: true} 1445 }, 1446}) 1447 1448TestIsEnumerableThrow(new Proxy({}, { 1449 get: function(pr, pk) { throw "myexn" } 1450})) 1451 1452TestIsEnumerableThrow(new Proxy({}, { 1453 get: function(pr, pk) { 1454 return function(k) { throw "myexn" } 1455 } 1456})); 1457 1458 1459 1460// --------------------------------------------------------------------------- 1461// Constructor functions with proxy prototypes. 1462 1463(function TestConstructorWithProxyPrototype() { 1464 TestWithProxies(TestConstructorWithProxyPrototype2, {}) 1465})(); 1466 1467function TestConstructorWithProxyPrototype2(create, handler) { 1468 function C() {}; 1469 C.prototype = create(handler); 1470 1471 var o = new C; 1472 assertSame(C.prototype, Object.getPrototypeOf(o)); 1473}; 1474 1475 1476(function TestOptWithProxyPrototype() { 1477 var handler = { 1478 get(t, k) { 1479 return 10; 1480 } 1481 }; 1482 1483 function C() {}; 1484 C.prototype = new Proxy({}, handler); 1485 var o = new C(); 1486 1487 function f() { 1488 return o.x; 1489 } 1490 assertEquals(10, f()); 1491 assertEquals(10, f()); 1492 %OptimizeFunctionOnNextCall(f); 1493 assertEquals(10, f()); 1494})(); 1495