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,
%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 +455,7 @@ function EnqueueSpliceRecord(array, index, removed, addedCount) {
ObjectFreeze(changeRecord);
ObjectFreeze(changeRecord.removed);
ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord);
ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
}
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, oldValue: oldValue };
ObjectFreeze(changeRecord);
ObjectInfoEnqueueChangeRecord(objectInfo, changeRecord);
ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
}
var notifierPrototype = {};
......@@ -462,19 +482,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 +499,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) {
......
......@@ -434,12 +434,10 @@ Thingy.prototype = {
notifier.performChange(Thingy.INCREMENT, function() {
self.a += amount;
self.b += amount;
});
notifier.notify({
object: this,
type: Thingy.INCREMENT,
incremented: amount
return {
incremented: amount
}; // implicit notify
});
},
......@@ -450,12 +448,10 @@ Thingy.prototype = {
notifier.performChange(Thingy.MULTIPLY, function() {
self.a *= amount;
self.b *= amount;
});
notifier.notify({
object: this,
type: Thingy.MULTIPLY,
multiplied: amount
return {
multiplied: amount
}; // implicit notify
});
},
......@@ -466,13 +462,11 @@ Thingy.prototype = {
notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() {
self.increment(incAmount);
self.multiply(multAmount);
});
notifier.notify({
object: this,
type: Thingy.INCREMENT_AND_MULTIPLY,
incremented: incAmount,
multiplied: multAmount
return {
incremented: incAmount,
multiplied: multAmount
}; // implicit notify
});
}
}
......@@ -545,7 +539,6 @@ RecursiveThingy.prototype = {
});
notifier.notify({
object: this,
type: RecursiveThingy.MULTIPLY_FIRST_N,
multiplied: amount,
n: n
......@@ -606,7 +599,6 @@ DeckSuit.prototype = {
});
notifier.notify({
object: this,
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