angular2
Version:
Angular 2 - a web framework for modern web apps
401 lines • 19.9 kB
JavaScript
'use strict';var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var lang_1 = require('angular2/src/facade/lang');
var exceptions_1 = require('angular2/src/facade/exceptions');
var collection_1 = require('angular2/src/facade/collection');
var abstract_change_detector_1 = require('./abstract_change_detector');
var change_detection_util_1 = require('./change_detection_util');
var constants_1 = require('./constants');
var proto_record_1 = require('./proto_record');
var DynamicChangeDetector = (function (_super) {
__extends(DynamicChangeDetector, _super);
function DynamicChangeDetector(id, dispatcher, numberOfPropertyProtoRecords, propertyBindingTargets, directiveIndices, strategy, _records, _eventBindings, _directiveRecords, _genConfig) {
_super.call(this, id, dispatcher, numberOfPropertyProtoRecords, propertyBindingTargets, directiveIndices, strategy);
this._records = _records;
this._eventBindings = _eventBindings;
this._directiveRecords = _directiveRecords;
this._genConfig = _genConfig;
this.directives = null;
var len = _records.length + 1;
this.values = collection_1.ListWrapper.createFixedSize(len);
this.localPipes = collection_1.ListWrapper.createFixedSize(len);
this.prevContexts = collection_1.ListWrapper.createFixedSize(len);
this.changes = collection_1.ListWrapper.createFixedSize(len);
this.dehydrateDirectives(false);
}
DynamicChangeDetector.prototype.handleEventInternal = function (eventName, elIndex, locals) {
var _this = this;
var preventDefault = false;
this._matchingEventBindings(eventName, elIndex)
.forEach(function (rec) {
var res = _this._processEventBinding(rec, locals);
if (res === false) {
preventDefault = true;
}
});
return preventDefault;
};
/** @internal */
DynamicChangeDetector.prototype._processEventBinding = function (eb, locals) {
var values = collection_1.ListWrapper.createFixedSize(eb.records.length);
values[0] = this.values[0];
for (var protoIdx = 0; protoIdx < eb.records.length; ++protoIdx) {
var proto = eb.records[protoIdx];
if (proto.isSkipRecord()) {
protoIdx += this._computeSkipLength(protoIdx, proto, values);
}
else {
var res = this._calculateCurrValue(proto, values, locals);
if (proto.lastInBinding) {
this._markPathAsCheckOnce(proto);
return res;
}
else {
this._writeSelf(proto, res, values);
}
}
}
throw new exceptions_1.BaseException("Cannot be reached");
};
DynamicChangeDetector.prototype._computeSkipLength = function (protoIndex, proto, values) {
if (proto.mode === proto_record_1.RecordType.SkipRecords) {
return proto.fixedArgs[0] - protoIndex - 1;
}
if (proto.mode === proto_record_1.RecordType.SkipRecordsIf) {
var condition = this._readContext(proto, values);
return condition ? proto.fixedArgs[0] - protoIndex - 1 : 0;
}
if (proto.mode === proto_record_1.RecordType.SkipRecordsIfNot) {
var condition = this._readContext(proto, values);
return condition ? 0 : proto.fixedArgs[0] - protoIndex - 1;
}
throw new exceptions_1.BaseException("Cannot be reached");
};
/** @internal */
DynamicChangeDetector.prototype._markPathAsCheckOnce = function (proto) {
if (!proto.bindingRecord.isDefaultChangeDetection()) {
var dir = proto.bindingRecord.directiveRecord;
this._getDetectorFor(dir.directiveIndex).markPathToRootAsCheckOnce();
}
};
/** @internal */
DynamicChangeDetector.prototype._matchingEventBindings = function (eventName, elIndex) {
return this._eventBindings.filter(function (eb) { return eb.eventName == eventName && eb.elIndex === elIndex; });
};
DynamicChangeDetector.prototype.hydrateDirectives = function (directives) {
this.values[0] = this.context;
this.directives = directives;
if (this.strategy === constants_1.ChangeDetectionStrategy.OnPushObserve) {
for (var i = 0; i < this.directiveIndices.length; ++i) {
var index = this.directiveIndices[i];
_super.prototype.observeDirective.call(this, directives.getDirectiveFor(index), i);
}
}
};
DynamicChangeDetector.prototype.dehydrateDirectives = function (destroyPipes) {
if (destroyPipes) {
this._destroyPipes();
}
this.values[0] = null;
this.directives = null;
collection_1.ListWrapper.fill(this.values, change_detection_util_1.ChangeDetectionUtil.uninitialized, 1);
collection_1.ListWrapper.fill(this.changes, false);
collection_1.ListWrapper.fill(this.localPipes, null);
collection_1.ListWrapper.fill(this.prevContexts, change_detection_util_1.ChangeDetectionUtil.uninitialized);
};
/** @internal */
DynamicChangeDetector.prototype._destroyPipes = function () {
for (var i = 0; i < this.localPipes.length; ++i) {
if (lang_1.isPresent(this.localPipes[i])) {
change_detection_util_1.ChangeDetectionUtil.callPipeOnDestroy(this.localPipes[i]);
}
}
};
DynamicChangeDetector.prototype.checkNoChanges = function () { this.runDetectChanges(true); };
DynamicChangeDetector.prototype.detectChangesInRecordsInternal = function (throwOnChange) {
var protos = this._records;
var changes = null;
var isChanged = false;
for (var protoIdx = 0; protoIdx < protos.length; ++protoIdx) {
var proto = protos[protoIdx];
var bindingRecord = proto.bindingRecord;
var directiveRecord = bindingRecord.directiveRecord;
if (this._firstInBinding(proto)) {
this.propertyBindingIndex = proto.propertyBindingIndex;
}
if (proto.isLifeCycleRecord()) {
if (proto.name === "DoCheck" && !throwOnChange) {
this._getDirectiveFor(directiveRecord.directiveIndex).doCheck();
}
else if (proto.name === "OnInit" && !throwOnChange &&
this.state == constants_1.ChangeDetectorState.NeverChecked) {
this._getDirectiveFor(directiveRecord.directiveIndex).onInit();
}
else if (proto.name === "OnChanges" && lang_1.isPresent(changes) && !throwOnChange) {
this._getDirectiveFor(directiveRecord.directiveIndex).onChanges(changes);
}
}
else if (proto.isSkipRecord()) {
protoIdx += this._computeSkipLength(protoIdx, proto, this.values);
}
else {
var change = this._check(proto, throwOnChange, this.values, this.locals);
if (lang_1.isPresent(change)) {
this._updateDirectiveOrElement(change, bindingRecord);
isChanged = true;
changes = this._addChange(bindingRecord, change, changes);
}
}
if (proto.lastInDirective) {
changes = null;
if (isChanged && !bindingRecord.isDefaultChangeDetection()) {
this._getDetectorFor(directiveRecord.directiveIndex).markAsCheckOnce();
}
isChanged = false;
}
}
};
/** @internal */
DynamicChangeDetector.prototype._firstInBinding = function (r) {
var prev = change_detection_util_1.ChangeDetectionUtil.protoByIndex(this._records, r.selfIndex - 1);
return lang_1.isBlank(prev) || prev.bindingRecord !== r.bindingRecord;
};
DynamicChangeDetector.prototype.afterContentLifecycleCallbacksInternal = function () {
var dirs = this._directiveRecords;
for (var i = dirs.length - 1; i >= 0; --i) {
var dir = dirs[i];
if (dir.callAfterContentInit && this.state == constants_1.ChangeDetectorState.NeverChecked) {
this._getDirectiveFor(dir.directiveIndex).afterContentInit();
}
if (dir.callAfterContentChecked) {
this._getDirectiveFor(dir.directiveIndex).afterContentChecked();
}
}
};
DynamicChangeDetector.prototype.afterViewLifecycleCallbacksInternal = function () {
var dirs = this._directiveRecords;
for (var i = dirs.length - 1; i >= 0; --i) {
var dir = dirs[i];
if (dir.callAfterViewInit && this.state == constants_1.ChangeDetectorState.NeverChecked) {
this._getDirectiveFor(dir.directiveIndex).afterViewInit();
}
if (dir.callAfterViewChecked) {
this._getDirectiveFor(dir.directiveIndex).afterViewChecked();
}
}
};
/** @internal */
DynamicChangeDetector.prototype._updateDirectiveOrElement = function (change, bindingRecord) {
if (lang_1.isBlank(bindingRecord.directiveRecord)) {
_super.prototype.notifyDispatcher.call(this, change.currentValue);
}
else {
var directiveIndex = bindingRecord.directiveRecord.directiveIndex;
bindingRecord.setter(this._getDirectiveFor(directiveIndex), change.currentValue);
}
if (this._genConfig.logBindingUpdate) {
_super.prototype.logBindingUpdate.call(this, change.currentValue);
}
};
/** @internal */
DynamicChangeDetector.prototype._addChange = function (bindingRecord, change, changes) {
if (bindingRecord.callOnChanges()) {
return _super.prototype.addChange.call(this, changes, change.previousValue, change.currentValue);
}
else {
return changes;
}
};
/** @internal */
DynamicChangeDetector.prototype._getDirectiveFor = function (directiveIndex) {
return this.directives.getDirectiveFor(directiveIndex);
};
/** @internal */
DynamicChangeDetector.prototype._getDetectorFor = function (directiveIndex) { return this.directives.getDetectorFor(directiveIndex); };
/** @internal */
DynamicChangeDetector.prototype._check = function (proto, throwOnChange, values, locals) {
if (proto.isPipeRecord()) {
return this._pipeCheck(proto, throwOnChange, values);
}
else {
return this._referenceCheck(proto, throwOnChange, values, locals);
}
};
/** @internal */
DynamicChangeDetector.prototype._referenceCheck = function (proto, throwOnChange, values, locals) {
if (this._pureFuncAndArgsDidNotChange(proto)) {
this._setChanged(proto, false);
return null;
}
var currValue = this._calculateCurrValue(proto, values, locals);
if (this.strategy === constants_1.ChangeDetectionStrategy.OnPushObserve) {
_super.prototype.observeValue.call(this, currValue, proto.selfIndex);
}
if (proto.shouldBeChecked()) {
var prevValue = this._readSelf(proto, values);
if (change_detection_util_1.ChangeDetectionUtil.looseNotIdentical(prevValue, currValue)) {
if (proto.lastInBinding) {
var change = change_detection_util_1.ChangeDetectionUtil.simpleChange(prevValue, currValue);
if (throwOnChange)
this.throwOnChangeError(prevValue, currValue);
this._writeSelf(proto, currValue, values);
this._setChanged(proto, true);
return change;
}
else {
this._writeSelf(proto, currValue, values);
this._setChanged(proto, true);
return null;
}
}
else {
this._setChanged(proto, false);
return null;
}
}
else {
this._writeSelf(proto, currValue, values);
this._setChanged(proto, true);
return null;
}
};
DynamicChangeDetector.prototype._calculateCurrValue = function (proto, values, locals) {
switch (proto.mode) {
case proto_record_1.RecordType.Self:
return this._readContext(proto, values);
case proto_record_1.RecordType.Const:
return proto.funcOrValue;
case proto_record_1.RecordType.PropertyRead:
var context = this._readContext(proto, values);
return proto.funcOrValue(context);
case proto_record_1.RecordType.SafeProperty:
var context = this._readContext(proto, values);
return lang_1.isBlank(context) ? null : proto.funcOrValue(context);
case proto_record_1.RecordType.PropertyWrite:
var context = this._readContext(proto, values);
var value = this._readArgs(proto, values)[0];
proto.funcOrValue(context, value);
return value;
case proto_record_1.RecordType.KeyedWrite:
var context = this._readContext(proto, values);
var key = this._readArgs(proto, values)[0];
var value = this._readArgs(proto, values)[1];
context[key] = value;
return value;
case proto_record_1.RecordType.Local:
return locals.get(proto.name);
case proto_record_1.RecordType.InvokeMethod:
var context = this._readContext(proto, values);
var args = this._readArgs(proto, values);
return proto.funcOrValue(context, args);
case proto_record_1.RecordType.SafeMethodInvoke:
var context = this._readContext(proto, values);
if (lang_1.isBlank(context)) {
return null;
}
var args = this._readArgs(proto, values);
return proto.funcOrValue(context, args);
case proto_record_1.RecordType.KeyedRead:
var arg = this._readArgs(proto, values)[0];
return this._readContext(proto, values)[arg];
case proto_record_1.RecordType.Chain:
var args = this._readArgs(proto, values);
return args[args.length - 1];
case proto_record_1.RecordType.InvokeClosure:
return lang_1.FunctionWrapper.apply(this._readContext(proto, values), this._readArgs(proto, values));
case proto_record_1.RecordType.Interpolate:
case proto_record_1.RecordType.PrimitiveOp:
case proto_record_1.RecordType.CollectionLiteral:
return lang_1.FunctionWrapper.apply(proto.funcOrValue, this._readArgs(proto, values));
default:
throw new exceptions_1.BaseException("Unknown operation " + proto.mode);
}
};
DynamicChangeDetector.prototype._pipeCheck = function (proto, throwOnChange, values) {
var context = this._readContext(proto, values);
var selectedPipe = this._pipeFor(proto, context);
if (!selectedPipe.pure || this._argsOrContextChanged(proto)) {
var args = this._readArgs(proto, values);
var currValue = selectedPipe.pipe.transform(context, args);
if (proto.shouldBeChecked()) {
var prevValue = this._readSelf(proto, values);
if (change_detection_util_1.ChangeDetectionUtil.looseNotIdentical(prevValue, currValue)) {
currValue = change_detection_util_1.ChangeDetectionUtil.unwrapValue(currValue);
if (proto.lastInBinding) {
var change = change_detection_util_1.ChangeDetectionUtil.simpleChange(prevValue, currValue);
if (throwOnChange)
this.throwOnChangeError(prevValue, currValue);
this._writeSelf(proto, currValue, values);
this._setChanged(proto, true);
return change;
}
else {
this._writeSelf(proto, currValue, values);
this._setChanged(proto, true);
return null;
}
}
else {
this._setChanged(proto, false);
return null;
}
}
else {
this._writeSelf(proto, currValue, values);
this._setChanged(proto, true);
return null;
}
}
};
DynamicChangeDetector.prototype._pipeFor = function (proto, context) {
var storedPipe = this._readPipe(proto);
if (lang_1.isPresent(storedPipe))
return storedPipe;
var pipe = this.pipes.get(proto.name);
this._writePipe(proto, pipe);
return pipe;
};
DynamicChangeDetector.prototype._readContext = function (proto, values) {
if (proto.contextIndex == -1) {
return this._getDirectiveFor(proto.directiveIndex);
}
return values[proto.contextIndex];
};
DynamicChangeDetector.prototype._readSelf = function (proto, values) { return values[proto.selfIndex]; };
DynamicChangeDetector.prototype._writeSelf = function (proto, value, values) { values[proto.selfIndex] = value; };
DynamicChangeDetector.prototype._readPipe = function (proto) { return this.localPipes[proto.selfIndex]; };
DynamicChangeDetector.prototype._writePipe = function (proto, value) { this.localPipes[proto.selfIndex] = value; };
DynamicChangeDetector.prototype._setChanged = function (proto, value) {
if (proto.argumentToPureFunction)
this.changes[proto.selfIndex] = value;
};
DynamicChangeDetector.prototype._pureFuncAndArgsDidNotChange = function (proto) {
return proto.isPureFunction() && !this._argsChanged(proto);
};
DynamicChangeDetector.prototype._argsChanged = function (proto) {
var args = proto.args;
for (var i = 0; i < args.length; ++i) {
if (this.changes[args[i]]) {
return true;
}
}
return false;
};
DynamicChangeDetector.prototype._argsOrContextChanged = function (proto) {
return this._argsChanged(proto) || this.changes[proto.contextIndex];
};
DynamicChangeDetector.prototype._readArgs = function (proto, values) {
var res = collection_1.ListWrapper.createFixedSize(proto.args.length);
var args = proto.args;
for (var i = 0; i < args.length; ++i) {
res[i] = values[args[i]];
}
return res;
};
return DynamicChangeDetector;
})(abstract_change_detector_1.AbstractChangeDetector);
exports.DynamicChangeDetector = DynamicChangeDetector;
//# sourceMappingURL=dynamic_change_detector.js.map