Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Simplified ArrayReduction
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelw committed Aug 17, 2013
1 parent 036fb3c commit 3c8009e
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 76 deletions.
2 changes: 1 addition & 1 deletion tests/test_array_reduction.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ suite('ArrayReduction Tests',function(){
path: 'id',
initial: [],
reduce: function(value,cur,i){
value.push([cur,i]);
value.push([cur.id,i]);
return value;
}
});
Expand Down
121 changes: 46 additions & 75 deletions util/array_reduction.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,98 +13,69 @@
// limitations under the License.

function ArrayReduction(array, path, reduceFn, initial) {
var values = [];
var observers = [];
var self = this;
var hasInitial = arguments.length == 4;

function reduce() {
self.value = hasInitial ?
values.reduce(reduceFn, initial) : values.reduce(reduceFn);
}

function newCallback(index) {
return function(value) {
values[index] = value;
reduce();
}
}

function handleSplice(splice) {
var valueArgs = [splice.index, splice.removed.length];
var observerArgs = [splice.index, splice.removed.length];
this.array = array;
this.path = path ? path.trim() : undefined;
this.reduceFn = reduceFn;
this.initial = initial;
this.arrayObserver = new ArrayObserver(array, this.handleSplices, this);
this.observers = this.path ? [] : undefined;

this.handleSplices([{
index: 0,
removed: [],
addedCount: array.length
}]);
}

var removeIndex = splice.index;
while (removeIndex < splice.index + splice.removed.length) {
observers[removeIndex].close();
observers[removeIndex] = undefined;
removeIndex++;
}
ArrayReduction.prototype = {
updateObservers: function(splices) {
for (var i = 0; i < splices.length; i++) {
var splice = splices[i];
var added = [];
for (var j = 0; j < splice.addedCount; j++) {
added.push(new PathObserver(this.array[splice.index + j], this.path,
this.reduce, this));
}

var addIndex = splice.index;
while (addIndex < splice.index + splice.addedCount) {
var itemPath = String(addIndex);
if (path)
itemPath += '.' + path;
var spliceArgs = [splice.index, splice.removed.length].concat(added);
var removed = Array.prototype.splice.apply(this.observers, spliceArgs);

valueArgs.push(PathObserver.getValueAtPath(array, itemPath));
observerArgs.push(new PathObserver(array, itemPath, newCallback(addIndex)));
addIndex++;
for (var j = 0; j < removed.length; j++) {
removed[j].close();
}
}
},

Array.prototype.splice.apply(values, valueArgs);
Array.prototype.splice.apply(observers, observerArgs);

// Correct the index/path being watched by the observers that watched indices
// after the splice.
var curIndex = splice.index + splice.addedCount;
while(curIndex < values.length) {
var expectedItemPath = (path ? (curIndex + '.' + path) : String(curIndex));

observers[curIndex].close();
observers[curIndex] = new PathObserver(array, expectedItemPath, newCallback(curIndex));
curIndex++;
}
}
handleSplices: function(splices) {
if (this.observers)
this.updateObservers(splices);

var arrayObserver = new ArrayObserver(array, function(splices) {
splices.forEach(handleSplice);
reduce();
});
this.reduce();
},

handleSplice({
index: 0,
removed: [],
addedCount: array.length
});
reduce: function() {
this.value = this.array.reduce(this.reduceFn, this.initial);
},

this.close = function() {
observers.forEach(function(observer) {
close: function() {
this.observers.forEach(function(observer) {
observer.close();
});
arrayObserver.close();
};

this.unobserved = function() {
self.close();
};
this.arrayObserver.close();
},

this.deliver = function() {
arrayObserver.deliver();
observers.forEach(function(observer) {
deliver: function() {
this.arrayObserver.deliver();
this.observers.forEach(function(observer) {
observer.deliver();
});
}

reduce();
}

ArrayReduction.defineProperty = function(object, name, descriptor) {
var observer;
if (descriptor.hasOwnProperty('initial'))
observer = new ArrayReduction(descriptor.array, descriptor.path, descriptor.reduce, descriptor.initial);
else
observer = new ArrayReduction(descriptor.array, descriptor.path, descriptor.reduce);
var observer = new ArrayReduction(descriptor.array, descriptor.path,
descriptor.reduce,
descriptor.initial);

Object.defineProperty(object, name, {
get: function() {
Expand Down

0 comments on commit 3c8009e

Please sign in to comment.