defineProperty-setup.js (29521B)
1 // |reftest| skip -- not a test. 2 // Any copyright is dedicated to the Public Domain. 3 // http://creativecommons.org/licenses/publicdomain/ 4 5 assertEq("defineProperty" in Object, true); 6 assertEq(Object.defineProperty.length, 3); 7 8 /* 9 * Disable an assertion that is pathologically slow given the exhaustiveness of 10 * these tests. 11 */ 12 if (typeof enableStackWalkingAssertion === "function") 13 enableStackWalkingAssertion(false); 14 15 if (!Object.prototype.toSource) 16 { 17 Object.defineProperty(Object.prototype, "toSource", 18 { 19 value: function toSource() 20 { 21 if (this instanceof RegExp) 22 { 23 var v = "new RegExp(" + uneval(this.source); 24 var f = (this.multiline ? "m" : "") + 25 (this.global ? "g" : "") + 26 (this.ignoreCase ? "i" : ""); 27 return v + (f ? ", '" + f + "'" : "") + ")"; 28 } 29 return JSON.stringify(this); 30 }, 31 enumerable: false, 32 configurable: true, 33 writable: true 34 }); 35 } 36 if (!("uneval" in this)) 37 { 38 Object.defineProperty(this, "uneval", 39 { 40 value: function uneval(v) 41 { 42 if (v === null) 43 return "null"; 44 if (typeof v === "object") 45 return v.toSource(); 46 if (typeof v === "string") 47 { 48 v = JSON.stringify({v:v}); 49 return v.substring(5, v.length - 1); 50 } 51 return "" + v; 52 }, 53 enumerable: false, 54 configurable: true, 55 writable: true 56 }); 57 } 58 59 // reimplemented for the benefit of engines which don't have this helper 60 function assertEq(v1, v2, m) 61 { 62 if (!SameValue(v1, v2)) 63 { 64 throw "assertion failed: " + 65 "got " + uneval(v1) + ", expected " + uneval(v2) + 66 (m ? ": " + m : ""); 67 } 68 } 69 70 function SameValue(v1, v2) 71 { 72 if (v1 === 0 && v2 === 0) 73 return 1 / v1 === 1 / v2; 74 if (v1 !== v1 && v2 !== v2) 75 return true; 76 return v1 === v2; 77 } 78 79 function PropertyDescriptor(pd) 80 { 81 if (pd) 82 this.update(pd); 83 } 84 PropertyDescriptor.prototype.update = function update(pd) 85 { 86 if ("get" in pd) 87 this.get = pd.get; 88 if ("set" in pd) 89 this.set = pd.set; 90 if ("configurable" in pd) 91 this.configurable = pd.configurable; 92 if ("writable" in pd) 93 this.writable = pd.writable; 94 if ("enumerable" in pd) 95 this.enumerable = pd.enumerable; 96 if ("value" in pd) 97 this.value = pd.value; 98 }; 99 PropertyDescriptor.prototype.convertToDataDescriptor = function convertToDataDescriptor() 100 { 101 delete this.get; 102 delete this.set; 103 this.writable = false; 104 this.value = undefined; 105 }; 106 PropertyDescriptor.prototype.convertToAccessorDescriptor = function convertToAccessorDescriptor() 107 { 108 delete this.writable; 109 delete this.value; 110 this.get = undefined; 111 this.set = undefined; 112 }; 113 114 function compareDescriptors(d1, d2) 115 { 116 if (d1 === undefined) 117 { 118 assertEq(d2, undefined, "non-descriptors"); 119 return; 120 } 121 if (d2 === undefined) 122 { 123 assertEq(true, false, "descriptor-equality mismatch: " + uneval(d1) + ", " + uneval(d2)); 124 return; 125 } 126 127 var props = ["value", "get", "set", "enumerable", "configurable", "writable"]; 128 for (var i = 0, sz = props.length; i < sz; i++) 129 { 130 var p = props[i]; 131 assertEq(p in d1, p in d2, p + " different in d1/d2"); 132 if (p in d1) 133 assertEq(d1[p], d2[p], p); 134 } 135 } 136 137 function examine(desc, field, allowDefault) 138 { 139 if (field in desc) 140 return desc[field]; 141 assertEq(allowDefault, true, "reimplementation error"); 142 switch (field) 143 { 144 case "value": 145 case "get": 146 case "set": 147 return undefined; 148 case "writable": 149 case "enumerable": 150 case "configurable": 151 return false; 152 default: 153 assertEq(true, false, "bad field name: " + field); 154 } 155 } 156 157 function IsAccessorDescriptor(desc) 158 { 159 if (!desc) 160 return false; 161 if (!("get" in desc) && !("set" in desc)) 162 return false; 163 return true; 164 } 165 166 function IsDataDescriptor(desc) 167 { 168 if (!desc) 169 return false; 170 if (!("value" in desc) && !("writable" in desc)) 171 return false; 172 return true; 173 } 174 175 function IsGenericDescriptor(desc) 176 { 177 if (!desc) 178 return false; 179 if (!IsAccessorDescriptor(desc) && !IsDataDescriptor(desc)) 180 return true; 181 return false; 182 } 183 184 185 186 function CustomObject() 187 { 188 this.properties = {}; 189 this.extensible = true; 190 } 191 CustomObject.prototype = 192 { 193 _reject: function _reject(throwing, msg) 194 { 195 if (throwing) 196 throw new TypeError(msg + "; rejected!"); 197 return false; 198 }, 199 defineOwnProperty: function defineOwnProperty(propname, desc, throwing) 200 { 201 assertEq(typeof propname, "string", "non-string propname"); 202 203 // Step 1. 204 var current = this.properties[propname]; 205 206 // Step 2. 207 var extensible = this.extensible; 208 209 // Step 3. 210 if (current === undefined && !extensible) 211 return this._reject(throwing, "object not extensible"); 212 213 // Step 4. 214 if (current === undefined && extensible) 215 { 216 var p; 217 // Step 4(a). 218 if (IsGenericDescriptor(desc) || IsDataDescriptor(desc)) 219 { 220 p = new PropertyDescriptor(); 221 p.value = examine(desc, "value", true); 222 p.writable = examine(desc, "writable", true); 223 p.enumerable = examine(desc, "enumerable", true); 224 p.configurable = examine(desc, "configurable", true); 225 } 226 // Step 4(b). 227 else 228 { 229 p = new PropertyDescriptor(); 230 p.get = examine(desc, "get", true); 231 p.set = examine(desc, "set", true); 232 p.enumerable = examine(desc, "enumerable", true); 233 p.configurable = examine(desc, "configurable", true); 234 } 235 236 this.properties[propname] = p; 237 238 // Step 4(c). 239 return true; 240 } 241 242 // Step 5. 243 if (!("value" in desc) && !("get" in desc) && !("set" in desc) && 244 !("writable" in desc) && !("enumerable" in desc) && 245 !("configurable" in desc)) 246 { 247 return; 248 } 249 250 // Step 6. 251 do 252 { 253 if ("value" in desc) 254 { 255 if (!("value" in current) || !SameValue(desc.value, current.value)) 256 break; 257 } 258 if ("get" in desc) 259 { 260 if (!("get" in current) || !SameValue(desc.get, current.get)) 261 break; 262 } 263 if ("set" in desc) 264 { 265 if (!("set" in current) || !SameValue(desc.set, current.set)) 266 break; 267 } 268 if ("writable" in desc) 269 { 270 if (!("writable" in current) || 271 !SameValue(desc.writable, current.writable)) 272 { 273 break; 274 } 275 } 276 if ("enumerable" in desc) 277 { 278 if (!("enumerable" in current) || 279 !SameValue(desc.enumerable, current.enumerable)) 280 { 281 break; 282 } 283 } 284 if ("configurable" in desc) 285 { 286 if (!("configurable" in current) || 287 !SameValue(desc.configurable, current.configurable)) 288 { 289 break; 290 } 291 } 292 293 // all fields in desc also in current, with the same values 294 return true; 295 } 296 while (false); 297 298 // Step 7. 299 if (!examine(current, "configurable")) 300 { 301 if ("configurable" in desc && examine(desc, "configurable")) 302 return this._reject(throwing, "can't make configurable again"); 303 if ("enumerable" in desc && 304 examine(current, "enumerable") !== examine(desc, "enumerable")) 305 { 306 return this._reject(throwing, "can't change enumerability"); 307 } 308 } 309 310 // Step 8. 311 if (IsGenericDescriptor(desc)) 312 { 313 // do nothing 314 } 315 // Step 9. 316 else if (IsDataDescriptor(current) !== IsDataDescriptor(desc)) 317 { 318 // Step 9(a). 319 if (!examine(current, "configurable")) 320 return this._reject(throwing, "can't change unconfigurable descriptor's type"); 321 // Step 9(b). 322 if (IsDataDescriptor(current)) 323 current.convertToAccessorDescriptor(); 324 // Step 9(c). 325 else 326 current.convertToDataDescriptor(); 327 } 328 // Step 10. 329 else if (IsDataDescriptor(current) && IsDataDescriptor(desc)) 330 { 331 // Step 10(a) 332 if (!examine(current, "configurable")) 333 { 334 // Step 10(a).i. 335 if (!examine(current, "writable") && 336 "writable" in desc && examine(desc, "writable")) 337 { 338 return this._reject(throwing, "can't make data property writable again"); 339 } 340 // Step 10(a).ii. 341 if (!examine(current, "writable")) 342 { 343 if ("value" in desc && 344 !SameValue(examine(desc, "value"), examine(current, "value"))) 345 { 346 return this._reject(throwing, "can't change value if not writable"); 347 } 348 } 349 } 350 // Step 10(b). 351 else 352 { 353 assertEq(examine(current, "configurable"), true, 354 "spec bug step 10(b)"); 355 } 356 } 357 // Step 11. 358 else 359 { 360 assertEq(IsAccessorDescriptor(current) && IsAccessorDescriptor(desc), 361 true, 362 "spec bug"); 363 364 // Step 11(a). 365 if (!examine(current, "configurable")) 366 { 367 // Step 11(a).i. 368 if ("set" in desc && 369 !SameValue(examine(desc, "set"), examine(current, "set"))) 370 { 371 return this._reject(throwing, "can't change setter if not configurable"); 372 } 373 // Step 11(a).ii. 374 if ("get" in desc && 375 !SameValue(examine(desc, "get"), examine(current, "get"))) 376 { 377 return this._reject(throwing, "can't change getter if not configurable"); 378 } 379 } 380 } 381 382 // Step 12. 383 current.update(desc); 384 385 // Step 13. 386 return true; 387 } 388 }; 389 390 function IsCallable(v) 391 { 392 return typeof v === "undefined" || typeof v === "function"; 393 } 394 395 var NativeTest = 396 { 397 newObject: function newObject() 398 { 399 return {}; 400 }, 401 defineProperty: function defineProperty(obj, propname, propdesc) 402 { 403 Object.defineProperty(obj, propname, propdesc); 404 }, 405 getDescriptor: function getDescriptor(obj, propname) 406 { 407 return Object.getOwnPropertyDescriptor(obj, propname); 408 } 409 }; 410 411 var ReimplTest = 412 { 413 newObject: function newObject() 414 { 415 return new CustomObject(); 416 }, 417 defineProperty: function defineProperty(obj, propname, propdesc) 418 { 419 assertEq(obj instanceof CustomObject, true, "obj not instanceof CustomObject"); 420 if ("get" in propdesc || "set" in propdesc) 421 { 422 if ("value" in propdesc || "writable" in propdesc) 423 throw new TypeError("get/set and value/writable"); 424 if (!IsCallable(propdesc.get)) 425 throw new TypeError("get defined, uncallable"); 426 if (!IsCallable(propdesc.set)) 427 throw new TypeError("set defined, uncallable"); 428 } 429 return obj.defineOwnProperty(propname, propdesc, true); 430 }, 431 getDescriptor: function getDescriptor(obj, propname) 432 { 433 if (!(propname in obj.properties)) 434 return undefined; 435 436 return new PropertyDescriptor(obj.properties[propname]); 437 } 438 }; 439 440 var JSVAL_INT_MAX = Math.pow(2, 30) - 1; 441 var JSVAL_INT_MIN = -Math.pow(2, 30); 442 443 444 function isValidDescriptor(propdesc) 445 { 446 if ("get" in propdesc || "set" in propdesc) 447 { 448 if ("value" in propdesc || "writable" in propdesc) 449 return false; 450 451 // We permit null here simply because this test's author believes the 452 // implementation may sometime be susceptible to making mistakes in this 453 // regard and would prefer to be cautious. 454 if (propdesc.get !== null && propdesc.get !== undefined && !IsCallable(propdesc.get)) 455 return false; 456 if (propdesc.set !== null && propdesc.set !== undefined && !IsCallable(propdesc.set)) 457 return false; 458 } 459 460 return true; 461 } 462 463 464 var OMIT = {}; 465 var VALUES = 466 [-Infinity, JSVAL_INT_MIN, -0, +0, 1.5, JSVAL_INT_MAX, Infinity, 467 NaN, "foo", "bar", null, undefined, true, false, {}, /a/, OMIT]; 468 var GETS = 469 [undefined, function get1() { return 1; }, function get2() { return 2; }, 470 null, 5, OMIT]; 471 var SETS = 472 [undefined, function set1() { return 1; }, function set2() { return 2; }, 473 null, 5, OMIT]; 474 var ENUMERABLES = [true, false, OMIT]; 475 var CONFIGURABLES = [true, false, OMIT]; 476 var WRITABLES = [true, false, OMIT]; 477 478 function mapTestDescriptors(filter) 479 { 480 var descs = []; 481 var desc = {}; 482 483 function put(field, value) 484 { 485 if (value !== OMIT) 486 desc[field] = value; 487 } 488 489 VALUES.forEach(function(value) 490 { 491 GETS.forEach(function(get) 492 { 493 SETS.forEach(function(set) 494 { 495 ENUMERABLES.forEach(function(enumerable) 496 { 497 CONFIGURABLES.forEach(function(configurable) 498 { 499 WRITABLES.forEach(function(writable) 500 { 501 desc = {}; 502 put("value", value); 503 put("get", get); 504 put("set", set); 505 put("enumerable", enumerable); 506 put("configurable", configurable); 507 put("writable", writable); 508 if (filter(desc)) 509 descs.push(desc); 510 }); 511 }); 512 }); 513 }); 514 }); 515 }); 516 517 return descs; 518 } 519 520 var ALL_DESCRIPTORS = mapTestDescriptors(function(d) { return true; }); 521 var VALID_DESCRIPTORS = mapTestDescriptors(isValidDescriptor); 522 523 function TestRunner() 524 { 525 this._logLines = []; 526 } 527 TestRunner.prototype = 528 { 529 // MAIN METHODS 530 531 runFunctionLengthTests: function runFunctionLengthTests() 532 { 533 var self = this; 534 function functionLengthTests() 535 { 536 self._fullFunctionLengthTests(() => Function("one", "/* body */"), 1); 537 self._fullFunctionLengthTests(() => function(one, two, three=null) { }, 2); 538 self._fullFunctionLengthTests(() => (one, two, ...etc) => 0, 2); 539 self._fullFunctionLengthTests(() => ({method(){}}.method), 0); 540 self._fullFunctionLengthTests(() => Object.getOwnPropertyDescriptor({set x(v){}}, "x").set, 1); 541 } 542 543 this._runTestSet(functionLengthTests, "Function length tests completed!"); 544 }, 545 546 runNotPresentTests: function runNotPresentTests() 547 { 548 var self = this; 549 function notPresentTests() 550 { 551 print("Running not-present tests now..."); 552 553 for (var i = 0, sz = ALL_DESCRIPTORS.length; i < sz; i++) 554 self._runSingleNotPresentTest(ALL_DESCRIPTORS[i]); 555 }; 556 557 this._runTestSet(notPresentTests, "Not-present length tests completed!"); 558 }, 559 560 runPropertyPresentTestsFraction: 561 function runPropertyPresentTestsFraction(part, parts) 562 { 563 var self = this; 564 function propertyPresentTests() 565 { 566 print("Running already-present tests now..."); 567 568 var total = VALID_DESCRIPTORS.length; 569 var start = Math.floor((part - 1) / parts * total); 570 var end = Math.floor(part / parts * total); 571 572 for (var i = start; i < end; i++) 573 { 574 var old = VALID_DESCRIPTORS[i]; 575 print("Starting test with old descriptor " + old.toSource() + "..."); 576 577 for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++) 578 self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []); 579 } 580 } 581 582 this._runTestSet(propertyPresentTests, 583 "Property-present fraction " + part + " of " + parts + 584 " completed!"); 585 }, 586 587 runNonTerminalPropertyPresentTestsFraction: 588 function runNonTerminalPropertyPresentTestsFraction(part, parts) 589 { 590 var self = this; 591 592 /* 593 * A plain old property to define on the object before redefining the 594 * originally-added property, to test redefinition of a property that's 595 * not also lastProperty. NB: we could loop over every possible 596 * descriptor here if we wanted, even try adding more than one, but we'd 597 * hit cubic complexity and worse, and SpiderMonkey only distinguishes by 598 * the mere presence of the middle property, not its precise details. 599 */ 600 var middleDefines = 601 [{ 602 property: "middle", 603 descriptor: 604 { value: 17, writable: true, configurable: true, enumerable: true } 605 }]; 606 607 function nonTerminalPropertyPresentTests() 608 { 609 print("Running non-terminal already-present tests now..."); 610 611 var total = VALID_DESCRIPTORS.length; 612 var start = Math.floor((part - 1) / parts * total); 613 var end = Math.floor(part / parts * total); 614 615 for (var i = start; i < end; i++) 616 { 617 var old = VALID_DESCRIPTORS[i]; 618 print("Starting test with old descriptor " + old.toSource() + "..."); 619 620 for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++) 621 { 622 self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], 623 middleDefines); 624 } 625 } 626 } 627 628 this._runTestSet(nonTerminalPropertyPresentTests, 629 "Non-terminal property-present fraction " + 630 part + " of " + parts + " completed!"); 631 }, 632 633 runDictionaryPropertyPresentTestsFraction: 634 function runDictionaryPropertyPresentTestsFraction(part, parts) 635 { 636 var self = this; 637 638 /* 639 * Add and readd properties such that the scope for the object is in 640 * dictionary mode. 641 */ 642 var middleDefines = 643 [ 644 { 645 property: "mid1", 646 descriptor: 647 { value: 17, writable: true, configurable: true, enumerable: true } 648 }, 649 { 650 property: "mid2", 651 descriptor: 652 { value: 17, writable: true, configurable: true, enumerable: true } 653 }, 654 { 655 property: "mid1", 656 descriptor: 657 { get: function g() { }, set: function s(v){}, configurable: false, 658 enumerable: true } 659 }, 660 ]; 661 662 function dictionaryPropertyPresentTests() 663 { 664 print("Running dictionary already-present tests now..."); 665 666 var total = VALID_DESCRIPTORS.length; 667 var start = Math.floor((part - 1) / parts * total); 668 var end = Math.floor(part / parts * total); 669 670 for (var i = start; i < end; i++) 671 { 672 var old = VALID_DESCRIPTORS[i]; 673 print("Starting test with old descriptor " + old.toSource() + "..."); 674 675 for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++) 676 { 677 self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], 678 middleDefines); 679 } 680 } 681 } 682 683 this._runTestSet(dictionaryPropertyPresentTests, 684 "Dictionary property-present fraction " + 685 part + " of " + parts + " completed!"); 686 }, 687 688 689 // HELPERS 690 691 runPropertyPresentTests: function runPropertyPresentTests() 692 { 693 print("Running already-present tests now..."); 694 695 for (var i = 0, sz = VALID_DESCRIPTORS.length; i < sz; i++) 696 { 697 var old = VALID_DESCRIPTORS[i]; 698 print("Starting test with old descriptor " + old.toSource() + "..."); 699 700 for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++) 701 this._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []); 702 } 703 }, 704 _runTestSet: function _runTestSet(fun, completeMessage) 705 { 706 try 707 { 708 fun(); 709 710 print(completeMessage); 711 } 712 catch (e) 713 { 714 print("ERROR, EXITING (line " + (e.lineNumber || -1) + "): " + e); 715 throw e; 716 } 717 finally 718 { 719 this._reportAllErrors(); 720 } 721 }, 722 _reportAllErrors: function _reportAllErrors() 723 { 724 var errorCount = this._logLines.length; 725 print("Full accumulated number of errors: " + errorCount); 726 if (errorCount > 0) 727 throw errorCount + " errors detected, FAIL"; 728 }, 729 _fullFunctionLengthTests: function _fullFunctionLengthTests(funFactory, len) 730 { 731 print("Running Function.length (" + funFactory + ") tests now..."); 732 733 for (var i = 0, sz = VALID_DESCRIPTORS.length; i < sz; i++) 734 { 735 var desc = VALID_DESCRIPTORS[i]; 736 this._runSingleFunctionLengthTest(funFactory(), len, desc); 737 } 738 }, 739 _log: function _log(v) 740 { 741 var m = "" + v; 742 print(m); 743 this._logLines.push(m); 744 }, 745 _runSingleNotPresentTest: function _runSingleNotPresentTest(desc) 746 { 747 var nativeObj = NativeTest.newObject(); 748 var reimplObj = ReimplTest.newObject(); 749 750 try 751 { 752 NativeTest.defineProperty(nativeObj, "foo", desc); 753 } 754 catch (e) 755 { 756 try 757 { 758 ReimplTest.defineProperty(reimplObj, "foo", desc); 759 } 760 catch (e2) 761 { 762 if (e.constructor !== e2.constructor) 763 { 764 this._log("Difference when comparing native/reimplementation " + 765 "behavior for new descriptor " + desc.toSource() + 766 ", native threw " + e + ", reimpl threw " + e2); 767 } 768 return; 769 } 770 this._log("Difference when comparing native/reimplementation " + 771 "behavior for new descriptor " + desc.toSource() + 772 ", error " + e); 773 return; 774 } 775 776 try 777 { 778 ReimplTest.defineProperty(reimplObj, "foo", desc); 779 } 780 catch (e) 781 { 782 this._log("Reimpl threw defining new descriptor " + desc.toSource() + 783 ", error: " + e); 784 return; 785 } 786 787 var nativeDesc = NativeTest.getDescriptor(nativeObj, "foo"); 788 var reimplDesc = ReimplTest.getDescriptor(reimplObj, "foo"); 789 try 790 { 791 compareDescriptors(nativeDesc, reimplDesc); 792 } 793 catch (e) 794 { 795 this._log("Difference comparing returned descriptors for new " + 796 "property defined with descriptor " + desc.toSource() + 797 "; error: " + e); 798 return; 799 } 800 }, 801 _runSinglePropertyPresentTest: 802 function _runSinglePropertyPresentTest(old, add, middleDefines) 803 { 804 var nativeObj = NativeTest.newObject(); 805 var reimplObj = ReimplTest.newObject(); 806 807 try 808 { 809 NativeTest.defineProperty(nativeObj, "foo", old); 810 } 811 catch (e) 812 { 813 if (!SameValue(NativeTest.getDescriptor(nativeObj, "foo"), undefined)) 814 { 815 this._log("defining bad property descriptor: " + old.toSource()); 816 return; 817 } 818 819 try 820 { 821 ReimplTest.defineProperty(reimplObj, "foo", old); 822 } 823 catch (e2) 824 { 825 if (!SameValue(ReimplTest.getDescriptor(reimplObj, "foo"), 826 undefined)) 827 { 828 this._log("defining bad property descriptor: " + old.toSource() + 829 "; reimplObj: " + uneval(reimplObj)); 830 } 831 832 if (e.constructor !== e2.constructor) 833 { 834 this._log("Different errors defining bad property descriptor: " + 835 old.toSource() + "; native threw " + e + ", reimpl " + 836 "threw " + e2); 837 } 838 839 return; 840 } 841 842 this._log("Difference defining a property with descriptor " + 843 old.toSource() + ", error " + e); 844 return; 845 } 846 847 try 848 { 849 ReimplTest.defineProperty(reimplObj, "foo", old); 850 } 851 catch (e) 852 { 853 this._log("Difference when comparing native/reimplementation " + 854 "behavior when adding descriptor " + add.toSource() + 855 ", error: " + e); 856 return; 857 } 858 859 // Now add (or even readd) however many properties were specified between 860 // the original property to add and the new one, to test redefining 861 // non-last-properties and properties in scopes in dictionary mode. 862 for (var i = 0, sz = middleDefines.length; i < sz; i++) 863 { 864 var middle = middleDefines[i]; 865 var prop = middle.property; 866 var desc = middle.descriptor; 867 868 try 869 { 870 NativeTest.defineProperty(nativeObj, prop, desc); 871 ReimplTest.defineProperty(reimplObj, prop, desc); 872 } 873 catch (e) 874 { 875 this._log("failure defining middle descriptor: " + desc.toSource() + 876 ", error " + e); 877 return; 878 } 879 880 // Sanity check 881 var nativeDesc = NativeTest.getDescriptor(nativeObj, prop); 882 var reimplDesc = ReimplTest.getDescriptor(reimplObj, prop); 883 884 compareDescriptors(nativeDesc, reimplDesc); 885 compareDescriptors(nativeDesc, desc); 886 } 887 888 try 889 { 890 NativeTest.defineProperty(nativeObj, "foo", add); 891 } 892 catch (e) 893 { 894 try 895 { 896 ReimplTest.defineProperty(reimplObj, "foo", add); 897 } 898 catch (e2) 899 { 900 if (e.constructor !== e2.constructor) 901 { 902 this._log("Difference when comparing native/reimplementation " + 903 "behavior for descriptor " + add.toSource() + 904 " overwriting descriptor " + old.toSource() + "; " + 905 "native threw " + e + ", reimpl threw " + e2); 906 } 907 return; 908 } 909 this._log("Difference when comparing native/reimplementation " + 910 "behavior for added descriptor " + add.toSource() + ", " + 911 "initial was " + old.toSource() + "; error: " + e); 912 return; 913 } 914 915 try 916 { 917 ReimplTest.defineProperty(reimplObj, "foo", add); 918 } 919 catch (e) 920 { 921 this._log("Difference when comparing native/reimplementation " + 922 "behavior for readded descriptor " + add.toSource() + ", " + 923 "initial was " + old.toSource() + "; native readd didn't " + 924 "throw, reimpl add did, error: " + e); 925 return; 926 } 927 928 var nativeDesc = NativeTest.getDescriptor(nativeObj, "foo"); 929 var reimplDesc = ReimplTest.getDescriptor(reimplObj, "foo"); 930 try 931 { 932 compareDescriptors(nativeDesc, reimplDesc); 933 } 934 catch (e) 935 { 936 this._log("Difference comparing returned descriptors for readded " + 937 "property defined with descriptor " + add.toSource() + "; " + 938 "initial was " + old.toSource() + "; error: " + e); 939 return; 940 } 941 }, 942 _runSingleFunctionLengthTest: function _runSingleFunctionLengthTest(fun, len, desc) 943 { 944 var nativeObj = fun; 945 var reimplObj = ReimplTest.newObject(); 946 ReimplTest.defineProperty(reimplObj, "length", 947 { 948 value: len, 949 enumerable: false, 950 configurable: true, 951 writable: false 952 }); 953 954 try 955 { 956 NativeTest.defineProperty(nativeObj, "length", desc); 957 } 958 catch (e) 959 { 960 try 961 { 962 ReimplTest.defineProperty(reimplObj, "length", desc); 963 } 964 catch (e2) 965 { 966 if (e.constructor !== e2.constructor) 967 { 968 this._log("Difference when comparing native/reimplementation " + 969 "behavior defining fun.length with " + desc.toSource() + 970 "; native threw " + e + ", reimpl threw " + e2); 971 } 972 return; 973 } 974 this._log("Difference when comparing Function.length native/reimpl " + 975 "behavior for descriptor " + desc.toSource() + 976 ", native impl threw error " + e); 977 return; 978 } 979 980 try 981 { 982 ReimplTest.defineProperty(reimplObj, "length", desc); 983 } 984 catch (e) 985 { 986 this._log("Difference defining new Function.length descriptor: impl " + 987 "succeeded, reimpl threw for descriptor " + 988 desc.toSource() + ", error: " + e); 989 return; 990 } 991 992 var nativeDesc = NativeTest.getDescriptor(nativeObj, "length"); 993 var reimplDesc = ReimplTest.getDescriptor(reimplObj, "length"); 994 try 995 { 996 compareDescriptors(nativeDesc, reimplDesc); 997 } 998 catch (e) 999 { 1000 this._log("Difference comparing returned descriptors for " + 1001 "Function.length with descriptor " + desc.toSource() + 1002 "; error: " + e); 1003 return; 1004 } 1005 } 1006 }; 1007 1008 function runDictionaryPropertyPresentTestsFraction(PART, PARTS) 1009 { 1010 var testfile = 1011 '15.2.3.6-dictionary-redefinition-' + PART + '-of-' + PARTS + '.js'; 1012 var BUGNUMBER = 560566; 1013 var summary = 1014 'ES5 Object.defineProperty(O, P, Attributes): dictionary redefinition ' + 1015 PART + ' of ' + PARTS; 1016 1017 print(BUGNUMBER + ": " + summary); 1018 1019 try 1020 { 1021 new TestRunner().runDictionaryPropertyPresentTestsFraction(PART, PARTS); 1022 } 1023 catch (e) 1024 { 1025 throw "Error thrown during testing: " + e + 1026 " at line " + e.lineNumber + "\n" + 1027 (e.stack 1028 ? "Stack: " + e.stack.split("\n").slice(2).join("\n") + "\n" 1029 : ""); 1030 } 1031 1032 if (typeof reportCompare === "function") 1033 reportCompare(true, true); 1034 1035 print("Tests complete!"); 1036 } 1037 1038 function runNonTerminalPropertyPresentTestsFraction(PART, PARTS) 1039 { 1040 var BUGNUMBER = 560566; 1041 var summary = 1042 'ES5 Object.defineProperty(O, P, Attributes): middle redefinition ' + 1043 PART + ' of ' + PARTS; 1044 1045 print(BUGNUMBER + ": " + summary); 1046 1047 1048 /************** 1049 * BEGIN TEST * 1050 **************/ 1051 1052 try 1053 { 1054 new TestRunner().runNonTerminalPropertyPresentTestsFraction(PART, PARTS); 1055 } 1056 catch (e) 1057 { 1058 throw "Error thrown during testing: " + e + 1059 " at line " + e.lineNumber + "\n" + 1060 (e.stack 1061 ? "Stack: " + e.stack.split("\n").slice(2).join("\n") + "\n" 1062 : ""); 1063 } 1064 1065 /******************************************************************************/ 1066 1067 if (typeof reportCompare === "function") 1068 reportCompare(true, true); 1069 1070 print("Tests complete!"); 1071 }