| 
									
										
										
										
											2015-02-05 13:08:05 -08:00
										 |  |  | import {isPresent} from 'angular2/src/facade/lang'; | 
					
						
							|  |  |  | import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection'; | 
					
						
							| 
									
										
										
										
											2015-06-09 15:45:45 +02:00
										 |  |  | import {RecordType, ProtoRecord} from './proto_record'; | 
					
						
							| 
									
										
										
										
											2015-01-25 16:59:06 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Removes "duplicate" records. It assuming 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. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-05-01 14:05:19 -07:00
										 |  |  | export function coalesce(records: List<ProtoRecord>): List<ProtoRecord> { | 
					
						
							| 
									
										
										
										
											2015-06-16 08:47:24 +02:00
										 |  |  |   var res: List<ProtoRecord> = ListWrapper.create(); | 
					
						
							|  |  |  |   var indexMap: Map<number, number> = MapWrapper.create(); | 
					
						
							| 
									
										
										
										
											2015-01-25 16:59:06 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (var i = 0; i < records.length; ++i) { | 
					
						
							|  |  |  |     var r = records[i]; | 
					
						
							|  |  |  |     var record = _replaceIndices(r, res.length + 1, indexMap); | 
					
						
							|  |  |  |     var matchingRecord = _findMatching(record, res); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (isPresent(matchingRecord) && record.lastInBinding) { | 
					
						
							|  |  |  |       ListWrapper.push(res, _selfRecord(record, matchingRecord.selfIndex, res.length + 1)); | 
					
						
							|  |  |  |       MapWrapper.set(indexMap, r.selfIndex, matchingRecord.selfIndex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } else if (isPresent(matchingRecord) && !record.lastInBinding) { | 
					
						
							|  |  |  |       MapWrapper.set(indexMap, r.selfIndex, matchingRecord.selfIndex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       ListWrapper.push(res, record); | 
					
						
							|  |  |  |       MapWrapper.set(indexMap, r.selfIndex, record.selfIndex); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-01 14:05:19 -07:00
										 |  |  | function _selfRecord(r: ProtoRecord, contextIndex: number, selfIndex: number): ProtoRecord { | 
					
						
							| 
									
										
										
										
											2015-06-09 15:45:45 +02:00
										 |  |  |   return new ProtoRecord(RecordType.SELF, "self", null, [], r.fixedArgs, contextIndex, | 
					
						
							| 
									
										
										
										
											2015-05-01 14:05:19 -07:00
										 |  |  |                          r.directiveIndex, selfIndex, r.bindingRecord, r.expressionAsString, | 
					
						
							|  |  |  |                          r.lastInBinding, r.lastInDirective); | 
					
						
							| 
									
										
										
										
											2015-01-25 16:59:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-01 14:05:19 -07:00
										 |  |  | function _findMatching(r: ProtoRecord, rs: List<ProtoRecord>) { | 
					
						
							| 
									
										
										
										
											2015-06-09 15:45:45 +02:00
										 |  |  |   return ListWrapper.find(rs, (rr) => rr.mode !== RecordType.DIRECTIVE_LIFECYCLE && | 
					
						
							| 
									
										
										
										
											2015-06-12 07:50:45 -07:00
										 |  |  |                                       rr.mode === r.mode && rr.funcOrValue === r.funcOrValue && | 
					
						
							|  |  |  |                                       rr.contextIndex === r.contextIndex && | 
					
						
							|  |  |  |                                       ListWrapper.equals(rr.args, r.args)); | 
					
						
							| 
									
										
										
										
											2015-01-25 16:59:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-01 14:05:19 -07:00
										 |  |  | function _replaceIndices(r: ProtoRecord, selfIndex: number, indexMap: Map<any, any>) { | 
					
						
							| 
									
										
										
										
											2015-01-25 16:59:06 -08:00
										 |  |  |   var args = ListWrapper.map(r.args, (a) => _map(indexMap, a)); | 
					
						
							|  |  |  |   var contextIndex = _map(indexMap, r.contextIndex); | 
					
						
							| 
									
										
										
										
											2015-05-01 14:05:19 -07:00
										 |  |  |   return new ProtoRecord(r.mode, r.name, r.funcOrValue, args, r.fixedArgs, contextIndex, | 
					
						
							|  |  |  |                          r.directiveIndex, selfIndex, r.bindingRecord, r.expressionAsString, | 
					
						
							|  |  |  |                          r.lastInBinding, r.lastInDirective); | 
					
						
							| 
									
										
										
										
											2015-01-25 16:59:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-01 14:05:19 -07:00
										 |  |  | function _map(indexMap: Map<any, any>, value: number) { | 
					
						
							|  |  |  |   var r = MapWrapper.get(indexMap, value); | 
					
						
							| 
									
										
										
										
											2015-01-25 16:59:06 -08:00
										 |  |  |   return isPresent(r) ? r : value; | 
					
						
							| 
									
										
										
										
											2015-06-09 15:45:45 +02:00
										 |  |  | } |