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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 assertCalled: function() { | 58 assertCalled: function() { |
59 assertEquals(1, this.callbackCount); | 59 assertEquals(1, this.callbackCount); |
60 }, | 60 }, |
61 assertRecordCount: function(count) { | 61 assertRecordCount: function(count) { |
62 this.assertCalled(); | 62 this.assertCalled(); |
63 assertEquals(count, this.records.length); | 63 assertEquals(count, this.records.length); |
64 }, | 64 }, |
65 assertCallbackRecords: function(recs) { | 65 assertCallbackRecords: function(recs) { |
66 this.assertRecordCount(recs.length); | 66 this.assertRecordCount(recs.length); |
67 for (var i = 0; i < recs.length; i++) { | 67 for (var i = 0; i < recs.length; i++) { |
68 if ('name' in recs[i]) | 68 if ('name' in recs[i]) recs[i].name = String(recs[i].name); |
69 recs[i].name = String(recs[i].name); | |
70 print(i, stringifyNoThrow(this.records[i]), stringifyNoThrow(recs[i])); | 69 print(i, stringifyNoThrow(this.records[i]), stringifyNoThrow(recs[i])); |
71 assertSame(this.records[i].object, recs[i].object); | 70 assertSame(this.records[i].object, recs[i].object); |
72 assertEquals('string', typeof recs[i].type); | 71 assertEquals('string', typeof recs[i].type); |
73 assertPropertiesEqual(this.records[i], recs[i]); | 72 assertPropertiesEqual(this.records[i], recs[i]); |
74 } | 73 } |
75 } | 74 } |
76 }; | 75 }; |
77 | 76 |
78 observer.callback = function(r) { | 77 observer.callback = function(r) { |
79 assertEquals(undefined, this); | 78 assertEquals(undefined, this); |
(...skipping 18 matching lines...) Expand all Loading... |
98 var changeRecordWithAccessor = { type: 'foo' }; | 97 var changeRecordWithAccessor = { type: 'foo' }; |
99 var recordCreated = false; | 98 var recordCreated = false; |
100 Object.defineProperty(changeRecordWithAccessor, 'name', { | 99 Object.defineProperty(changeRecordWithAccessor, 'name', { |
101 get: function() { | 100 get: function() { |
102 recordCreated = true; | 101 recordCreated = true; |
103 return "bar"; | 102 return "bar"; |
104 }, | 103 }, |
105 enumerable: true | 104 enumerable: true |
106 }) | 105 }) |
107 | 106 |
| 107 |
108 // Object.observe | 108 // Object.observe |
109 assertThrows(function() { Object.observe("non-object", observer.callback); }, Ty
peError); | 109 assertThrows(function() { Object.observe("non-object", observer.callback); }, Ty
peError); |
110 assertThrows(function() { Object.observe(obj, nonFunction); }, TypeError); | 110 assertThrows(function() { Object.observe(obj, nonFunction); }, TypeError); |
111 assertThrows(function() { Object.observe(obj, frozenFunction); }, TypeError); | 111 assertThrows(function() { Object.observe(obj, frozenFunction); }, TypeError); |
112 assertEquals(obj, Object.observe(obj, observer.callback)); | 112 assertEquals(obj, Object.observe(obj, observer.callback)); |
113 | 113 |
| 114 |
114 // Object.unobserve | 115 // Object.unobserve |
115 assertThrows(function() { Object.unobserve(4, observer.callback); }, TypeError); | 116 assertThrows(function() { Object.unobserve(4, observer.callback); }, TypeError); |
116 assertThrows(function() { Object.unobserve(obj, nonFunction); }, TypeError); | 117 assertThrows(function() { Object.unobserve(obj, nonFunction); }, TypeError); |
117 assertEquals(obj, Object.unobserve(obj, observer.callback)); | 118 assertEquals(obj, Object.unobserve(obj, observer.callback)); |
118 | 119 |
| 120 |
119 // Object.getNotifier | 121 // Object.getNotifier |
120 var notifier = Object.getNotifier(obj); | 122 var notifier = Object.getNotifier(obj); |
121 assertSame(notifier, Object.getNotifier(obj)); | 123 assertSame(notifier, Object.getNotifier(obj)); |
122 assertEquals(null, Object.getNotifier(Object.freeze({}))); | 124 assertEquals(null, Object.getNotifier(Object.freeze({}))); |
123 assertFalse(notifier.hasOwnProperty('notify')); | 125 assertFalse(notifier.hasOwnProperty('notify')); |
124 assertEquals([], Object.keys(notifier)); | 126 assertEquals([], Object.keys(notifier)); |
125 var notifyDesc = Object.getOwnPropertyDescriptor(notifier.__proto__, 'notify'); | 127 var notifyDesc = Object.getOwnPropertyDescriptor(notifier.__proto__, 'notify'); |
126 assertTrue(notifyDesc.configurable); | 128 assertTrue(notifyDesc.configurable); |
127 assertTrue(notifyDesc.writable); | 129 assertTrue(notifyDesc.writable); |
128 assertFalse(notifyDesc.enumerable); | 130 assertFalse(notifyDesc.enumerable); |
129 assertThrows(function() { notifier.notify({}); }, TypeError); | 131 assertThrows(function() { notifier.notify({}); }, TypeError); |
130 assertThrows(function() { notifier.notify({ type: 4 }); }, TypeError); | 132 assertThrows(function() { notifier.notify({ type: 4 }); }, TypeError); |
131 var notify = notifier.notify; | 133 var notify = notifier.notify; |
132 assertThrows(function() { notify.call(undefined, { type: 'a' }); }, TypeError); | 134 assertThrows(function() { notify.call(undefined, { type: 'a' }); }, TypeError); |
133 assertThrows(function() { notify.call(null, { type: 'a' }); }, TypeError); | 135 assertThrows(function() { notify.call(null, { type: 'a' }); }, TypeError); |
134 assertThrows(function() { notify.call(5, { type: 'a' }); }, TypeError); | 136 assertThrows(function() { notify.call(5, { type: 'a' }); }, TypeError); |
135 assertThrows(function() { notify.call('hello', { type: 'a' }); }, TypeError); | 137 assertThrows(function() { notify.call('hello', { type: 'a' }); }, TypeError); |
136 assertThrows(function() { notify.call(false, { type: 'a' }); }, TypeError); | 138 assertThrows(function() { notify.call(false, { type: 'a' }); }, TypeError); |
137 assertThrows(function() { notify.call({}, { type: 'a' }); }, TypeError); | 139 assertThrows(function() { notify.call({}, { type: 'a' }); }, TypeError); |
138 assertFalse(recordCreated); | 140 assertFalse(recordCreated); |
139 notifier.notify(changeRecordWithAccessor); | 141 notifier.notify(changeRecordWithAccessor); |
140 assertFalse(recordCreated); // not observed yet | 142 assertFalse(recordCreated); // not observed yet |
141 | 143 |
| 144 |
142 // Object.deliverChangeRecords | 145 // Object.deliverChangeRecords |
143 assertThrows(function() { Object.deliverChangeRecords(nonFunction); }, TypeError
); | 146 assertThrows(function() { Object.deliverChangeRecords(nonFunction); }, TypeError
); |
144 | 147 |
145 Object.observe(obj, observer.callback); | 148 Object.observe(obj, observer.callback); |
146 | 149 |
| 150 |
147 // notify uses to [[CreateOwnProperty]] to create changeRecord; | 151 // notify uses to [[CreateOwnProperty]] to create changeRecord; |
148 reset(); | 152 reset(); |
149 var protoExpandoAccessed = false; | 153 var protoExpandoAccessed = false; |
150 Object.defineProperty(Object.prototype, 'protoExpando', | 154 Object.defineProperty(Object.prototype, 'protoExpando', |
151 { | 155 { |
152 configurable: true, | 156 configurable: true, |
153 set: function() { protoExpandoAccessed = true; } | 157 set: function() { protoExpandoAccessed = true; } |
154 } | 158 } |
155 ); | 159 ); |
156 notifier.notify({ type: 'foo', protoExpando: 'val'}); | 160 notifier.notify({ type: 'foo', protoExpando: 'val'}); |
157 assertFalse(protoExpandoAccessed); | 161 assertFalse(protoExpandoAccessed); |
158 delete Object.prototype.protoExpando; | 162 delete Object.prototype.protoExpando; |
159 Object.deliverChangeRecords(observer.callback); | 163 Object.deliverChangeRecords(observer.callback); |
160 | 164 |
| 165 |
161 // Multiple records are delivered. | 166 // Multiple records are delivered. |
162 reset(); | 167 reset(); |
163 notifier.notify({ | 168 notifier.notify({ |
164 type: 'updated', | 169 type: 'updated', |
165 name: 'foo', | 170 name: 'foo', |
166 expando: 1 | 171 expando: 1 |
167 }); | 172 }); |
168 | 173 |
169 notifier.notify({ | 174 notifier.notify({ |
170 object: notifier, // object property is ignored | 175 object: notifier, // object property is ignored |
171 type: 'deleted', | 176 type: 'deleted', |
172 name: 'bar', | 177 name: 'bar', |
173 expando2: 'str' | 178 expando2: 'str' |
174 }); | 179 }); |
175 Object.deliverChangeRecords(observer.callback); | 180 Object.deliverChangeRecords(observer.callback); |
176 observer.assertCallbackRecords([ | 181 observer.assertCallbackRecords([ |
177 { object: obj, name: 'foo', type: 'updated', expando: 1 }, | 182 { object: obj, name: 'foo', type: 'updated', expando: 1 }, |
178 { object: obj, name: 'bar', type: 'deleted', expando2: 'str' } | 183 { object: obj, name: 'bar', type: 'deleted', expando2: 'str' } |
179 ]); | 184 ]); |
180 | 185 |
| 186 |
181 // No delivery takes place if no records are pending | 187 // No delivery takes place if no records are pending |
182 reset(); | 188 reset(); |
183 Object.deliverChangeRecords(observer.callback); | 189 Object.deliverChangeRecords(observer.callback); |
184 observer.assertNotCalled(); | 190 observer.assertNotCalled(); |
185 | 191 |
| 192 |
186 // Multiple observation has no effect. | 193 // Multiple observation has no effect. |
187 reset(); | 194 reset(); |
188 Object.observe(obj, observer.callback); | 195 Object.observe(obj, observer.callback); |
189 Object.observe(obj, observer.callback); | 196 Object.observe(obj, observer.callback); |
190 Object.getNotifier(obj).notify({ | 197 Object.getNotifier(obj).notify({ |
191 type: 'foo', | 198 type: 'foo', |
192 }); | 199 }); |
193 Object.deliverChangeRecords(observer.callback); | 200 Object.deliverChangeRecords(observer.callback); |
194 observer.assertCalled(); | 201 observer.assertCalled(); |
195 | 202 |
| 203 |
196 // Observation can be stopped. | 204 // Observation can be stopped. |
197 reset(); | 205 reset(); |
198 Object.unobserve(obj, observer.callback); | 206 Object.unobserve(obj, observer.callback); |
199 Object.getNotifier(obj).notify({ | 207 Object.getNotifier(obj).notify({ |
200 type: 'foo', | 208 type: 'foo', |
201 }); | 209 }); |
202 Object.deliverChangeRecords(observer.callback); | 210 Object.deliverChangeRecords(observer.callback); |
203 observer.assertNotCalled(); | 211 observer.assertNotCalled(); |
204 | 212 |
| 213 |
205 // Multiple unobservation has no effect | 214 // Multiple unobservation has no effect |
206 reset(); | 215 reset(); |
207 Object.unobserve(obj, observer.callback); | 216 Object.unobserve(obj, observer.callback); |
208 Object.unobserve(obj, observer.callback); | 217 Object.unobserve(obj, observer.callback); |
209 Object.getNotifier(obj).notify({ | 218 Object.getNotifier(obj).notify({ |
210 type: 'foo', | 219 type: 'foo', |
211 }); | 220 }); |
212 Object.deliverChangeRecords(observer.callback); | 221 Object.deliverChangeRecords(observer.callback); |
213 observer.assertNotCalled(); | 222 observer.assertNotCalled(); |
214 | 223 |
| 224 |
215 // Re-observation works and only includes changeRecords after of call. | 225 // Re-observation works and only includes changeRecords after of call. |
216 reset(); | 226 reset(); |
217 Object.getNotifier(obj).notify({ | 227 Object.getNotifier(obj).notify({ |
218 type: 'foo', | 228 type: 'foo', |
219 }); | 229 }); |
220 Object.observe(obj, observer.callback); | 230 Object.observe(obj, observer.callback); |
221 Object.getNotifier(obj).notify({ | 231 Object.getNotifier(obj).notify({ |
222 type: 'foo', | 232 type: 'foo', |
223 }); | 233 }); |
224 records = undefined; | 234 records = undefined; |
225 Object.deliverChangeRecords(observer.callback); | 235 Object.deliverChangeRecords(observer.callback); |
226 observer.assertRecordCount(1); | 236 observer.assertRecordCount(1); |
227 | 237 |
| 238 |
228 // Observing a continuous stream of changes, while itermittantly unobserving. | 239 // Observing a continuous stream of changes, while itermittantly unobserving. |
229 reset(); | 240 reset(); |
230 Object.observe(obj, observer.callback); | 241 Object.observe(obj, observer.callback); |
231 Object.getNotifier(obj).notify({ | 242 Object.getNotifier(obj).notify({ |
232 type: 'foo', | 243 type: 'foo', |
233 val: 1 | 244 val: 1 |
234 }); | 245 }); |
235 | 246 |
236 Object.unobserve(obj, observer.callback); | 247 Object.unobserve(obj, observer.callback); |
237 Object.getNotifier(obj).notify({ | 248 Object.getNotifier(obj).notify({ |
(...skipping 20 matching lines...) Expand all Loading... |
258 }); | 269 }); |
259 | 270 |
260 Object.unobserve(obj, observer.callback); | 271 Object.unobserve(obj, observer.callback); |
261 Object.deliverChangeRecords(observer.callback); | 272 Object.deliverChangeRecords(observer.callback); |
262 observer.assertCallbackRecords([ | 273 observer.assertCallbackRecords([ |
263 { object: obj, type: 'foo', val: 1 }, | 274 { object: obj, type: 'foo', val: 1 }, |
264 { object: obj, type: 'foo', val: 3 }, | 275 { object: obj, type: 'foo', val: 3 }, |
265 { object: obj, type: 'foo', val: 5 } | 276 { object: obj, type: 'foo', val: 5 } |
266 ]); | 277 ]); |
267 | 278 |
| 279 |
268 // Observing multiple objects; records appear in order. | 280 // Observing multiple objects; records appear in order. |
269 reset(); | 281 reset(); |
270 var obj2 = {}; | 282 var obj2 = {}; |
271 var obj3 = {} | 283 var obj3 = {} |
272 Object.observe(obj, observer.callback); | 284 Object.observe(obj, observer.callback); |
273 Object.observe(obj3, observer.callback); | 285 Object.observe(obj3, observer.callback); |
274 Object.observe(obj2, observer.callback); | 286 Object.observe(obj2, observer.callback); |
275 Object.getNotifier(obj).notify({ | 287 Object.getNotifier(obj).notify({ |
276 type: 'foo1', | 288 type: 'foo1', |
277 }); | 289 }); |
278 Object.getNotifier(obj2).notify({ | 290 Object.getNotifier(obj2).notify({ |
279 type: 'foo2', | 291 type: 'foo2', |
280 }); | 292 }); |
281 Object.getNotifier(obj3).notify({ | 293 Object.getNotifier(obj3).notify({ |
282 type: 'foo3', | 294 type: 'foo3', |
283 }); | 295 }); |
284 Object.observe(obj3, observer.callback); | 296 Object.observe(obj3, observer.callback); |
285 Object.deliverChangeRecords(observer.callback); | 297 Object.deliverChangeRecords(observer.callback); |
286 observer.assertCallbackRecords([ | 298 observer.assertCallbackRecords([ |
287 { object: obj, type: 'foo1' }, | 299 { object: obj, type: 'foo1' }, |
288 { object: obj2, type: 'foo2' }, | 300 { object: obj2, type: 'foo2' }, |
289 { object: obj3, type: 'foo3' } | 301 { object: obj3, type: 'foo3' } |
290 ]); | 302 ]); |
291 | 303 |
| 304 |
| 305 // Recursive observation. |
| 306 var obj = {a: 1}; |
| 307 var callbackCount = 0; |
| 308 function recursiveObserver(r) { |
| 309 assertEquals(1, r.length); |
| 310 ++callbackCount; |
| 311 if (r[0].oldValue < 100) ++obj[r[0].name]; |
| 312 } |
| 313 Object.observe(obj, recursiveObserver); |
| 314 ++obj.a; |
| 315 Object.deliverChangeRecords(recursiveObserver); |
| 316 assertEquals(100, callbackCount); |
| 317 |
| 318 var obj1 = {a: 1}; |
| 319 var obj2 = {a: 1}; |
| 320 var recordCount = 0; |
| 321 function recursiveObserver2(r) { |
| 322 recordCount += r.length; |
| 323 if (r[0].oldValue < 100) { |
| 324 ++obj1.a; |
| 325 ++obj2.a; |
| 326 } |
| 327 } |
| 328 Object.observe(obj1, recursiveObserver2); |
| 329 Object.observe(obj2, recursiveObserver2); |
| 330 ++obj1.a; |
| 331 Object.deliverChangeRecords(recursiveObserver2); |
| 332 assertEquals(199, recordCount); |
| 333 |
| 334 |
292 // Observing named properties. | 335 // Observing named properties. |
293 reset(); | 336 reset(); |
294 var obj = {a: 1} | 337 var obj = {a: 1} |
295 Object.observe(obj, observer.callback); | 338 Object.observe(obj, observer.callback); |
296 obj.a = 2; | 339 obj.a = 2; |
297 obj["a"] = 3; | 340 obj["a"] = 3; |
298 delete obj.a; | 341 delete obj.a; |
299 obj.a = 4; | 342 obj.a = 4; |
300 obj.a = 4; // ignored | 343 obj.a = 4; // ignored |
301 obj.a = 5; | 344 obj.a = 5; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 { object: obj, name: "a", type: "reconfigured" }, | 376 { object: obj, name: "a", type: "reconfigured" }, |
334 { object: obj, name: "a", type: "reconfigured" }, | 377 { object: obj, name: "a", type: "reconfigured" }, |
335 { object: obj, name: "a", type: "deleted" }, | 378 { object: obj, name: "a", type: "deleted" }, |
336 { object: obj, name: "a", type: "new" }, | 379 { object: obj, name: "a", type: "new" }, |
337 { object: obj, name: "a", type: "reconfigured" }, | 380 { object: obj, name: "a", type: "reconfigured" }, |
338 { object: obj, name: "a", type: "updated", oldValue: 9 }, | 381 { object: obj, name: "a", type: "updated", oldValue: 9 }, |
339 { object: obj, name: "a", type: "deleted", oldValue: 10 }, | 382 { object: obj, name: "a", type: "deleted", oldValue: 10 }, |
340 { object: obj, name: "a", type: "new" }, | 383 { object: obj, name: "a", type: "new" }, |
341 ]); | 384 ]); |
342 | 385 |
| 386 |
343 // Observing indexed properties. | 387 // Observing indexed properties. |
344 reset(); | 388 reset(); |
345 var obj = {'1': 1} | 389 var obj = {'1': 1} |
346 Object.observe(obj, observer.callback); | 390 Object.observe(obj, observer.callback); |
347 obj[1] = 2; | 391 obj[1] = 2; |
348 obj[1] = 3; | 392 obj[1] = 3; |
349 delete obj[1]; | 393 delete obj[1]; |
350 obj[1] = 4; | 394 obj[1] = 4; |
351 obj[1] = 4; // ignored | 395 obj[1] = 4; // ignored |
352 obj[1] = 5; | 396 obj[1] = 5; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 function TestObserveNonConfigurable(obj, prop, desc) { | 503 function TestObserveNonConfigurable(obj, prop, desc) { |
460 reset(); | 504 reset(); |
461 obj[prop] = 1; | 505 obj[prop] = 1; |
462 Object.observe(obj, observer.callback); | 506 Object.observe(obj, observer.callback); |
463 obj[prop] = 4; | 507 obj[prop] = 4; |
464 obj[prop] = 4; // ignored | 508 obj[prop] = 4; // ignored |
465 obj[prop] = 5; | 509 obj[prop] = 5; |
466 Object.defineProperty(obj, prop, {value: 6}); | 510 Object.defineProperty(obj, prop, {value: 6}); |
467 Object.defineProperty(obj, prop, {value: 6}); // ignored | 511 Object.defineProperty(obj, prop, {value: 6}); // ignored |
468 Object.defineProperty(obj, prop, {value: 7}); | 512 Object.defineProperty(obj, prop, {value: 7}); |
469 Object.defineProperty(obj, prop, | 513 Object.defineProperty(obj, prop, {enumerable: desc.enumerable}); // ignored |
470 {enumerable: desc.enumerable}); // ignored | |
471 Object.defineProperty(obj, prop, {writable: false}); | 514 Object.defineProperty(obj, prop, {writable: false}); |
472 obj[prop] = 7; // ignored | 515 obj[prop] = 7; // ignored |
473 Object.deliverChangeRecords(observer.callback); | 516 Object.deliverChangeRecords(observer.callback); |
474 observer.assertCallbackRecords([ | 517 observer.assertCallbackRecords([ |
475 { object: obj, name: prop, type: "updated", oldValue: 1 }, | 518 { object: obj, name: prop, type: "updated", oldValue: 1 }, |
476 { object: obj, name: prop, type: "updated", oldValue: 4 }, | 519 { object: obj, name: prop, type: "updated", oldValue: 4 }, |
477 { object: obj, name: prop, type: "updated", oldValue: 5 }, | 520 { object: obj, name: prop, type: "updated", oldValue: 5 }, |
478 { object: obj, name: prop, type: "updated", oldValue: 6 }, | 521 { object: obj, name: prop, type: "updated", oldValue: 6 }, |
479 { object: obj, name: prop, type: "reconfigured", oldValue: 7 }, | 522 { object: obj, name: prop, type: "reconfigured", oldValue: 7 }, |
480 ]); | 523 ]); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 new Set, new Map, new WeakMap, | 577 new Set, new Map, new WeakMap, |
535 new ArrayBuffer(10), new Int32Array(5), | 578 new ArrayBuffer(10), new Int32Array(5), |
536 createProxy(Proxy.create, null), | 579 createProxy(Proxy.create, null), |
537 createProxy(Proxy.createFunction, function(){}), | 580 createProxy(Proxy.createFunction, function(){}), |
538 ]; | 581 ]; |
539 var properties = ["a", "1", 1, "length", "prototype", "name", "caller"]; | 582 var properties = ["a", "1", 1, "length", "prototype", "name", "caller"]; |
540 | 583 |
541 // Cases that yield non-standard results. | 584 // Cases that yield non-standard results. |
542 function blacklisted(obj, prop) { | 585 function blacklisted(obj, prop) { |
543 return (obj instanceof Int32Array && prop == 1) || | 586 return (obj instanceof Int32Array && prop == 1) || |
544 (obj instanceof Int32Array && prop === "length") || | 587 (obj instanceof Int32Array && prop === "length") || |
545 (obj instanceof ArrayBuffer && prop == 1) | 588 (obj instanceof ArrayBuffer && prop == 1) |
546 } | 589 } |
547 | 590 |
548 for (var i in objects) for (var j in properties) { | 591 for (var i in objects) for (var j in properties) { |
549 var obj = objects[i]; | 592 var obj = objects[i]; |
550 var prop = properties[j]; | 593 var prop = properties[j]; |
551 if (blacklisted(obj, prop)) continue; | 594 if (blacklisted(obj, prop)) continue; |
552 var desc = Object.getOwnPropertyDescriptor(obj, prop); | 595 var desc = Object.getOwnPropertyDescriptor(obj, prop); |
553 print("***", typeof obj, stringifyNoThrow(obj), prop); | 596 print("***", typeof obj, stringifyNoThrow(obj), prop); |
554 if (!desc || desc.configurable) | 597 if (!desc || desc.configurable) |
555 TestObserveConfigurable(obj, prop); | 598 TestObserveConfigurable(obj, prop); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 { object: arr2, name: '1', type: 'deleted', oldValue: 'beta' }, | 640 { object: arr2, name: '1', type: 'deleted', oldValue: 'beta' }, |
598 { object: arr2, name: 'length', type: 'updated', oldValue: 2 }, | 641 { object: arr2, name: 'length', type: 'updated', oldValue: 2 }, |
599 { object: arr2, name: 'length', type: 'reconfigured', oldValue: 1 }, | 642 { object: arr2, name: 'length', type: 'reconfigured', oldValue: 1 }, |
600 { object: arr3, name: '2', type: 'deleted', oldValue: 'goodbye' }, | 643 { object: arr3, name: '2', type: 'deleted', oldValue: 'goodbye' }, |
601 { object: arr3, name: '0', type: 'deleted', oldValue: 'hello' }, | 644 { object: arr3, name: '0', type: 'deleted', oldValue: 'hello' }, |
602 { object: arr3, name: 'length', type: 'updated', oldValue: 6 }, | 645 { object: arr3, name: 'length', type: 'updated', oldValue: 6 }, |
603 { object: arr3, name: 'length', type: 'updated', oldValue: 0 }, | 646 { object: arr3, name: 'length', type: 'updated', oldValue: 0 }, |
604 { object: arr3, name: 'length', type: 'reconfigured', oldValue: 5 }, | 647 { object: arr3, name: 'length', type: 'reconfigured', oldValue: 5 }, |
605 ]); | 648 ]); |
606 | 649 |
| 650 |
607 // Assignments in loops (checking different IC states). | 651 // Assignments in loops (checking different IC states). |
608 reset(); | 652 reset(); |
609 var obj = {}; | 653 var obj = {}; |
610 Object.observe(obj, observer.callback); | 654 Object.observe(obj, observer.callback); |
611 for (var i = 0; i < 5; i++) { | 655 for (var i = 0; i < 5; i++) { |
612 obj["a" + i] = i; | 656 obj["a" + i] = i; |
613 } | 657 } |
614 Object.deliverChangeRecords(observer.callback); | 658 Object.deliverChangeRecords(observer.callback); |
615 observer.assertCallbackRecords([ | 659 observer.assertCallbackRecords([ |
616 { object: obj, name: "a0", type: "new" }, | 660 { object: obj, name: "a0", type: "new" }, |
(...skipping 11 matching lines...) Expand all Loading... |
628 } | 672 } |
629 Object.deliverChangeRecords(observer.callback); | 673 Object.deliverChangeRecords(observer.callback); |
630 observer.assertCallbackRecords([ | 674 observer.assertCallbackRecords([ |
631 { object: obj, name: "0", type: "new" }, | 675 { object: obj, name: "0", type: "new" }, |
632 { object: obj, name: "1", type: "new" }, | 676 { object: obj, name: "1", type: "new" }, |
633 { object: obj, name: "2", type: "new" }, | 677 { object: obj, name: "2", type: "new" }, |
634 { object: obj, name: "3", type: "new" }, | 678 { object: obj, name: "3", type: "new" }, |
635 { object: obj, name: "4", type: "new" }, | 679 { object: obj, name: "4", type: "new" }, |
636 ]); | 680 ]); |
637 | 681 |
| 682 |
638 // Adding elements past the end of an array should notify on length | 683 // Adding elements past the end of an array should notify on length |
639 reset(); | 684 reset(); |
640 var arr = [1, 2, 3]; | 685 var arr = [1, 2, 3]; |
641 Object.observe(arr, observer.callback); | 686 Object.observe(arr, observer.callback); |
642 arr[3] = 10; | 687 arr[3] = 10; |
643 arr[100] = 20; | 688 arr[100] = 20; |
644 Object.defineProperty(arr, '200', {value: 7}); | 689 Object.defineProperty(arr, '200', {value: 7}); |
645 Object.defineProperty(arr, '400', {get: function(){}}); | 690 Object.defineProperty(arr, '400', {get: function(){}}); |
646 arr[50] = 30; // no length change expected | 691 arr[50] = 30; // no length change expected |
647 Object.deliverChangeRecords(observer.callback); | 692 Object.deliverChangeRecords(observer.callback); |
648 observer.assertCallbackRecords([ | 693 observer.assertCallbackRecords([ |
649 { object: arr, name: '3', type: 'new' }, | 694 { object: arr, name: '3', type: 'new' }, |
650 { object: arr, name: 'length', type: 'updated', oldValue: 3 }, | 695 { object: arr, name: 'length', type: 'updated', oldValue: 3 }, |
651 { object: arr, name: '100', type: 'new' }, | 696 { object: arr, name: '100', type: 'new' }, |
652 { object: arr, name: 'length', type: 'updated', oldValue: 4 }, | 697 { object: arr, name: 'length', type: 'updated', oldValue: 4 }, |
653 { object: arr, name: '200', type: 'new' }, | 698 { object: arr, name: '200', type: 'new' }, |
654 { object: arr, name: 'length', type: 'updated', oldValue: 101 }, | 699 { object: arr, name: 'length', type: 'updated', oldValue: 101 }, |
655 { object: arr, name: '400', type: 'new' }, | 700 { object: arr, name: '400', type: 'new' }, |
656 { object: arr, name: 'length', type: 'updated', oldValue: 201 }, | 701 { object: arr, name: 'length', type: 'updated', oldValue: 201 }, |
657 { object: arr, name: '50', type: 'new' }, | 702 { object: arr, name: '50', type: 'new' }, |
658 ]); | 703 ]); |
659 | 704 |
| 705 |
660 // Tests for array methods, first on arrays and then on plain objects | 706 // Tests for array methods, first on arrays and then on plain objects |
661 // | 707 // |
662 // === ARRAYS === | 708 // === ARRAYS === |
663 // | 709 // |
664 // Push | 710 // Push |
665 reset(); | 711 reset(); |
666 var array = [1, 2]; | 712 var array = [1, 2]; |
667 Object.observe(array, observer.callback); | 713 Object.observe(array, observer.callback); |
668 array.push(3, 4); | 714 array.push(3, 4); |
669 Object.deliverChangeRecords(observer.callback); | 715 Object.deliverChangeRecords(observer.callback); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 Object.observe(array, observer.callback); | 769 Object.observe(array, observer.callback); |
724 array.splice(1, 1, 4, 5); | 770 array.splice(1, 1, 4, 5); |
725 Object.deliverChangeRecords(observer.callback); | 771 Object.deliverChangeRecords(observer.callback); |
726 observer.assertCallbackRecords([ | 772 observer.assertCallbackRecords([ |
727 { object: array, name: '3', type: 'new' }, | 773 { object: array, name: '3', type: 'new' }, |
728 { object: array, name: 'length', type: 'updated', oldValue: 3 }, | 774 { object: array, name: 'length', type: 'updated', oldValue: 3 }, |
729 { object: array, name: '1', type: 'updated', oldValue: 2 }, | 775 { object: array, name: '1', type: 'updated', oldValue: 2 }, |
730 { object: array, name: '2', type: 'updated', oldValue: 3 }, | 776 { object: array, name: '2', type: 'updated', oldValue: 3 }, |
731 ]); | 777 ]); |
732 | 778 |
| 779 |
733 // | 780 // |
734 // === PLAIN OBJECTS === | 781 // === PLAIN OBJECTS === |
735 // | 782 // |
736 // Push | 783 // Push |
737 reset() | 784 reset() |
738 var array = {0: 1, 1: 2, length: 2} | 785 var array = {0: 1, 1: 2, length: 2} |
739 Object.observe(array, observer.callback); | 786 Object.observe(array, observer.callback); |
740 Array.prototype.push.call(array, 3, 4); | 787 Array.prototype.push.call(array, 3, 4); |
741 Object.deliverChangeRecords(observer.callback); | 788 Object.deliverChangeRecords(observer.callback); |
742 observer.assertCallbackRecords([ | 789 observer.assertCallbackRecords([ |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 // TODO(adamk): Add tests for objects with hidden prototypes | 876 // TODO(adamk): Add tests for objects with hidden prototypes |
830 // once we support observing the global object. | 877 // once we support observing the global object. |
831 Object.deliverChangeRecords(observer.callback); | 878 Object.deliverChangeRecords(observer.callback); |
832 observer.assertCallbackRecords([ | 879 observer.assertCallbackRecords([ |
833 { object: obj, name: '__proto__', type: 'prototype', | 880 { object: obj, name: '__proto__', type: 'prototype', |
834 oldValue: Object.prototype }, | 881 oldValue: Object.prototype }, |
835 { object: obj, name: '__proto__', type: 'prototype', oldValue: p }, | 882 { object: obj, name: '__proto__', type: 'prototype', oldValue: p }, |
836 { object: obj, name: '__proto__', type: 'prototype', oldValue: null }, | 883 { object: obj, name: '__proto__', type: 'prototype', oldValue: null }, |
837 ]); | 884 ]); |
838 | 885 |
| 886 |
839 // Function.prototype | 887 // Function.prototype |
840 reset(); | 888 reset(); |
841 var fun = function(){}; | 889 var fun = function(){}; |
842 Object.observe(fun, observer.callback); | 890 Object.observe(fun, observer.callback); |
843 var myproto = {foo: 'bar'}; | 891 var myproto = {foo: 'bar'}; |
844 fun.prototype = myproto; | 892 fun.prototype = myproto; |
845 fun.prototype = 7; | 893 fun.prototype = 7; |
846 fun.prototype = 7; // ignored | 894 fun.prototype = 7; // ignored |
847 Object.defineProperty(fun, 'prototype', {value: 8}); | 895 Object.defineProperty(fun, 'prototype', {value: 8}); |
848 Object.deliverChangeRecords(observer.callback); | 896 Object.deliverChangeRecords(observer.callback); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 observer.assertCallbackRecords([ | 945 observer.assertCallbackRecords([ |
898 { object: arr, name: '1', type: 'updated', oldValue: 212 } | 946 { object: arr, name: '1', type: 'updated', oldValue: 212 } |
899 ]); | 947 ]); |
900 } | 948 } |
901 | 949 |
902 for (var b1 = 0; b1 < 2; ++b1) | 950 for (var b1 = 0; b1 < 2; ++b1) |
903 for (var b2 = 0; b2 < 2; ++b2) | 951 for (var b2 = 0; b2 < 2; ++b2) |
904 for (var b3 = 0; b3 < 2; ++b3) | 952 for (var b3 = 0; b3 < 2; ++b3) |
905 TestFastElements(b1 != 0, b2 != 0, b3 != 0); | 953 TestFastElements(b1 != 0, b2 != 0, b3 != 0); |
906 | 954 |
907 | |
908 function TestFastElementsLength(polymorphic, optimize, oldSize, newSize) { | 955 function TestFastElementsLength(polymorphic, optimize, oldSize, newSize) { |
909 var setLength = eval( | 956 var setLength = eval( |
910 "(function setLength(a, n) { a.length = n " + | 957 "(function setLength(a, n) { a.length = n " + |
911 "/* " + polymorphic + " " + optimize + " " + oldSize + " " + newSize + " */" | 958 "/* " + polymorphic + " " + optimize + " " + oldSize + " " + newSize + " */" |
912 + "})" | 959 + "})" |
913 ); | 960 ); |
914 print("TestFastElementsLength:", setLength); | 961 print("TestFastElementsLength:", setLength); |
915 | 962 |
916 function array(n) { | 963 function array(n) { |
917 var arr = new Array(n); | 964 var arr = new Array(n); |
(...skipping 23 matching lines...) Expand all Loading... |
941 assertEquals('updated', lengthRecord.type); | 988 assertEquals('updated', lengthRecord.type); |
942 assertSame(oldSize, lengthRecord.oldValue); | 989 assertSame(oldSize, lengthRecord.oldValue); |
943 } | 990 } |
944 } | 991 } |
945 | 992 |
946 for (var b1 = 0; b1 < 2; ++b1) | 993 for (var b1 = 0; b1 < 2; ++b1) |
947 for (var b2 = 0; b2 < 2; ++b2) | 994 for (var b2 = 0; b2 < 2; ++b2) |
948 for (var n1 = 0; n1 < 3; ++n1) | 995 for (var n1 = 0; n1 < 3; ++n1) |
949 for (var n2 = 0; n2 < 3; ++n2) | 996 for (var n2 = 0; n2 < 3; ++n2) |
950 TestFastElementsLength(b1 != 0, b2 != 0, 20*n1, 20*n2); | 997 TestFastElementsLength(b1 != 0, b2 != 0, 20*n1, 20*n2); |
OLD | NEW |