Commit 4a8319c7 authored by rafaelw@chromium.org's avatar rafaelw@chromium.org

[Object.observe] Implement implicit notification from performChange

R=arv@chromium.org, rossberg@chromium.org, rossberg
BUG=v8:2942

Review URL: https://codereview.chromium.org/36313002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17476 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d0c5614f
...@@ -386,8 +386,28 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord, ...@@ -386,8 +386,28 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord,
%SetObserverDeliveryPending(); %SetObserverDeliveryPending();
} }
function ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord, function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) {
skipAccessCheck) { 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. // TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(changeRecord.name)) return; if (IS_SYMBOL(changeRecord.name)) return;
...@@ -435,7 +455,7 @@ function EnqueueSpliceRecord(array, index, removed, addedCount) { ...@@ -435,7 +455,7 @@ function EnqueueSpliceRecord(array, index, removed, addedCount) {
ObjectFreeze(changeRecord); ObjectFreeze(changeRecord);
ObjectFreeze(changeRecord.removed); ObjectFreeze(changeRecord.removed);
ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord); ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
} }
function NotifyChange(type, object, name, oldValue) { function NotifyChange(type, object, name, oldValue) {
...@@ -447,7 +467,7 @@ function NotifyChange(type, object, name, oldValue) { ...@@ -447,7 +467,7 @@ function NotifyChange(type, object, name, oldValue) {
{ type: type, object: object, name: name } : { type: type, object: object, name: name } :
{ type: type, object: object, name: name, oldValue: oldValue }; { type: type, object: object, name: name, oldValue: oldValue };
ObjectFreeze(changeRecord); ObjectFreeze(changeRecord);
ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord); ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
} }
var notifierPrototype = {}; var notifierPrototype = {};
...@@ -462,19 +482,7 @@ function ObjectNotifierNotify(changeRecord) { ...@@ -462,19 +482,7 @@ function ObjectNotifierNotify(changeRecord) {
if (!IS_STRING(changeRecord.type)) if (!IS_STRING(changeRecord.type))
throw MakeTypeError("observe_type_non_string"); throw MakeTypeError("observe_type_non_string");
if (!ObjectInfoHasActiveObservers(objectInfo)) ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord);
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 */);
} }
function ObjectNotifierPerformChange(changeType, changeFn) { function ObjectNotifierPerformChange(changeType, changeFn) {
...@@ -491,11 +499,16 @@ function ObjectNotifierPerformChange(changeType, changeFn) { ...@@ -491,11 +499,16 @@ function ObjectNotifierPerformChange(changeType, changeFn) {
throw MakeTypeError("observe_perform_non_function"); throw MakeTypeError("observe_perform_non_function");
ObjectInfoAddPerformingType(objectInfo, changeType); ObjectInfoAddPerformingType(objectInfo, changeType);
var changeRecord;
try { try {
%_CallFunction(UNDEFINED, changeFn); changeRecord = %_CallFunction(UNDEFINED, changeFn);
} finally { } finally {
ObjectInfoRemovePerformingType(objectInfo, changeType); ObjectInfoRemovePerformingType(objectInfo, changeType);
} }
if (IS_SPEC_OBJECT(changeRecord))
ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, changeType);
} }
function ObjectGetNotifier(object) { function ObjectGetNotifier(object) {
......
...@@ -434,12 +434,10 @@ Thingy.prototype = { ...@@ -434,12 +434,10 @@ Thingy.prototype = {
notifier.performChange(Thingy.INCREMENT, function() { notifier.performChange(Thingy.INCREMENT, function() {
self.a += amount; self.a += amount;
self.b += amount; self.b += amount;
});
notifier.notify({ return {
object: this, incremented: amount
type: Thingy.INCREMENT, }; // implicit notify
incremented: amount
}); });
}, },
...@@ -450,12 +448,10 @@ Thingy.prototype = { ...@@ -450,12 +448,10 @@ Thingy.prototype = {
notifier.performChange(Thingy.MULTIPLY, function() { notifier.performChange(Thingy.MULTIPLY, function() {
self.a *= amount; self.a *= amount;
self.b *= amount; self.b *= amount;
});
notifier.notify({ return {
object: this, multiplied: amount
type: Thingy.MULTIPLY, }; // implicit notify
multiplied: amount
}); });
}, },
...@@ -466,13 +462,11 @@ Thingy.prototype = { ...@@ -466,13 +462,11 @@ Thingy.prototype = {
notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() { notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() {
self.increment(incAmount); self.increment(incAmount);
self.multiply(multAmount); self.multiply(multAmount);
});
notifier.notify({ return {
object: this, incremented: incAmount,
type: Thingy.INCREMENT_AND_MULTIPLY, multiplied: multAmount
incremented: incAmount, }; // implicit notify
multiplied: multAmount
}); });
} }
} }
...@@ -545,7 +539,6 @@ RecursiveThingy.prototype = { ...@@ -545,7 +539,6 @@ RecursiveThingy.prototype = {
}); });
notifier.notify({ notifier.notify({
object: this,
type: RecursiveThingy.MULTIPLY_FIRST_N, type: RecursiveThingy.MULTIPLY_FIRST_N,
multiplied: amount, multiplied: amount,
n: n n: n
...@@ -606,7 +599,6 @@ DeckSuit.prototype = { ...@@ -606,7 +599,6 @@ DeckSuit.prototype = {
}); });
notifier.notify({ notifier.notify({
object: this,
type: DeckSuit.SHUFFLE type: DeckSuit.SHUFFLE
}); });
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment