OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 "use strict"; | 5 "use strict"; |
6 | 6 |
7 // Overview: | 7 // Overview: |
8 // | 8 // |
9 // This file contains all of the routing and accounting for Object.observe. | 9 // This file contains all of the routing and accounting for Object.observe. |
10 // User code will interact with these mechanisms via the Object.observe APIs | 10 // User code will interact with these mechanisms via the Object.observe APIs |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
393 } | 393 } |
394 | 394 |
395 function ObserverEnqueueIfActive(observer, objectInfo, changeRecord, | 395 function ObserverEnqueueIfActive(observer, objectInfo, changeRecord, |
396 needsAccessCheck) { | 396 needsAccessCheck) { |
397 if (!ObserverIsActive(observer, objectInfo) || | 397 if (!ObserverIsActive(observer, objectInfo) || |
398 !TypeMapHasType(ObserverGetAcceptTypes(observer), changeRecord.type)) { | 398 !TypeMapHasType(ObserverGetAcceptTypes(observer), changeRecord.type)) { |
399 return; | 399 return; |
400 } | 400 } |
401 | 401 |
402 var callback = ObserverGetCallback(observer); | 402 var callback = ObserverGetCallback(observer); |
403 if (needsAccessCheck && | 403 if (needsAccessCheck && !%IsAccessAllowedForObserver(callback, |
404 // Drop all splice records on the floor for access-checked objects | 404 changeRecord.object, |
405 (changeRecord.type == 'splice' || | 405 changeRecord)) { |
406 !%IsAccessAllowedForObserver( | |
407 callback, changeRecord.object, changeRecord.name))) { | |
408 return; | 406 return; |
409 } | 407 } |
410 | 408 |
411 var callbackInfo = CallbackInfoNormalize(callback); | 409 var callbackInfo = CallbackInfoNormalize(callback); |
412 if (IS_NULL(GetPendingObservers())) { | 410 if (IS_NULL(GetPendingObservers())) { |
413 SetPendingObservers(nullProtoObject()) | 411 SetPendingObservers(nullProtoObject()) |
414 GetMicrotaskQueue().push(ObserveMicrotaskRunner); | 412 GetMicrotaskQueue().push(ObserveMicrotaskRunner); |
415 %SetMicrotaskPending(true); | 413 %SetMicrotaskPending(true); |
416 } | 414 } |
417 GetPendingObservers()[callbackInfo.priority] = callback; | 415 GetPendingObservers()[callbackInfo.priority] = callback; |
418 callbackInfo.push(changeRecord); | 416 callbackInfo.push(changeRecord); |
419 } | 417 } |
420 | 418 |
421 function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) { | 419 function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) { |
422 if (!ObjectInfoHasActiveObservers(objectInfo)) | 420 if (!ObjectInfoHasActiveObservers(objectInfo)) |
423 return; | 421 return; |
424 | 422 |
425 var hasType = !IS_UNDEFINED(type); | 423 var hasType = !IS_UNDEFINED(type); |
426 var newRecord = hasType ? | 424 var newRecord = hasType ? |
427 { object: ObjectInfoGetObject(objectInfo), type: type } : | 425 { object: ObjectInfoGetObject(objectInfo), type: type } : |
428 { object: ObjectInfoGetObject(objectInfo) }; | 426 { object: ObjectInfoGetObject(objectInfo) }; |
429 | 427 |
430 for (var prop in changeRecord) { | 428 for (var prop in changeRecord) { |
431 if (prop === 'object' || (hasType && prop === 'type')) continue; | 429 if (prop === 'object' || (hasType && prop === 'type')) continue; |
432 %DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop], | 430 %DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop], |
433 READ_ONLY + DONT_DELETE); | 431 READ_ONLY + DONT_DELETE); |
434 } | 432 } |
435 ObjectFreeze(newRecord); | 433 ObjectFreeze(newRecord); |
436 | 434 |
437 ObjectInfoEnqueueInternalChangeRecord(objectInfo, newRecord, | 435 ObjectInfoEnqueueInternalChangeRecord(objectInfo, newRecord); |
438 true /* skip access check */); | |
439 } | 436 } |
440 | 437 |
441 function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord, | 438 function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord) { |
442 skipAccessCheck) { | |
443 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 439 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
444 if (IS_SYMBOL(changeRecord.name)) return; | 440 if (IS_SYMBOL(changeRecord.name)) return; |
445 | 441 |
446 var needsAccessCheck = !skipAccessCheck && | 442 var needsAccessCheck = %IsAccessCheckNeeded(changeRecord.object); |
rossberg
2014/04/30 11:28:32
I believe you always need to do the same-origin ch
rafaelw
2014/05/02 03:22:32
Done.
| |
447 %IsAccessCheckNeeded(changeRecord.object); | |
448 | 443 |
449 if (ChangeObserversIsOptimized(objectInfo.changeObservers)) { | 444 if (ChangeObserversIsOptimized(objectInfo.changeObservers)) { |
450 var observer = objectInfo.changeObservers; | 445 var observer = objectInfo.changeObservers; |
451 ObserverEnqueueIfActive(observer, objectInfo, changeRecord, | 446 ObserverEnqueueIfActive(observer, objectInfo, changeRecord, |
452 needsAccessCheck); | 447 needsAccessCheck); |
453 return; | 448 return; |
454 } | 449 } |
455 | 450 |
456 for (var priority in objectInfo.changeObservers) { | 451 for (var priority in objectInfo.changeObservers) { |
457 var observer = objectInfo.changeObservers[priority]; | 452 var observer = objectInfo.changeObservers[priority]; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
555 if (IS_SPEC_OBJECT(changeRecord)) | 550 if (IS_SPEC_OBJECT(changeRecord)) |
556 ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, changeType); | 551 ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, changeType); |
557 } | 552 } |
558 | 553 |
559 function ObjectGetNotifier(object) { | 554 function ObjectGetNotifier(object) { |
560 if (!IS_SPEC_OBJECT(object)) | 555 if (!IS_SPEC_OBJECT(object)) |
561 throw MakeTypeError("observe_non_object", ["getNotifier"]); | 556 throw MakeTypeError("observe_non_object", ["getNotifier"]); |
562 | 557 |
563 if (ObjectIsFrozen(object)) return null; | 558 if (ObjectIsFrozen(object)) return null; |
564 | 559 |
560 if (!%ObjectWasCreatedInCurrentOrigin(object)) return null; | |
561 | |
565 var objectInfo = ObjectInfoGetOrCreate(object); | 562 var objectInfo = ObjectInfoGetOrCreate(object); |
566 return ObjectInfoGetNotifier(objectInfo); | 563 return ObjectInfoGetNotifier(objectInfo); |
567 } | 564 } |
568 | 565 |
569 function CallbackDeliverPending(callback) { | 566 function CallbackDeliverPending(callback) { |
570 var callbackInfo = GetCallbackInfoMap().get(callback); | 567 var callbackInfo = GetCallbackInfoMap().get(callback); |
571 if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo)) | 568 if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo)) |
572 return false; | 569 return false; |
573 | 570 |
574 // Clear the pending change records from callback and return it to its | 571 // Clear the pending change records from callback and return it to its |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
616 InstallFunctions($Array, DONT_ENUM, $Array( | 613 InstallFunctions($Array, DONT_ENUM, $Array( |
617 "observe", ArrayObserve, | 614 "observe", ArrayObserve, |
618 "unobserve", ArrayUnobserve | 615 "unobserve", ArrayUnobserve |
619 )); | 616 )); |
620 InstallFunctions(notifierPrototype, DONT_ENUM, $Array( | 617 InstallFunctions(notifierPrototype, DONT_ENUM, $Array( |
621 "notify", ObjectNotifierNotify, | 618 "notify", ObjectNotifierNotify, |
622 "performChange", ObjectNotifierPerformChange | 619 "performChange", ObjectNotifierPerformChange |
623 )); | 620 )); |
624 } | 621 } |
625 | 622 |
626 // Disable Object.observe API for M35. | 623 SetupObjectObserve(); |
627 // SetupObjectObserve(); | |
OLD | NEW |