Skip to content

Commit abea92a

Browse files
committed
refactor(change_detection): call onChange from the change detector
1 parent bcbed28 commit abea92a

File tree

7 files changed

+183
-255
lines changed

7 files changed

+183
-255
lines changed

modules/angular2/src/change_detection/change_detection_jit_generator.es6

Lines changed: 72 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var CHANGES_LOCAL = "changes";
4040
var LOCALS_ACCESSOR = "this.locals";
4141
var MODE_ACCESSOR = "this.mode";
4242
var TEMP_LOCAL = "temp";
43+
var CURRENT_PROTO = "currentProto";
4344

4445
function typeTemplate(type:string, cons:string, detectChanges:string,
4546
notifyOnAllChangesDone:string, setContext:string):string {
@@ -113,58 +114,55 @@ function onAllChangesDoneTemplate(index:number):string {
113114
}
114115

115116

116-
function bodyTemplate(localDefinitions:string, changeDefinitions:string, records:string):string {
117+
function detectChangesBodyTemplate(localDefinitions:string, changeDefinitions:string, records:string):string {
117118
return `
118119
${localDefinitions}
119120
${changeDefinitions}
120121
var ${TEMP_LOCAL};
121122
var ${CHANGE_LOCAL};
123+
var ${CURRENT_PROTO};
122124
var ${CHANGES_LOCAL} = null;
123125
124126
context = ${CONTEXT_ACCESSOR};
125127
${records}
126128
`;
127129
}
128130

129-
function notifyTemplate(index:number):string{
130-
return `
131-
if (${CHANGES_LOCAL} && ${CHANGES_LOCAL}.length > 0) {
132-
if(throwOnChange) ${UTIL}.throwOnChange(${PROTOS_ACCESSOR}[${index}], ${CHANGES_LOCAL}[0]);
133-
${DISPATCHER_ACCESSOR}.onRecordChange(${PROTOS_ACCESSOR}[${index}].directiveMemento, ${CHANGES_LOCAL});
134-
${CHANGES_LOCAL} = null;
135-
}
136-
`;
137-
}
138-
139-
function pipeCheckTemplate(context:string, bindingPropagationConfig:string, pipe:string, pipeType:string,
140-
value:string, change:string, addRecord:string, notify:string):string{
131+
function pipeCheckTemplate(protoIndex:number, context:string, bindingPropagationConfig:string, pipe:string, pipeType:string,
132+
oldValue:string, newValue:string, change:string, invokeMementoAndAddChange:string,
133+
addToChanges, lastInDirective:string):string{
141134
return `
135+
${CURRENT_PROTO} = ${PROTOS_ACCESSOR}[${protoIndex}];
142136
if (${pipe} === ${UTIL}.unitialized()) {
143137
${pipe} = ${PIPE_REGISTRY_ACCESSOR}.get('${pipeType}', ${context}, ${bindingPropagationConfig});
144138
} else if (!${pipe}.supports(${context})) {
145139
${pipe}.onDestroy();
146140
${pipe} = ${PIPE_REGISTRY_ACCESSOR}.get('${pipeType}', ${context}, ${bindingPropagationConfig});
147141
}
148142
149-
${CHANGE_LOCAL} = ${pipe}.transform(${context});
150-
if (! ${UTIL}.noChangeMarker(${CHANGE_LOCAL})) {
151-
${value} = ${CHANGE_LOCAL};
143+
${newValue} = ${pipe}.transform(${context});
144+
if (! ${UTIL}.noChangeMarker(${newValue})) {
152145
${change} = true;
153-
${addRecord}
146+
${invokeMementoAndAddChange}
147+
${addToChanges}
148+
${oldValue} = ${newValue};
154149
}
155-
${notify}
150+
${lastInDirective}
156151
`;
157152
}
158153

159-
function referenceCheckTemplate(assignment, newValue, oldValue, change, addRecord, notify) {
154+
function referenceCheckTemplate(protoIndex:number, assignment:string, oldValue:string, newValue:string, change:string,
155+
invokeMementoAndAddChange:string, addToChanges:string, lastInDirective:string):string {
160156
return `
157+
${CURRENT_PROTO} = ${PROTOS_ACCESSOR}[${protoIndex}];
161158
${assignment}
162159
if (${newValue} !== ${oldValue} || (${newValue} !== ${newValue}) && (${oldValue} !== ${oldValue})) {
163160
${change} = true;
164-
${addRecord}
161+
${invokeMementoAndAddChange}
162+
${addToChanges}
165163
${oldValue} = ${newValue};
166164
}
167-
${notify}
165+
${lastInDirective}
168166
`;
169167
}
170168

@@ -193,9 +191,25 @@ if (${cond}) {
193191
`;
194192
}
195193

196-
function addSimpleChangeRecordTemplate(protoIndex:number, oldValue:string, newValue:string) {
197-
return `${CHANGES_LOCAL} = ${UTIL}.addRecord(${CHANGES_LOCAL},
198-
${UTIL}.simpleChangeRecord(${PROTOS_ACCESSOR}[${protoIndex}].bindingMemento, ${oldValue}, ${newValue}));`;
194+
function addToChangesTemplate(oldValue:string, newValue:string):string {
195+
return `${CHANGES_LOCAL} = ${UTIL}.addChange(${CHANGES_LOCAL}, ${CURRENT_PROTO}.bindingMemento, ${UTIL}.simpleChange(${oldValue}, ${newValue}));`;
196+
}
197+
198+
function invokeBindingMemento(oldValue:string, newValue:string):string {
199+
return `
200+
if(throwOnChange) ${UTIL}.throwOnChange(${CURRENT_PROTO}, ${UTIL}.simpleChange(${oldValue}, ${newValue}));
201+
202+
${DISPATCHER_ACCESSOR}.invokeMementoFor(${CURRENT_PROTO}.bindingMemento, ${newValue});
203+
`;
204+
}
205+
206+
function lastInDirectiveTemplate(protoIndex:number):string{
207+
return `
208+
if (${CHANGES_LOCAL}) {
209+
${DISPATCHER_ACCESSOR}.onChange(${PROTOS_ACCESSOR}[${protoIndex}].directiveMemento, ${CHANGES_LOCAL});
210+
}
211+
${CHANGES_LOCAL} = null;
212+
`;
199213
}
200214

201215

@@ -277,7 +291,7 @@ export class ChangeDetectorJITGenerator {
277291
}
278292

279293
genDetectChanges():string {
280-
var body = this.genBody();
294+
var body = this.genDetectChangesBody();
281295
return detectChangesTemplate(this.typeName, body);
282296
}
283297

@@ -295,9 +309,9 @@ export class ChangeDetectorJITGenerator {
295309
return callOnAllChangesDoneTemplate(this.typeName, notifications.join(";\n"));
296310
}
297311

298-
genBody():string {
312+
genDetectChangesBody():string {
299313
var rec = this.records.map((r) => this.genRecord(r)).join("\n");
300-
return bodyTemplate(this.genLocalDefinitions(), this.genChangeDefinitions(), rec);
314+
return detectChangesBodyTemplate(this.genLocalDefinitions(), this.genChangeDefinitions(), rec);
301315
}
302316

303317
genLocalDefinitions():string {
@@ -318,27 +332,33 @@ export class ChangeDetectorJITGenerator {
318332

319333
genPipeCheck(r:ProtoRecord):string {
320334
var context = this.localNames[r.contextIndex];
321-
var pipe = this.pipeNames[r.selfIndex];
322-
var newValue = this.localNames[r.selfIndex];
323335
var oldValue = this.fieldNames[r.selfIndex];
336+
var newValue = this.localNames[r.selfIndex];
324337
var change = this.changeNames[r.selfIndex];
338+
339+
var pipe = this.pipeNames[r.selfIndex];
325340
var bpc = r.mode === RECORD_TYPE_BINDING_PIPE ? "this.bindingPropagationConfig" : "null";
326341

327-
var addRecord = addSimpleChangeRecordTemplate(r.selfIndex - 1, oldValue, newValue);
328-
var notify = this.genNotify(r);
342+
var invokeMemento = this.getInvokeMementoAndAddChangeTemplate(r);
343+
var addToChanges = this.genAddToChanges(r);
344+
var lastInDirective = this.genLastInDirective(r);
329345

330-
return pipeCheckTemplate(context, bpc, pipe, r.name, newValue, change, addRecord, notify);
346+
return pipeCheckTemplate(r.selfIndex - 1, context, bpc, pipe, r.name, oldValue, newValue, change,
347+
invokeMemento, addToChanges, lastInDirective);
331348
}
332349

333350
genReferenceCheck(r:ProtoRecord):string {
334-
var newValue = this.localNames[r.selfIndex];
335351
var oldValue = this.fieldNames[r.selfIndex];
352+
var newValue = this.localNames[r.selfIndex];
336353
var change = this.changeNames[r.selfIndex];
337354
var assignment = this.genUpdateCurrentValue(r);
338-
var addRecord = addSimpleChangeRecordTemplate(r.selfIndex - 1, oldValue, newValue);
339-
var notify = this.genNotify(r);
340355

341-
var check = referenceCheckTemplate(assignment, newValue, oldValue, change, r.lastInBinding ? addRecord : '', notify);
356+
var invokeMemento = this.getInvokeMementoAndAddChangeTemplate(r);
357+
var addToChanges = this.genAddToChanges(r);
358+
var lastInDirective = this.genLastInDirective(r);
359+
360+
var check = referenceCheckTemplate(r.selfIndex - 1, assignment, oldValue, newValue, change,
361+
invokeMemento, addToChanges, lastInDirective);
342362
if (r.isPureFunction()) {
343363
return this.ifChangedGuard(r, check);
344364
} else {
@@ -405,8 +425,22 @@ export class ChangeDetectorJITGenerator {
405425
return JSON.stringify(value);
406426
}
407427

408-
genNotify(r):string{
409-
return r.lastInDirective ? notifyTemplate(r.selfIndex - 1) : '';
428+
getInvokeMementoAndAddChangeTemplate(r:ProtoRecord):string {
429+
var newValue = this.localNames[r.selfIndex];
430+
var oldValue = this.fieldNames[r.selfIndex];
431+
return r.lastInBinding ? invokeBindingMemento(oldValue, newValue) : "";
432+
}
433+
434+
genAddToChanges(r:ProtoRecord):string {
435+
var newValue = this.localNames[r.selfIndex];
436+
var oldValue = this.fieldNames[r.selfIndex];
437+
var callOnChange = r.directiveMemento && r.directiveMemento.callOnChange;
438+
return callOnChange ? addToChangesTemplate(oldValue, newValue) : "";
439+
}
440+
441+
genLastInDirective(r:ProtoRecord):string{
442+
var callOnChange = r.directiveMemento && r.directiveMemento.callOnChange;
443+
return r.lastInDirective && callOnChange ? lastInDirectiveTemplate(r.selfIndex - 1) : '';
410444
}
411445

412446
genArgs(r:ProtoRecord):string {

modules/angular2/src/change_detection/change_detection_util.js

Lines changed: 9 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/faca
33
import {ProtoRecord} from './proto_record';
44
import {ExpressionChangedAfterItHasBeenChecked} from './exceptions';
55
import {NO_CHANGE} from './pipes/pipe';
6-
import {ChangeRecord, ChangeDetector} from './interfaces';
76
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
87

98
export var uninitialized = new Object();
@@ -40,31 +39,7 @@ var _simpleChanges = [
4039
new SimpleChange(null, null),
4140
new SimpleChange(null, null),
4241
new SimpleChange(null, null)
43-
]
44-
45-
var _changeRecordsIndex = 0;
46-
var _changeRecords = [
47-
new ChangeRecord(null, null),
48-
new ChangeRecord(null, null),
49-
new ChangeRecord(null, null),
50-
new ChangeRecord(null, null),
51-
new ChangeRecord(null, null),
52-
new ChangeRecord(null, null),
53-
new ChangeRecord(null, null),
54-
new ChangeRecord(null, null),
55-
new ChangeRecord(null, null),
56-
new ChangeRecord(null, null),
57-
new ChangeRecord(null, null),
58-
new ChangeRecord(null, null),
59-
new ChangeRecord(null, null),
60-
new ChangeRecord(null, null),
61-
new ChangeRecord(null, null),
62-
new ChangeRecord(null, null),
63-
new ChangeRecord(null, null),
64-
new ChangeRecord(null, null),
65-
new ChangeRecord(null, null),
66-
new ChangeRecord(null, null)
67-
]
42+
];
6843

6944
function _simpleChange(previousValue, currentValue) {
7045
var index = _simpleChangesIndex++ % 20;
@@ -74,16 +49,6 @@ function _simpleChange(previousValue, currentValue) {
7449
return s;
7550
}
7651

77-
function _changeRecord(bindingMemento, change) {
78-
var index = _changeRecordsIndex++ % 20;
79-
var s = _changeRecords[index];
80-
s.bindingMemento = bindingMemento;
81-
s.change = change;
82-
return s;
83-
}
84-
85-
var _singleElementList = [null];
86-
8752
export class ChangeDetectionUtil {
8853
static unitialized() {
8954
return uninitialized;
@@ -152,33 +117,19 @@ export class ChangeDetectionUtil {
152117
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
153118
}
154119

155-
static simpleChange(previousValue:any, currentValue:any):SimpleChange {
156-
return _simpleChange(previousValue, currentValue);
157-
}
158-
159-
static changeRecord(memento:any, change:any):ChangeRecord {
160-
return _changeRecord(memento, change);
161-
}
162-
163-
static simpleChangeRecord(memento:any, previousValue:any, currentValue:any):ChangeRecord {
164-
return _changeRecord(memento, _simpleChange(previousValue, currentValue));
165-
}
166-
167120
static changeDetectionMode(strategy:string) {
168121
return strategy == ON_PUSH ? CHECK_ONCE : CHECK_ALWAYS;
169122
}
170123

171-
static addRecord(updatedRecords:List, changeRecord:ChangeRecord):List {
172-
if (isBlank(updatedRecords)) {
173-
updatedRecords = _singleElementList;
174-
updatedRecords[0] = changeRecord;
175-
176-
} else if (updatedRecords === _singleElementList) {
177-
updatedRecords = [_singleElementList[0], changeRecord];
124+
static simpleChange(previousValue:any, currentValue:any):SimpleChange {
125+
return _simpleChange(previousValue, currentValue);
126+
}
178127

179-
} else {
180-
ListWrapper.push(updatedRecords, changeRecord);
128+
static addChange(changes, bindingMemento, change){
129+
if (isBlank(changes)) {
130+
changes = {};
181131
}
182-
return updatedRecords;
132+
changes[bindingMemento.propertyName] = change;
133+
return changes;
183134
}
184135
}

modules/angular2/src/change_detection/dynamic_change_detector.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,21 +89,31 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
8989
detectChangesInRecords(throwOnChange:boolean) {
9090
var protos:List<ProtoRecord> = this.protos;
9191

92-
var updatedRecords = null;
92+
var changes = null;
93+
var currentDirectiveMemento = null;
94+
9395
for (var i = 0; i < protos.length; ++i) {
9496
var proto:ProtoRecord = protos[i];
95-
var change = this._check(proto);
97+
if (isBlank(currentDirectiveMemento)) {
98+
currentDirectiveMemento = proto.directiveMemento;
99+
}
96100

101+
var change = this._check(proto);
97102
if (isPresent(change)) {
98-
var record = ChangeDetectionUtil.changeRecord(proto.bindingMemento, change);
99-
updatedRecords = ChangeDetectionUtil.addRecord(updatedRecords, record);
100-
}
103+
if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, change);
104+
this.dispatcher.invokeMementoFor(proto.bindingMemento, change.currentValue);
101105

102-
if (proto.lastInDirective && isPresent(updatedRecords)) {
103-
if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, updatedRecords[0]);
106+
if (isPresent(currentDirectiveMemento) && currentDirectiveMemento.callOnChange) {
107+
changes = ChangeDetectionUtil.addChange(changes, proto.bindingMemento, change);
108+
}
109+
}
104110

105-
this.dispatcher.onRecordChange(proto.directiveMemento, updatedRecords);
106-
updatedRecords = null;
111+
if (proto.lastInDirective) {
112+
if (isPresent(changes)) {
113+
this.dispatcher.onChange(currentDirectiveMemento, changes);
114+
}
115+
currentDirectiveMemento = null;
116+
changes = null;
107117
}
108118
}
109119
}
@@ -285,3 +295,6 @@ function isSame(a, b) {
285295
if ((a !== a) && (b !== b)) return true;
286296
return false;
287297
}
298+
299+
300+

0 commit comments

Comments
 (0)