Revision: 14705
Author: [email protected]
Date: Thu May 16 04:19:37 2013
Log: Implement Array.observe and emit splice change records for
ArrayPush
Review URL: https://codereview.chromium.org/14978007
Patch from Rafael Weinstein <[email protected]>.
http://code.google.com/p/v8/source/detail?r=14705
Modified:
/branches/bleeding_edge/src/array.js
/branches/bleeding_edge/src/object-observe.js
/branches/bleeding_edge/test/mjsunit/harmony/object-observe.js
=======================================
--- /branches/bleeding_edge/src/array.js Thu Apr 11 05:15:25 2013
+++ /branches/bleeding_edge/src/array.js Thu May 16 04:19:37 2013
@@ -416,6 +416,26 @@
}
+function ObservedArrayPush() {
+ var n = TO_UINT32(this.length);
+ var m = %_ArgumentsLength();
+
+ EnqueueSpliceRecord(this, n, [], 0, m);
+
+ try {
+ BeginPerformSplice(this);
+
+ for (var i = 0; i < m; i++) {
+ this[i+n] = %_Arguments(i);
+ }
+ this.length = n + m;
+ } finally {
+ EndPerformSplice(this);
+ }
+
+ return this.length;
+}
+
// Appends the arguments to the end of the array and returns the new
// length of the array. See ECMA-262, section 15.4.4.7.
function ArrayPush() {
@@ -423,6 +443,9 @@
throw MakeTypeError("called_on_null_or_undefined",
["Array.prototype.push"]);
}
+
+ if (%IsObserved(this))
+ return ObservedArrayPush.apply(this, arguments);
var n = TO_UINT32(this.length);
var m = %_ArgumentsLength();
=======================================
--- /branches/bleeding_edge/src/object-observe.js Wed May 15 15:09:40 2013
+++ /branches/bleeding_edge/src/object-observe.js Thu May 16 04:19:37 2013
@@ -166,7 +166,7 @@
objectInfo);
}
-function ensureObserverRemoved(objectInfo, callback) {
+function EnsureObserverRemoved(objectInfo, callback) {
function remove(observerList) {
for (var i = 0; i < observerList.length; i++) {
if (observerList[i].callback === callback) {
@@ -219,7 +219,7 @@
if (IS_UNDEFINED(objectInfo)) objectInfo = CreateObjectInfo(object);
%SetIsObserved(object, true);
- ensureObserverRemoved(objectInfo, callback);
+ EnsureObserverRemoved(objectInfo, callback);
var observer = CreateObserver(callback, accept);
if (ObserverIsActive(observer, objectInfo))
@@ -240,7 +240,7 @@
if (IS_UNDEFINED(objectInfo))
return object;
- ensureObserverRemoved(objectInfo, callback);
+ EnsureObserverRemoved(objectInfo, callback);
if (objectInfo.changeObservers.length === 0 &&
objectInfo.inactiveObservers.length === 0) {
@@ -249,6 +249,17 @@
return object;
}
+
+function ArrayObserve(object, callback) {
+ return ObjectObserve(object, callback, ['new',
+ 'updated',
+ 'deleted',
+ 'splice']);
+}
+
+function ArrayUnobserve(object, callback) {
+ return ObjectUnobserve(object, callback);
+}
function EnqueueChangeRecord(changeRecord, observers) {
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
@@ -270,6 +281,39 @@
}
}
}
+
+function BeginPerformSplice(array) {
+ var objectInfo = objectInfoMap.get(array);
+ if (!IS_UNDEFINED(objectInfo))
+ BeginPerformChange(objectInfo, 'splice');
+}
+
+function EndPerformSplice(array) {
+ var objectInfo = objectInfoMap.get(array);
+ if (!IS_UNDEFINED(objectInfo))
+ EndPerformChange(objectInfo, 'splice');
+}
+
+function EnqueueSpliceRecord(array, index, removed, deleteCount,
addedCount) {
+ var objectInfo = objectInfoMap.get(array);
+ if (IS_UNDEFINED(objectInfo) || objectInfo.changeObservers.length === 0)
+ return;
+
+ var changeRecord = {
+ type: 'splice',
+ object: array,
+ index: index,
+ removed: removed,
+ addedCount: addedCount
+ };
+
+ changeRecord.removed.length = deleteCount;
+ // TODO(rafaelw): This breaks spec-compliance. Re-enable when freezing
isn't
+ // slow.
+ // ObjectFreeze(changeRecord);
+ // ObjectFreeze(changeRecord.removed);
+ EnqueueChangeRecord(changeRecord, objectInfo.changeObservers);
+}
function NotifyChange(type, object, name, oldValue) {
var objectInfo = objectInfoMap.get(object);
@@ -405,6 +449,10 @@
"observe", ObjectObserve,
"unobserve", ObjectUnobserve
));
+ InstallFunctions($Array, DONT_ENUM, $Array(
+ "observe", ArrayObserve,
+ "unobserve", ArrayUnobserve
+ ));
InstallFunctions(notifierPrototype, DONT_ENUM, $Array(
"notify", ObjectNotifierNotify,
"performChange", ObjectNotifierPerformChange
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/object-observe.js Wed May
15 15:09:40 2013
+++ /branches/bleeding_edge/test/mjsunit/harmony/object-observe.js Thu May
16 04:19:37 2013
@@ -1068,13 +1068,22 @@
reset();
var array = [1, 2];
Object.observe(array, observer.callback);
+Array.observe(array, observer2.callback);
array.push(3, 4);
+array.push(5);
Object.deliverChangeRecords(observer.callback);
observer.assertCallbackRecords([
{ object: array, name: '2', type: 'new' },
{ object: array, name: 'length', type: 'updated', oldValue: 2 },
{ object: array, name: '3', type: 'new' },
{ object: array, name: 'length', type: 'updated', oldValue: 3 },
+ { object: array, name: '4', type: 'new' },
+ { object: array, name: 'length', type: 'updated', oldValue: 4 },
+]);
+Object.deliverChangeRecords(observer2.callback);
+observer2.assertCallbackRecords([
+ { object: array, type: 'splice', index: 2, removed: [], addedCount: 2 },
+ { object: array, type: 'splice', index: 4, removed: [], addedCount: 1 }
]);
// Pop
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.