@@ -36,7 +36,7 @@ var PIPE_REGISTRY_ACCESSOR = "this.pipeRegistry";
3636var PROTOS_ACCESSOR = "this.protos" ;
3737var DIRECTIVES_ACCESSOR = "this.directiveRecords" ;
3838var CONTEXT_ACCESSOR = "this.context" ;
39- var CHANGE_LOCAL = "change " ;
39+ var IS_CHANGED_LOCAL = "isChanged " ;
4040var CHANGES_LOCAL = "changes" ;
4141var LOCALS_ACCESSOR = "this.locals" ;
4242var MODE_ACCESSOR = "this.mode" ;
@@ -78,10 +78,15 @@ function pipeOnDestroyTemplate(pipeNames:List) {
7878}
7979
8080function hydrateTemplate ( type :string , mode :string , fieldDefinitions :string , pipeOnDestroy :string ,
81- directiveFieldNames :List < String > ) :string {
81+ directiveFieldNames :List < String > , detectorFieldNames : List < String > ) :string {
8282 var directiveInit = "" ;
8383 for ( var i = 0 ; i < directiveFieldNames . length ; ++ i ) {
84- directiveInit += `${ directiveFieldNames [ i ] } = directives.directive(this.directiveRecords[${ i } ]);\n` ;
84+ directiveInit += `${ directiveFieldNames [ i ] } = directives.getDirectiveFor(this.directiveRecords[${ i } ]);\n` ;
85+ }
86+
87+ var detectorInit = "" ;
88+ for ( var i = 0 ; i < detectorFieldNames . length ; ++ i ) {
89+ detectorInit += `${ detectorFieldNames [ i ] } = directives.getDetectorFor(this.directiveRecords[${ i } ]);\n` ;
8590 }
8691
8792 return `
@@ -90,6 +95,7 @@ ${type}.prototype.hydrate = function(context, locals, directives) {
9095 $ { CONTEXT_ACCESSOR } = context ;
9196 $ { LOCALS_ACCESSOR } = locals ;
9297 $ { directiveInit }
98+ $ { detectorInit }
9399}
94100$ { type } . prototype . dehydrate = function ( ) {
95101 $ { pipeOnDestroy }
@@ -128,7 +134,7 @@ function detectChangesBodyTemplate(localDefinitions:string, changeDefinitions:st
128134${localDefinitions }
129135${changeDefinitions }
130136var ${TEMP_LOCAL } ;
131- var ${ CHANGE_LOCAL } ;
137+ var ${IS_CHANGED_LOCAL } = false ;
132138var ${CURRENT_PROTO } ;
133139var ${CHANGES_LOCAL } = null ;
134140
@@ -208,6 +214,7 @@ function updateDirectiveTemplate(oldValue:string, newValue:string, directiveProp
208214 return `
209215if ( throwOnChange ) $ { UTIL } . throwOnChange ( $ { CURRENT_PROTO } , $ { UTIL } . simpleChange ( $ { oldValue} , $ { newValue} ) ) ;
210216$ { directiveProperty } = ${newValue } ;
217+ $ { IS_CHANGED_LOCAL } = true ;
211218 `;
212219}
213220
@@ -227,6 +234,22 @@ if(${CHANGES_LOCAL}) {
227234`;
228235}
229236
237+ function notifyOnPushDetectorsTemplate(detector:string):string{
238+ return `
239+ if ( $ { IS_CHANGED_LOCAL } ) {
240+ $ { detector } . markAsCheckOnce ( ) ;
241+ }
242+ `;
243+ }
244+
245+ function lastInDirectiveTemplate(notifyOnChanges:string, notifyOnPush:string):string{
246+ return `
247+ $ { notifyOnChanges }
248+ $ { notifyOnPush }
249+ $ { IS_CHANGED_LOCAL } = false ;
250+ `;
251+ }
252+
230253
231254export class ChangeDetectorJITGenerator {
232255 typeName:string;
@@ -285,22 +308,32 @@ export class ChangeDetectorJITGenerator {
285308 genHydrate():string {
286309 var mode = ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy);
287310 return hydrateTemplate(this.typeName, mode, this.genFieldDefinitions(),
288- pipeOnDestroyTemplate(this.getNonNullPipeNames()), this.getDirectiveFieldNames());
311+ pipeOnDestroyTemplate(this.getNonNullPipeNames()),
312+ this.getDirectiveFieldNames(), this.getDetectorFieldNames());
289313 }
290314
291315 getDirectiveFieldNames():List<string> {
292316 return this.directiveRecords.map((d) => this.getDirective(d));
293317 }
294318
319+ getDetectorFieldNames():List<string> {
320+ return this.directiveRecords.filter(r => r.isOnPushChangeDetection()).map((d) => this.getDetector(d));
321+ }
322+
295323 getDirective(d:DirectiveRecord) {
296324 return ` this . directive_$ { d . name } `;
297325 }
298326
327+ getDetector(d:DirectiveRecord) {
328+ return ` this . detector_$ { d . name } `;
329+ }
330+
299331 genFieldDefinitions() {
300332 var fields = [];
301333 fields = fields.concat(this.fieldNames);
302334 fields = fields.concat(this.getNonNullPipeNames());
303335 fields = fields.concat(this.getDirectiveFieldNames());
336+ fields = fields.concat(this.getDetectorFieldNames());
304337 return fieldDefinitionsTemplate(fields);
305338 }
306339
@@ -362,11 +395,11 @@ export class ChangeDetectorJITGenerator {
362395 var change = this.changeNames[r.selfIndex];
363396
364397 var pipe = this.pipeNames[r.selfIndex];
365- var cdRef = r.mode === RECORD_TYPE_BINDING_PIPE ? "this.changeDetectorRef " : "null";
398+ var cdRef = r.mode === RECORD_TYPE_BINDING_PIPE ? "this.ref " : "null";
366399
367400 var update = this.genUpdateDirectiveOrElement(r);
368401 var addToChanges = this.genAddToChanges(r);
369- var lastInDirective = this.genNotifyOnChanges (r);
402+ var lastInDirective = this.genLastInDirective (r);
370403
371404 return pipeCheckTemplate(r.selfIndex - 1, context, cdRef, pipe, r.name, oldValue, newValue, change,
372405 update, addToChanges, lastInDirective);
@@ -380,7 +413,7 @@ export class ChangeDetectorJITGenerator {
380413
381414 var update = this.genUpdateDirectiveOrElement(r);
382415 var addToChanges = this.genAddToChanges(r);
383- var lastInDirective = this.genNotifyOnChanges (r);
416+ var lastInDirective = this.genLastInDirective (r);
384417
385418 var check = referenceCheckTemplate(r.selfIndex - 1, assignment, oldValue, newValue, change,
386419 update, addToChanges, lastInDirective);
@@ -471,6 +504,12 @@ export class ChangeDetectorJITGenerator {
471504 return r . bindingRecord . callOnChange ( ) ? addToChangesTemplate ( oldValue , newValue ) : "" ;
472505 }
473506
507+ genLastInDirective ( r :ProtoRecord ) :string {
508+ var onChanges = this . genNotifyOnChanges ( r ) ;
509+ var onPush = this . genNotifyOnPushDetectors ( r ) ;
510+ return lastInDirectiveTemplate ( onChanges , onPush ) ;
511+ }
512+
474513 genNotifyOnChanges ( r :ProtoRecord ) :string {
475514 var br = r . bindingRecord ;
476515 if ( r . lastInDirective && br . callOnChange ( ) ) {
@@ -480,6 +519,15 @@ export class ChangeDetectorJITGenerator {
480519 }
481520 }
482521
522+ genNotifyOnPushDetectors ( r :ProtoRecord ) :string {
523+ var br = r . bindingRecord ;
524+ if ( r . lastInDirective && br . isOnPushChangeDetection ( ) ) {
525+ return notifyOnPushDetectorsTemplate ( this . getDetector ( br . directiveRecord ) ) ;
526+ } else {
527+ return "" ;
528+ }
529+ }
530+
483531 genArgs ( r :ProtoRecord ) :string {
484532 return r . args . map ( ( arg ) => this . localNames [ arg ] ) . join ( ", " ) ;
485533 }
0 commit comments