@@ -138,9 +138,10 @@ ${type}.prototype.detectChangesInRecords = function(throwOnChange) {
138138}
139139
140140
141- function bodyTemplate ( localDefinitions :string , records :string ) :string {
141+ function bodyTemplate ( localDefinitions :string , changeDefinitions : string , records :string ) :string {
142142 return `
143143${ localDefinitions }
144+ ${ changeDefinitions }
144145var ${ TEMP_LOCAL } ;
145146var ${ CHANGE_LOCAL } ;
146147var ${ CHANGES_LOCAL } = [];
@@ -172,10 +173,11 @@ ${notify}
172173` ;
173174}
174175
175- function referenceCheckTemplate ( assignment , newValue , oldValue , addRecord , notify ) {
176+ function referenceCheckTemplate ( assignment , newValue , oldValue , change , addRecord , notify ) {
176177 return `
177178${ assignment }
178179if (${ newValue } !== ${ oldValue } || (${ newValue } !== ${ newValue } ) && (${ oldValue } !== ${ oldValue } )) {
180+ ${ change } = true;
179181 ${ addRecord }
180182 ${ oldValue } = ${ newValue } ;
181183}
@@ -202,10 +204,23 @@ function localDefinitionsTemplate(names:List):string {
202204 return names . map ( ( n ) => `var ${ n } ;` ) . join ( "\n" ) ;
203205}
204206
207+ function changeDefinitionsTemplate ( names :List ) :string {
208+ return names . map ( ( n ) => `var ${ n } = false;` ) . join ( "\n" ) ;
209+ }
210+
205211function fieldDefinitionsTemplate ( names :List ) :string {
206212 return names . map ( ( n ) => `${ n } = ${ UTIL } .unitialized();` ) . join ( "\n" ) ;
207213}
208214
215+ function ifChangedGuardTemplate ( changeNames :List , body :string ) :string {
216+ var cond = changeNames . join ( " || " ) ;
217+ return `
218+ if (${ cond } ) {
219+ ${ body }
220+ }
221+ ` ;
222+ }
223+
209224function addSimpleChangeRecordTemplate ( protoIndex :number , oldValue :string , newValue :string ) {
210225 return `${ CHANGES_LOCAL } .push(${ UTIL } .simpleChangeRecord(${ PROTOS_ACCESSOR } [${ protoIndex } ].bindingMemento, ${ oldValue } , ${ newValue } ));` ;
211226}
@@ -215,13 +230,15 @@ export class ChangeDetectorJITGenerator {
215230 typeName :string ;
216231 records :List < ProtoRecord > ;
217232 localNames :List < String > ;
233+ changeNames :List < String > ;
218234 fieldNames :List < String > ;
219235
220236 constructor ( typeName :string , records :List < ProtoRecord > ) {
221237 this . typeName = typeName ;
222238 this . records = records ;
223239
224240 this . localNames = this . getLocalNames ( records ) ;
241+ this . changeNames = this . getChangeNames ( this . localNames ) ;
225242 this . fieldNames = this . getFieldNames ( this . localNames ) ;
226243 }
227244
@@ -234,6 +251,10 @@ export class ChangeDetectorJITGenerator {
234251 return [ "context" ] . concat ( names ) ;
235252 }
236253
254+ getChangeNames ( localNames :List < String > ) :List < String > {
255+ return localNames . map ( ( n ) => `change_${ n } ` ) ;
256+ }
257+
237258 getFieldNames ( localNames :List < String > ) :List < String > {
238259 return localNames . map ( ( n ) => `this.${ n } ` ) ;
239260 }
@@ -259,13 +280,17 @@ export class ChangeDetectorJITGenerator {
259280
260281 genBody ( ) :string {
261282 var rec = this . records . map ( ( r ) => this . genRecord ( r ) ) . join ( "\n" ) ;
262- return bodyTemplate ( this . genLocalDefinitions ( ) , rec ) ;
283+ return bodyTemplate ( this . genLocalDefinitions ( ) , this . genChangeDefinitions ( ) , rec ) ;
263284 }
264285
265286 genLocalDefinitions ( ) :string {
266287 return localDefinitionsTemplate ( this . localNames ) ;
267288 }
268289
290+ genChangeDefinitions ( ) :string {
291+ return changeDefinitionsTemplate ( this . changeNames ) ;
292+ }
293+
269294 genRecord ( r :ProtoRecord ) :string {
270295 if ( r . mode == RECORD_TYPE_STRUCTURAL_CHECK ) {
271296 return this . getStructuralCheck ( r ) ;
@@ -283,10 +308,17 @@ export class ChangeDetectorJITGenerator {
283308 genReferenceCheck ( r :ProtoRecord ) :string {
284309 var newValue = this . localNames [ r . selfIndex ] ;
285310 var oldValue = this . fieldNames [ r . selfIndex ] ;
311+ var change = this . changeNames [ r . selfIndex ] ;
286312 var assignment = this . genUpdateCurrentValue ( r ) ;
287313 var addRecord = addSimpleChangeRecordTemplate ( r . selfIndex - 1 , oldValue , newValue ) ;
288314 var notify = this . genNotify ( r ) ;
289- return referenceCheckTemplate ( assignment , newValue , oldValue , r . lastInBinding ? addRecord : '' , notify ) ;
315+
316+ var check = referenceCheckTemplate ( assignment , newValue , oldValue , change , r . lastInBinding ? addRecord : '' , notify ) ; ;
317+ if ( r . isPureFunction ( ) ) {
318+ return this . ifChangedGuard ( r , check ) ;
319+ } else {
320+ return check ;
321+ }
290322 }
291323
292324 genUpdateCurrentValue ( r :ProtoRecord ) :string {
@@ -320,18 +352,22 @@ export class ChangeDetectorJITGenerator {
320352 case RECORD_TYPE_INTERPOLATE:
321353 return assignmentTemplate(newValue, this.genInterpolation(r));
322354
355+ case RECORD_TYPE_INVOKE_FORMATTER:
356+ return assignmentTemplate(newValue, ` $ { FORMATTERS_ACCESSOR } . get ( "${r.name}" ) ( $ { args} ) `);
357+
323358 case RECORD_TYPE_KEYED_ACCESS:
324359 var key = this.localNames[r.args[0]];
325360 return assignmentTemplate(newValue, ` $ { context } [ $ { key} ] `);
326361
327- case RECORD_TYPE_INVOKE_FORMATTER:
328- return assignmentTemplate(newValue, ` $ { FORMATTERS_ACCESSOR } . get ( "${r.name}" ) ( $ { args} ) `);
329-
330362 default:
331363 throw new BaseException(` Unknown operation $ { r . mode } `) ;
332364 }
333365 }
334366
367+ ifChangedGuard ( r :ProtoRecord , body :string ) :string {
368+ return ifChangedGuardTemplate ( r . args . map ( ( a ) => this . changeNames [ a ] ) , body ) ;
369+ }
370+
335371 genInterpolation ( r :ProtoRecord ) :string {
336372 var res = "" ;
337373 for ( var i = 0 ; i < r . args . length ; ++ i ) {
0 commit comments