Skip to content

Commit

Permalink
feat(SetObservation): add set observation
Browse files Browse the repository at this point in the history
  • Loading branch information
martingust authored and jdanyow committed Jan 6, 2016
1 parent e426534 commit 9bb1731
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 7 deletions.
3 changes: 2 additions & 1 deletion build/tasks/build.js
Expand Up @@ -43,7 +43,8 @@ gulp.task('build-index', function(){
'binding-behavior-resource.js',
'listener-expression.js',
'name-expression.js',
'binding-engine.js'
'binding-engine.js',
'set-observation.js'
].map(function(file){
return paths.root + file;
});
Expand Down
6 changes: 4 additions & 2 deletions src/binding-engine.js
Expand Up @@ -66,8 +66,10 @@ export class BindingEngine {
observer = this.observerLocator.getArrayObserver(collection);
} else if (collection instanceof Map) {
observer = this.observerLocator.getMapObserver(collection);
} else {
throw new Error('collection must be an instance of Array or Map.');
} else if (collection instanceof Set) {
observer = this.observerLocator.getSetObserver(collection);
} else {
throw new Error('collection must be an instance of Array, Map or Set.');
}
observer.subscribe(callback);
return {
Expand Down
8 changes: 4 additions & 4 deletions src/collection-observation.js
Expand Up @@ -10,7 +10,7 @@ export class ModifyCollectionObserver {
this.changeRecords = null;
this.oldCollection = null;
this.collection = collection;
this.lengthPropertyName = collection instanceof Map ? 'size' : 'length';
this.lengthPropertyName = collection instanceof Map || collection instanceof Set ? 'size' : 'length';
}

subscribe(context, callable) {
Expand Down Expand Up @@ -83,14 +83,14 @@ export class ModifyCollectionObserver {
if (this.hasSubscribers()) {
if (oldCollection){
// TODO (martingust) we might want to refactor this to a common, independent of collection type, way of getting the records
if (this.collection instanceof Map) {
if (this.collection instanceof Map || this.collection instanceof Set) {
records = getChangeRecords(oldCollection);
} else {
//we might need to combine this with existing change records....
records = calcSplices(this.collection, 0, this.collection.length, oldCollection, 0, oldCollection.length);
}
} else {
if (this.collection instanceof Map) {
if (this.collection instanceof Map || this.collection instanceof Set) {
records = changeRecords;
} else {
records = projectArraySplices(this.collection, changeRecords);
Expand All @@ -110,7 +110,7 @@ export class ModifyCollectionObserver {
export class CollectionLengthObserver {
constructor(collection) {
this.collection = collection;
this.lengthPropertyName = collection instanceof Map ? 'size' : 'length';
this.lengthPropertyName = collection instanceof Map || collection instanceof Set ? 'size' : 'length';
this.currentValue = collection[this.lengthPropertyName];
}

Expand Down
15 changes: 15 additions & 0 deletions src/observer-locator.js
Expand Up @@ -2,6 +2,7 @@ import {DOM} from 'aurelia-pal';
import {TaskQueue} from 'aurelia-task-queue';
import {getArrayObserver} from './array-observation';
import {getMapObserver} from './map-observation';
import {getSetObserver} from './set-observation';
import {EventManager} from './event-manager';
import {DirtyChecker, DirtyCheckProperty} from './dirty-checking';
import {
Expand Down Expand Up @@ -160,6 +161,12 @@ export class ObserverLocator {
} else {
return new DirtyCheckProperty(this.dirtyChecker, obj, propertyName);
}
} else if (obj instanceof Set) {
if (propertyName === 'size') {
return this.getSetObserver(obj).getLengthObserver();
} else {
return new DirtyCheckProperty(this.dirtyChecker, obj, propertyName);
}
}

return new SetterObserver(this.taskQueue, obj, propertyName);
Expand Down Expand Up @@ -197,6 +204,14 @@ export class ObserverLocator {

return map.__map_observer__ = getMapObserver(this.taskQueue, map);
}

getSetObserver(set){
if ('__set_observer__' in set) {
return set.__set_observer__;
}

return set.__set_observer__ = getSetObserver(this.taskQueue, set);
}
}

export class ObjectObservationAdapter {
Expand Down
57 changes: 57 additions & 0 deletions src/set-observation.js
@@ -0,0 +1,57 @@
import 'core-js';
import {getChangeRecords} from './map-change-records';
import {ModifyCollectionObserver} from './collection-observation';

let setProto = Set.prototype;

export function getSetObserver(taskQueue, set){
return ModifySetObserver.create(taskQueue, set);
}

class ModifySetObserver extends ModifyCollectionObserver {
constructor(taskQueue, set){
super(taskQueue, set);
}

static create(taskQueue, set) {
let observer = new ModifySetObserver(taskQueue, set);

set['add'] = function () {
let type = 'add';
let hasValue = set.has(arguments[0]);
let methodCallResult = setProto['add'].apply(set, arguments);
if (!hasValue) {
observer.addChangeRecord({
type: type,
object: set,
value: arguments[0]
});
}
return methodCallResult;
}

set['delete'] = function () {
let hasValue = set.has(arguments[0]);
let methodCallResult = setProto['delete'].apply(set, arguments);
if (hasValue) {
observer.addChangeRecord({
type: 'delete',
object: set,
value: arguments[0]
});
}
return methodCallResult;
}

set['clear'] = function () {
let methodCallResult = setProto['clear'].apply(set, arguments);
observer.addChangeRecord({
type: 'clear',
object: set
});
return methodCallResult;
}

return observer;
}
}

0 comments on commit 9bb1731

Please sign in to comment.