@danielkalen/simplybind
Version:
Magically simple, framework-less one-way/two-way data binding for frontend/backend in ~5kb.
1,805 lines (1,447 loc) • 162 kB
JavaScript
export { _getArrayObserver as getArrayObserver };
export { _getMapObserver as getMapObserver };
export { _getSetObserver as getSetObserver };
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _dec, _dec2, _class, _dec3, _class2, _dec4, _class3, _dec5, _class5, _dec6, _class7, _dec7, _class8, _dec8, _class9, _dec9, _class10, _class11, _temp, _dec10, _class12, _class13, _temp2;
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
import * as LogManager from 'aurelia-logging';
import { PLATFORM, DOM } from 'aurelia-pal';
import { TaskQueue } from 'aurelia-task-queue';
import { metadata } from 'aurelia-metadata';
var map = Object.create(null);
export function camelCase(name) {
if (name in map) {
return map[name];
}
var result = name.charAt(0).toLowerCase() + name.slice(1).replace(/[_.-](\w|$)/g, function (_, x) {
return x.toUpperCase();
});
map[name] = result;
return result;
}
export function createOverrideContext(bindingContext, parentOverrideContext) {
return {
bindingContext: bindingContext,
parentOverrideContext: parentOverrideContext || null
};
}
export function getContextFor(name, scope, ancestor) {
var oc = scope.overrideContext;
if (ancestor) {
while (ancestor && oc) {
ancestor--;
oc = oc.parentOverrideContext;
}
if (ancestor || !oc) {
return undefined;
}
return name in oc ? oc : oc.bindingContext;
}
while (oc && !(name in oc) && !(oc.bindingContext && name in oc.bindingContext)) {
oc = oc.parentOverrideContext;
}
if (oc) {
return name in oc ? oc : oc.bindingContext;
}
return scope.bindingContext || scope.overrideContext;
}
export function createScopeForTest(bindingContext, parentBindingContext) {
if (parentBindingContext) {
return {
bindingContext: bindingContext,
overrideContext: createOverrideContext(bindingContext, createOverrideContext(parentBindingContext))
};
}
return {
bindingContext: bindingContext,
overrideContext: createOverrideContext(bindingContext)
};
}
export var sourceContext = 'Binding:source';
var slotNames = [];
var versionSlotNames = [];
for (var i = 0; i < 100; i++) {
slotNames.push('_observer' + i);
versionSlotNames.push('_observerVersion' + i);
}
function addObserver(observer) {
var observerSlots = this._observerSlots === undefined ? 0 : this._observerSlots;
var i = observerSlots;
while (i-- && this[slotNames[i]] !== observer) {}
if (i === -1) {
i = 0;
while (this[slotNames[i]]) {
i++;
}
this[slotNames[i]] = observer;
observer.subscribe(sourceContext, this);
if (i === observerSlots) {
this._observerSlots = i + 1;
}
}
if (this._version === undefined) {
this._version = 0;
}
this[versionSlotNames[i]] = this._version;
}
function observeProperty(obj, propertyName) {
var observer = this.observerLocator.getObserver(obj, propertyName);
addObserver.call(this, observer);
}
function observeArray(array) {
var observer = this.observerLocator.getArrayObserver(array);
addObserver.call(this, observer);
}
function unobserve(all) {
var i = this._observerSlots;
while (i--) {
if (all || this[versionSlotNames[i]] !== this._version) {
var observer = this[slotNames[i]];
this[slotNames[i]] = null;
if (observer) {
observer.unsubscribe(sourceContext, this);
}
}
}
}
export function connectable() {
return function (target) {
target.prototype.observeProperty = observeProperty;
target.prototype.observeArray = observeArray;
target.prototype.unobserve = unobserve;
target.prototype.addObserver = addObserver;
};
}
var bindings = new Map();
var minimumImmediate = 100;
var frameBudget = 15;
var isFlushRequested = false;
var immediate = 0;
function flush(animationFrameStart) {
var i = 0;
var keys = bindings.keys();
var item = void 0;
while (item = keys.next()) {
if (item.done) {
break;
}
var binding = item.value;
bindings.delete(binding);
binding.connect(true);
i++;
if (i % 100 === 0 && PLATFORM.performance.now() - animationFrameStart > frameBudget) {
break;
}
}
if (bindings.size) {
PLATFORM.requestAnimationFrame(flush);
} else {
isFlushRequested = false;
immediate = 0;
}
}
export function enqueueBindingConnect(binding) {
if (immediate < minimumImmediate) {
immediate++;
binding.connect(false);
} else {
bindings.set(binding);
}
if (!isFlushRequested) {
isFlushRequested = true;
PLATFORM.requestAnimationFrame(flush);
}
}
function addSubscriber(context, callable) {
if (this.hasSubscriber(context, callable)) {
return false;
}
if (!this._context0) {
this._context0 = context;
this._callable0 = callable;
return true;
}
if (!this._context1) {
this._context1 = context;
this._callable1 = callable;
return true;
}
if (!this._context2) {
this._context2 = context;
this._callable2 = callable;
return true;
}
if (!this._contextsRest) {
this._contextsRest = [context];
this._callablesRest = [callable];
return true;
}
this._contextsRest.push(context);
this._callablesRest.push(callable);
return true;
}
function removeSubscriber(context, callable) {
if (this._context0 === context && this._callable0 === callable) {
this._context0 = null;
this._callable0 = null;
return true;
}
if (this._context1 === context && this._callable1 === callable) {
this._context1 = null;
this._callable1 = null;
return true;
}
if (this._context2 === context && this._callable2 === callable) {
this._context2 = null;
this._callable2 = null;
return true;
}
var rest = this._contextsRest;
var index = void 0;
if (!rest || !rest.length || (index = rest.indexOf(context)) === -1 || this._callablesRest[index] !== callable) {
return false;
}
rest.splice(index, 1);
this._callablesRest.splice(index, 1);
return true;
}
var arrayPool1 = [];
var arrayPool2 = [];
var poolUtilization = [];
function callSubscribers(newValue, oldValue) {
var context0 = this._context0;
var callable0 = this._callable0;
var context1 = this._context1;
var callable1 = this._callable1;
var context2 = this._context2;
var callable2 = this._callable2;
var length = this._contextsRest ? this._contextsRest.length : 0;
var contextsRest = void 0;
var callablesRest = void 0;
var poolIndex = void 0;
var i = void 0;
if (length) {
poolIndex = poolUtilization.length;
while (poolIndex-- && poolUtilization[poolIndex]) {}
if (poolIndex < 0) {
poolIndex = poolUtilization.length;
contextsRest = [];
callablesRest = [];
poolUtilization.push(true);
arrayPool1.push(contextsRest);
arrayPool2.push(callablesRest);
} else {
poolUtilization[poolIndex] = true;
contextsRest = arrayPool1[poolIndex];
callablesRest = arrayPool2[poolIndex];
}
i = length;
while (i--) {
contextsRest[i] = this._contextsRest[i];
callablesRest[i] = this._callablesRest[i];
}
}
if (context0) {
if (callable0) {
callable0.call(context0, newValue, oldValue);
} else {
context0(newValue, oldValue);
}
}
if (context1) {
if (callable1) {
callable1.call(context1, newValue, oldValue);
} else {
context1(newValue, oldValue);
}
}
if (context2) {
if (callable2) {
callable2.call(context2, newValue, oldValue);
} else {
context2(newValue, oldValue);
}
}
if (length) {
for (i = 0; i < length; i++) {
var callable = callablesRest[i];
var context = contextsRest[i];
if (callable) {
callable.call(context, newValue, oldValue);
} else {
context(newValue, oldValue);
}
contextsRest[i] = null;
callablesRest[i] = null;
}
poolUtilization[poolIndex] = false;
}
}
function hasSubscribers() {
return !!(this._context0 || this._context1 || this._context2 || this._contextsRest && this._contextsRest.length);
}
function hasSubscriber(context, callable) {
var has = this._context0 === context && this._callable0 === callable || this._context1 === context && this._callable1 === callable || this._context2 === context && this._callable2 === callable;
if (has) {
return true;
}
var index = void 0;
var contexts = this._contextsRest;
if (!contexts || (index = contexts.length) === 0) {
return false;
}
var callables = this._callablesRest;
while (index--) {
if (contexts[index] === context && callables[index] === callable) {
return true;
}
}
return false;
}
export function subscriberCollection() {
return function (target) {
target.prototype.addSubscriber = addSubscriber;
target.prototype.removeSubscriber = removeSubscriber;
target.prototype.callSubscribers = callSubscribers;
target.prototype.hasSubscribers = hasSubscribers;
target.prototype.hasSubscriber = hasSubscriber;
};
}
export var ExpressionObserver = (_dec = connectable(), _dec2 = subscriberCollection(), _dec(_class = _dec2(_class = function () {
function ExpressionObserver(scope, expression, observerLocator, lookupFunctions) {
this.scope = scope;
this.expression = expression;
this.observerLocator = observerLocator;
this.lookupFunctions = lookupFunctions;
}
ExpressionObserver.prototype.getValue = function getValue() {
return this.expression.evaluate(this.scope, this.lookupFunctions);
};
ExpressionObserver.prototype.setValue = function setValue(newValue) {
this.expression.assign(this.scope, newValue);
};
ExpressionObserver.prototype.subscribe = function subscribe(context, callable) {
var _this = this;
if (!this.hasSubscribers()) {
this.oldValue = this.expression.evaluate(this.scope, this.lookupFunctions);
this.expression.connect(this, this.scope);
}
this.addSubscriber(context, callable);
if (arguments.length === 1 && context instanceof Function) {
return {
dispose: function dispose() {
_this.unsubscribe(context, callable);
}
};
}
};
ExpressionObserver.prototype.unsubscribe = function unsubscribe(context, callable) {
if (this.removeSubscriber(context, callable) && !this.hasSubscribers()) {
this.unobserve(true);
this.oldValue = undefined;
}
};
ExpressionObserver.prototype.call = function call() {
var newValue = this.expression.evaluate(this.scope, this.lookupFunctions);
var oldValue = this.oldValue;
if (newValue !== oldValue) {
this.oldValue = newValue;
this.callSubscribers(newValue, oldValue);
}
this._version++;
this.expression.connect(this, this.scope);
this.unobserve(false);
};
return ExpressionObserver;
}()) || _class) || _class);
function isIndex(s) {
return +s === s >>> 0;
}
function toNumber(s) {
return +s;
}
function newSplice(index, removed, addedCount) {
return {
index: index,
removed: removed,
addedCount: addedCount
};
}
var EDIT_LEAVE = 0;
var EDIT_UPDATE = 1;
var EDIT_ADD = 2;
var EDIT_DELETE = 3;
function ArraySplice() {}
ArraySplice.prototype = {
calcEditDistances: function calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd) {
var rowCount = oldEnd - oldStart + 1;
var columnCount = currentEnd - currentStart + 1;
var distances = new Array(rowCount);
var north = void 0;
var west = void 0;
for (var _i = 0; _i < rowCount; ++_i) {
distances[_i] = new Array(columnCount);
distances[_i][0] = _i;
}
for (var j = 0; j < columnCount; ++j) {
distances[0][j] = j;
}
for (var _i2 = 1; _i2 < rowCount; ++_i2) {
for (var _j = 1; _j < columnCount; ++_j) {
if (this.equals(current[currentStart + _j - 1], old[oldStart + _i2 - 1])) {
distances[_i2][_j] = distances[_i2 - 1][_j - 1];
} else {
north = distances[_i2 - 1][_j] + 1;
west = distances[_i2][_j - 1] + 1;
distances[_i2][_j] = north < west ? north : west;
}
}
}
return distances;
},
spliceOperationsFromEditDistances: function spliceOperationsFromEditDistances(distances) {
var i = distances.length - 1;
var j = distances[0].length - 1;
var current = distances[i][j];
var edits = [];
while (i > 0 || j > 0) {
if (i === 0) {
edits.push(EDIT_ADD);
j--;
continue;
}
if (j === 0) {
edits.push(EDIT_DELETE);
i--;
continue;
}
var northWest = distances[i - 1][j - 1];
var west = distances[i - 1][j];
var north = distances[i][j - 1];
var min = void 0;
if (west < north) {
min = west < northWest ? west : northWest;
} else {
min = north < northWest ? north : northWest;
}
if (min === northWest) {
if (northWest === current) {
edits.push(EDIT_LEAVE);
} else {
edits.push(EDIT_UPDATE);
current = northWest;
}
i--;
j--;
} else if (min === west) {
edits.push(EDIT_DELETE);
i--;
current = west;
} else {
edits.push(EDIT_ADD);
j--;
current = north;
}
}
edits.reverse();
return edits;
},
calcSplices: function calcSplices(current, currentStart, currentEnd, old, oldStart, oldEnd) {
var prefixCount = 0;
var suffixCount = 0;
var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
if (currentStart === 0 && oldStart === 0) {
prefixCount = this.sharedPrefix(current, old, minLength);
}
if (currentEnd === current.length && oldEnd === old.length) {
suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
}
currentStart += prefixCount;
oldStart += prefixCount;
currentEnd -= suffixCount;
oldEnd -= suffixCount;
if (currentEnd - currentStart === 0 && oldEnd - oldStart === 0) {
return [];
}
if (currentStart === currentEnd) {
var _splice = newSplice(currentStart, [], 0);
while (oldStart < oldEnd) {
_splice.removed.push(old[oldStart++]);
}
return [_splice];
} else if (oldStart === oldEnd) {
return [newSplice(currentStart, [], currentEnd - currentStart)];
}
var ops = this.spliceOperationsFromEditDistances(this.calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd));
var splice = undefined;
var splices = [];
var index = currentStart;
var oldIndex = oldStart;
for (var _i3 = 0; _i3 < ops.length; ++_i3) {
switch (ops[_i3]) {
case EDIT_LEAVE:
if (splice) {
splices.push(splice);
splice = undefined;
}
index++;
oldIndex++;
break;
case EDIT_UPDATE:
if (!splice) {
splice = newSplice(index, [], 0);
}
splice.addedCount++;
index++;
splice.removed.push(old[oldIndex]);
oldIndex++;
break;
case EDIT_ADD:
if (!splice) {
splice = newSplice(index, [], 0);
}
splice.addedCount++;
index++;
break;
case EDIT_DELETE:
if (!splice) {
splice = newSplice(index, [], 0);
}
splice.removed.push(old[oldIndex]);
oldIndex++;
break;
}
}
if (splice) {
splices.push(splice);
}
return splices;
},
sharedPrefix: function sharedPrefix(current, old, searchLength) {
for (var _i4 = 0; _i4 < searchLength; ++_i4) {
if (!this.equals(current[_i4], old[_i4])) {
return _i4;
}
}
return searchLength;
},
sharedSuffix: function sharedSuffix(current, old, searchLength) {
var index1 = current.length;
var index2 = old.length;
var count = 0;
while (count < searchLength && this.equals(current[--index1], old[--index2])) {
count++;
}
return count;
},
calculateSplices: function calculateSplices(current, previous) {
return this.calcSplices(current, 0, current.length, previous, 0, previous.length);
},
equals: function equals(currentValue, previousValue) {
return currentValue === previousValue;
}
};
var arraySplice = new ArraySplice();
export function calcSplices(current, currentStart, currentEnd, old, oldStart, oldEnd) {
return arraySplice.calcSplices(current, currentStart, currentEnd, old, oldStart, oldEnd);
}
function intersect(start1, end1, start2, end2) {
if (end1 < start2 || end2 < start1) {
return -1;
}
if (end1 === start2 || end2 === start1) {
return 0;
}
if (start1 < start2) {
if (end1 < end2) {
return end1 - start2;
}
return end2 - start2;
}
if (end2 < end1) {
return end2 - start1;
}
return end1 - start1;
}
export function mergeSplice(splices, index, removed, addedCount) {
var splice = newSplice(index, removed, addedCount);
var inserted = false;
var insertionOffset = 0;
for (var _i5 = 0; _i5 < splices.length; _i5++) {
var current = splices[_i5];
current.index += insertionOffset;
if (inserted) {
continue;
}
var intersectCount = intersect(splice.index, splice.index + splice.removed.length, current.index, current.index + current.addedCount);
if (intersectCount >= 0) {
splices.splice(_i5, 1);
_i5--;
insertionOffset -= current.addedCount - current.removed.length;
splice.addedCount += current.addedCount - intersectCount;
var deleteCount = splice.removed.length + current.removed.length - intersectCount;
if (!splice.addedCount && !deleteCount) {
inserted = true;
} else {
var currentRemoved = current.removed;
if (splice.index < current.index) {
var prepend = splice.removed.slice(0, current.index - splice.index);
Array.prototype.push.apply(prepend, currentRemoved);
currentRemoved = prepend;
}
if (splice.index + splice.removed.length > current.index + current.addedCount) {
var append = splice.removed.slice(current.index + current.addedCount - splice.index);
Array.prototype.push.apply(currentRemoved, append);
}
splice.removed = currentRemoved;
if (current.index < splice.index) {
splice.index = current.index;
}
}
} else if (splice.index < current.index) {
inserted = true;
splices.splice(_i5, 0, splice);
_i5++;
var offset = splice.addedCount - splice.removed.length;
current.index += offset;
insertionOffset += offset;
}
}
if (!inserted) {
splices.push(splice);
}
}
function createInitialSplices(array, changeRecords) {
var splices = [];
for (var _i6 = 0; _i6 < changeRecords.length; _i6++) {
var record = changeRecords[_i6];
switch (record.type) {
case 'splice':
mergeSplice(splices, record.index, record.removed.slice(), record.addedCount);
break;
case 'add':
case 'update':
case 'delete':
if (!isIndex(record.name)) {
continue;
}
var index = toNumber(record.name);
if (index < 0) {
continue;
}
mergeSplice(splices, index, [record.oldValue], record.type === 'delete' ? 0 : 1);
break;
default:
console.error('Unexpected record type: ' + JSON.stringify(record));
break;
}
}
return splices;
}
export function projectArraySplices(array, changeRecords) {
var splices = [];
createInitialSplices(array, changeRecords).forEach(function (splice) {
if (splice.addedCount === 1 && splice.removed.length === 1) {
if (splice.removed[0] !== array[splice.index]) {
splices.push(splice);
}
return;
}
splices = splices.concat(calcSplices(array, splice.index, splice.index + splice.addedCount, splice.removed, 0, splice.removed.length));
});
return splices;
}
function newRecord(type, object, key, oldValue) {
return {
type: type,
object: object,
key: key,
oldValue: oldValue
};
}
export function getChangeRecords(map) {
var entries = new Array(map.size);
var keys = map.keys();
var i = 0;
var item = void 0;
while (item = keys.next()) {
if (item.done) {
break;
}
entries[i] = newRecord('added', map, item.value);
i++;
}
return entries;
}
export var ModifyCollectionObserver = (_dec3 = subscriberCollection(), _dec3(_class2 = function () {
function ModifyCollectionObserver(taskQueue, collection) {
this.taskQueue = taskQueue;
this.queued = false;
this.changeRecords = null;
this.oldCollection = null;
this.collection = collection;
this.lengthPropertyName = collection instanceof Map || collection instanceof Set ? 'size' : 'length';
}
ModifyCollectionObserver.prototype.subscribe = function subscribe(context, callable) {
this.addSubscriber(context, callable);
};
ModifyCollectionObserver.prototype.unsubscribe = function unsubscribe(context, callable) {
this.removeSubscriber(context, callable);
};
ModifyCollectionObserver.prototype.addChangeRecord = function addChangeRecord(changeRecord) {
if (!this.hasSubscribers() && !this.lengthObserver) {
return;
}
if (changeRecord.type === 'splice') {
var index = changeRecord.index;
var arrayLength = changeRecord.object.length;
if (index > arrayLength) {
index = arrayLength - changeRecord.addedCount;
} else if (index < 0) {
index = arrayLength + changeRecord.removed.length + index - changeRecord.addedCount;
}
if (index < 0) {
index = 0;
}
changeRecord.index = index;
}
if (this.changeRecords === null) {
this.changeRecords = [changeRecord];
} else {
this.changeRecords.push(changeRecord);
}
if (!this.queued) {
this.queued = true;
this.taskQueue.queueMicroTask(this);
}
};
ModifyCollectionObserver.prototype.flushChangeRecords = function flushChangeRecords() {
if (this.changeRecords && this.changeRecords.length || this.oldCollection) {
this.call();
}
};
ModifyCollectionObserver.prototype.reset = function reset(oldCollection) {
this.oldCollection = oldCollection;
if (this.hasSubscribers() && !this.queued) {
this.queued = true;
this.taskQueue.queueMicroTask(this);
}
};
ModifyCollectionObserver.prototype.getLengthObserver = function getLengthObserver() {
return this.lengthObserver || (this.lengthObserver = new CollectionLengthObserver(this.collection));
};
ModifyCollectionObserver.prototype.call = function call() {
var changeRecords = this.changeRecords;
var oldCollection = this.oldCollection;
var records = void 0;
this.queued = false;
this.changeRecords = [];
this.oldCollection = null;
if (this.hasSubscribers()) {
if (oldCollection) {
if (this.collection instanceof Map || this.collection instanceof Set) {
records = getChangeRecords(oldCollection);
} else {
records = calcSplices(this.collection, 0, this.collection.length, oldCollection, 0, oldCollection.length);
}
} else {
if (this.collection instanceof Map || this.collection instanceof Set) {
records = changeRecords;
} else {
records = projectArraySplices(this.collection, changeRecords);
}
}
this.callSubscribers(records);
}
if (this.lengthObserver) {
this.lengthObserver.call(this.collection[this.lengthPropertyName]);
}
};
return ModifyCollectionObserver;
}()) || _class2);
export var CollectionLengthObserver = (_dec4 = subscriberCollection(), _dec4(_class3 = function () {
function CollectionLengthObserver(collection) {
this.collection = collection;
this.lengthPropertyName = collection instanceof Map || collection instanceof Set ? 'size' : 'length';
this.currentValue = collection[this.lengthPropertyName];
}
CollectionLengthObserver.prototype.getValue = function getValue() {
return this.collection[this.lengthPropertyName];
};
CollectionLengthObserver.prototype.setValue = function setValue(newValue) {
this.collection[this.lengthPropertyName] = newValue;
};
CollectionLengthObserver.prototype.subscribe = function subscribe(context, callable) {
this.addSubscriber(context, callable);
};
CollectionLengthObserver.prototype.unsubscribe = function unsubscribe(context, callable) {
this.removeSubscriber(context, callable);
};
CollectionLengthObserver.prototype.call = function call(newValue) {
var oldValue = this.currentValue;
this.callSubscribers(newValue, oldValue);
this.currentValue = newValue;
};
return CollectionLengthObserver;
}()) || _class3);
var pop = Array.prototype.pop;
var push = Array.prototype.push;
var reverse = Array.prototype.reverse;
var shift = Array.prototype.shift;
var sort = Array.prototype.sort;
var splice = Array.prototype.splice;
var unshift = Array.prototype.unshift;
Array.prototype.pop = function () {
var notEmpty = this.length > 0;
var methodCallResult = pop.apply(this, arguments);
if (notEmpty && this.__array_observer__ !== undefined) {
this.__array_observer__.addChangeRecord({
type: 'delete',
object: this,
name: this.length,
oldValue: methodCallResult
});
}
return methodCallResult;
};
Array.prototype.push = function () {
var methodCallResult = push.apply(this, arguments);
if (this.__array_observer__ !== undefined) {
this.__array_observer__.addChangeRecord({
type: 'splice',
object: this,
index: this.length - arguments.length,
removed: [],
addedCount: arguments.length
});
}
return methodCallResult;
};
Array.prototype.reverse = function () {
var oldArray = void 0;
if (this.__array_observer__ !== undefined) {
this.__array_observer__.flushChangeRecords();
oldArray = this.slice();
}
var methodCallResult = reverse.apply(this, arguments);
if (this.__array_observer__ !== undefined) {
this.__array_observer__.reset(oldArray);
}
return methodCallResult;
};
Array.prototype.shift = function () {
var notEmpty = this.length > 0;
var methodCallResult = shift.apply(this, arguments);
if (notEmpty && this.__array_observer__ !== undefined) {
this.__array_observer__.addChangeRecord({
type: 'delete',
object: this,
name: 0,
oldValue: methodCallResult
});
}
return methodCallResult;
};
Array.prototype.sort = function () {
var oldArray = void 0;
if (this.__array_observer__ !== undefined) {
this.__array_observer__.flushChangeRecords();
oldArray = this.slice();
}
var methodCallResult = sort.apply(this, arguments);
if (this.__array_observer__ !== undefined) {
this.__array_observer__.reset(oldArray);
}
return methodCallResult;
};
Array.prototype.splice = function () {
var methodCallResult = splice.apply(this, arguments);
if (this.__array_observer__ !== undefined) {
this.__array_observer__.addChangeRecord({
type: 'splice',
object: this,
index: arguments[0],
removed: methodCallResult,
addedCount: arguments.length > 2 ? arguments.length - 2 : 0
});
}
return methodCallResult;
};
Array.prototype.unshift = function () {
var methodCallResult = unshift.apply(this, arguments);
if (this.__array_observer__ !== undefined) {
this.__array_observer__.addChangeRecord({
type: 'splice',
object: this,
index: 0,
removed: [],
addedCount: arguments.length
});
}
return methodCallResult;
};
function _getArrayObserver(taskQueue, array) {
return ModifyArrayObserver.for(taskQueue, array);
}
var ModifyArrayObserver = function (_ModifyCollectionObse) {
_inherits(ModifyArrayObserver, _ModifyCollectionObse);
function ModifyArrayObserver(taskQueue, array) {
return _possibleConstructorReturn(this, _ModifyCollectionObse.call(this, taskQueue, array));
}
ModifyArrayObserver.for = function _for(taskQueue, array) {
if (!('__array_observer__' in array)) {
Reflect.defineProperty(array, '__array_observer__', {
value: ModifyArrayObserver.create(taskQueue, array),
enumerable: false, configurable: false
});
}
return array.__array_observer__;
};
ModifyArrayObserver.create = function create(taskQueue, array) {
return new ModifyArrayObserver(taskQueue, array);
};
return ModifyArrayObserver;
}(ModifyCollectionObserver);
export var Expression = function () {
function Expression() {
this.isChain = false;
this.isAssignable = false;
}
Expression.prototype.evaluate = function evaluate(scope, lookupFunctions, args) {
throw new Error('Binding expression "' + this + '" cannot be evaluated.');
};
Expression.prototype.assign = function assign(scope, value, lookupFunctions) {
throw new Error('Binding expression "' + this + '" cannot be assigned to.');
};
Expression.prototype.toString = function toString() {
return Unparser.unparse(this);
};
return Expression;
}();
export var Chain = function (_Expression) {
_inherits(Chain, _Expression);
function Chain(expressions) {
var _this3 = _possibleConstructorReturn(this, _Expression.call(this));
_this3.expressions = expressions;
_this3.isChain = true;
return _this3;
}
Chain.prototype.evaluate = function evaluate(scope, lookupFunctions) {
var result = void 0;
var expressions = this.expressions;
var last = void 0;
for (var _i7 = 0, length = expressions.length; _i7 < length; ++_i7) {
last = expressions[_i7].evaluate(scope, lookupFunctions);
if (last !== null) {
result = last;
}
}
return result;
};
Chain.prototype.accept = function accept(visitor) {
return visitor.visitChain(this);
};
return Chain;
}(Expression);
export var BindingBehavior = function (_Expression2) {
_inherits(BindingBehavior, _Expression2);
function BindingBehavior(expression, name, args) {
var _this4 = _possibleConstructorReturn(this, _Expression2.call(this));
_this4.expression = expression;
_this4.name = name;
_this4.args = args;
return _this4;
}
BindingBehavior.prototype.evaluate = function evaluate(scope, lookupFunctions) {
return this.expression.evaluate(scope, lookupFunctions);
};
BindingBehavior.prototype.assign = function assign(scope, value, lookupFunctions) {
return this.expression.assign(scope, value, lookupFunctions);
};
BindingBehavior.prototype.accept = function accept(visitor) {
return visitor.visitBindingBehavior(this);
};
BindingBehavior.prototype.connect = function connect(binding, scope) {
this.expression.connect(binding, scope);
};
BindingBehavior.prototype.bind = function bind(binding, scope, lookupFunctions) {
if (this.expression.expression && this.expression.bind) {
this.expression.bind(binding, scope, lookupFunctions);
}
var behavior = lookupFunctions.bindingBehaviors(this.name);
if (!behavior) {
throw new Error('No BindingBehavior named "' + this.name + '" was found!');
}
var behaviorKey = 'behavior-' + this.name;
if (binding[behaviorKey]) {
throw new Error('A binding behavior named "' + this.name + '" has already been applied to "' + this.expression + '"');
}
binding[behaviorKey] = behavior;
behavior.bind.apply(behavior, [binding, scope].concat(evalList(scope, this.args, binding.lookupFunctions)));
};
BindingBehavior.prototype.unbind = function unbind(binding, scope) {
var behaviorKey = 'behavior-' + this.name;
binding[behaviorKey].unbind(binding, scope);
binding[behaviorKey] = null;
if (this.expression.expression && this.expression.unbind) {
this.expression.unbind(binding, scope);
}
};
return BindingBehavior;
}(Expression);
export var ValueConverter = function (_Expression3) {
_inherits(ValueConverter, _Expression3);
function ValueConverter(expression, name, args, allArgs) {
var _this5 = _possibleConstructorReturn(this, _Expression3.call(this));
_this5.expression = expression;
_this5.name = name;
_this5.args = args;
_this5.allArgs = allArgs;
return _this5;
}
ValueConverter.prototype.evaluate = function evaluate(scope, lookupFunctions) {
var converter = lookupFunctions.valueConverters(this.name);
if (!converter) {
throw new Error('No ValueConverter named "' + this.name + '" was found!');
}
if ('toView' in converter) {
return converter.toView.apply(converter, evalList(scope, this.allArgs, lookupFunctions));
}
return this.allArgs[0].evaluate(scope, lookupFunctions);
};
ValueConverter.prototype.assign = function assign(scope, value, lookupFunctions) {
var converter = lookupFunctions.valueConverters(this.name);
if (!converter) {
throw new Error('No ValueConverter named "' + this.name + '" was found!');
}
if ('fromView' in converter) {
value = converter.fromView.apply(converter, [value].concat(evalList(scope, this.args, lookupFunctions)));
}
return this.allArgs[0].assign(scope, value, lookupFunctions);
};
ValueConverter.prototype.accept = function accept(visitor) {
return visitor.visitValueConverter(this);
};
ValueConverter.prototype.connect = function connect(binding, scope) {
var expressions = this.allArgs;
var i = expressions.length;
while (i--) {
expressions[i].connect(binding, scope);
}
};
return ValueConverter;
}(Expression);
export var Assign = function (_Expression4) {
_inherits(Assign, _Expression4);
function Assign(target, value) {
var _this6 = _possibleConstructorReturn(this, _Expression4.call(this));
_this6.target = target;
_this6.value = value;
return _this6;
}
Assign.prototype.evaluate = function evaluate(scope, lookupFunctions) {
return this.target.assign(scope, this.value.evaluate(scope, lookupFunctions));
};
Assign.prototype.accept = function accept(vistor) {
vistor.visitAssign(this);
};
Assign.prototype.connect = function connect(binding, scope) {};
return Assign;
}(Expression);
export var Conditional = function (_Expression5) {
_inherits(Conditional, _Expression5);
function Conditional(condition, yes, no) {
var _this7 = _possibleConstructorReturn(this, _Expression5.call(this));
_this7.condition = condition;
_this7.yes = yes;
_this7.no = no;
return _this7;
}
Conditional.prototype.evaluate = function evaluate(scope, lookupFunctions) {
return !!this.condition.evaluate(scope) ? this.yes.evaluate(scope) : this.no.evaluate(scope);
};
Conditional.prototype.accept = function accept(visitor) {
return visitor.visitConditional(this);
};
Conditional.prototype.connect = function connect(binding, scope) {
this.condition.connect(binding, scope);
if (this.condition.evaluate(scope)) {
this.yes.connect(binding, scope);
} else {
this.no.connect(binding, scope);
}
};
return Conditional;
}(Expression);
export var AccessThis = function (_Expression6) {
_inherits(AccessThis, _Expression6);
function AccessThis(ancestor) {
var _this8 = _possibleConstructorReturn(this, _Expression6.call(this));
_this8.ancestor = ancestor;
return _this8;
}
AccessThis.prototype.evaluate = function evaluate(scope, lookupFunctions) {
var oc = scope.overrideContext;
var i = this.ancestor;
while (i-- && oc) {
oc = oc.parentOverrideContext;
}
return i < 1 && oc ? oc.bindingContext : undefined;
};
AccessThis.prototype.accept = function accept(visitor) {
return visitor.visitAccessThis(this);
};
AccessThis.prototype.connect = function connect(binding, scope) {};
return AccessThis;
}(Expression);
export var AccessScope = function (_Expression7) {
_inherits(AccessScope, _Expression7);
function AccessScope(name, ancestor) {
var _this9 = _possibleConstructorReturn(this, _Expression7.call(this));
_this9.name = name;
_this9.ancestor = ancestor;
_this9.isAssignable = true;
return _this9;
}
AccessScope.prototype.evaluate = function evaluate(scope, lookupFunctions) {
var context = getContextFor(this.name, scope, this.ancestor);
return context[this.name];
};
AccessScope.prototype.assign = function assign(scope, value) {
var context = getContextFor(this.name, scope, this.ancestor);
return context ? context[this.name] = value : undefined;
};
AccessScope.prototype.accept = function accept(visitor) {
return visitor.visitAccessScope(this);
};
AccessScope.prototype.connect = function connect(binding, scope) {
var context = getContextFor(this.name, scope, this.ancestor);
binding.observeProperty(context, this.name);
};
return AccessScope;
}(Expression);
export var AccessMember = function (_Expression8) {
_inherits(AccessMember, _Expression8);
function AccessMember(object, name) {
var _this10 = _possibleConstructorReturn(this, _Expression8.call(this));
_this10.object = object;
_this10.name = name;
_this10.isAssignable = true;
return _this10;
}
AccessMember.prototype.evaluate = function evaluate(scope, lookupFunctions) {
var instance = this.object.evaluate(scope, lookupFunctions);
return instance === null || instance === undefined ? instance : instance[this.name];
};
AccessMember.prototype.assign = function assign(scope, value) {
var instance = this.object.evaluate(scope);
if (instance === null || instance === undefined) {
instance = {};
this.object.assign(scope, instance);
}
instance[this.name] = value;
return value;
};
AccessMember.prototype.accept = function accept(visitor) {
return visitor.visitAccessMember(this);
};
AccessMember.prototype.connect = function connect(binding, scope) {
this.object.connect(binding, scope);
var obj = this.object.evaluate(scope);
if (obj) {
binding.observeProperty(obj, this.name);
}
};
return AccessMember;
}(Expression);
export var AccessKeyed = function (_Expression9) {
_inherits(AccessKeyed, _Expression9);
function AccessKeyed(object, key) {
var _this11 = _possibleConstructorReturn(this, _Expression9.call(this));
_this11.object = object;
_this11.key = key;
_this11.isAssignable = true;
return _this11;
}
AccessKeyed.prototype.evaluate = function evaluate(scope, lookupFunctions) {
var instance = this.object.evaluate(scope, lookupFunctions);
var lookup = this.key.evaluate(scope, lookupFunctions);
return getKeyed(instance, lookup);
};
AccessKeyed.prototype.assign = function assign(scope, value) {
var instance = this.object.evaluate(scope);
var lookup = this.key.evaluate(scope);
return setKeyed(instance, lookup, value);
};
AccessKeyed.prototype.accept = function accept(visitor) {
return visitor.visitAccessKeyed(this);
};
AccessKeyed.prototype.connect = function connect(binding, scope) {
this.object.connect(binding, scope);
var obj = this.object.evaluate(scope);
if (obj instanceof Object) {
this.key.connect(binding, scope);
var key = this.key.evaluate(scope);
if (key !== null && key !== undefined && !(Array.isArray(obj) && typeof key === 'number')) {
binding.observeProperty(obj, key);
}
}
};
return AccessKeyed;
}(Expression);
export var CallScope = function (_Expression10) {
_inherits(CallScope, _Expression10);
function CallScope(name, args, ancestor) {
var _this12 = _possibleConstructorReturn(this, _Expression10.call(this));
_this12.name = name;
_this12.args = args;
_this12.ancestor = ancestor;
return _this12;
}
CallScope.prototype.evaluate = function evaluate(scope, lookupFunctions, mustEvaluate) {
var args = evalList(scope, this.args, lookupFunctions);
var context = getContextFor(this.name, scope, this.ancestor);
var func = getFunction(context, this.name, mustEvaluate);
if (func) {
return func.apply(context, args);
}
return undefined;
};
CallScope.prototype.accept = function accept(visitor) {
return visitor.visitCallScope(this);
};
CallScope.prototype.connect = function connect(binding, scope) {
var args = this.args;
var i = args.length;
while (i--) {
args[i].connect(binding, scope);
}
};
return CallScope;
}(Expression);
export var CallMember = function (_Expression11) {
_inherits(CallMember, _Expression11);
function CallMember(object, name, args) {
var _this13 = _possibleConstructorReturn(this, _Expression11.call(this));
_this13.object = object;
_this13.name = name;
_this13.args = args;
return _this13;
}
CallMember.prototype.evaluate = function evaluate(scope, lookupFunctions, mustEvaluate) {
var instance = this.object.evaluate(scope, lookupFunctions);
var args = evalList(scope, this.args, lookupFunctions);
var func = getFunction(instance, this.name, mustEvaluate);
if (func) {
return func.apply(instance, args);
}
return undefined;
};
CallMember.prototype.accept = function accept(visitor) {
return visitor.visitCallMember(this);
};
CallMember.prototype.connect = function connect(binding, scope) {
this.object.connect(binding, scope);
var obj = this.object.evaluate(scope);
if (getFunction(obj, this.name, false)) {
var args = this.args;
var _i8 = args.length;
while (_i8--) {
args[_i8].connect(binding, scope);
}
}
};
return CallMember;
}(Expression);
export var CallFunction = function (_Expression12) {
_inherits(CallFunction, _Expression12);
function CallFunction(func, args) {
var _this14 = _possibleConstructorReturn(this, _Expression12.call(this));
_this14.func = func;
_this14.args = args;
return _this14;
}
CallFunction.prototype.evaluate = function evaluate(scope, lookupFunctions, mustEvaluate) {
var func = this.func.evaluate(scope, lookupFunctions);
if (typeof func === 'function') {
return func.apply(null, evalList(scope, this.args, lookupFunctions));
}
if (!mustEvaluate && (func === null || func === undefined)) {
return undefined;
}
throw new Error(this.func + ' is not a function');
};
CallFunction.prototype.accept = function accept(visitor) {
return visitor.visitCallFunction(this);
};
CallFunction.prototype.connect = function connect(binding, scope) {
this.func.connect(binding, scope);
var func = this.func.evaluate(scope);
if (typeof func === 'function') {
var args = this.args;
var _i9 = args.length;
while (_i9--) {
args[_i9].connect(binding, scope);
}
}
};
return CallFunction;
}(Expression);
export var Binary = function (_Expression13) {
_inherits(Binary, _Expression13);
function Binary(operation, left, right) {
var _this15 = _possibleConstructorReturn(this, _Expression13.call(this));
_this15.operation = operation;
_this15.left = left;
_this15.right = right;
return _this15;
}
Binary.prototype.evaluate = function evaluate(scope, lookupFunctions) {
var left = this.left.evaluate(scope);
switch (this.operation) {
case '&&':
return left && this.right.evaluate(scope);
case '||':
return left || this.right.evaluate(scope);
}
var right = this.right.evaluate(scope);
switch (this.operation) {
case '==':
return left == right;
case '===':
return left === right;
case '!=':
return left != right;
case '!==':
return left !== right;
}
if (left === null || right === null || left === undefined || right === undefined) {
switch (this.operation) {
case '+':
if (left !== null && left !== undefined) return left;
if (right !== null && right !== undefined) return right;
return 0;
case '-':
if (left !== null && left !== undefined) return left;
if (right !== null && right !== undefined) return 0 - right;
return 0;
}
return null;
}
switch (this.operation) {
case '+':
return autoConvertAdd(left, right);
case '-':
return left - right;
case '*':
return left * right;
case '/':
return left / right;
case '%':
return left % right;
case '<':
return left < right;
case '>':
return left > right;
case '<=':
return left <= right;
case '>=':
return left >= right;
case '^':
return left ^ right;
}
throw new Error('Internal error [' + this.operation + '] not handled');
};
Binary.prototype.accept = function accept(visitor) {
return visitor.visitBinary(this);
};
Binary.prototype.connect = function connect(binding, scope) {
this.left.connect(binding, scope);
var left = this.left.evaluate(scope);
if (this.operation === '&&' && !left || this.operation === '||' && left) {
return;
}
this.right.connect(binding, scope);
};
return Binary;
}(Expression);
export var PrefixNot = function (_Expression14) {
_inherits(PrefixNot, _Expression14);
function PrefixNot(operation, expression) {
var _this16 = _possibleConstructorReturn(this, _Expression14.call(this));
_this16.operation = operation;
_this16.expression = expression;
return _this16;
}
PrefixNot.prototype.evaluate = function evaluate(scope, lookupFunctions) {
return !this.expression.evaluate(scope);
};
PrefixNot.prototype.accept = function accept(visitor) {
return visitor.visitPrefix(this);
};
PrefixNot.prototype.connect = function connect(binding, scope) {
this.expression.connect(binding, scope);
};
return PrefixNot;
}(Expression);
export var LiteralPrimitive = function (_Expression15) {
_inherits(LiteralPrimitive, _Expression15);
function LiteralPrimitive(value) {
var _this17 = _possibleConstructorReturn(this, _Expression15.call(this));
_this17.value = value;
return _this17;
}
LiteralPrimitive.prototype.evaluate = function evaluate(scope, lookupFunctions) {
return this.value;
};
LiteralPrimitive.prototype.accept = function accept(visitor) {
return visitor.visitLiteralPrimitive(this);
};
LiteralPrimitive.prototype.connect = function connect(binding, scope) {};
return LiteralPrimitive;
}(Expression);
export var LiteralString = function (_Expression16) {
_inherits(LiteralString, _Expression16);
function LiteralString(value) {
var _this18 = _possibleConstructorReturn(this, _Expression16.call(this));
_this18.value = value;
return _this18;
}
LiteralString.prototype.evaluate = function evaluate(scope, lookupFunctions) {
return this.value;
};
LiteralString.prototype.accept = function accept(visitor) {
return visitor.visitLiteralString(this);
};
LiteralString.prototype.connect = function connect(binding, scope) {};
return LiteralString;
}(Expression);
export var LiteralArray = function (_Expression17) {
_inherits(LiteralArray, _Expression17);
function LiteralArray(elements) {
var _this19 = _possibleConstructorReturn(this, _Expression17.call(this));
_this19.elements = elements;
return _this19;
}
LiteralArray.prototype.evaluate = function evaluate(scope, lookupFunctions) {
var elements = this.elements;
var result = [];
for (var _i10 = 0, length = elements.length; _i10 < length; ++_i10) {
result[_i10] = elements[_i10].evaluate(scope, lookupFunctions);
}
return result;
};
LiteralArray.prototype.accept = function accept(visitor) {
return visitor.visitLiteralArray(this);
};
LiteralArray.prototype.connect = function connect(binding, scope) {
var length = this.elements.length;
for (var _i11 = 0; _i11 < length; _i11++) {
this.elements[_i11].connect(binding, scope);
}
};
return LiteralArray;
}(Expression);
export var LiteralObject