 Chromium Code Reviews
 Chromium Code Reviews Issue 183683022:
  Enable Object.observe by default  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 183683022:
  Enable Object.observe by default  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| 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 | 
| 11 // with the distribution. | 11 // with the distribution. | 
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its | 
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived | 
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. | 
| 15 // | 15 // | 
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 27 | 27 | 
| 28 "use strict"; | |
| 
rafaelw
2014/03/05 00:48:46
it seems like all the built-in native js files are
 
rossberg
2014/03/06 08:41:35
That's surprising. The directive here should only
 
rafaelw
2014/03/07 04:33:06
You are right. I tried adding it back and got not
 
rossberg
2014/03/07 07:14:44
Please keep it nevertheless -- we have a midterm g
 
rafaelw
2014/03/08 02:48:19
Ok. Seems wrong, but I'll leave it in.
On 2014/03
 | |
| 29 | |
| 30 // Overview: | 28 // Overview: | 
| 31 // | 29 // | 
| 32 // This file contains all of the routing and accounting for Object.observe. | 30 // This file contains all of the routing and accounting for Object.observe. | 
| 33 // User code will interact with these mechanisms via the Object.observe APIs | 31 // User code will interact with these mechanisms via the Object.observe APIs | 
| 34 // and, as a side effect of mutation objects which are observed. The V8 runtime | 32 // and, as a side effect of mutation objects which are observed. The V8 runtime | 
| 35 // (both C++ and JS) will interact with these mechanisms primarily by enqueuing | 33 // (both C++ and JS) will interact with these mechanisms primarily by enqueuing | 
| 36 // proper change records for objects which were mutated. The Object.observe | 34 // proper change records for objects which were mutated. The Object.observe | 
| 37 // routing and accounting consists primarily of three participants | 35 // routing and accounting consists primarily of three participants | 
| 38 // | 36 // | 
| 39 // 1) ObjectInfo. This represents the observed state of a given object. It | 37 // 1) ObjectInfo. This represents the observed state of a given object. It | 
| 40 // records what callbacks are observing the object, with what options, and | 38 // records what callbacks are observing the object, with what options, and | 
| 41 // what "change types" are in progress on the object (i.e. via | 39 // what "change types" are in progress on the object (i.e. via | 
| 42 // notifier.performChange). | 40 // notifier.performChange). | 
| 43 // | 41 // | 
| 44 // 2) CallbackInfo. This represents a callback used for observation. It holds | 42 // 2) CallbackInfo. This represents a callback used for observation. It holds | 
| 45 // the records which must be delivered to the callback, as well as the global | 43 // the records which must be delivered to the callback, as well as the global | 
| 46 // priority of the callback (which determines delivery order between | 44 // priority of the callback (which determines delivery order between | 
| 47 // callbacks). | 45 // callbacks). | 
| 48 // | 46 // | 
| 49 // 3) observationState.pendingObservers. This is the set of observers which | 47 // 3) observationState.pendingObservers. This is the set of observers which | 
| 50 // have change records which must be delivered. During "normal" delivery | 48 // have change records which must be delivered. During "normal" delivery | 
| 51 // (i.e. not Object.deliverChangeRecords), this is the mechanism by which | 49 // (i.e. not Object.deliverChangeRecords), this is the mechanism by which | 
| 52 // callbacks are invoked in the proper order until there are no more | 50 // callbacks are invoked in the proper order until there are no more | 
| 53 // change records pending to a callback. | 51 // change records pending to a callback. | 
| 54 // | 52 // | 
| 55 // Note that in order to reduce allocation and processing costs, the | 53 // Note that in order to reduce allocation and processing costs, the | 
| 56 // implementation of (1) and (2) have "optimized" states which represent | 54 // implementation of (1) and (2) have "optimized" states which represent | 
| 57 // common cases which can be handled more efficiently. | 55 // common cases which can be handled more efficiently. | 
| 58 | 56 | 
| 59 var observationState = %GetObservationState(); | 57 var observationState; | 
| 60 if (IS_UNDEFINED(observationState.callbackInfoMap)) { | 58 | 
| 61 observationState.callbackInfoMap = %ObservationWeakMapCreate(); | 59 function GetObservationState() { | 
| 62 observationState.objectInfoMap = %ObservationWeakMapCreate(); | 60 if (IS_UNDEFINED(observationState)) | 
| 63 observationState.notifierObjectInfoMap = %ObservationWeakMapCreate(); | 61 observationState = %GetObservationState(); | 
| 64 observationState.pendingObservers = null; | 62 | 
| 65 observationState.nextCallbackPriority = 0; | 63 if (IS_UNDEFINED(observationState.callbackInfoMap)) { | 
| 64 observationState.callbackInfoMap = %ObservationWeakMapCreate(); | |
| 65 observationState.objectInfoMap = %ObservationWeakMapCreate(); | |
| 66 observationState.notifierObjectInfoMap = %ObservationWeakMapCreate(); | |
| 67 observationState.pendingObservers = null; | |
| 68 observationState.nextCallbackPriority = 0; | |
| 69 } | |
| 70 | |
| 71 return observationState; | |
| 66 } | 72 } | 
| 67 | 73 | 
| 68 function ObservationWeakMap(map) { | 74 function GetWeakMapWrapper() { | 
| 69 this.map_ = map; | 75 function MapWrapper(map) { | 
| 76 this.map_ = map; | |
| 77 }; | |
| 78 | |
| 79 MapWrapper.prototype = { | |
| 80 get: function(key) { | |
| 81 key = %UnwrapGlobalProxy(key); | |
| 82 if (!IS_SPEC_OBJECT(key)) return UNDEFINED; | |
| 83 return %WeakCollectionGet(this.map_, key); | |
| 84 }, | |
| 85 set: function(key, value) { | |
| 86 key = %UnwrapGlobalProxy(key); | |
| 87 if (!IS_SPEC_OBJECT(key)) return UNDEFINED; | |
| 88 %WeakCollectionSet(this.map_, key, value); | |
| 89 }, | |
| 90 has: function(key) { | |
| 91 return !IS_UNDEFINED(this.get(key)); | |
| 92 } | |
| 93 }; | |
| 94 | |
| 95 return MapWrapper; | |
| 70 } | 96 } | 
| 71 | 97 | 
| 72 ObservationWeakMap.prototype = { | 98 var contextMaps; | 
| 73 get: function(key) { | 99 | 
| 74 key = %UnwrapGlobalProxy(key); | 100 function GetContextMaps() { | 
| 75 if (!IS_SPEC_OBJECT(key)) return UNDEFINED; | 101 if (IS_UNDEFINED(contextMaps)) { | 
| 76 return %WeakCollectionGet(this.map_, key); | 102 var map = GetWeakMapWrapper(); | 
| 77 }, | 103 var observationState = GetObservationState(); | 
| 78 set: function(key, value) { | 104 contextMaps = { | 
| 79 key = %UnwrapGlobalProxy(key); | 105 callbackInfoMap: new map(observationState.callbackInfoMap), | 
| 80 if (!IS_SPEC_OBJECT(key)) return UNDEFINED; | 106 objectInfoMap: new map(observationState.objectInfoMap), | 
| 81 %WeakCollectionSet(this.map_, key, value); | 107 notifierObjectInfoMap: new map(observationState.notifierObjectInfoMap) | 
| 82 }, | 108 }; | 
| 83 has: function(key) { | |
| 84 return !IS_UNDEFINED(this.get(key)); | |
| 85 } | 109 } | 
| 86 }; | |
| 87 | 110 | 
| 88 var callbackInfoMap = | 111 return contextMaps; | 
| 89 new ObservationWeakMap(observationState.callbackInfoMap); | 112 } | 
| 90 var objectInfoMap = new ObservationWeakMap(observationState.objectInfoMap); | 113 | 
| 91 var notifierObjectInfoMap = | 114 function GetCallbackInfoMap() { | 
| 92 new ObservationWeakMap(observationState.notifierObjectInfoMap); | 115 return GetContextMaps().callbackInfoMap; | 
| 116 } | |
| 117 | |
| 118 function GetObjectInfoMap() { | |
| 119 return GetContextMaps().objectInfoMap; | |
| 120 } | |
| 121 | |
| 122 function GetNotifierObjectInfoMap() { | |
| 123 return GetContextMaps().notifierObjectInfoMap; | |
| 124 } | |
| 125 | |
| 126 function GetPendingObservers() { | |
| 127 return GetObservationState().pendingObservers; | |
| 128 } | |
| 129 | |
| 130 function SetPendingObservers(pendingObservers) { | |
| 131 GetObservationState().pendingObservers = pendingObservers; | |
| 132 } | |
| 133 | |
| 134 function GetNextCallbackPriority() { | |
| 135 return GetObservationState().nextCallbackPriority++; | |
| 136 } | |
| 93 | 137 | 
| 94 function nullProtoObject() { | 138 function nullProtoObject() { | 
| 95 return { __proto__: null }; | 139 return { __proto__: null }; | 
| 96 } | 140 } | 
| 97 | 141 | 
| 98 function TypeMapCreate() { | 142 function TypeMapCreate() { | 
| 99 return nullProtoObject(); | 143 return nullProtoObject(); | 
| 100 } | 144 } | 
| 101 | 145 | 
| 102 function TypeMapAddType(typeMap, type, ignoreDuplicate) { | 146 function TypeMapAddType(typeMap, type, ignoreDuplicate) { | 
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 if (!%IsJSProxy(object)) | 217 if (!%IsJSProxy(object)) | 
| 174 %SetIsObserved(object); | 218 %SetIsObserved(object); | 
| 175 | 219 | 
| 176 objectInfo = { | 220 objectInfo = { | 
| 177 object: object, | 221 object: object, | 
| 178 changeObservers: null, | 222 changeObservers: null, | 
| 179 notifier: null, | 223 notifier: null, | 
| 180 performing: null, | 224 performing: null, | 
| 181 performingCount: 0, | 225 performingCount: 0, | 
| 182 }; | 226 }; | 
| 183 objectInfoMap.set(object, objectInfo); | 227 GetObjectInfoMap().set(object, objectInfo); | 
| 184 } | 228 } | 
| 185 return objectInfo; | 229 return objectInfo; | 
| 186 } | 230 } | 
| 187 | 231 | 
| 188 function ObjectInfoGet(object) { | 232 function ObjectInfoGet(object) { | 
| 189 return objectInfoMap.get(object); | 233 return GetObjectInfoMap().get(object); | 
| 190 } | 234 } | 
| 191 | 235 | 
| 192 function ObjectInfoGetFromNotifier(notifier) { | 236 function ObjectInfoGetFromNotifier(notifier) { | 
| 193 return notifierObjectInfoMap.get(notifier); | 237 return GetNotifierObjectInfoMap().get(notifier); | 
| 194 } | 238 } | 
| 195 | 239 | 
| 196 function ObjectInfoGetNotifier(objectInfo) { | 240 function ObjectInfoGetNotifier(objectInfo) { | 
| 197 if (IS_NULL(objectInfo.notifier)) { | 241 if (IS_NULL(objectInfo.notifier)) { | 
| 198 objectInfo.notifier = { __proto__: notifierPrototype }; | 242 objectInfo.notifier = { __proto__: notifierPrototype }; | 
| 199 notifierObjectInfoMap.set(objectInfo.notifier, objectInfo); | 243 GetNotifierObjectInfoMap().set(objectInfo.notifier, objectInfo); | 
| 200 } | 244 } | 
| 201 | 245 | 
| 202 return objectInfo.notifier; | 246 return objectInfo.notifier; | 
| 203 } | 247 } | 
| 204 | 248 | 
| 205 function ObjectInfoGetObject(objectInfo) { | 249 function ObjectInfoGetObject(objectInfo) { | 
| 206 return objectInfo.object; | 250 return objectInfo.object; | 
| 207 } | 251 } | 
| 208 | 252 | 
| 209 function ChangeObserversIsOptimized(changeObservers) { | 253 function ChangeObserversIsOptimized(changeObservers) { | 
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 arg.length < 0) | 339 arg.length < 0) | 
| 296 return false; | 340 return false; | 
| 297 | 341 | 
| 298 return true; | 342 return true; | 
| 299 } | 343 } | 
| 300 | 344 | 
| 301 // CallbackInfo's optimized state is just a number which represents its global | 345 // CallbackInfo's optimized state is just a number which represents its global | 
| 302 // priority. When a change record must be enqueued for the callback, it | 346 // priority. When a change record must be enqueued for the callback, it | 
| 303 // normalizes. When delivery clears any pending change records, it re-optimizes. | 347 // normalizes. When delivery clears any pending change records, it re-optimizes. | 
| 304 function CallbackInfoGet(callback) { | 348 function CallbackInfoGet(callback) { | 
| 305 return callbackInfoMap.get(callback); | 349 return GetCallbackInfoMap().get(callback); | 
| 306 } | 350 } | 
| 307 | 351 | 
| 308 function CallbackInfoGetOrCreate(callback) { | 352 function CallbackInfoGetOrCreate(callback) { | 
| 309 var callbackInfo = callbackInfoMap.get(callback); | 353 var callbackInfo = GetCallbackInfoMap().get(callback); | 
| 310 if (!IS_UNDEFINED(callbackInfo)) | 354 if (!IS_UNDEFINED(callbackInfo)) | 
| 311 return callbackInfo; | 355 return callbackInfo; | 
| 312 | 356 | 
| 313 var priority = observationState.nextCallbackPriority++ | 357 var priority = GetNextCallbackPriority(); | 
| 314 callbackInfoMap.set(callback, priority); | 358 GetCallbackInfoMap().set(callback, priority); | 
| 315 return priority; | 359 return priority; | 
| 316 } | 360 } | 
| 317 | 361 | 
| 318 function CallbackInfoGetPriority(callbackInfo) { | 362 function CallbackInfoGetPriority(callbackInfo) { | 
| 319 if (IS_NUMBER(callbackInfo)) | 363 if (IS_NUMBER(callbackInfo)) | 
| 320 return callbackInfo; | 364 return callbackInfo; | 
| 321 else | 365 else | 
| 322 return callbackInfo.priority; | 366 return callbackInfo.priority; | 
| 323 } | 367 } | 
| 324 | 368 | 
| 325 function CallbackInfoNormalize(callback) { | 369 function CallbackInfoNormalize(callback) { | 
| 326 var callbackInfo = callbackInfoMap.get(callback); | 370 var callbackInfo = GetCallbackInfoMap().get(callback); | 
| 327 if (IS_NUMBER(callbackInfo)) { | 371 if (IS_NUMBER(callbackInfo)) { | 
| 328 var priority = callbackInfo; | 372 var priority = callbackInfo; | 
| 329 callbackInfo = new InternalArray; | 373 callbackInfo = new InternalArray; | 
| 330 callbackInfo.priority = priority; | 374 callbackInfo.priority = priority; | 
| 331 callbackInfoMap.set(callback, callbackInfo); | 375 GetCallbackInfoMap().set(callback, callbackInfo); | 
| 332 } | 376 } | 
| 333 return callbackInfo; | 377 return callbackInfo; | 
| 334 } | 378 } | 
| 335 | 379 | 
| 336 function ObjectObserve(object, callback, acceptList) { | 380 function ObjectObserve(object, callback, acceptList) { | 
| 337 if (!IS_SPEC_OBJECT(object)) | 381 if (!IS_SPEC_OBJECT(object)) | 
| 338 throw MakeTypeError("observe_non_object", ["observe"]); | 382 throw MakeTypeError("observe_non_object", ["observe"]); | 
| 339 if (!IS_SPEC_FUNCTION(callback)) | 383 if (!IS_SPEC_FUNCTION(callback)) | 
| 340 throw MakeTypeError("observe_non_function", ["observe"]); | 384 throw MakeTypeError("observe_non_function", ["observe"]); | 
| 341 if (ObjectIsFrozen(callback)) | 385 if (ObjectIsFrozen(callback)) | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 var callback = ObserverGetCallback(observer); | 427 var callback = ObserverGetCallback(observer); | 
| 384 if (needsAccessCheck && | 428 if (needsAccessCheck && | 
| 385 // Drop all splice records on the floor for access-checked objects | 429 // Drop all splice records on the floor for access-checked objects | 
| 386 (changeRecord.type == 'splice' || | 430 (changeRecord.type == 'splice' || | 
| 387 !%IsAccessAllowedForObserver( | 431 !%IsAccessAllowedForObserver( | 
| 388 callback, changeRecord.object, changeRecord.name))) { | 432 callback, changeRecord.object, changeRecord.name))) { | 
| 389 return; | 433 return; | 
| 390 } | 434 } | 
| 391 | 435 | 
| 392 var callbackInfo = CallbackInfoNormalize(callback); | 436 var callbackInfo = CallbackInfoNormalize(callback); | 
| 393 if (IS_NULL(observationState.pendingObservers)) { | 437 if (IS_NULL(GetPendingObservers())) { | 
| 394 observationState.pendingObservers = nullProtoObject(); | 438 SetPendingObservers(nullProtoObject()) | 
| 395 GetMicrotaskQueue().push(ObserveMicrotaskRunner); | 439 GetMicrotaskQueue().push(ObserveMicrotaskRunner); | 
| 396 %SetMicrotaskPending(true); | 440 %SetMicrotaskPending(true); | 
| 397 } | 441 } | 
| 398 observationState.pendingObservers[callbackInfo.priority] = callback; | 442 GetPendingObservers()[callbackInfo.priority] = callback; | 
| 399 callbackInfo.push(changeRecord); | 443 callbackInfo.push(changeRecord); | 
| 400 } | 444 } | 
| 401 | 445 | 
| 402 function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) { | 446 function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) { | 
| 403 if (!ObjectInfoHasActiveObservers(objectInfo)) | 447 if (!ObjectInfoHasActiveObservers(objectInfo)) | 
| 404 return; | 448 return; | 
| 405 | 449 | 
| 406 var hasType = !IS_UNDEFINED(type); | 450 var hasType = !IS_UNDEFINED(type); | 
| 407 var newRecord = hasType ? | 451 var newRecord = hasType ? | 
| 408 { object: ObjectInfoGetObject(objectInfo), type: type } : | 452 { object: ObjectInfoGetObject(objectInfo), type: type } : | 
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 if (!IS_SPEC_OBJECT(object)) | 585 if (!IS_SPEC_OBJECT(object)) | 
| 542 throw MakeTypeError("observe_non_object", ["getNotifier"]); | 586 throw MakeTypeError("observe_non_object", ["getNotifier"]); | 
| 543 | 587 | 
| 544 if (ObjectIsFrozen(object)) return null; | 588 if (ObjectIsFrozen(object)) return null; | 
| 545 | 589 | 
| 546 var objectInfo = ObjectInfoGetOrCreate(object); | 590 var objectInfo = ObjectInfoGetOrCreate(object); | 
| 547 return ObjectInfoGetNotifier(objectInfo); | 591 return ObjectInfoGetNotifier(objectInfo); | 
| 548 } | 592 } | 
| 549 | 593 | 
| 550 function CallbackDeliverPending(callback) { | 594 function CallbackDeliverPending(callback) { | 
| 551 var callbackInfo = callbackInfoMap.get(callback); | 595 var callbackInfo = GetCallbackInfoMap().get(callback); | 
| 552 if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo)) | 596 if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo)) | 
| 553 return false; | 597 return false; | 
| 554 | 598 | 
| 555 // Clear the pending change records from callback and return it to its | 599 // Clear the pending change records from callback and return it to its | 
| 556 // "optimized" state. | 600 // "optimized" state. | 
| 557 var priority = callbackInfo.priority; | 601 var priority = callbackInfo.priority; | 
| 558 callbackInfoMap.set(callback, priority); | 602 GetCallbackInfoMap().set(callback, priority); | 
| 559 | 603 | 
| 560 if (observationState.pendingObservers) | 604 if (GetPendingObservers()) | 
| 561 delete observationState.pendingObservers[priority]; | 605 delete GetPendingObservers()[priority]; | 
| 562 | 606 | 
| 563 var delivered = []; | 607 var delivered = []; | 
| 564 %MoveArrayContents(callbackInfo, delivered); | 608 %MoveArrayContents(callbackInfo, delivered); | 
| 565 | 609 | 
| 566 try { | 610 try { | 
| 567 %_CallFunction(UNDEFINED, delivered, callback); | 611 %_CallFunction(UNDEFINED, delivered, callback); | 
| 568 } catch (ex) {} // TODO(rossberg): perhaps log uncaught exceptions. | 612 } catch (ex) {} // TODO(rossberg): perhaps log uncaught exceptions. | 
| 569 return true; | 613 return true; | 
| 570 } | 614 } | 
| 571 | 615 | 
| 572 function ObjectDeliverChangeRecords(callback) { | 616 function ObjectDeliverChangeRecords(callback) { | 
| 573 if (!IS_SPEC_FUNCTION(callback)) | 617 if (!IS_SPEC_FUNCTION(callback)) | 
| 574 throw MakeTypeError("observe_non_function", ["deliverChangeRecords"]); | 618 throw MakeTypeError("observe_non_function", ["deliverChangeRecords"]); | 
| 575 | 619 | 
| 576 while (CallbackDeliverPending(callback)) {} | 620 while (CallbackDeliverPending(callback)) {} | 
| 577 } | 621 } | 
| 578 | 622 | 
| 579 function ObserveMicrotaskRunner() { | 623 function ObserveMicrotaskRunner() { | 
| 580 var pendingObservers = observationState.pendingObservers; | 624 var pendingObservers = GetPendingObservers(); | 
| 581 if (pendingObservers) { | 625 if (pendingObservers) { | 
| 582 observationState.pendingObservers = null; | 626 SetPendingObservers(null); | 
| 583 for (var i in pendingObservers) { | 627 for (var i in pendingObservers) { | 
| 584 CallbackDeliverPending(pendingObservers[i]); | 628 CallbackDeliverPending(pendingObservers[i]); | 
| 585 } | 629 } | 
| 586 } | 630 } | 
| 587 } | 631 } | 
| 588 | 632 | 
| 589 function SetupObjectObserve() { | 633 function SetupObjectObserve() { | 
| 590 %CheckIsBootstrapping(); | 634 %CheckIsBootstrapping(); | 
| 591 InstallFunctions($Object, DONT_ENUM, $Array( | 635 InstallFunctions($Object, DONT_ENUM, $Array( | 
| 592 "deliverChangeRecords", ObjectDeliverChangeRecords, | 636 "deliverChangeRecords", ObjectDeliverChangeRecords, | 
| 593 "getNotifier", ObjectGetNotifier, | 637 "getNotifier", ObjectGetNotifier, | 
| 594 "observe", ObjectObserve, | 638 "observe", ObjectObserve, | 
| 595 "unobserve", ObjectUnobserve | 639 "unobserve", ObjectUnobserve | 
| 596 )); | 640 )); | 
| 597 InstallFunctions($Array, DONT_ENUM, $Array( | 641 InstallFunctions($Array, DONT_ENUM, $Array( | 
| 598 "observe", ArrayObserve, | 642 "observe", ArrayObserve, | 
| 599 "unobserve", ArrayUnobserve | 643 "unobserve", ArrayUnobserve | 
| 600 )); | 644 )); | 
| 601 InstallFunctions(notifierPrototype, DONT_ENUM, $Array( | 645 InstallFunctions(notifierPrototype, DONT_ENUM, $Array( | 
| 602 "notify", ObjectNotifierNotify, | 646 "notify", ObjectNotifierNotify, | 
| 603 "performChange", ObjectNotifierPerformChange | 647 "performChange", ObjectNotifierPerformChange | 
| 604 )); | 648 )); | 
| 605 } | 649 } | 
| 606 | 650 | 
| 607 SetupObjectObserve(); | 651 SetupObjectObserve(); | 
| OLD | NEW |