UNPKG

angular2

Version:

Angular 2 - a web framework for modern web apps

145 lines 6.59 kB
'use strict';var lang_1 = require('angular2/src/facade/lang'); var collection_1 = require('angular2/src/facade/collection'); var proto_record_1 = require('./proto_record'); /** * Removes "duplicate" records. It assumes that record evaluation does not have side-effects. * * Records that are not last in bindings are removed and all the indices of the records that depend * on them are updated. * * Records that are last in bindings CANNOT be removed, and instead are replaced with very cheap * SELF records. * * @internal */ function coalesce(srcRecords) { var dstRecords = []; var excludedIdxs = []; var indexMap = new collection_1.Map(); var skipDepth = 0; var skipSources = collection_1.ListWrapper.createFixedSize(srcRecords.length); for (var protoIndex = 0; protoIndex < srcRecords.length; protoIndex++) { var skipRecord = skipSources[protoIndex]; if (lang_1.isPresent(skipRecord)) { skipDepth--; skipRecord.fixedArgs[0] = dstRecords.length; } var src = srcRecords[protoIndex]; var dst = _cloneAndUpdateIndexes(src, dstRecords, indexMap); if (dst.isSkipRecord()) { dstRecords.push(dst); skipDepth++; skipSources[dst.fixedArgs[0]] = dst; } else { var record = _mayBeAddRecord(dst, dstRecords, excludedIdxs, skipDepth > 0); indexMap.set(src.selfIndex, record.selfIndex); } } return _optimizeSkips(dstRecords); } exports.coalesce = coalesce; /** * - Conditional skip of 1 record followed by an unconditional skip of N are replaced by a * conditional skip of N with the negated condition, * - Skips of 0 records are removed */ function _optimizeSkips(srcRecords) { var dstRecords = []; var skipSources = collection_1.ListWrapper.createFixedSize(srcRecords.length); var indexMap = new collection_1.Map(); for (var protoIndex = 0; protoIndex < srcRecords.length; protoIndex++) { var skipRecord = skipSources[protoIndex]; if (lang_1.isPresent(skipRecord)) { skipRecord.fixedArgs[0] = dstRecords.length; } var src = srcRecords[protoIndex]; if (src.isSkipRecord()) { if (src.isConditionalSkipRecord() && src.fixedArgs[0] === protoIndex + 2 && protoIndex < srcRecords.length - 1 && srcRecords[protoIndex + 1].mode === proto_record_1.RecordType.SkipRecords) { src.mode = src.mode === proto_record_1.RecordType.SkipRecordsIf ? proto_record_1.RecordType.SkipRecordsIfNot : proto_record_1.RecordType.SkipRecordsIf; src.fixedArgs[0] = srcRecords[protoIndex + 1].fixedArgs[0]; protoIndex++; } if (src.fixedArgs[0] > protoIndex + 1) { var dst = _cloneAndUpdateIndexes(src, dstRecords, indexMap); dstRecords.push(dst); skipSources[dst.fixedArgs[0]] = dst; } } else { var dst = _cloneAndUpdateIndexes(src, dstRecords, indexMap); dstRecords.push(dst); indexMap.set(src.selfIndex, dst.selfIndex); } } return dstRecords; } /** * Add a new record or re-use one of the existing records. */ function _mayBeAddRecord(record, dstRecords, excludedIdxs, excluded) { var match = _findFirstMatch(record, dstRecords, excludedIdxs); if (lang_1.isPresent(match)) { if (record.lastInBinding) { dstRecords.push(_createSelfRecord(record, match.selfIndex, dstRecords.length + 1)); match.referencedBySelf = true; } else { if (record.argumentToPureFunction) { match.argumentToPureFunction = true; } } return match; } if (excluded) { excludedIdxs.push(record.selfIndex); } dstRecords.push(record); return record; } /** * Returns the first `ProtoRecord` that matches the record. */ function _findFirstMatch(record, dstRecords, excludedIdxs) { return dstRecords.find( // TODO(vicb): optimize excludedIdxs.indexOf (sorted array) function (rr) { return excludedIdxs.indexOf(rr.selfIndex) == -1 && rr.mode !== proto_record_1.RecordType.DirectiveLifecycle && _haveSameDirIndex(rr, record) && rr.mode === record.mode && lang_1.looseIdentical(rr.funcOrValue, record.funcOrValue) && rr.contextIndex === record.contextIndex && lang_1.looseIdentical(rr.name, record.name) && collection_1.ListWrapper.equals(rr.args, record.args); }); } /** * Clone the `ProtoRecord` and changes the indexes for the ones in the destination array for: * - the arguments, * - the context, * - self */ function _cloneAndUpdateIndexes(record, dstRecords, indexMap) { var args = record.args.map(function (src) { return _srcToDstSelfIndex(indexMap, src); }); var contextIndex = _srcToDstSelfIndex(indexMap, record.contextIndex); var selfIndex = dstRecords.length + 1; return new proto_record_1.ProtoRecord(record.mode, record.name, record.funcOrValue, args, record.fixedArgs, contextIndex, record.directiveIndex, selfIndex, record.bindingRecord, record.lastInBinding, record.lastInDirective, record.argumentToPureFunction, record.referencedBySelf, record.propertyBindingIndex); } /** * Returns the index in the destination array corresponding to the index in the src array. * When the element is not present in the destination array, return the source index. */ function _srcToDstSelfIndex(indexMap, srcIdx) { var dstIdx = indexMap.get(srcIdx); return lang_1.isPresent(dstIdx) ? dstIdx : srcIdx; } function _createSelfRecord(r, contextIndex, selfIndex) { return new proto_record_1.ProtoRecord(proto_record_1.RecordType.Self, "self", null, [], r.fixedArgs, contextIndex, r.directiveIndex, selfIndex, r.bindingRecord, r.lastInBinding, r.lastInDirective, false, false, r.propertyBindingIndex); } function _haveSameDirIndex(a, b) { var di1 = lang_1.isBlank(a.directiveIndex) ? null : a.directiveIndex.directiveIndex; var ei1 = lang_1.isBlank(a.directiveIndex) ? null : a.directiveIndex.elementIndex; var di2 = lang_1.isBlank(b.directiveIndex) ? null : b.directiveIndex.directiveIndex; var ei2 = lang_1.isBlank(b.directiveIndex) ? null : b.directiveIndex.elementIndex; return di1 === di2 && ei1 === ei2; } //# sourceMappingURL=coalesce.js.map