OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 { object: obj, name: prop, type: "new" }, | 448 { object: obj, name: prop, type: "new" }, |
449 { object: obj, name: prop, type: "reconfigured" }, | 449 { object: obj, name: prop, type: "reconfigured" }, |
450 { object: obj, name: prop, type: "updated", oldValue: 9 }, | 450 { object: obj, name: prop, type: "updated", oldValue: 9 }, |
451 { object: obj, name: prop, type: "deleted", oldValue: 10 }, | 451 { object: obj, name: prop, type: "deleted", oldValue: 10 }, |
452 { object: obj, name: prop, type: "new" }, | 452 { object: obj, name: prop, type: "new" }, |
453 ]); | 453 ]); |
454 Object.unobserve(obj, observer.callback); | 454 Object.unobserve(obj, observer.callback); |
455 delete obj[prop]; | 455 delete obj[prop]; |
456 } | 456 } |
457 | 457 |
458 function TestObserveNonConfigurable(obj, prop) { | 458 function TestObserveNonConfigurable(obj, prop, desc) { |
459 reset(); | 459 reset(); |
460 obj[prop] = 1; | 460 obj[prop] = 1; |
461 Object.observe(obj, observer.callback); | 461 Object.observe(obj, observer.callback); |
462 obj[prop] = 4; | 462 obj[prop] = 4; |
463 obj[prop] = 4; // ignored | 463 obj[prop] = 4; // ignored |
464 obj[prop] = 5; | 464 obj[prop] = 5; |
465 Object.defineProperty(obj, prop, {value: 6}); | 465 Object.defineProperty(obj, prop, {value: 6}); |
466 Object.defineProperty(obj, prop, {value: 6}); // ignored | 466 Object.defineProperty(obj, prop, {value: 6}); // ignored |
467 Object.defineProperty(obj, prop, {value: 7}); | 467 Object.defineProperty(obj, prop, {value: 7}); |
468 Object.defineProperty(obj, prop, {enumerable: true}); // ignored | 468 Object.defineProperty(obj, prop, |
| 469 {enumerable: desc.enumerable}); // ignored |
469 Object.defineProperty(obj, prop, {writable: false}); | 470 Object.defineProperty(obj, prop, {writable: false}); |
470 obj[prop] = 7; // ignored | 471 obj[prop] = 7; // ignored |
471 Object.defineProperty(obj, prop, {get: function() {}}); // ignored | |
472 Object.deliverChangeRecords(observer.callback); | 472 Object.deliverChangeRecords(observer.callback); |
473 observer.assertCallbackRecords([ | 473 observer.assertCallbackRecords([ |
474 { object: obj, name: prop, type: "updated", oldValue: 1 }, | 474 { object: obj, name: prop, type: "updated", oldValue: 1 }, |
475 { object: obj, name: prop, type: "updated", oldValue: 4 }, | 475 { object: obj, name: prop, type: "updated", oldValue: 4 }, |
476 { object: obj, name: prop, type: "updated", oldValue: 5 }, | 476 { object: obj, name: prop, type: "updated", oldValue: 5 }, |
477 { object: obj, name: prop, type: "updated", oldValue: 6 }, | 477 { object: obj, name: prop, type: "updated", oldValue: 6 }, |
478 { object: obj, name: prop, type: "reconfigured", oldValue: 7 }, | 478 { object: obj, name: prop, type: "reconfigured", oldValue: 7 }, |
479 ]); | 479 ]); |
480 Object.unobserve(obj, observer.callback); | 480 Object.unobserve(obj, observer.callback); |
481 } | 481 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 ]; | 537 ]; |
538 var properties = ["a", "1", 1, "length", "prototype"]; | 538 var properties = ["a", "1", 1, "length", "prototype"]; |
539 | 539 |
540 // Cases that yield non-standard results. | 540 // Cases that yield non-standard results. |
541 // TODO(observe): ...or don't work yet. | 541 // TODO(observe): ...or don't work yet. |
542 function blacklisted(obj, prop) { | 542 function blacklisted(obj, prop) { |
543 return (obj instanceof Int32Array && prop == 1) || | 543 return (obj instanceof Int32Array && prop == 1) || |
544 (obj instanceof Int32Array && prop === "length") || | 544 (obj instanceof Int32Array && prop === "length") || |
545 (obj instanceof ArrayBuffer && prop == 1) || | 545 (obj instanceof ArrayBuffer && prop == 1) || |
546 // TODO(observe): oldValue when reconfiguring array length | 546 // TODO(observe): oldValue when reconfiguring array length |
547 (obj instanceof Array && prop === "length") || | 547 (obj instanceof Array && prop === "length") |
548 // TODO(observe): prototype property on functions | |
549 (obj instanceof Function && prop === "prototype") | |
550 } | 548 } |
551 | 549 |
552 for (var i in objects) for (var j in properties) { | 550 for (var i in objects) for (var j in properties) { |
553 var obj = objects[i]; | 551 var obj = objects[i]; |
554 var prop = properties[j]; | 552 var prop = properties[j]; |
555 if (blacklisted(obj, prop)) continue; | 553 if (blacklisted(obj, prop)) continue; |
556 var desc = Object.getOwnPropertyDescriptor(obj, prop); | 554 var desc = Object.getOwnPropertyDescriptor(obj, prop); |
557 print("***", typeof obj, stringifyNoThrow(obj), prop); | 555 print("***", typeof obj, stringifyNoThrow(obj), prop); |
558 if (!desc || desc.configurable) | 556 if (!desc || desc.configurable) |
559 TestObserveConfigurable(obj, prop); | 557 TestObserveConfigurable(obj, prop); |
560 else if (desc.writable) | 558 else if (desc.writable) |
561 TestObserveNonConfigurable(obj, prop); | 559 TestObserveNonConfigurable(obj, prop, desc); |
562 } | 560 } |
563 | 561 |
564 | 562 |
565 // Observing array length (including truncation) | 563 // Observing array length (including truncation) |
566 reset(); | 564 reset(); |
567 var arr = ['a', 'b', 'c', 'd']; | 565 var arr = ['a', 'b', 'c', 'd']; |
568 var arr2 = ['alpha', 'beta']; | 566 var arr2 = ['alpha', 'beta']; |
569 var arr3 = ['hello']; | 567 var arr3 = ['hello']; |
570 arr3[2] = 'goodbye'; | 568 arr3[2] = 'goodbye'; |
571 arr3.length = 6; | 569 arr3.length = 6; |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 Object.unobserve(dummy, observer.callback); | 808 Object.unobserve(dummy, observer.callback); |
811 var array = [0]; | 809 var array = [0]; |
812 Object.observe(array, observer.callback); | 810 Object.observe(array, observer.callback); |
813 array.splice(0, 1); | 811 array.splice(0, 1); |
814 Object.deliverChangeRecords(observer.callback); | 812 Object.deliverChangeRecords(observer.callback); |
815 observer.assertCallbackRecords([ | 813 observer.assertCallbackRecords([ |
816 { object: array, name: '0', type: 'deleted', oldValue: 0 }, | 814 { object: array, name: '0', type: 'deleted', oldValue: 0 }, |
817 { object: array, name: 'length', type: 'updated', oldValue: 1}, | 815 { object: array, name: 'length', type: 'updated', oldValue: 1}, |
818 ]); | 816 ]); |
819 | 817 |
| 818 |
820 // __proto__ | 819 // __proto__ |
821 reset(); | 820 reset(); |
822 var obj = {}; | 821 var obj = {}; |
823 Object.observe(obj, observer.callback); | 822 Object.observe(obj, observer.callback); |
824 var p = {foo: 'yes'}; | 823 var p = {foo: 'yes'}; |
825 var q = {bar: 'no'}; | 824 var q = {bar: 'no'}; |
826 obj.__proto__ = p; | 825 obj.__proto__ = p; |
827 obj.__proto__ = p; // ignored | 826 obj.__proto__ = p; // ignored |
828 obj.__proto__ = null; | 827 obj.__proto__ = null; |
829 obj.__proto__ = q; | 828 obj.__proto__ = q; |
830 // TODO(adamk): Add tests for objects with hidden prototypes | 829 // TODO(adamk): Add tests for objects with hidden prototypes |
831 // once we support observing the global object. | 830 // once we support observing the global object. |
832 Object.deliverChangeRecords(observer.callback); | 831 Object.deliverChangeRecords(observer.callback); |
833 observer.assertCallbackRecords([ | 832 observer.assertCallbackRecords([ |
834 { object: obj, name: '__proto__', type: 'prototype', | 833 { object: obj, name: '__proto__', type: 'prototype', |
835 oldValue: Object.prototype }, | 834 oldValue: Object.prototype }, |
836 { object: obj, name: '__proto__', type: 'prototype', oldValue: p }, | 835 { object: obj, name: '__proto__', type: 'prototype', oldValue: p }, |
837 { object: obj, name: '__proto__', type: 'prototype', oldValue: null }, | 836 { object: obj, name: '__proto__', type: 'prototype', oldValue: null }, |
838 ]); | 837 ]); |
| 838 |
| 839 // Function.prototype |
| 840 reset(); |
| 841 var fun = function(){}; |
| 842 Object.observe(fun, observer.callback); |
| 843 var myproto = {foo: 'bar'}; |
| 844 fun.prototype = myproto; |
| 845 fun.prototype = 7; |
| 846 fun.prototype = 7; // ignored |
| 847 Object.defineProperty(fun, 'prototype', {value: 8}); |
| 848 Object.deliverChangeRecords(observer.callback); |
| 849 observer.assertRecordCount(3); |
| 850 // Manually examine the first record in order to test |
| 851 // lazy creation of oldValue |
| 852 assertSame(fun, observer.records[0].object); |
| 853 assertEquals('prototype', observer.records[0].name); |
| 854 assertEquals('updated', observer.records[0].type); |
| 855 // The only existing reference to the oldValue object is in this |
| 856 // record, so to test that lazy creation happened correctly |
| 857 // we compare its constructor to our function (one of the invariants |
| 858 // ensured when creating an object via AllocateFunctionPrototype). |
| 859 assertSame(fun, observer.records[0].oldValue.constructor); |
| 860 observer.records.splice(0, 1); |
| 861 observer.assertCallbackRecords([ |
| 862 { object: fun, name: 'prototype', type: 'updated', oldValue: myproto }, |
| 863 { object: fun, name: 'prototype', type: 'updated', oldValue: 7 }, |
| 864 ]); |
| 865 |
| 866 // Function.prototype should not be observable except on the object itself |
| 867 reset(); |
| 868 var fun = function(){}; |
| 869 var obj = { __proto__: fun }; |
| 870 Object.observe(obj, observer.callback); |
| 871 obj.prototype = 7; |
| 872 Object.deliverChangeRecords(observer.callback); |
| 873 observer.assertNotCalled(); |
OLD | NEW |