| 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 observer.records = r; | 81 observer.records = r; |
| 82 observer.callbackCount++; | 82 observer.callbackCount++; |
| 83 }; | 83 }; |
| 84 | 84 |
| 85 observer.reset(); | 85 observer.reset(); |
| 86 allObservers.push(observer); | 86 allObservers.push(observer); |
| 87 return observer; | 87 return observer; |
| 88 } | 88 } |
| 89 | 89 |
| 90 var observer = createObserver(); | 90 var observer = createObserver(); |
| 91 var observer2 = createObserver(); | |
| 92 | |
| 93 assertEquals("function", typeof observer.callback); | 91 assertEquals("function", typeof observer.callback); |
| 94 assertEquals("function", typeof observer2.callback); | |
| 95 | |
| 96 var obj = {}; | 92 var obj = {}; |
| 97 | 93 |
| 98 function frozenFunction() {} | 94 function frozenFunction() {} |
| 99 Object.freeze(frozenFunction); | 95 Object.freeze(frozenFunction); |
| 100 var nonFunction = {}; | 96 var nonFunction = {}; |
| 101 var changeRecordWithAccessor = { type: 'foo' }; | 97 var changeRecordWithAccessor = { type: 'foo' }; |
| 102 var recordCreated = false; | 98 var recordCreated = false; |
| 103 Object.defineProperty(changeRecordWithAccessor, 'name', { | 99 Object.defineProperty(changeRecordWithAccessor, 'name', { |
| 104 get: function() { | 100 get: function() { |
| 105 recordCreated = true; | 101 recordCreated = true; |
| 106 return "bar"; | 102 return "bar"; |
| 107 }, | 103 }, |
| 108 enumerable: true | 104 enumerable: true |
| 109 }) | 105 }) |
| 110 | 106 |
| 111 | 107 |
| 112 // Object.observe | 108 // Object.observe |
| 113 assertThrows(function() { Object.observe("non-object", observer.callback); }, Ty
peError); | 109 assertThrows(function() { Object.observe("non-object", observer.callback); }, Ty
peError); |
| 114 assertThrows(function() { Object.observe(obj, nonFunction); }, TypeError); | 110 assertThrows(function() { Object.observe(obj, nonFunction); }, TypeError); |
| 115 assertThrows(function() { Object.observe(obj, frozenFunction); }, TypeError); | 111 assertThrows(function() { Object.observe(obj, frozenFunction); }, TypeError); |
| 116 assertThrows(function() { Object.observe(obj, function() {}, 1); }, TypeError); | |
| 117 assertThrows(function() { Object.observe(obj, function() {}, [undefined]); }, Ty
peError); | |
| 118 assertThrows(function() { Object.observe(obj, function() {}, [1]); }, TypeError)
; | |
| 119 assertThrows(function() { Object.observe(obj, function() {}, ['foo', null]); },
TypeError); | |
| 120 assertEquals(obj, Object.observe(obj, observer.callback, ['foo', 'bar', 'baz']))
; | |
| 121 assertEquals(obj, Object.observe(obj, observer.callback, [])); | |
| 122 assertEquals(obj, Object.observe(obj, observer.callback, undefined)); | |
| 123 assertEquals(obj, Object.observe(obj, observer.callback)); | 112 assertEquals(obj, Object.observe(obj, observer.callback)); |
| 124 | 113 |
| 114 |
| 125 // Object.unobserve | 115 // Object.unobserve |
| 126 assertThrows(function() { Object.unobserve(4, observer.callback); }, TypeError); | 116 assertThrows(function() { Object.unobserve(4, observer.callback); }, TypeError); |
| 127 assertThrows(function() { Object.unobserve(obj, nonFunction); }, TypeError); | 117 assertThrows(function() { Object.unobserve(obj, nonFunction); }, TypeError); |
| 128 assertEquals(obj, Object.unobserve(obj, observer.callback)); | 118 assertEquals(obj, Object.unobserve(obj, observer.callback)); |
| 129 | 119 |
| 130 | 120 |
| 131 // Object.getNotifier | 121 // Object.getNotifier |
| 132 var notifier = Object.getNotifier(obj); | 122 var notifier = Object.getNotifier(obj); |
| 133 assertSame(notifier, Object.getNotifier(obj)); | 123 assertSame(notifier, Object.getNotifier(obj)); |
| 134 assertEquals(null, Object.getNotifier(Object.freeze({}))); | 124 assertEquals(null, Object.getNotifier(Object.freeze({}))); |
| 135 assertFalse(notifier.hasOwnProperty('notify')); | 125 assertFalse(notifier.hasOwnProperty('notify')); |
| 136 assertEquals([], Object.keys(notifier)); | 126 assertEquals([], Object.keys(notifier)); |
| 137 var notifyDesc = Object.getOwnPropertyDescriptor(notifier.__proto__, 'notify'); | 127 var notifyDesc = Object.getOwnPropertyDescriptor(notifier.__proto__, 'notify'); |
| 138 assertTrue(notifyDesc.configurable); | 128 assertTrue(notifyDesc.configurable); |
| 139 assertTrue(notifyDesc.writable); | 129 assertTrue(notifyDesc.writable); |
| 140 assertFalse(notifyDesc.enumerable); | 130 assertFalse(notifyDesc.enumerable); |
| 141 assertThrows(function() { notifier.notify({}); }, TypeError); | 131 assertThrows(function() { notifier.notify({}); }, TypeError); |
| 142 assertThrows(function() { notifier.notify({ type: 4 }); }, TypeError); | 132 assertThrows(function() { notifier.notify({ type: 4 }); }, TypeError); |
| 143 | |
| 144 assertThrows(function() { notifier.performChange(1, function(){}); }, TypeError)
; | |
| 145 assertThrows(function() { notifier.performChange(undefined, function(){}); }, Ty
peError); | |
| 146 assertThrows(function() { notifier.performChange('foo', undefined); }, TypeError
); | |
| 147 assertThrows(function() { notifier.performChange('foo', 'bar'); }, TypeError); | |
| 148 var testSelf = {}; | |
| 149 notifier.performChange('foo', function() { | |
| 150 assertTrue(testSelf === this); | |
| 151 }, testSelf); | |
| 152 var self = this; | |
| 153 notifier.performChange('foo', function() { | |
| 154 assertTrue(self === this); | |
| 155 }); | |
| 156 | |
| 157 var notify = notifier.notify; | 133 var notify = notifier.notify; |
| 158 assertThrows(function() { notify.call(undefined, { type: 'a' }); }, TypeError); | 134 assertThrows(function() { notify.call(undefined, { type: 'a' }); }, TypeError); |
| 159 assertThrows(function() { notify.call(null, { type: 'a' }); }, TypeError); | 135 assertThrows(function() { notify.call(null, { type: 'a' }); }, TypeError); |
| 160 assertThrows(function() { notify.call(5, { type: 'a' }); }, TypeError); | 136 assertThrows(function() { notify.call(5, { type: 'a' }); }, TypeError); |
| 161 assertThrows(function() { notify.call('hello', { type: 'a' }); }, TypeError); | 137 assertThrows(function() { notify.call('hello', { type: 'a' }); }, TypeError); |
| 162 assertThrows(function() { notify.call(false, { type: 'a' }); }, TypeError); | 138 assertThrows(function() { notify.call(false, { type: 'a' }); }, TypeError); |
| 163 assertThrows(function() { notify.call({}, { type: 'a' }); }, TypeError); | 139 assertThrows(function() { notify.call({}, { type: 'a' }); }, TypeError); |
| 164 assertFalse(recordCreated); | 140 assertFalse(recordCreated); |
| 165 notifier.notify(changeRecordWithAccessor); | 141 notifier.notify(changeRecordWithAccessor); |
| 166 assertFalse(recordCreated); // not observed yet | 142 assertFalse(recordCreated); // not observed yet |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 reset(); | 188 reset(); |
| 213 Object.deliverChangeRecords(observer.callback); | 189 Object.deliverChangeRecords(observer.callback); |
| 214 observer.assertNotCalled(); | 190 observer.assertNotCalled(); |
| 215 | 191 |
| 216 | 192 |
| 217 // Multiple observation has no effect. | 193 // Multiple observation has no effect. |
| 218 reset(); | 194 reset(); |
| 219 Object.observe(obj, observer.callback); | 195 Object.observe(obj, observer.callback); |
| 220 Object.observe(obj, observer.callback); | 196 Object.observe(obj, observer.callback); |
| 221 Object.getNotifier(obj).notify({ | 197 Object.getNotifier(obj).notify({ |
| 222 type: 'updated', | 198 type: 'foo', |
| 223 }); | 199 }); |
| 224 Object.deliverChangeRecords(observer.callback); | 200 Object.deliverChangeRecords(observer.callback); |
| 225 observer.assertCalled(); | 201 observer.assertCalled(); |
| 226 | 202 |
| 227 | 203 |
| 228 // Observation can be stopped. | 204 // Observation can be stopped. |
| 229 reset(); | 205 reset(); |
| 230 Object.unobserve(obj, observer.callback); | 206 Object.unobserve(obj, observer.callback); |
| 231 Object.getNotifier(obj).notify({ | 207 Object.getNotifier(obj).notify({ |
| 232 type: 'updated', | 208 type: 'foo', |
| 233 }); | 209 }); |
| 234 Object.deliverChangeRecords(observer.callback); | 210 Object.deliverChangeRecords(observer.callback); |
| 235 observer.assertNotCalled(); | 211 observer.assertNotCalled(); |
| 236 | 212 |
| 237 | 213 |
| 238 // Multiple unobservation has no effect | 214 // Multiple unobservation has no effect |
| 239 reset(); | 215 reset(); |
| 240 Object.unobserve(obj, observer.callback); | 216 Object.unobserve(obj, observer.callback); |
| 241 Object.unobserve(obj, observer.callback); | 217 Object.unobserve(obj, observer.callback); |
| 242 Object.getNotifier(obj).notify({ | 218 Object.getNotifier(obj).notify({ |
| 243 type: 'updated', | 219 type: 'foo', |
| 244 }); | 220 }); |
| 245 Object.deliverChangeRecords(observer.callback); | 221 Object.deliverChangeRecords(observer.callback); |
| 246 observer.assertNotCalled(); | 222 observer.assertNotCalled(); |
| 247 | 223 |
| 248 | 224 |
| 249 // Re-observation works and only includes changeRecords after of call. | 225 // Re-observation works and only includes changeRecords after of call. |
| 250 reset(); | 226 reset(); |
| 251 Object.getNotifier(obj).notify({ | 227 Object.getNotifier(obj).notify({ |
| 252 type: 'updated', | 228 type: 'foo', |
| 253 }); | 229 }); |
| 254 Object.observe(obj, observer.callback); | 230 Object.observe(obj, observer.callback); |
| 255 Object.getNotifier(obj).notify({ | 231 Object.getNotifier(obj).notify({ |
| 256 type: 'updated', | 232 type: 'foo', |
| 257 }); | 233 }); |
| 258 records = undefined; | 234 records = undefined; |
| 259 Object.deliverChangeRecords(observer.callback); | 235 Object.deliverChangeRecords(observer.callback); |
| 260 observer.assertRecordCount(1); | 236 observer.assertRecordCount(1); |
| 261 | 237 |
| 262 | 238 |
| 263 // Observing a continuous stream of changes, while itermittantly unobserving. | 239 // Observing a continuous stream of changes, while itermittantly unobserving. |
| 264 reset(); | 240 reset(); |
| 265 Object.observe(obj, observer.callback); | 241 Object.observe(obj, observer.callback); |
| 266 Object.getNotifier(obj).notify({ | 242 Object.getNotifier(obj).notify({ |
| 267 type: 'updated', | 243 type: 'foo', |
| 268 val: 1 | 244 val: 1 |
| 269 }); | 245 }); |
| 270 | 246 |
| 271 Object.unobserve(obj, observer.callback); | 247 Object.unobserve(obj, observer.callback); |
| 272 Object.getNotifier(obj).notify({ | 248 Object.getNotifier(obj).notify({ |
| 273 type: 'updated', | 249 type: 'foo', |
| 274 val: 2 | 250 val: 2 |
| 275 }); | 251 }); |
| 276 | 252 |
| 277 Object.observe(obj, observer.callback); | 253 Object.observe(obj, observer.callback); |
| 278 Object.getNotifier(obj).notify({ | 254 Object.getNotifier(obj).notify({ |
| 279 type: 'updated', | 255 type: 'foo', |
| 280 val: 3 | 256 val: 3 |
| 281 }); | 257 }); |
| 282 | 258 |
| 283 Object.unobserve(obj, observer.callback); | 259 Object.unobserve(obj, observer.callback); |
| 284 Object.getNotifier(obj).notify({ | 260 Object.getNotifier(obj).notify({ |
| 285 type: 'updated', | 261 type: 'foo', |
| 286 val: 4 | 262 val: 4 |
| 287 }); | 263 }); |
| 288 | 264 |
| 289 Object.observe(obj, observer.callback); | 265 Object.observe(obj, observer.callback); |
| 290 Object.getNotifier(obj).notify({ | 266 Object.getNotifier(obj).notify({ |
| 291 type: 'updated', | 267 type: 'foo', |
| 292 val: 5 | 268 val: 5 |
| 293 }); | 269 }); |
| 294 | 270 |
| 295 Object.unobserve(obj, observer.callback); | 271 Object.unobserve(obj, observer.callback); |
| 296 Object.deliverChangeRecords(observer.callback); | 272 Object.deliverChangeRecords(observer.callback); |
| 297 observer.assertCallbackRecords([ | 273 observer.assertCallbackRecords([ |
| 298 { object: obj, type: 'updated', val: 1 }, | 274 { object: obj, type: 'foo', val: 1 }, |
| 299 { object: obj, type: 'updated', val: 3 }, | 275 { object: obj, type: 'foo', val: 3 }, |
| 300 { object: obj, type: 'updated', val: 5 } | 276 { object: obj, type: 'foo', val: 5 } |
| 301 ]); | |
| 302 | |
| 303 // Accept | |
| 304 reset(); | |
| 305 Object.observe(obj, observer.callback, []); | |
| 306 Object.getNotifier(obj).notify({ | |
| 307 type: 'new' | |
| 308 }); | |
| 309 Object.getNotifier(obj).notify({ | |
| 310 type: 'updated' | |
| 311 }); | |
| 312 Object.getNotifier(obj).notify({ | |
| 313 type: 'deleted' | |
| 314 }); | |
| 315 Object.getNotifier(obj).notify({ | |
| 316 type: 'reconfigured' | |
| 317 }); | |
| 318 Object.getNotifier(obj).notify({ | |
| 319 type: 'prototype' | |
| 320 }); | |
| 321 Object.deliverChangeRecords(observer.callback); | |
| 322 observer.assertNotCalled(); | |
| 323 | |
| 324 reset(); | |
| 325 Object.observe(obj, observer.callback, ['new', 'deleted', 'prototype']); | |
| 326 Object.getNotifier(obj).notify({ | |
| 327 type: 'new' | |
| 328 }); | |
| 329 Object.getNotifier(obj).notify({ | |
| 330 type: 'updated' | |
| 331 }); | |
| 332 Object.getNotifier(obj).notify({ | |
| 333 type: 'deleted' | |
| 334 }); | |
| 335 Object.getNotifier(obj).notify({ | |
| 336 type: 'deleted' | |
| 337 }); | |
| 338 Object.getNotifier(obj).notify({ | |
| 339 type: 'reconfigured' | |
| 340 }); | |
| 341 Object.getNotifier(obj).notify({ | |
| 342 type: 'prototype' | |
| 343 }); | |
| 344 Object.deliverChangeRecords(observer.callback); | |
| 345 observer.assertCallbackRecords([ | |
| 346 { object: obj, type: 'new' }, | |
| 347 { object: obj, type: 'deleted' }, | |
| 348 { object: obj, type: 'deleted' }, | |
| 349 { object: obj, type: 'prototype' } | |
| 350 ]); | |
| 351 | |
| 352 reset(); | |
| 353 Object.observe(obj, observer.callback, ['updated', 'foo']); | |
| 354 Object.getNotifier(obj).notify({ | |
| 355 type: 'new' | |
| 356 }); | |
| 357 Object.getNotifier(obj).notify({ | |
| 358 type: 'updated' | |
| 359 }); | |
| 360 Object.getNotifier(obj).notify({ | |
| 361 type: 'deleted' | |
| 362 }); | |
| 363 Object.getNotifier(obj).notify({ | |
| 364 type: 'foo' | |
| 365 }); | |
| 366 Object.getNotifier(obj).notify({ | |
| 367 type: 'bar' | |
| 368 }); | |
| 369 Object.getNotifier(obj).notify({ | |
| 370 type: 'foo' | |
| 371 }); | |
| 372 Object.deliverChangeRecords(observer.callback); | |
| 373 observer.assertCallbackRecords([ | |
| 374 { object: obj, type: 'updated' }, | |
| 375 { object: obj, type: 'foo' }, | |
| 376 { object: obj, type: 'foo' } | |
| 377 ]); | |
| 378 | |
| 379 reset(); | |
| 380 function Thingy(a, b, c) { | |
| 381 this.a = a; | |
| 382 this.b = b; | |
| 383 } | |
| 384 | |
| 385 Thingy.MULTIPLY = 'multiply'; | |
| 386 Thingy.INCREMENT = 'increment'; | |
| 387 Thingy.INCREMENT_AND_MULTIPLY = 'incrementAndMultiply'; | |
| 388 | |
| 389 Thingy.prototype = { | |
| 390 increment: function(amount) { | |
| 391 var notifier = Object.getNotifier(this); | |
| 392 | |
| 393 notifier.performChange(Thingy.INCREMENT, function() { | |
| 394 this.a += amount; | |
| 395 this.b += amount; | |
| 396 }, this); | |
| 397 | |
| 398 notifier.notify({ | |
| 399 object: this, | |
| 400 type: Thingy.INCREMENT, | |
| 401 incremented: amount | |
| 402 }); | |
| 403 }, | |
| 404 | |
| 405 multiply: function(amount) { | |
| 406 var notifier = Object.getNotifier(this); | |
| 407 | |
| 408 notifier.performChange(Thingy.MULTIPLY, function() { | |
| 409 this.a *= amount; | |
| 410 this.b *= amount; | |
| 411 }, this); | |
| 412 | |
| 413 notifier.notify({ | |
| 414 object: this, | |
| 415 type: Thingy.MULTIPLY, | |
| 416 multiplied: amount | |
| 417 }); | |
| 418 }, | |
| 419 | |
| 420 incrementAndMultiply: function(incAmount, multAmount) { | |
| 421 var notifier = Object.getNotifier(this); | |
| 422 | |
| 423 notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() { | |
| 424 this.increment(incAmount); | |
| 425 this.multiply(multAmount); | |
| 426 }, this); | |
| 427 | |
| 428 notifier.notify({ | |
| 429 object: this, | |
| 430 type: Thingy.INCREMENT_AND_MULTIPLY, | |
| 431 incremented: incAmount, | |
| 432 multiplied: multAmount | |
| 433 }); | |
| 434 } | |
| 435 } | |
| 436 | |
| 437 Thingy.observe = function(thingy, callback) { | |
| 438 Object.observe(thingy, callback, [Thingy.INCREMENT, | |
| 439 Thingy.MULTIPLY, | |
| 440 Thingy.INCREMENT_AND_MULTIPLY, | |
| 441 'updated']); | |
| 442 } | |
| 443 | |
| 444 Thingy.unobserve = function(thingy, callback) { | |
| 445 Object.unobserve(thingy); | |
| 446 } | |
| 447 | |
| 448 var thingy = new Thingy(2, 4); | |
| 449 | |
| 450 Object.observe(thingy, observer.callback); | |
| 451 Thingy.observe(thingy, observer2.callback); | |
| 452 thingy.increment(3); // { a: 5, b: 7 } | |
| 453 thingy.b++; // { a: 5, b: 8 } | |
| 454 thingy.multiply(2); // { a: 10, b: 16 } | |
| 455 thingy.a++; // { a: 11, b: 16 } | |
| 456 thingy.incrementAndMultiply(2, 2); // { a: 26, b: 36 } | |
| 457 | |
| 458 Object.deliverChangeRecords(observer.callback); | |
| 459 Object.deliverChangeRecords(observer2.callback); | |
| 460 observer.assertCallbackRecords([ | |
| 461 { object: thingy, type: 'updated', name: 'a', oldValue: 2 }, | |
| 462 { object: thingy, type: 'updated', name: 'b', oldValue: 4 }, | |
| 463 { object: thingy, type: 'updated', name: 'b', oldValue: 7 }, | |
| 464 { object: thingy, type: 'updated', name: 'a', oldValue: 5 }, | |
| 465 { object: thingy, type: 'updated', name: 'b', oldValue: 8 }, | |
| 466 { object: thingy, type: 'updated', name: 'a', oldValue: 10 }, | |
| 467 { object: thingy, type: 'updated', name: 'a', oldValue: 11 }, | |
| 468 { object: thingy, type: 'updated', name: 'b', oldValue: 16 }, | |
| 469 { object: thingy, type: 'updated', name: 'a', oldValue: 13 }, | |
| 470 { object: thingy, type: 'updated', name: 'b', oldValue: 18 }, | |
| 471 ]); | |
| 472 observer2.assertCallbackRecords([ | |
| 473 { object: thingy, type: Thingy.INCREMENT, incremented: 3 }, | |
| 474 { object: thingy, type: 'updated', name: 'b', oldValue: 7 }, | |
| 475 { object: thingy, type: Thingy.MULTIPLY, multiplied: 2 }, | |
| 476 { object: thingy, type: 'updated', name: 'a', oldValue: 10 }, | |
| 477 { | |
| 478 object: thingy, | |
| 479 type: Thingy.INCREMENT_AND_MULTIPLY, | |
| 480 incremented: 2, | |
| 481 multiplied: 2 | |
| 482 } | |
| 483 ]); | 277 ]); |
| 484 | 278 |
| 485 | 279 |
| 486 reset(); | |
| 487 function RecursiveThingy() {} | |
| 488 | |
| 489 RecursiveThingy.MULTIPLY_FIRST_N = 'multiplyFirstN'; | |
| 490 | |
| 491 RecursiveThingy.prototype = { | |
| 492 __proto__: Array.prototype, | |
| 493 | |
| 494 multiplyFirstN: function(amount, n) { | |
| 495 if (!n) | |
| 496 return; | |
| 497 var notifier = Object.getNotifier(this); | |
| 498 notifier.performChange(RecursiveThingy.MULTIPLY_FIRST_N, function() { | |
| 499 this[n-1] = this[n-1]*amount; | |
| 500 this.multiplyFirstN(amount, n-1); | |
| 501 }, this); | |
| 502 | |
| 503 notifier.notify({ | |
| 504 object: this, | |
| 505 type: RecursiveThingy.MULTIPLY_FIRST_N, | |
| 506 multiplied: amount, | |
| 507 n: n | |
| 508 }); | |
| 509 }, | |
| 510 } | |
| 511 | |
| 512 RecursiveThingy.observe = function(thingy, callback) { | |
| 513 Object.observe(thingy, callback, [RecursiveThingy.MULTIPLY_FIRST_N]); | |
| 514 } | |
| 515 | |
| 516 RecursiveThingy.unobserve = function(thingy, callback) { | |
| 517 Object.unobserve(thingy); | |
| 518 } | |
| 519 | |
| 520 var thingy = new RecursiveThingy; | |
| 521 thingy.push(1, 2, 3, 4); | |
| 522 | |
| 523 Object.observe(thingy, observer.callback); | |
| 524 RecursiveThingy.observe(thingy, observer2.callback); | |
| 525 thingy.multiplyFirstN(2, 3); // [2, 4, 6, 4] | |
| 526 | |
| 527 Object.deliverChangeRecords(observer.callback); | |
| 528 Object.deliverChangeRecords(observer2.callback); | |
| 529 observer.assertCallbackRecords([ | |
| 530 { object: thingy, type: 'updated', name: '2', oldValue: 3 }, | |
| 531 { object: thingy, type: 'updated', name: '1', oldValue: 2 }, | |
| 532 { object: thingy, type: 'updated', name: '0', oldValue: 1 } | |
| 533 ]); | |
| 534 observer2.assertCallbackRecords([ | |
| 535 { object: thingy, type: RecursiveThingy.MULTIPLY_FIRST_N, multiplied: 2, n: 3
} | |
| 536 ]); | |
| 537 | |
| 538 reset(); | |
| 539 function DeckSuit() { | |
| 540 this.push('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'A', 'Q', 'K'); | |
| 541 } | |
| 542 | |
| 543 DeckSuit.SHUFFLE = 'shuffle'; | |
| 544 | |
| 545 DeckSuit.prototype = { | |
| 546 __proto__: Array.prototype, | |
| 547 | |
| 548 shuffle: function() { | |
| 549 var notifier = Object.getNotifier(this); | |
| 550 notifier.performChange(DeckSuit.SHUFFLE, function() { | |
| 551 this.reverse(); | |
| 552 this.sort(function() { return Math.random()* 2 - 1; }); | |
| 553 var cut = this.splice(0, 6); | |
| 554 Array.prototype.push.apply(this, cut); | |
| 555 this.reverse(); | |
| 556 this.sort(function() { return Math.random()* 2 - 1; }); | |
| 557 var cut = this.splice(0, 6); | |
| 558 Array.prototype.push.apply(this, cut); | |
| 559 this.reverse(); | |
| 560 this.sort(function() { return Math.random()* 2 - 1; }); | |
| 561 }, this); | |
| 562 | |
| 563 notifier.notify({ | |
| 564 object: this, | |
| 565 type: DeckSuit.SHUFFLE | |
| 566 }); | |
| 567 }, | |
| 568 } | |
| 569 | |
| 570 DeckSuit.observe = function(thingy, callback) { | |
| 571 Object.observe(thingy, callback, [DeckSuit.SHUFFLE]); | |
| 572 } | |
| 573 | |
| 574 DeckSuit.unobserve = function(thingy, callback) { | |
| 575 Object.unobserve(thingy); | |
| 576 } | |
| 577 | |
| 578 var deck = new DeckSuit; | |
| 579 | |
| 580 DeckSuit.observe(deck, observer2.callback); | |
| 581 deck.shuffle(); | |
| 582 | |
| 583 Object.deliverChangeRecords(observer2.callback); | |
| 584 observer2.assertCallbackRecords([ | |
| 585 { object: deck, type: DeckSuit.SHUFFLE } | |
| 586 ]); | |
| 587 | |
| 588 // Observing multiple objects; records appear in order. | 280 // Observing multiple objects; records appear in order. |
| 589 reset(); | 281 reset(); |
| 590 var obj2 = {}; | 282 var obj2 = {}; |
| 591 var obj3 = {} | 283 var obj3 = {} |
| 592 Object.observe(obj, observer.callback); | 284 Object.observe(obj, observer.callback); |
| 593 Object.observe(obj3, observer.callback); | 285 Object.observe(obj3, observer.callback); |
| 594 Object.observe(obj2, observer.callback); | 286 Object.observe(obj2, observer.callback); |
| 595 Object.getNotifier(obj).notify({ | 287 Object.getNotifier(obj).notify({ |
| 596 type: 'new', | 288 type: 'foo1', |
| 597 }); | 289 }); |
| 598 Object.getNotifier(obj2).notify({ | 290 Object.getNotifier(obj2).notify({ |
| 599 type: 'updated', | 291 type: 'foo2', |
| 600 }); | 292 }); |
| 601 Object.getNotifier(obj3).notify({ | 293 Object.getNotifier(obj3).notify({ |
| 602 type: 'deleted', | 294 type: 'foo3', |
| 603 }); | 295 }); |
| 604 Object.observe(obj3, observer.callback); | 296 Object.observe(obj3, observer.callback); |
| 605 Object.deliverChangeRecords(observer.callback); | 297 Object.deliverChangeRecords(observer.callback); |
| 606 observer.assertCallbackRecords([ | 298 observer.assertCallbackRecords([ |
| 607 { object: obj, type: 'new' }, | 299 { object: obj, type: 'foo1' }, |
| 608 { object: obj2, type: 'updated' }, | 300 { object: obj2, type: 'foo2' }, |
| 609 { object: obj3, type: 'deleted' } | 301 { object: obj3, type: 'foo3' } |
| 610 ]); | 302 ]); |
| 611 | 303 |
| 612 | 304 |
| 613 // Recursive observation. | 305 // Recursive observation. |
| 614 var obj = {a: 1}; | 306 var obj = {a: 1}; |
| 615 var callbackCount = 0; | 307 var callbackCount = 0; |
| 616 function recursiveObserver(r) { | 308 function recursiveObserver(r) { |
| 617 assertEquals(1, r.length); | 309 assertEquals(1, r.length); |
| 618 ++callbackCount; | 310 ++callbackCount; |
| 619 if (r[0].oldValue < 100) ++obj[r[0].name]; | 311 if (r[0].oldValue < 100) ++obj[r[0].name]; |
| (...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1378 for (var n1 = 0; n1 < 3; ++n1) | 1070 for (var n1 = 0; n1 < 3; ++n1) |
| 1379 for (var n2 = 0; n2 < 3; ++n2) | 1071 for (var n2 = 0; n2 < 3; ++n2) |
| 1380 for (var i in mutation) | 1072 for (var i in mutation) |
| 1381 TestFastElementsLength(mutation[i], b1 != 0, b2 != 0, 20*n1, 20*n2); | 1073 TestFastElementsLength(mutation[i], b1 != 0, b2 != 0, 20*n1, 20*n2); |
| 1382 | 1074 |
| 1383 for (var b1 = 0; b1 < 2; ++b1) | 1075 for (var b1 = 0; b1 < 2; ++b1) |
| 1384 for (var b2 = 0; b2 < 2; ++b2) | 1076 for (var b2 = 0; b2 < 2; ++b2) |
| 1385 for (var n = 0; n < 3; ++n) | 1077 for (var n = 0; n < 3; ++n) |
| 1386 for (var i in mutationByIncr) | 1078 for (var i in mutationByIncr) |
| 1387 TestFastElementsLength(mutationByIncr[i], b1 != 0, b2 != 0, 7*n, 7*n+1); | 1079 TestFastElementsLength(mutationByIncr[i], b1 != 0, b2 != 0, 7*n, 7*n+1); |
| OLD | NEW |