Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(599)

Unified Diff: test/mjsunit/harmony/object-observe.js

Issue 198383002: Reland "Enable Object.observe by default" again (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/mjsunit/es7/object-observe.js ('k') | test/webkit/fast/js/Object-getOwnPropertyNames-expected.txt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/mjsunit/harmony/object-observe.js
diff --git a/test/mjsunit/harmony/object-observe.js b/test/mjsunit/harmony/object-observe.js
deleted file mode 100644
index fb15a1fa835a06f5211f880938dbe1be03901c57..0000000000000000000000000000000000000000
--- a/test/mjsunit/harmony/object-observe.js
+++ /dev/null
@@ -1,1789 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-observation --harmony-proxies --harmony-collections
-// Flags: --harmony-symbols --allow-natives-syntax
-
-var allObservers = [];
-function reset() {
- allObservers.forEach(function(observer) { observer.reset(); });
-}
-
-function stringifyNoThrow(arg) {
- try {
- return JSON.stringify(arg);
- } catch (e) {
- return '{<circular reference>}';
- }
-}
-
-function createObserver() {
- "use strict"; // So that |this| in callback can be undefined.
-
- var observer = {
- records: undefined,
- callbackCount: 0,
- reset: function() {
- this.records = undefined;
- this.callbackCount = 0;
- },
- assertNotCalled: function() {
- assertEquals(undefined, this.records);
- assertEquals(0, this.callbackCount);
- },
- assertCalled: function() {
- assertEquals(1, this.callbackCount);
- },
- assertRecordCount: function(count) {
- this.assertCalled();
- assertEquals(count, this.records.length);
- },
- assertCallbackRecords: function(recs) {
- this.assertRecordCount(recs.length);
- for (var i = 0; i < recs.length; i++) {
- if ('name' in recs[i]) recs[i].name = String(recs[i].name);
- print(i, stringifyNoThrow(this.records[i]), stringifyNoThrow(recs[i]));
- assertSame(this.records[i].object, recs[i].object);
- assertEquals('string', typeof recs[i].type);
- assertPropertiesEqual(this.records[i], recs[i]);
- }
- }
- };
-
- observer.callback = function(r) {
- assertEquals(undefined, this);
- assertEquals('object', typeof r);
- assertTrue(r instanceof Array)
- observer.records = r;
- observer.callbackCount++;
- };
-
- observer.reset();
- allObservers.push(observer);
- return observer;
-}
-
-var observer = createObserver();
-var observer2 = createObserver();
-
-assertEquals("function", typeof observer.callback);
-assertEquals("function", typeof observer2.callback);
-
-var obj = {};
-
-function frozenFunction() {}
-Object.freeze(frozenFunction);
-var nonFunction = {};
-var changeRecordWithAccessor = { type: 'foo' };
-var recordCreated = false;
-Object.defineProperty(changeRecordWithAccessor, 'name', {
- get: function() {
- recordCreated = true;
- return "bar";
- },
- enumerable: true
-})
-
-
-// Object.observe
-assertThrows(function() { Object.observe("non-object", observer.callback); },
- TypeError);
-assertThrows(function() { Object.observe(obj, nonFunction); }, TypeError);
-assertThrows(function() { Object.observe(obj, frozenFunction); }, TypeError);
-assertEquals(obj, Object.observe(obj, observer.callback, [1]));
-assertEquals(obj, Object.observe(obj, observer.callback, [true]));
-assertEquals(obj, Object.observe(obj, observer.callback, ['foo', null]));
-assertEquals(obj, Object.observe(obj, observer.callback, [undefined]));
-assertEquals(obj, Object.observe(obj, observer.callback,
- ['foo', 'bar', 'baz']));
-assertEquals(obj, Object.observe(obj, observer.callback, []));
-assertEquals(obj, Object.observe(obj, observer.callback, undefined));
-assertEquals(obj, Object.observe(obj, observer.callback));
-
-// Object.unobserve
-assertThrows(function() { Object.unobserve(4, observer.callback); }, TypeError);
-assertThrows(function() { Object.unobserve(obj, nonFunction); }, TypeError);
-assertEquals(obj, Object.unobserve(obj, observer.callback));
-
-
-// Object.getNotifier
-var notifier = Object.getNotifier(obj);
-assertSame(notifier, Object.getNotifier(obj));
-assertEquals(null, Object.getNotifier(Object.freeze({})));
-assertFalse(notifier.hasOwnProperty('notify'));
-assertEquals([], Object.keys(notifier));
-var notifyDesc = Object.getOwnPropertyDescriptor(notifier.__proto__, 'notify');
-assertTrue(notifyDesc.configurable);
-assertTrue(notifyDesc.writable);
-assertFalse(notifyDesc.enumerable);
-assertThrows(function() { notifier.notify({}); }, TypeError);
-assertThrows(function() { notifier.notify({ type: 4 }); }, TypeError);
-
-assertThrows(function() { notifier.performChange(1, function(){}); }, TypeError);
-assertThrows(function() { notifier.performChange(undefined, function(){}); }, TypeError);
-assertThrows(function() { notifier.performChange('foo', undefined); }, TypeError);
-assertThrows(function() { notifier.performChange('foo', 'bar'); }, TypeError);
-var global = this;
-notifier.performChange('foo', function() {
- assertEquals(global, this);
-});
-
-var notify = notifier.notify;
-assertThrows(function() { notify.call(undefined, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call(null, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call(5, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call('hello', { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call(false, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call({}, { type: 'a' }); }, TypeError);
-assertFalse(recordCreated);
-notifier.notify(changeRecordWithAccessor);
-assertFalse(recordCreated); // not observed yet
-
-
-// Object.deliverChangeRecords
-assertThrows(function() { Object.deliverChangeRecords(nonFunction); }, TypeError);
-
-Object.observe(obj, observer.callback);
-
-
-// notify uses to [[CreateOwnProperty]] to create changeRecord;
-reset();
-var protoExpandoAccessed = false;
-Object.defineProperty(Object.prototype, 'protoExpando',
- {
- configurable: true,
- set: function() { protoExpandoAccessed = true; }
- }
-);
-notifier.notify({ type: 'foo', protoExpando: 'val'});
-assertFalse(protoExpandoAccessed);
-delete Object.prototype.protoExpando;
-Object.deliverChangeRecords(observer.callback);
-
-
-// Multiple records are delivered.
-reset();
-notifier.notify({
- type: 'update',
- name: 'foo',
- expando: 1
-});
-
-notifier.notify({
- object: notifier, // object property is ignored
- type: 'delete',
- name: 'bar',
- expando2: 'str'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: 'foo', type: 'update', expando: 1 },
- { object: obj, name: 'bar', type: 'delete', expando2: 'str' }
-]);
-
-// Non-string accept values are coerced to strings
-reset();
-Object.observe(obj, observer.callback, [true, 1, null, undefined]);
-notifier = Object.getNotifier(obj);
-notifier.notify({ type: 'true' });
-notifier.notify({ type: 'false' });
-notifier.notify({ type: '1' });
-notifier.notify({ type: '-1' });
-notifier.notify({ type: 'null' });
-notifier.notify({ type: 'nill' });
-notifier.notify({ type: 'undefined' });
-notifier.notify({ type: 'defined' });
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'true' },
- { object: obj, type: '1' },
- { object: obj, type: 'null' },
- { object: obj, type: 'undefined' }
-]);
-
-// No delivery takes place if no records are pending
-reset();
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Multiple observation has no effect.
-reset();
-Object.observe(obj, observer.callback);
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCalled();
-
-
-// Observation can be stopped.
-reset();
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Multiple unobservation has no effect
-reset();
-Object.unobserve(obj, observer.callback);
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Re-observation works and only includes changeRecords after of call.
-reset();
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-records = undefined;
-Object.deliverChangeRecords(observer.callback);
-observer.assertRecordCount(1);
-
-// Get notifier prior to observing
-reset();
-var obj = {};
-Object.getNotifier(obj);
-Object.observe(obj, observer.callback);
-obj.id = 1;
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add', name: 'id' },
-]);
-
-// The empty-string property is observable
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-obj[''] = '';
-obj[''] = ' ';
-delete obj[''];
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add', name: '' },
- { object: obj, type: 'update', name: '', oldValue: '' },
- { object: obj, type: 'delete', name: '', oldValue: ' ' },
-]);
-
-// Object.preventExtensions
-reset();
-var obj = { foo: 'bar'};
-Object.observe(obj, observer.callback);
-obj.baz = 'bat';
-Object.preventExtensions(obj);
-
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add', name: 'baz' },
- { object: obj, type: 'preventExtensions' },
-]);
-
-reset();
-var obj = { foo: 'bar'};
-Object.preventExtensions(obj);
-Object.observe(obj, observer.callback);
-Object.preventExtensions(obj);
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-// Object.freeze
-reset();
-var obj = { a: 'a' };
-Object.defineProperty(obj, 'b', {
- writable: false,
- configurable: true,
- value: 'b'
-});
-Object.defineProperty(obj, 'c', {
- writable: true,
- configurable: false,
- value: 'c'
-});
-Object.defineProperty(obj, 'd', {
- writable: false,
- configurable: false,
- value: 'd'
-});
-Object.observe(obj, observer.callback);
-Object.freeze(obj);
-
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'reconfigure', name: 'a' },
- { object: obj, type: 'reconfigure', name: 'b' },
- { object: obj, type: 'reconfigure', name: 'c' },
- { object: obj, type: 'preventExtensions' },
-]);
-
-reset();
-var obj = { foo: 'bar'};
-Object.freeze(obj);
-Object.observe(obj, observer.callback);
-Object.freeze(obj);
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-// Object.seal
-reset();
-var obj = { a: 'a' };
-Object.defineProperty(obj, 'b', {
- writable: false,
- configurable: true,
- value: 'b'
-});
-Object.defineProperty(obj, 'c', {
- writable: true,
- configurable: false,
- value: 'c'
-});
-Object.defineProperty(obj, 'd', {
- writable: false,
- configurable: false,
- value: 'd'
-});
-Object.observe(obj, observer.callback);
-Object.seal(obj);
-
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'reconfigure', name: 'a' },
- { object: obj, type: 'reconfigure', name: 'b' },
- { object: obj, type: 'preventExtensions' },
-]);
-
-reset();
-var obj = { foo: 'bar'};
-Object.seal(obj);
-Object.observe(obj, observer.callback);
-Object.seal(obj);
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-// Observing a continuous stream of changes, while itermittantly unobserving.
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 1
-});
-
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 2
-});
-
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 3
-});
-
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 4
-});
-
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 5
-});
-
-Object.unobserve(obj, observer.callback);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'update', val: 1 },
- { object: obj, type: 'update', val: 3 },
- { object: obj, type: 'update', val: 5 }
-]);
-
-// Accept
-reset();
-Object.observe(obj, observer.callback, ['somethingElse']);
-Object.getNotifier(obj).notify({
- type: 'add'
-});
-Object.getNotifier(obj).notify({
- type: 'update'
-});
-Object.getNotifier(obj).notify({
- type: 'delete'
-});
-Object.getNotifier(obj).notify({
- type: 'reconfigure'
-});
-Object.getNotifier(obj).notify({
- type: 'setPrototype'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-reset();
-Object.observe(obj, observer.callback, ['add', 'delete', 'setPrototype']);
-Object.getNotifier(obj).notify({
- type: 'add'
-});
-Object.getNotifier(obj).notify({
- type: 'update'
-});
-Object.getNotifier(obj).notify({
- type: 'delete'
-});
-Object.getNotifier(obj).notify({
- type: 'delete'
-});
-Object.getNotifier(obj).notify({
- type: 'reconfigure'
-});
-Object.getNotifier(obj).notify({
- type: 'setPrototype'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add' },
- { object: obj, type: 'delete' },
- { object: obj, type: 'delete' },
- { object: obj, type: 'setPrototype' }
-]);
-
-reset();
-Object.observe(obj, observer.callback, ['update', 'foo']);
-Object.getNotifier(obj).notify({
- type: 'add'
-});
-Object.getNotifier(obj).notify({
- type: 'update'
-});
-Object.getNotifier(obj).notify({
- type: 'delete'
-});
-Object.getNotifier(obj).notify({
- type: 'foo'
-});
-Object.getNotifier(obj).notify({
- type: 'bar'
-});
-Object.getNotifier(obj).notify({
- type: 'foo'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'update' },
- { object: obj, type: 'foo' },
- { object: obj, type: 'foo' }
-]);
-
-reset();
-function Thingy(a, b, c) {
- this.a = a;
- this.b = b;
-}
-
-Thingy.MULTIPLY = 'multiply';
-Thingy.INCREMENT = 'increment';
-Thingy.INCREMENT_AND_MULTIPLY = 'incrementAndMultiply';
-
-Thingy.prototype = {
- increment: function(amount) {
- var notifier = Object.getNotifier(this);
-
- var self = this;
- notifier.performChange(Thingy.INCREMENT, function() {
- self.a += amount;
- self.b += amount;
-
- return {
- incremented: amount
- }; // implicit notify
- });
- },
-
- multiply: function(amount) {
- var notifier = Object.getNotifier(this);
-
- var self = this;
- notifier.performChange(Thingy.MULTIPLY, function() {
- self.a *= amount;
- self.b *= amount;
-
- return {
- multiplied: amount
- }; // implicit notify
- });
- },
-
- incrementAndMultiply: function(incAmount, multAmount) {
- var notifier = Object.getNotifier(this);
-
- var self = this;
- notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() {
- self.increment(incAmount);
- self.multiply(multAmount);
-
- return {
- incremented: incAmount,
- multiplied: multAmount
- }; // implicit notify
- });
- }
-}
-
-Thingy.observe = function(thingy, callback) {
- Object.observe(thingy, callback, [Thingy.INCREMENT,
- Thingy.MULTIPLY,
- Thingy.INCREMENT_AND_MULTIPLY,
- 'update']);
-}
-
-Thingy.unobserve = function(thingy, callback) {
- Object.unobserve(thingy);
-}
-
-var thingy = new Thingy(2, 4);
-
-Object.observe(thingy, observer.callback);
-Thingy.observe(thingy, observer2.callback);
-thingy.increment(3); // { a: 5, b: 7 }
-thingy.b++; // { a: 5, b: 8 }
-thingy.multiply(2); // { a: 10, b: 16 }
-thingy.a++; // { a: 11, b: 16 }
-thingy.incrementAndMultiply(2, 2); // { a: 26, b: 36 }
-
-Object.deliverChangeRecords(observer.callback);
-Object.deliverChangeRecords(observer2.callback);
-observer.assertCallbackRecords([
- { object: thingy, type: 'update', name: 'a', oldValue: 2 },
- { object: thingy, type: 'update', name: 'b', oldValue: 4 },
- { object: thingy, type: 'update', name: 'b', oldValue: 7 },
- { object: thingy, type: 'update', name: 'a', oldValue: 5 },
- { object: thingy, type: 'update', name: 'b', oldValue: 8 },
- { object: thingy, type: 'update', name: 'a', oldValue: 10 },
- { object: thingy, type: 'update', name: 'a', oldValue: 11 },
- { object: thingy, type: 'update', name: 'b', oldValue: 16 },
- { object: thingy, type: 'update', name: 'a', oldValue: 13 },
- { object: thingy, type: 'update', name: 'b', oldValue: 18 },
-]);
-observer2.assertCallbackRecords([
- { object: thingy, type: Thingy.INCREMENT, incremented: 3 },
- { object: thingy, type: 'update', name: 'b', oldValue: 7 },
- { object: thingy, type: Thingy.MULTIPLY, multiplied: 2 },
- { object: thingy, type: 'update', name: 'a', oldValue: 10 },
- {
- object: thingy,
- type: Thingy.INCREMENT_AND_MULTIPLY,
- incremented: 2,
- multiplied: 2
- }
-]);
-
-// ArrayPush cached stub
-reset();
-
-function pushMultiple(arr) {
- arr.push('a');
- arr.push('b');
- arr.push('c');
-}
-
-for (var i = 0; i < 5; i++) {
- var arr = [];
- pushMultiple(arr);
-}
-
-for (var i = 0; i < 5; i++) {
- reset();
- var arr = [];
- Object.observe(arr, observer.callback);
- pushMultiple(arr);
- Object.unobserve(arr, observer.callback);
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: arr, type: 'add', name: '0' },
- { object: arr, type: 'update', name: 'length', oldValue: 0 },
- { object: arr, type: 'add', name: '1' },
- { object: arr, type: 'update', name: 'length', oldValue: 1 },
- { object: arr, type: 'add', name: '2' },
- { object: arr, type: 'update', name: 'length', oldValue: 2 },
- ]);
-}
-
-
-// ArrayPop cached stub
-reset();
-
-function popMultiple(arr) {
- arr.pop();
- arr.pop();
- arr.pop();
-}
-
-for (var i = 0; i < 5; i++) {
- var arr = ['a', 'b', 'c'];
- popMultiple(arr);
-}
-
-for (var i = 0; i < 5; i++) {
- reset();
- var arr = ['a', 'b', 'c'];
- Object.observe(arr, observer.callback);
- popMultiple(arr);
- Object.unobserve(arr, observer.callback);
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: arr, type: 'delete', name: '2', oldValue: 'c' },
- { object: arr, type: 'update', name: 'length', oldValue: 3 },
- { object: arr, type: 'delete', name: '1', oldValue: 'b' },
- { object: arr, type: 'update', name: 'length', oldValue: 2 },
- { object: arr, type: 'delete', name: '0', oldValue: 'a' },
- { object: arr, type: 'update', name: 'length', oldValue: 1 },
- ]);
-}
-
-
-reset();
-function RecursiveThingy() {}
-
-RecursiveThingy.MULTIPLY_FIRST_N = 'multiplyFirstN';
-
-RecursiveThingy.prototype = {
- __proto__: Array.prototype,
-
- multiplyFirstN: function(amount, n) {
- if (!n)
- return;
- var notifier = Object.getNotifier(this);
- var self = this;
- notifier.performChange(RecursiveThingy.MULTIPLY_FIRST_N, function() {
- self[n-1] = self[n-1]*amount;
- self.multiplyFirstN(amount, n-1);
- });
-
- notifier.notify({
- type: RecursiveThingy.MULTIPLY_FIRST_N,
- multiplied: amount,
- n: n
- });
- },
-}
-
-RecursiveThingy.observe = function(thingy, callback) {
- Object.observe(thingy, callback, [RecursiveThingy.MULTIPLY_FIRST_N]);
-}
-
-RecursiveThingy.unobserve = function(thingy, callback) {
- Object.unobserve(thingy);
-}
-
-var thingy = new RecursiveThingy;
-thingy.push(1, 2, 3, 4);
-
-Object.observe(thingy, observer.callback);
-RecursiveThingy.observe(thingy, observer2.callback);
-thingy.multiplyFirstN(2, 3); // [2, 4, 6, 4]
-
-Object.deliverChangeRecords(observer.callback);
-Object.deliverChangeRecords(observer2.callback);
-observer.assertCallbackRecords([
- { object: thingy, type: 'update', name: '2', oldValue: 3 },
- { object: thingy, type: 'update', name: '1', oldValue: 2 },
- { object: thingy, type: 'update', name: '0', oldValue: 1 }
-]);
-observer2.assertCallbackRecords([
- { object: thingy, type: RecursiveThingy.MULTIPLY_FIRST_N, multiplied: 2, n: 3 }
-]);
-
-reset();
-function DeckSuit() {
- this.push('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'A', 'Q', 'K');
-}
-
-DeckSuit.SHUFFLE = 'shuffle';
-
-DeckSuit.prototype = {
- __proto__: Array.prototype,
-
- shuffle: function() {
- var notifier = Object.getNotifier(this);
- var self = this;
- notifier.performChange(DeckSuit.SHUFFLE, function() {
- self.reverse();
- self.sort(function() { return Math.random()* 2 - 1; });
- var cut = self.splice(0, 6);
- Array.prototype.push.apply(self, cut);
- self.reverse();
- self.sort(function() { return Math.random()* 2 - 1; });
- var cut = self.splice(0, 6);
- Array.prototype.push.apply(self, cut);
- self.reverse();
- self.sort(function() { return Math.random()* 2 - 1; });
- });
-
- notifier.notify({
- type: DeckSuit.SHUFFLE
- });
- },
-}
-
-DeckSuit.observe = function(thingy, callback) {
- Object.observe(thingy, callback, [DeckSuit.SHUFFLE]);
-}
-
-DeckSuit.unobserve = function(thingy, callback) {
- Object.unobserve(thingy);
-}
-
-var deck = new DeckSuit;
-
-DeckSuit.observe(deck, observer2.callback);
-deck.shuffle();
-
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: deck, type: DeckSuit.SHUFFLE }
-]);
-
-// Observing multiple objects; records appear in order.
-reset();
-var obj2 = {};
-var obj3 = {}
-Object.observe(obj, observer.callback);
-Object.observe(obj3, observer.callback);
-Object.observe(obj2, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'add',
-});
-Object.getNotifier(obj2).notify({
- type: 'update',
-});
-Object.getNotifier(obj3).notify({
- type: 'delete',
-});
-Object.observe(obj3, observer.callback);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add' },
- { object: obj2, type: 'update' },
- { object: obj3, type: 'delete' }
-]);
-
-
-// Recursive observation.
-var obj = {a: 1};
-var callbackCount = 0;
-function recursiveObserver(r) {
- assertEquals(1, r.length);
- ++callbackCount;
- if (r[0].oldValue < 100) ++obj[r[0].name];
-}
-Object.observe(obj, recursiveObserver);
-++obj.a;
-Object.deliverChangeRecords(recursiveObserver);
-assertEquals(100, callbackCount);
-
-var obj1 = {a: 1};
-var obj2 = {a: 1};
-var recordCount = 0;
-function recursiveObserver2(r) {
- recordCount += r.length;
- if (r[0].oldValue < 100) {
- ++obj1.a;
- ++obj2.a;
- }
-}
-Object.observe(obj1, recursiveObserver2);
-Object.observe(obj2, recursiveObserver2);
-++obj1.a;
-Object.deliverChangeRecords(recursiveObserver2);
-assertEquals(199, recordCount);
-
-
-// Observing named properties.
-reset();
-var obj = {a: 1}
-Object.observe(obj, observer.callback);
-obj.a = 2;
-obj["a"] = 3;
-delete obj.a;
-obj.a = 4;
-obj.a = 4; // ignored
-obj.a = 5;
-Object.defineProperty(obj, "a", {value: 6});
-Object.defineProperty(obj, "a", {writable: false});
-obj.a = 7; // ignored
-Object.defineProperty(obj, "a", {value: 8});
-Object.defineProperty(obj, "a", {value: 7, writable: true});
-Object.defineProperty(obj, "a", {get: function() {}});
-Object.defineProperty(obj, "a", {get: frozenFunction});
-Object.defineProperty(obj, "a", {get: frozenFunction}); // ignored
-Object.defineProperty(obj, "a", {get: frozenFunction, set: frozenFunction});
-Object.defineProperty(obj, "a", {set: frozenFunction}); // ignored
-Object.defineProperty(obj, "a", {get: undefined, set: frozenFunction});
-delete obj.a;
-delete obj.a;
-Object.defineProperty(obj, "a", {get: function() {}, configurable: true});
-Object.defineProperty(obj, "a", {value: 9, writable: true});
-obj.a = 10;
-++obj.a;
-obj.a++;
-obj.a *= 3;
-delete obj.a;
-Object.defineProperty(obj, "a", {value: 11, configurable: true});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: "a", type: "update", oldValue: 1 },
- { object: obj, name: "a", type: "update", oldValue: 2 },
- { object: obj, name: "a", type: "delete", oldValue: 3 },
- { object: obj, name: "a", type: "add" },
- { object: obj, name: "a", type: "update", oldValue: 4 },
- { object: obj, name: "a", type: "update", oldValue: 5 },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "update", oldValue: 6 },
- { object: obj, name: "a", type: "reconfigure", oldValue: 8 },
- { object: obj, name: "a", type: "reconfigure", oldValue: 7 },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "delete" },
- { object: obj, name: "a", type: "add" },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "update", oldValue: 9 },
- { object: obj, name: "a", type: "update", oldValue: 10 },
- { object: obj, name: "a", type: "update", oldValue: 11 },
- { object: obj, name: "a", type: "update", oldValue: 12 },
- { object: obj, name: "a", type: "delete", oldValue: 36 },
- { object: obj, name: "a", type: "add" },
-]);
-
-
-// Observing indexed properties.
-reset();
-var obj = {'1': 1}
-Object.observe(obj, observer.callback);
-obj[1] = 2;
-obj[1] = 3;
-delete obj[1];
-obj[1] = 4;
-obj[1] = 4; // ignored
-obj[1] = 5;
-Object.defineProperty(obj, "1", {value: 6});
-Object.defineProperty(obj, "1", {writable: false});
-obj[1] = 7; // ignored
-Object.defineProperty(obj, "1", {value: 8});
-Object.defineProperty(obj, "1", {value: 7, writable: true});
-Object.defineProperty(obj, "1", {get: function() {}});
-Object.defineProperty(obj, "1", {get: frozenFunction});
-Object.defineProperty(obj, "1", {get: frozenFunction}); // ignored
-Object.defineProperty(obj, "1", {get: frozenFunction, set: frozenFunction});
-Object.defineProperty(obj, "1", {set: frozenFunction}); // ignored
-Object.defineProperty(obj, "1", {get: undefined, set: frozenFunction});
-delete obj[1];
-delete obj[1];
-Object.defineProperty(obj, "1", {get: function() {}, configurable: true});
-Object.defineProperty(obj, "1", {value: 9, writable: true});
-obj[1] = 10;
-++obj[1];
-obj[1]++;
-obj[1] *= 3;
-delete obj[1];
-Object.defineProperty(obj, "1", {value: 11, configurable: true});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: "1", type: "update", oldValue: 1 },
- { object: obj, name: "1", type: "update", oldValue: 2 },
- { object: obj, name: "1", type: "delete", oldValue: 3 },
- { object: obj, name: "1", type: "add" },
- { object: obj, name: "1", type: "update", oldValue: 4 },
- { object: obj, name: "1", type: "update", oldValue: 5 },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "update", oldValue: 6 },
- { object: obj, name: "1", type: "reconfigure", oldValue: 8 },
- { object: obj, name: "1", type: "reconfigure", oldValue: 7 },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "delete" },
- { object: obj, name: "1", type: "add" },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "update", oldValue: 9 },
- { object: obj, name: "1", type: "update", oldValue: 10 },
- { object: obj, name: "1", type: "update", oldValue: 11 },
- { object: obj, name: "1", type: "update", oldValue: 12 },
- { object: obj, name: "1", type: "delete", oldValue: 36 },
- { object: obj, name: "1", type: "add" },
-]);
-
-
-// Observing symbol properties (not).
-print("*****")
-reset();
-var obj = {}
-var symbol = Symbol("secret");
-Object.observe(obj, observer.callback);
-obj[symbol] = 3;
-delete obj[symbol];
-Object.defineProperty(obj, symbol, {get: function() {}, configurable: true});
-Object.defineProperty(obj, symbol, {value: 6});
-Object.defineProperty(obj, symbol, {writable: false});
-delete obj[symbol];
-Object.defineProperty(obj, symbol, {value: 7});
-++obj[symbol];
-obj[symbol]++;
-obj[symbol] *= 3;
-delete obj[symbol];
-obj.__defineSetter__(symbol, function() {});
-obj.__defineGetter__(symbol, function() {});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Test all kinds of objects generically.
-function TestObserveConfigurable(obj, prop) {
- reset();
- Object.observe(obj, observer.callback);
- Object.unobserve(obj, observer.callback);
- obj[prop] = 1;
- Object.observe(obj, observer.callback);
- obj[prop] = 2;
- obj[prop] = 3;
- delete obj[prop];
- obj[prop] = 4;
- obj[prop] = 4; // ignored
- obj[prop] = 5;
- Object.defineProperty(obj, prop, {value: 6});
- Object.defineProperty(obj, prop, {writable: false});
- obj[prop] = 7; // ignored
- Object.defineProperty(obj, prop, {value: 8});
- Object.defineProperty(obj, prop, {value: 7, writable: true});
- Object.defineProperty(obj, prop, {get: function() {}});
- Object.defineProperty(obj, prop, {get: frozenFunction});
- Object.defineProperty(obj, prop, {get: frozenFunction}); // ignored
- Object.defineProperty(obj, prop, {get: frozenFunction, set: frozenFunction});
- Object.defineProperty(obj, prop, {set: frozenFunction}); // ignored
- Object.defineProperty(obj, prop, {get: undefined, set: frozenFunction});
- obj.__defineSetter__(prop, frozenFunction); // ignored
- obj.__defineSetter__(prop, function() {});
- obj.__defineGetter__(prop, function() {});
- delete obj[prop];
- delete obj[prop]; // ignored
- obj.__defineGetter__(prop, function() {});
- delete obj[prop];
- Object.defineProperty(obj, prop, {get: function() {}, configurable: true});
- Object.defineProperty(obj, prop, {value: 9, writable: true});
- obj[prop] = 10;
- ++obj[prop];
- obj[prop]++;
- obj[prop] *= 3;
- delete obj[prop];
- Object.defineProperty(obj, prop, {value: 11, configurable: true});
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: obj, name: prop, type: "update", oldValue: 1 },
- { object: obj, name: prop, type: "update", oldValue: 2 },
- { object: obj, name: prop, type: "delete", oldValue: 3 },
- { object: obj, name: prop, type: "add" },
- { object: obj, name: prop, type: "update", oldValue: 4 },
- { object: obj, name: prop, type: "update", oldValue: 5 },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "update", oldValue: 6 },
- { object: obj, name: prop, type: "reconfigure", oldValue: 8 },
- { object: obj, name: prop, type: "reconfigure", oldValue: 7 },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "delete" },
- { object: obj, name: prop, type: "add" },
- { object: obj, name: prop, type: "delete" },
- { object: obj, name: prop, type: "add" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "update", oldValue: 9 },
- { object: obj, name: prop, type: "update", oldValue: 10 },
- { object: obj, name: prop, type: "update", oldValue: 11 },
- { object: obj, name: prop, type: "update", oldValue: 12 },
- { object: obj, name: prop, type: "delete", oldValue: 36 },
- { object: obj, name: prop, type: "add" },
- ]);
- Object.unobserve(obj, observer.callback);
- delete obj[prop];
-}
-
-function TestObserveNonConfigurable(obj, prop, desc) {
- reset();
- Object.observe(obj, observer.callback);
- Object.unobserve(obj, observer.callback);
- obj[prop] = 1;
- Object.observe(obj, observer.callback);
- obj[prop] = 4;
- obj[prop] = 4; // ignored
- obj[prop] = 5;
- Object.defineProperty(obj, prop, {value: 6});
- Object.defineProperty(obj, prop, {value: 6}); // ignored
- Object.defineProperty(obj, prop, {value: 7});
- Object.defineProperty(obj, prop, {enumerable: desc.enumerable}); // ignored
- Object.defineProperty(obj, prop, {writable: false});
- obj[prop] = 7; // ignored
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: obj, name: prop, type: "update", oldValue: 1 },
- { object: obj, name: prop, type: "update", oldValue: 4 },
- { object: obj, name: prop, type: "update", oldValue: 5 },
- { object: obj, name: prop, type: "update", oldValue: 6 },
- { object: obj, name: prop, type: "reconfigure" },
- ]);
- Object.unobserve(obj, observer.callback);
-}
-
-function createProxy(create, x) {
- var handler = {
- getPropertyDescriptor: function(k) {
- for (var o = this.target; o; o = Object.getPrototypeOf(o)) {
- var desc = Object.getOwnPropertyDescriptor(o, k);
- if (desc) return desc;
- }
- return undefined;
- },
- getOwnPropertyDescriptor: function(k) {
- return Object.getOwnPropertyDescriptor(this.target, k);
- },
- defineProperty: function(k, desc) {
- var x = Object.defineProperty(this.target, k, desc);
- Object.deliverChangeRecords(this.callback);
- return x;
- },
- delete: function(k) {
- var x = delete this.target[k];
- Object.deliverChangeRecords(this.callback);
- return x;
- },
- getPropertyNames: function() {
- return Object.getOwnPropertyNames(this.target);
- },
- target: {isProxy: true},
- callback: function(changeRecords) {
- print("callback", stringifyNoThrow(handler.proxy), stringifyNoThrow(got));
- for (var i in changeRecords) {
- var got = changeRecords[i];
- var change = {object: handler.proxy, name: got.name, type: got.type};
- if ("oldValue" in got) change.oldValue = got.oldValue;
- Object.getNotifier(handler.proxy).notify(change);
- }
- },
- };
- Object.observe(handler.target, handler.callback);
- return handler.proxy = create(handler, x);
-}
-
-var objects = [
- {},
- [],
- this, // global object
- function(){},
- (function(){ return arguments })(),
- (function(){ "use strict"; return arguments })(),
- Object(1), Object(true), Object("bla"),
- new Date(),
- Object, Function, Date, RegExp,
- new Set, new Map, new WeakMap,
- new ArrayBuffer(10), new Int32Array(5),
- createProxy(Proxy.create, null),
- createProxy(Proxy.createFunction, function(){}),
-];
-var properties = ["a", "1", 1, "length", "setPrototype", "name", "caller"];
-
-// Cases that yield non-standard results.
-function blacklisted(obj, prop) {
- return (obj instanceof Int32Array && prop == 1) ||
- (obj instanceof Int32Array && prop === "length") ||
- (obj instanceof ArrayBuffer && prop == 1)
-}
-
-for (var i in objects) for (var j in properties) {
- var obj = objects[i];
- var prop = properties[j];
- if (blacklisted(obj, prop)) continue;
- var desc = Object.getOwnPropertyDescriptor(obj, prop);
- print("***", typeof obj, stringifyNoThrow(obj), prop);
- if (!desc || desc.configurable)
- TestObserveConfigurable(obj, prop);
- else if (desc.writable)
- TestObserveNonConfigurable(obj, prop, desc);
-}
-
-
-// Observing array length (including truncation)
-reset();
-var arr = ['a', 'b', 'c', 'd'];
-var arr2 = ['alpha', 'beta'];
-var arr3 = ['hello'];
-arr3[2] = 'goodbye';
-arr3.length = 6;
-Object.defineProperty(arr, '0', {configurable: false});
-Object.defineProperty(arr, '2', {get: function(){}});
-Object.defineProperty(arr2, '0', {get: function(){}, configurable: false});
-Object.observe(arr, observer.callback);
-Array.observe(arr, observer2.callback);
-Object.observe(arr2, observer.callback);
-Array.observe(arr2, observer2.callback);
-Object.observe(arr3, observer.callback);
-Array.observe(arr3, observer2.callback);
-arr.length = 2;
-arr.length = 0;
-arr.length = 10;
-Object.defineProperty(arr, 'length', {writable: false});
-arr2.length = 0;
-arr2.length = 1; // no change expected
-Object.defineProperty(arr2, 'length', {value: 1, writable: false});
-arr3.length = 0;
-++arr3.length;
-arr3.length++;
-arr3.length /= 2;
-Object.defineProperty(arr3, 'length', {value: 5});
-arr3[4] = 5;
-Object.defineProperty(arr3, 'length', {value: 1, writable: false});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: arr, name: '3', type: 'delete', oldValue: 'd' },
- { object: arr, name: '2', type: 'delete' },
- { object: arr, name: 'length', type: 'update', oldValue: 4 },
- { object: arr, name: '1', type: 'delete', oldValue: 'b' },
- { object: arr, name: 'length', type: 'update', oldValue: 2 },
- { object: arr, name: 'length', type: 'update', oldValue: 1 },
- { object: arr, name: 'length', type: 'reconfigure' },
- { object: arr2, name: '1', type: 'delete', oldValue: 'beta' },
- { object: arr2, name: 'length', type: 'update', oldValue: 2 },
- { object: arr2, name: 'length', type: 'reconfigure' },
- { object: arr3, name: '2', type: 'delete', oldValue: 'goodbye' },
- { object: arr3, name: '0', type: 'delete', oldValue: 'hello' },
- { object: arr3, name: 'length', type: 'update', oldValue: 6 },
- { object: arr3, name: 'length', type: 'update', oldValue: 0 },
- { object: arr3, name: 'length', type: 'update', oldValue: 1 },
- { object: arr3, name: 'length', type: 'update', oldValue: 2 },
- { object: arr3, name: 'length', type: 'update', oldValue: 1 },
- { object: arr3, name: '4', type: 'add' },
- { object: arr3, name: '4', type: 'delete', oldValue: 5 },
- // TODO(rafaelw): It breaks spec compliance to get two records here.
- // When the TODO in v8natives.js::DefineArrayProperty is addressed
- // which prevents DefineProperty from over-writing the magic length
- // property, these will collapse into a single record.
- { object: arr3, name: 'length', type: 'update', oldValue: 5 },
- { object: arr3, name: 'length', type: 'reconfigure' }
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: arr, type: 'splice', index: 2, removed: [, 'd'], addedCount: 0 },
- { object: arr, type: 'splice', index: 1, removed: ['b'], addedCount: 0 },
- { object: arr, type: 'splice', index: 1, removed: [], addedCount: 9 },
- { object: arr2, type: 'splice', index: 1, removed: ['beta'], addedCount: 0 },
- { object: arr3, type: 'splice', index: 0, removed: ['hello',, 'goodbye',,,,], addedCount: 0 },
- { object: arr3, type: 'splice', index: 0, removed: [], addedCount: 1 },
- { object: arr3, type: 'splice', index: 1, removed: [], addedCount: 1 },
- { object: arr3, type: 'splice', index: 1, removed: [,], addedCount: 0 },
- { object: arr3, type: 'splice', index: 1, removed: [], addedCount: 4 },
- { object: arr3, name: '4', type: 'add' },
- { object: arr3, type: 'splice', index: 1, removed: [,,,5], addedCount: 0 }
-]);
-
-
-// Updating length on large (slow) array
-reset();
-var slow_arr = new Array(1000000000);
-slow_arr[500000000] = 'hello';
-Object.observe(slow_arr, observer.callback);
-var spliceRecords;
-function slowSpliceCallback(records) {
- spliceRecords = records;
-}
-Array.observe(slow_arr, slowSpliceCallback);
-slow_arr.length = 100;
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: slow_arr, name: '500000000', type: 'delete', oldValue: 'hello' },
- { object: slow_arr, name: 'length', type: 'update', oldValue: 1000000000 },
-]);
-Object.deliverChangeRecords(slowSpliceCallback);
-assertEquals(spliceRecords.length, 1);
-// Have to custom assert this splice record because the removed array is huge.
-var splice = spliceRecords[0];
-assertSame(splice.object, slow_arr);
-assertEquals(splice.type, 'splice');
-assertEquals(splice.index, 100);
-assertEquals(splice.addedCount, 0);
-var array_keys = %GetArrayKeys(splice.removed, splice.removed.length);
-assertEquals(array_keys.length, 1);
-assertEquals(array_keys[0], 499999900);
-assertEquals(splice.removed[499999900], 'hello');
-assertEquals(splice.removed.length, 999999900);
-
-
-// Assignments in loops (checking different IC states).
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-for (var i = 0; i < 5; i++) {
- obj["a" + i] = i;
-}
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: "a0", type: "add" },
- { object: obj, name: "a1", type: "add" },
- { object: obj, name: "a2", type: "add" },
- { object: obj, name: "a3", type: "add" },
- { object: obj, name: "a4", type: "add" },
-]);
-
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-for (var i = 0; i < 5; i++) {
- obj[i] = i;
-}
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: "0", type: "add" },
- { object: obj, name: "1", type: "add" },
- { object: obj, name: "2", type: "add" },
- { object: obj, name: "3", type: "add" },
- { object: obj, name: "4", type: "add" },
-]);
-
-
-// Adding elements past the end of an array should notify on length for
-// Object.observe and emit "splices" for Array.observe.
-reset();
-var arr = [1, 2, 3];
-Object.observe(arr, observer.callback);
-Array.observe(arr, observer2.callback);
-arr[3] = 10;
-arr[100] = 20;
-Object.defineProperty(arr, '200', {value: 7});
-Object.defineProperty(arr, '400', {get: function(){}});
-arr[50] = 30; // no length change expected
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: arr, name: '3', type: 'add' },
- { object: arr, name: 'length', type: 'update', oldValue: 3 },
- { object: arr, name: '100', type: 'add' },
- { object: arr, name: 'length', type: 'update', oldValue: 4 },
- { object: arr, name: '200', type: 'add' },
- { object: arr, name: 'length', type: 'update', oldValue: 101 },
- { object: arr, name: '400', type: 'add' },
- { object: arr, name: 'length', type: 'update', oldValue: 201 },
- { object: arr, name: '50', type: 'add' },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: arr, type: 'splice', index: 3, removed: [], addedCount: 1 },
- { object: arr, type: 'splice', index: 4, removed: [], addedCount: 97 },
- { object: arr, type: 'splice', index: 101, removed: [], addedCount: 100 },
- { object: arr, type: 'splice', index: 201, removed: [], addedCount: 200 },
- { object: arr, type: 'add', name: '50' },
-]);
-
-
-// Tests for array methods, first on arrays and then on plain objects
-//
-// === ARRAYS ===
-//
-// Push
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.push(3, 4);
-array.push(5);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '2', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 3 },
- { object: array, name: '4', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 4 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 2, removed: [], addedCount: 2 },
- { object: array, type: 'splice', index: 4, removed: [], addedCount: 1 }
-]);
-
-// Pop
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-array.pop();
-array.pop();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '1', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'delete', oldValue: 1 },
- { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-
-// Shift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-array.shift();
-array.shift();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-
-// Unshift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-array.unshift(3, 4);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'add' },
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 2 },
-]);
-
-// Splice
-reset();
-var array = [1, 2, 3];
-Object.observe(array, observer.callback);
-array.splice(1, 1, 4, 5);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 3 },
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'update', oldValue: 3 },
-]);
-
-// Sort
-reset();
-var array = [3, 2, 1];
-Object.observe(array, observer.callback);
-array.sort();
-assertEquals(1, array[0]);
-assertEquals(2, array[1]);
-assertEquals(3, array[2]);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'update', oldValue: 3 },
- { object: array, name: '2', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 3 },
- { object: array, name: '0', type: 'update', oldValue: 2 },
-]);
-
-// Splice emitted after Array mutation methods
-function MockArray(initial, observer) {
- for (var i = 0; i < initial.length; i++)
- this[i] = initial[i];
-
- this.length_ = initial.length;
- this.observer = observer;
-}
-MockArray.prototype = {
- set length(length) {
- Object.getNotifier(this).notify({ type: 'lengthChange' });
- this.length_ = length;
- Object.observe(this, this.observer.callback, ['splice']);
- },
- get length() {
- return this.length_;
- }
-}
-
-reset();
-var array = new MockArray([], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.push.call(array, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 },
-]);
-
-reset();
-var array = new MockArray([1], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.pop.call(array);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
-]);
-
-reset();
-var array = new MockArray([1], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.shift.call(array);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
-]);
-
-reset();
-var array = new MockArray([], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.unshift.call(array, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 },
-]);
-
-reset();
-var array = new MockArray([0, 1, 2], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.splice.call(array, 1, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 1, removed: [1], addedCount: 0 },
-]);
-
-//
-// === PLAIN OBJECTS ===
-//
-// Push
-reset()
-var array = {0: 1, 1: 2, length: 2}
-Object.observe(array, observer.callback);
-Array.prototype.push.call(array, 3, 4);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '2', type: 'add' },
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
-]);
-
-// Pop
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.pop();
-array.pop();
-array.pop();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '1', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'delete', oldValue: 1 },
- { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 1, removed: [2], addedCount: 0 },
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 }
-]);
-
-// Shift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.shift();
-array.shift();
-array.shift();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
- { object: array, type: 'splice', index: 0, removed: [2], addedCount: 0 }
-]);
-
-// Unshift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.unshift(3, 4);
-array.unshift(5);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'add' },
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '4', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 4 },
- { object: array, name: '3', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 4 },
- { object: array, name: '0', type: 'update', oldValue: 3 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 2 },
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 }
-]);
-
-// Splice
-reset();
-var array = [1, 2, 3];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.splice(1, 0, 4, 5); // 1 4 5 2 3
-array.splice(0, 2); // 5 2 3
-array.splice(1, 2, 6, 7); // 5 6 7
-array.splice(2, 0);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '4', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 3 },
- { object: array, name: '3', type: 'add' },
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'update', oldValue: 3 },
-
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 4 },
- { object: array, name: '2', type: 'update', oldValue: 5 },
- { object: array, name: '4', type: 'delete', oldValue: 3 },
- { object: array, name: '3', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 5 },
-
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'update', oldValue: 3 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 1, removed: [], addedCount: 2 },
- { object: array, type: 'splice', index: 0, removed: [1, 4], addedCount: 0 },
- { object: array, type: 'splice', index: 1, removed: [2, 3], addedCount: 2 },
-]);
-
-// Exercise StoreIC_ArrayLength
-reset();
-var dummy = {};
-Object.observe(dummy, observer.callback);
-Object.unobserve(dummy, observer.callback);
-var array = [0];
-Object.observe(array, observer.callback);
-array.splice(0, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '0', type: 'delete', oldValue: 0 },
- { object: array, name: 'length', type: 'update', oldValue: 1},
-]);
-
-
-// __proto__
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-var p = {foo: 'yes'};
-var q = {bar: 'no'};
-obj.__proto__ = p;
-obj.__proto__ = p; // ignored
-obj.__proto__ = null;
-obj.__proto__ = q; // the __proto__ accessor is gone
-// TODO(adamk): Add tests for objects with hidden prototypes
-// once we support observing the global object.
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: '__proto__', type: 'setPrototype',
- oldValue: Object.prototype },
- { object: obj, name: '__proto__', type: 'setPrototype', oldValue: p },
- { object: obj, name: '__proto__', type: 'add' },
-]);
-
-
-// Function.prototype
-reset();
-var fun = function(){};
-Object.observe(fun, observer.callback);
-var myproto = {foo: 'bar'};
-fun.prototype = myproto;
-fun.prototype = 7;
-fun.prototype = 7; // ignored
-Object.defineProperty(fun, 'prototype', {value: 8});
-Object.deliverChangeRecords(observer.callback);
-observer.assertRecordCount(3);
-// Manually examine the first record in order to test
-// lazy creation of oldValue
-assertSame(fun, observer.records[0].object);
-assertEquals('prototype', observer.records[0].name);
-assertEquals('update', observer.records[0].type);
-// The only existing reference to the oldValue object is in this
-// record, so to test that lazy creation happened correctly
-// we compare its constructor to our function (one of the invariants
-// ensured when creating an object via AllocateFunctionPrototype).
-assertSame(fun, observer.records[0].oldValue.constructor);
-observer.records.splice(0, 1);
-observer.assertCallbackRecords([
- { object: fun, name: 'prototype', type: 'update', oldValue: myproto },
- { object: fun, name: 'prototype', type: 'update', oldValue: 7 },
-]);
-
-// Function.prototype should not be observable except on the object itself
-reset();
-var fun = function(){};
-var obj = { __proto__: fun };
-Object.observe(obj, observer.callback);
-obj.prototype = 7;
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Check that changes in observation status are detected in all IC states and
-// in optimized code, especially in cases usually using fast elements.
-var mutation = [
- "a[i] = v",
- "a[i] ? ++a[i] : a[i] = v",
- "a[i] ? a[i]++ : a[i] = v",
- "a[i] ? a[i] += 1 : a[i] = v",
- "a[i] ? a[i] -= -1 : a[i] = v",
-];
-
-var props = [1, "1", "a"];
-
-function TestFastElements(prop, mutation, prepopulate, polymorphic, optimize) {
- var setElement = eval(
- "(function setElement(a, i, v) { " + mutation + "; " +
- "/* " + [].join.call(arguments, " ") + " */" +
- "})"
- );
- print("TestFastElements:", setElement);
-
- var arr = prepopulate ? [1, 2, 3, 4, 5] : [0];
- if (prepopulate) arr[prop] = 2; // for non-element case
- setElement(arr, prop, 3);
- setElement(arr, prop, 4);
- if (polymorphic) setElement(["M", "i", "l", "n", "e", "r"], 0, "m");
- if (optimize) %OptimizeFunctionOnNextCall(setElement);
- setElement(arr, prop, 5);
-
- reset();
- Object.observe(arr, observer.callback);
- setElement(arr, prop, 989898);
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: arr, name: "" + prop, type: 'update', oldValue: 5 }
- ]);
-}
-
-for (var b1 = 0; b1 < 2; ++b1)
- for (var b2 = 0; b2 < 2; ++b2)
- for (var b3 = 0; b3 < 2; ++b3)
- for (var i in props)
- for (var j in mutation)
- TestFastElements(props[i], mutation[j], b1 != 0, b2 != 0, b3 != 0);
-
-
-var mutation = [
- "a.length = v",
- "a.length += newSize - oldSize",
- "a.length -= oldSize - newSize",
-];
-
-var mutationByIncr = [
- "++a.length",
- "a.length++",
-];
-
-function TestFastElementsLength(
- mutation, polymorphic, optimize, oldSize, newSize) {
- var setLength = eval(
- "(function setLength(a, v) { " + mutation + "; " +
- "/* " + [].join.call(arguments, " ") + " */"
- + "})"
- );
- print("TestFastElementsLength:", setLength);
-
- function array(n) {
- var arr = new Array(n);
- for (var i = 0; i < n; ++i) arr[i] = i;
- return arr;
- }
-
- setLength(array(oldSize), newSize);
- setLength(array(oldSize), newSize);
- if (polymorphic) setLength(array(oldSize).map(isNaN), newSize);
- if (optimize) %OptimizeFunctionOnNextCall(setLength);
- setLength(array(oldSize), newSize);
-
- reset();
- var arr = array(oldSize);
- Object.observe(arr, observer.callback);
- setLength(arr, newSize);
- Object.deliverChangeRecords(observer.callback);
- if (oldSize === newSize) {
- observer.assertNotCalled();
- } else {
- var count = oldSize > newSize ? oldSize - newSize : 0;
- observer.assertRecordCount(count + 1);
- var lengthRecord = observer.records[count];
- assertSame(arr, lengthRecord.object);
- assertEquals('length', lengthRecord.name);
- assertEquals('update', lengthRecord.type);
- assertSame(oldSize, lengthRecord.oldValue);
- }
-}
-
-for (var b1 = 0; b1 < 2; ++b1)
- for (var b2 = 0; b2 < 2; ++b2)
- for (var n1 = 0; n1 < 3; ++n1)
- for (var n2 = 0; n2 < 3; ++n2)
- for (var i in mutation)
- TestFastElementsLength(mutation[i], b1 != 0, b2 != 0, 20*n1, 20*n2);
-
-for (var b1 = 0; b1 < 2; ++b1)
- for (var b2 = 0; b2 < 2; ++b2)
- for (var n = 0; n < 3; ++n)
- for (var i in mutationByIncr)
- TestFastElementsLength(mutationByIncr[i], b1 != 0, b2 != 0, 7*n, 7*n+1);
« no previous file with comments | « test/mjsunit/es7/object-observe.js ('k') | test/webkit/fast/js/Object-getOwnPropertyNames-expected.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698