2017-09-11 16:09:25 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
function dirtyReporter() {
|
|
|
|
const dirty = new Map();
|
|
|
|
const onchanges = [];
|
|
|
|
|
|
|
|
function add(obj, value) {
|
|
|
|
const saved = dirty.get(obj);
|
|
|
|
if (!saved) {
|
|
|
|
dirty.set(obj, {type: 'add', newValue: value});
|
|
|
|
} else if (saved.type === 'remove') {
|
|
|
|
if (saved.savedValue === value) {
|
|
|
|
dirty.delete(obj);
|
|
|
|
} else {
|
|
|
|
saved.newValue = value;
|
|
|
|
saved.type = 'modify';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function remove(obj, value) {
|
|
|
|
const saved = dirty.get(obj);
|
|
|
|
if (!saved) {
|
|
|
|
dirty.set(obj, {type: 'remove', savedValue: value});
|
|
|
|
} else if (saved.type === 'add') {
|
|
|
|
dirty.delete(obj);
|
|
|
|
} else if (saved.type === 'modify') {
|
|
|
|
saved.type = 'remove';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function modify(obj, oldValue, newValue) {
|
|
|
|
const saved = dirty.get(obj);
|
|
|
|
if (!saved) {
|
|
|
|
if (oldValue !== newValue) {
|
|
|
|
dirty.set(obj, {type: 'modify', savedValue: oldValue, newValue});
|
|
|
|
}
|
|
|
|
} else if (saved.type === 'modify') {
|
|
|
|
if (saved.savedValue === newValue) {
|
|
|
|
dirty.delete(obj);
|
|
|
|
} else {
|
|
|
|
saved.newValue = newValue;
|
|
|
|
}
|
|
|
|
} else if (saved.type === 'add') {
|
|
|
|
saved.newValue = newValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function clear() {
|
|
|
|
dirty.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
function isDirty() {
|
|
|
|
return dirty.size > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
function onChange(cb) {
|
2017-09-12 13:28:26 +00:00
|
|
|
// make sure the callback doesn't throw
|
2017-09-11 16:09:25 +00:00
|
|
|
onchanges.push(cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
function wrap(obj) {
|
|
|
|
for (const key of ['add', 'remove', 'modify', 'clear']) {
|
|
|
|
obj[key] = trackChange(obj[key]);
|
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
function emitChange() {
|
|
|
|
for (const cb of onchanges) {
|
2017-09-12 13:28:26 +00:00
|
|
|
cb();
|
2017-09-11 16:09:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function trackChange(fn) {
|
|
|
|
return function () {
|
|
|
|
const dirty = isDirty();
|
|
|
|
const result = fn.apply(null, arguments);
|
|
|
|
if (dirty !== isDirty()) {
|
|
|
|
emitChange();
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-09-11 17:23:32 +00:00
|
|
|
function has(key) {
|
|
|
|
return dirty.has(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
return wrap({add, remove, modify, clear, isDirty, onChange, has});
|
2017-09-11 16:09:25 +00:00
|
|
|
}
|