UNPKG

angular2

Version:

Angular 2 - a web framework for modern web apps

385 lines 20.6 kB
'use strict';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 ast_1 = require('./parser/ast'); var change_detection_util_1 = require('./change_detection_util'); var dynamic_change_detector_1 = require('./dynamic_change_detector'); var directive_record_1 = require('./directive_record'); var event_binding_1 = require('./event_binding'); var coalesce_1 = require('./coalesce'); var proto_record_1 = require('./proto_record'); var DynamicProtoChangeDetector = (function () { function DynamicProtoChangeDetector(_definition) { this._definition = _definition; this._propertyBindingRecords = createPropertyRecords(_definition); this._eventBindingRecords = createEventRecords(_definition); this._propertyBindingTargets = this._definition.bindingRecords.map(function (b) { return b.target; }); this._directiveIndices = this._definition.directiveRecords.map(function (d) { return d.directiveIndex; }); } DynamicProtoChangeDetector.prototype.instantiate = function (dispatcher) { return new dynamic_change_detector_1.DynamicChangeDetector(this._definition.id, dispatcher, this._propertyBindingRecords.length, this._propertyBindingTargets, this._directiveIndices, this._definition.strategy, this._propertyBindingRecords, this._eventBindingRecords, this._definition.directiveRecords, this._definition.genConfig); }; return DynamicProtoChangeDetector; })(); exports.DynamicProtoChangeDetector = DynamicProtoChangeDetector; function createPropertyRecords(definition) { var recordBuilder = new ProtoRecordBuilder(); collection_1.ListWrapper.forEachWithIndex(definition.bindingRecords, function (b, index) { return recordBuilder.add(b, definition.variableNames, index); }); return coalesce_1.coalesce(recordBuilder.records); } exports.createPropertyRecords = createPropertyRecords; function createEventRecords(definition) { // TODO: vsavkin: remove $event when the compiler handles render-side variables properly var varNames = collection_1.ListWrapper.concat(['$event'], definition.variableNames); return definition.eventRecords.map(function (er) { var records = _ConvertAstIntoProtoRecords.create(er, varNames); var dirIndex = er.implicitReceiver instanceof directive_record_1.DirectiveIndex ? er.implicitReceiver : null; return new event_binding_1.EventBinding(er.target.name, er.target.elementIndex, dirIndex, records); }); } exports.createEventRecords = createEventRecords; var ProtoRecordBuilder = (function () { function ProtoRecordBuilder() { this.records = []; } ProtoRecordBuilder.prototype.add = function (b, variableNames, bindingIndex) { var oldLast = collection_1.ListWrapper.last(this.records); if (lang_1.isPresent(oldLast) && oldLast.bindingRecord.directiveRecord == b.directiveRecord) { oldLast.lastInDirective = false; } var numberOfRecordsBefore = this.records.length; this._appendRecords(b, variableNames, bindingIndex); var newLast = collection_1.ListWrapper.last(this.records); if (lang_1.isPresent(newLast) && newLast !== oldLast) { newLast.lastInBinding = true; newLast.lastInDirective = true; this._setArgumentToPureFunction(numberOfRecordsBefore); } }; /** @internal */ ProtoRecordBuilder.prototype._setArgumentToPureFunction = function (startIndex) { var _this = this; for (var i = startIndex; i < this.records.length; ++i) { var rec = this.records[i]; if (rec.isPureFunction()) { rec.args.forEach(function (recordIndex) { return _this.records[recordIndex - 1].argumentToPureFunction = true; }); } if (rec.mode === proto_record_1.RecordType.Pipe) { rec.args.forEach(function (recordIndex) { return _this.records[recordIndex - 1].argumentToPureFunction = true; }); this.records[rec.contextIndex - 1].argumentToPureFunction = true; } } }; /** @internal */ ProtoRecordBuilder.prototype._appendRecords = function (b, variableNames, bindingIndex) { if (b.isDirectiveLifecycle()) { this.records.push(new proto_record_1.ProtoRecord(proto_record_1.RecordType.DirectiveLifecycle, b.lifecycleEvent, null, [], [], -1, null, this.records.length + 1, b, false, false, false, false, null)); } else { _ConvertAstIntoProtoRecords.append(this.records, b, variableNames, bindingIndex); } }; return ProtoRecordBuilder; })(); exports.ProtoRecordBuilder = ProtoRecordBuilder; var _ConvertAstIntoProtoRecords = (function () { function _ConvertAstIntoProtoRecords(_records, _bindingRecord, _variableNames, _bindingIndex) { this._records = _records; this._bindingRecord = _bindingRecord; this._variableNames = _variableNames; this._bindingIndex = _bindingIndex; } _ConvertAstIntoProtoRecords.append = function (records, b, variableNames, bindingIndex) { var c = new _ConvertAstIntoProtoRecords(records, b, variableNames, bindingIndex); b.ast.visit(c); }; _ConvertAstIntoProtoRecords.create = function (b, variableNames) { var rec = []; _ConvertAstIntoProtoRecords.append(rec, b, variableNames, null); rec[rec.length - 1].lastInBinding = true; return rec; }; _ConvertAstIntoProtoRecords.prototype.visitImplicitReceiver = function (ast) { return this._bindingRecord.implicitReceiver; }; _ConvertAstIntoProtoRecords.prototype.visitInterpolation = function (ast) { var args = this._visitAll(ast.expressions); return this._addRecord(proto_record_1.RecordType.Interpolate, "interpolate", _interpolationFn(ast.strings), args, ast.strings, 0); }; _ConvertAstIntoProtoRecords.prototype.visitLiteralPrimitive = function (ast) { return this._addRecord(proto_record_1.RecordType.Const, "literal", ast.value, [], null, 0); }; _ConvertAstIntoProtoRecords.prototype.visitPropertyRead = function (ast) { var receiver = ast.receiver.visit(this); if (lang_1.isPresent(this._variableNames) && collection_1.ListWrapper.contains(this._variableNames, ast.name) && ast.receiver instanceof ast_1.ImplicitReceiver) { return this._addRecord(proto_record_1.RecordType.Local, ast.name, ast.name, [], null, receiver); } else { return this._addRecord(proto_record_1.RecordType.PropertyRead, ast.name, ast.getter, [], null, receiver); } }; _ConvertAstIntoProtoRecords.prototype.visitPropertyWrite = function (ast) { if (lang_1.isPresent(this._variableNames) && collection_1.ListWrapper.contains(this._variableNames, ast.name) && ast.receiver instanceof ast_1.ImplicitReceiver) { throw new exceptions_1.BaseException("Cannot reassign a variable binding " + ast.name); } else { var receiver = ast.receiver.visit(this); var value = ast.value.visit(this); return this._addRecord(proto_record_1.RecordType.PropertyWrite, ast.name, ast.setter, [value], null, receiver); } }; _ConvertAstIntoProtoRecords.prototype.visitKeyedWrite = function (ast) { var obj = ast.obj.visit(this); var key = ast.key.visit(this); var value = ast.value.visit(this); return this._addRecord(proto_record_1.RecordType.KeyedWrite, null, null, [key, value], null, obj); }; _ConvertAstIntoProtoRecords.prototype.visitSafePropertyRead = function (ast) { var receiver = ast.receiver.visit(this); return this._addRecord(proto_record_1.RecordType.SafeProperty, ast.name, ast.getter, [], null, receiver); }; _ConvertAstIntoProtoRecords.prototype.visitMethodCall = function (ast) { var receiver = ast.receiver.visit(this); var args = this._visitAll(ast.args); if (lang_1.isPresent(this._variableNames) && collection_1.ListWrapper.contains(this._variableNames, ast.name)) { var target = this._addRecord(proto_record_1.RecordType.Local, ast.name, ast.name, [], null, receiver); return this._addRecord(proto_record_1.RecordType.InvokeClosure, "closure", null, args, null, target); } else { return this._addRecord(proto_record_1.RecordType.InvokeMethod, ast.name, ast.fn, args, null, receiver); } }; _ConvertAstIntoProtoRecords.prototype.visitSafeMethodCall = function (ast) { var receiver = ast.receiver.visit(this); var args = this._visitAll(ast.args); return this._addRecord(proto_record_1.RecordType.SafeMethodInvoke, ast.name, ast.fn, args, null, receiver); }; _ConvertAstIntoProtoRecords.prototype.visitFunctionCall = function (ast) { var target = ast.target.visit(this); var args = this._visitAll(ast.args); return this._addRecord(proto_record_1.RecordType.InvokeClosure, "closure", null, args, null, target); }; _ConvertAstIntoProtoRecords.prototype.visitLiteralArray = function (ast) { var primitiveName = "arrayFn" + ast.expressions.length; return this._addRecord(proto_record_1.RecordType.CollectionLiteral, primitiveName, _arrayFn(ast.expressions.length), this._visitAll(ast.expressions), null, 0); }; _ConvertAstIntoProtoRecords.prototype.visitLiteralMap = function (ast) { return this._addRecord(proto_record_1.RecordType.CollectionLiteral, _mapPrimitiveName(ast.keys), change_detection_util_1.ChangeDetectionUtil.mapFn(ast.keys), this._visitAll(ast.values), null, 0); }; _ConvertAstIntoProtoRecords.prototype.visitBinary = function (ast) { var left = ast.left.visit(this); switch (ast.operation) { case '&&': var branchEnd = [null]; this._addRecord(proto_record_1.RecordType.SkipRecordsIfNot, "SkipRecordsIfNot", null, [], branchEnd, left); var right = ast.right.visit(this); branchEnd[0] = right; return this._addRecord(proto_record_1.RecordType.PrimitiveOp, "cond", change_detection_util_1.ChangeDetectionUtil.cond, [left, right, left], null, 0); case '||': var branchEnd = [null]; this._addRecord(proto_record_1.RecordType.SkipRecordsIf, "SkipRecordsIf", null, [], branchEnd, left); var right = ast.right.visit(this); branchEnd[0] = right; return this._addRecord(proto_record_1.RecordType.PrimitiveOp, "cond", change_detection_util_1.ChangeDetectionUtil.cond, [left, left, right], null, 0); default: var right = ast.right.visit(this); return this._addRecord(proto_record_1.RecordType.PrimitiveOp, _operationToPrimitiveName(ast.operation), _operationToFunction(ast.operation), [left, right], null, 0); } }; _ConvertAstIntoProtoRecords.prototype.visitPrefixNot = function (ast) { var exp = ast.expression.visit(this); return this._addRecord(proto_record_1.RecordType.PrimitiveOp, "operation_negate", change_detection_util_1.ChangeDetectionUtil.operation_negate, [exp], null, 0); }; _ConvertAstIntoProtoRecords.prototype.visitConditional = function (ast) { var condition = ast.condition.visit(this); var startOfFalseBranch = [null]; var endOfFalseBranch = [null]; this._addRecord(proto_record_1.RecordType.SkipRecordsIfNot, "SkipRecordsIfNot", null, [], startOfFalseBranch, condition); var whenTrue = ast.trueExp.visit(this); var skip = this._addRecord(proto_record_1.RecordType.SkipRecords, "SkipRecords", null, [], endOfFalseBranch, 0); var whenFalse = ast.falseExp.visit(this); startOfFalseBranch[0] = skip; endOfFalseBranch[0] = whenFalse; return this._addRecord(proto_record_1.RecordType.PrimitiveOp, "cond", change_detection_util_1.ChangeDetectionUtil.cond, [condition, whenTrue, whenFalse], null, 0); }; _ConvertAstIntoProtoRecords.prototype.visitPipe = function (ast) { var value = ast.exp.visit(this); var args = this._visitAll(ast.args); return this._addRecord(proto_record_1.RecordType.Pipe, ast.name, ast.name, args, null, value); }; _ConvertAstIntoProtoRecords.prototype.visitKeyedRead = function (ast) { var obj = ast.obj.visit(this); var key = ast.key.visit(this); return this._addRecord(proto_record_1.RecordType.KeyedRead, "keyedAccess", change_detection_util_1.ChangeDetectionUtil.keyedAccess, [key], null, obj); }; _ConvertAstIntoProtoRecords.prototype.visitChain = function (ast) { var _this = this; var args = ast.expressions.map(function (e) { return e.visit(_this); }); return this._addRecord(proto_record_1.RecordType.Chain, "chain", null, args, null, 0); }; _ConvertAstIntoProtoRecords.prototype._visitAll = function (asts) { var res = collection_1.ListWrapper.createFixedSize(asts.length); for (var i = 0; i < asts.length; ++i) { res[i] = asts[i].visit(this); } return res; }; /** * Adds a `ProtoRecord` and returns its selfIndex. */ _ConvertAstIntoProtoRecords.prototype._addRecord = function (type, name, funcOrValue, args, fixedArgs, context) { var selfIndex = this._records.length + 1; if (context instanceof directive_record_1.DirectiveIndex) { this._records.push(new proto_record_1.ProtoRecord(type, name, funcOrValue, args, fixedArgs, -1, context, selfIndex, this._bindingRecord, false, false, false, false, this._bindingIndex)); } else { this._records.push(new proto_record_1.ProtoRecord(type, name, funcOrValue, args, fixedArgs, context, null, selfIndex, this._bindingRecord, false, false, false, false, this._bindingIndex)); } return selfIndex; }; return _ConvertAstIntoProtoRecords; })(); function _arrayFn(length) { switch (length) { case 0: return change_detection_util_1.ChangeDetectionUtil.arrayFn0; case 1: return change_detection_util_1.ChangeDetectionUtil.arrayFn1; case 2: return change_detection_util_1.ChangeDetectionUtil.arrayFn2; case 3: return change_detection_util_1.ChangeDetectionUtil.arrayFn3; case 4: return change_detection_util_1.ChangeDetectionUtil.arrayFn4; case 5: return change_detection_util_1.ChangeDetectionUtil.arrayFn5; case 6: return change_detection_util_1.ChangeDetectionUtil.arrayFn6; case 7: return change_detection_util_1.ChangeDetectionUtil.arrayFn7; case 8: return change_detection_util_1.ChangeDetectionUtil.arrayFn8; case 9: return change_detection_util_1.ChangeDetectionUtil.arrayFn9; default: throw new exceptions_1.BaseException("Does not support literal maps with more than 9 elements"); } } function _mapPrimitiveName(keys) { var stringifiedKeys = keys.map(function (k) { return lang_1.isString(k) ? "\"" + k + "\"" : "" + k; }).join(', '); return "mapFn([" + stringifiedKeys + "])"; } function _operationToPrimitiveName(operation) { switch (operation) { case '+': return "operation_add"; case '-': return "operation_subtract"; case '*': return "operation_multiply"; case '/': return "operation_divide"; case '%': return "operation_remainder"; case '==': return "operation_equals"; case '!=': return "operation_not_equals"; case '===': return "operation_identical"; case '!==': return "operation_not_identical"; case '<': return "operation_less_then"; case '>': return "operation_greater_then"; case '<=': return "operation_less_or_equals_then"; case '>=': return "operation_greater_or_equals_then"; default: throw new exceptions_1.BaseException("Unsupported operation " + operation); } } function _operationToFunction(operation) { switch (operation) { case '+': return change_detection_util_1.ChangeDetectionUtil.operation_add; case '-': return change_detection_util_1.ChangeDetectionUtil.operation_subtract; case '*': return change_detection_util_1.ChangeDetectionUtil.operation_multiply; case '/': return change_detection_util_1.ChangeDetectionUtil.operation_divide; case '%': return change_detection_util_1.ChangeDetectionUtil.operation_remainder; case '==': return change_detection_util_1.ChangeDetectionUtil.operation_equals; case '!=': return change_detection_util_1.ChangeDetectionUtil.operation_not_equals; case '===': return change_detection_util_1.ChangeDetectionUtil.operation_identical; case '!==': return change_detection_util_1.ChangeDetectionUtil.operation_not_identical; case '<': return change_detection_util_1.ChangeDetectionUtil.operation_less_then; case '>': return change_detection_util_1.ChangeDetectionUtil.operation_greater_then; case '<=': return change_detection_util_1.ChangeDetectionUtil.operation_less_or_equals_then; case '>=': return change_detection_util_1.ChangeDetectionUtil.operation_greater_or_equals_then; default: throw new exceptions_1.BaseException("Unsupported operation " + operation); } } function s(v) { return lang_1.isPresent(v) ? "" + v : ''; } function _interpolationFn(strings) { var length = strings.length; var c0 = length > 0 ? strings[0] : null; var c1 = length > 1 ? strings[1] : null; var c2 = length > 2 ? strings[2] : null; var c3 = length > 3 ? strings[3] : null; var c4 = length > 4 ? strings[4] : null; var c5 = length > 5 ? strings[5] : null; var c6 = length > 6 ? strings[6] : null; var c7 = length > 7 ? strings[7] : null; var c8 = length > 8 ? strings[8] : null; var c9 = length > 9 ? strings[9] : null; switch (length - 1) { case 1: return function (a1) { return c0 + s(a1) + c1; }; case 2: return function (a1, a2) { return c0 + s(a1) + c1 + s(a2) + c2; }; case 3: return function (a1, a2, a3) { return c0 + s(a1) + c1 + s(a2) + c2 + s(a3) + c3; }; case 4: return function (a1, a2, a3, a4) { return c0 + s(a1) + c1 + s(a2) + c2 + s(a3) + c3 + s(a4) + c4; }; case 5: return function (a1, a2, a3, a4, a5) { return c0 + s(a1) + c1 + s(a2) + c2 + s(a3) + c3 + s(a4) + c4 + s(a5) + c5; }; case 6: return function (a1, a2, a3, a4, a5, a6) { return c0 + s(a1) + c1 + s(a2) + c2 + s(a3) + c3 + s(a4) + c4 + s(a5) + c5 + s(a6) + c6; }; case 7: return function (a1, a2, a3, a4, a5, a6, a7) { return c0 + s(a1) + c1 + s(a2) + c2 + s(a3) + c3 + s(a4) + c4 + s(a5) + c5 + s(a6) + c6 + s(a7) + c7; }; case 8: return function (a1, a2, a3, a4, a5, a6, a7, a8) { return c0 + s(a1) + c1 + s(a2) + c2 + s(a3) + c3 + s(a4) + c4 + s(a5) + c5 + s(a6) + c6 + s(a7) + c7 + s(a8) + c8; }; case 9: return function (a1, a2, a3, a4, a5, a6, a7, a8, a9) { return c0 + s(a1) + c1 + s(a2) + c2 + s(a3) + c3 + s(a4) + c4 + s(a5) + c5 + s(a6) + c6 + s(a7) + c7 + s(a8) + c8 + s(a9) + c9; }; default: throw new exceptions_1.BaseException("Does not support more than 9 expressions"); } } //# sourceMappingURL=proto_change_detector.js.map