| Index: src/object-observe.js
|
| diff --git a/src/object-observe.js b/src/object-observe.js
|
| index 9c7ac3889eb573b04ae6c4612dc5d4791174fda0..73a5d34c7ca2bcff899f60402f6fa15cb71e6042 100644
|
| --- a/src/object-observe.js
|
| +++ b/src/object-observe.js
|
| @@ -128,11 +128,12 @@ function TypeMapIsDisjointFrom(typeMap1, typeMap2) {
|
| }
|
|
|
| var defaultAcceptTypes = TypeMapCreateFromList([
|
| - 'new',
|
| - 'updated',
|
| - 'deleted',
|
| - 'prototype',
|
| - 'reconfigured'
|
| + 'add',
|
| + 'update',
|
| + 'delete',
|
| + 'setPrototype',
|
| + 'reconfigure',
|
| + 'preventExtensions'
|
| ]);
|
|
|
| // An Observer is a registration to observe an object by a callback with
|
| @@ -352,9 +353,9 @@ function ObjectUnobserve(object, callback) {
|
| }
|
|
|
| function ArrayObserve(object, callback) {
|
| - return ObjectObserve(object, callback, ['new',
|
| - 'updated',
|
| - 'deleted',
|
| + return ObjectObserve(object, callback, ['add',
|
| + 'update',
|
| + 'delete',
|
| 'splice']);
|
| }
|
|
|
| @@ -386,8 +387,28 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord,
|
| %SetObserverDeliveryPending();
|
| }
|
|
|
| -function ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord,
|
| - skipAccessCheck) {
|
| +function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) {
|
| + if (!ObjectInfoHasActiveObservers(objectInfo))
|
| + return;
|
| +
|
| + var hasType = !IS_UNDEFINED(type);
|
| + var newRecord = hasType ?
|
| + { object: ObjectInfoGetObject(objectInfo), type: type } :
|
| + { object: ObjectInfoGetObject(objectInfo) };
|
| +
|
| + for (var prop in changeRecord) {
|
| + if (prop === 'object' || (hasType && prop === 'type')) continue;
|
| + %DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop],
|
| + READ_ONLY + DONT_DELETE);
|
| + }
|
| + ObjectFreeze(newRecord);
|
| +
|
| + ObjectInfoEnqueueInternalChangeRecord(objectInfo, newRecord,
|
| + true /* skip access check */);
|
| +}
|
| +
|
| +function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord,
|
| + skipAccessCheck) {
|
| // TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
| if (IS_SYMBOL(changeRecord.name)) return;
|
|
|
| @@ -435,7 +456,7 @@ function EnqueueSpliceRecord(array, index, removed, addedCount) {
|
|
|
| ObjectFreeze(changeRecord);
|
| ObjectFreeze(changeRecord.removed);
|
| - ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord);
|
| + ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
|
| }
|
|
|
| function NotifyChange(type, object, name, oldValue) {
|
| @@ -443,11 +464,22 @@ function NotifyChange(type, object, name, oldValue) {
|
| if (!ObjectInfoHasActiveObservers(objectInfo))
|
| return;
|
|
|
| - var changeRecord = (arguments.length < 4) ?
|
| - { type: type, object: object, name: name } :
|
| - { type: type, object: object, name: name, oldValue: oldValue };
|
| + var changeRecord;
|
| + if (arguments.length == 2) {
|
| + changeRecord = { type: type, object: object };
|
| + } else if (arguments.length == 3) {
|
| + changeRecord = { type: type, object: object, name: name };
|
| + } else {
|
| + changeRecord = {
|
| + type: type,
|
| + object: object,
|
| + name: name,
|
| + oldValue: oldValue
|
| + };
|
| + }
|
| +
|
| ObjectFreeze(changeRecord);
|
| - ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord);
|
| + ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
|
| }
|
|
|
| var notifierPrototype = {};
|
| @@ -462,19 +494,7 @@ function ObjectNotifierNotify(changeRecord) {
|
| if (!IS_STRING(changeRecord.type))
|
| throw MakeTypeError("observe_type_non_string");
|
|
|
| - if (!ObjectInfoHasActiveObservers(objectInfo))
|
| - return;
|
| -
|
| - var newRecord = { object: ObjectInfoGetObject(objectInfo) };
|
| - for (var prop in changeRecord) {
|
| - if (prop === 'object') continue;
|
| - %DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop],
|
| - READ_ONLY + DONT_DELETE);
|
| - }
|
| - ObjectFreeze(newRecord);
|
| -
|
| - ObjectInfoEnqueueChangeRecord(objectInfo, newRecord,
|
| - true /* skip access check */);
|
| + ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord);
|
| }
|
|
|
| function ObjectNotifierPerformChange(changeType, changeFn) {
|
| @@ -491,11 +511,16 @@ function ObjectNotifierPerformChange(changeType, changeFn) {
|
| throw MakeTypeError("observe_perform_non_function");
|
|
|
| ObjectInfoAddPerformingType(objectInfo, changeType);
|
| +
|
| + var changeRecord;
|
| try {
|
| - %_CallFunction(UNDEFINED, changeFn);
|
| + changeRecord = %_CallFunction(UNDEFINED, changeFn);
|
| } finally {
|
| ObjectInfoRemovePerformingType(objectInfo, changeType);
|
| }
|
| +
|
| + if (IS_SPEC_OBJECT(changeRecord))
|
| + ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, changeType);
|
| }
|
|
|
| function ObjectGetNotifier(object) {
|
|
|