Skip to content

Commit f80f972

Browse files
committed
refactor(change_detection): made ChangeDetector and ProtoChangeDetector interfaces
List of changes: - Makes ChangeDetector and ProtoChangeDetector interfaces - Assigns a unique id to every detector
1 parent ee8da36 commit f80f972

File tree

20 files changed

+134
-93
lines changed

20 files changed

+134
-93
lines changed

modules/angular2/change_detection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ export {
2525
} from './src/change_detection/exceptions';
2626
export {
2727
ProtoChangeDetector,
28-
ChangeDispatcher,
2928
ChangeDetector,
29+
ChangeDispatcher,
3030
ChangeDetection,
3131
ChangeDetectorDefinition
3232
} from './src/change_detection/interfaces';

modules/angular2/src/change_detection/abstract_change_detector.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,17 @@ import {isPresent} from 'angular2/src/facade/lang';
22
import {List, ListWrapper} from 'angular2/src/facade/collection';
33
import {ChangeDetectorRef} from './change_detector_ref';
44
import {ChangeDetector} from './interfaces';
5+
import {Locals} from './parser/locals';
56
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
67

7-
export class AbstractChangeDetector extends ChangeDetector {
8+
export class AbstractChangeDetector implements ChangeDetector {
89
lightDomChildren: List<any> = [];
910
shadowDomChildren: List<any> = [];
1011
parent: ChangeDetector;
1112
mode: string = null;
1213
ref: ChangeDetectorRef;
1314

14-
constructor() {
15-
super();
16-
this.ref = new ChangeDetectorRef(this);
17-
}
15+
constructor(public id: string) { this.ref = new ChangeDetectorRef(this); }
1816

1917
addChild(cd: ChangeDetector): void {
2018
this.lightDomChildren.push(cd);
@@ -51,6 +49,11 @@ export class AbstractChangeDetector extends ChangeDetector {
5149
}
5250

5351
detectChangesInRecords(throwOnChange: boolean): void {}
52+
53+
hydrate(context: any, locals: Locals, directives: any): void {}
54+
55+
dehydrate(): void {}
56+
5457
callOnAllChangesDone(): void {}
5558

5659
_detectChangesInLightDomChildren(throwOnChange: boolean): void {

modules/angular2/src/change_detection/change_detection_jit_generator.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class ChangeDetectorJITGenerator {
3838
_fieldNames: List<string>;
3939
_pipeNames: List<string>;
4040

41-
constructor(public typeName: string, public changeDetectionStrategy: string,
41+
constructor(public id: string, public changeDetectionStrategy: string,
4242
public records: List<ProtoRecord>, public directiveRecords: List<any>) {
4343
this._localNames = this._getLocalNames(records);
4444
this._changeNames = this._getChangeNames(this._localNames);
@@ -48,10 +48,7 @@ export class ChangeDetectorJITGenerator {
4848

4949
_getLocalNames(records: List<ProtoRecord>): List<string> {
5050
var index = 0;
51-
var names = records.map((r) => {
52-
var sanitizedName = r.name.replace(new RegExp("\\W", "g"), '');
53-
return `${sanitizedName}${index++}`
54-
});
51+
var names = records.map((r) => { return _sanitizeName(`${r.name}${index++}`); });
5552
return ["context"].concat(names);
5653
}
5754

@@ -68,9 +65,10 @@ export class ChangeDetectorJITGenerator {
6865
}
6966

7067
generate(): Function {
68+
var typeName = _sanitizeName(`ChangeDetector_${this.id}`);
7169
var classDefinition = `
72-
var ${this.typeName} = function ${this.typeName}(dispatcher, pipeRegistry, protos, directiveRecords) {
73-
${ABSTRACT_CHANGE_DETECTOR}.call(this);
70+
var ${typeName} = function ${typeName}(dispatcher, pipeRegistry, protos, directiveRecords) {
71+
${ABSTRACT_CHANGE_DETECTOR}.call(this, ${JSON.stringify(this.id)});
7472
${DISPATCHER_ACCESSOR} = dispatcher;
7573
${PIPE_REGISTRY_ACCESSOR} = pipeRegistry;
7674
${PROTOS_ACCESSOR} = protos;
@@ -80,9 +78,9 @@ export class ChangeDetectorJITGenerator {
8078
${this._genFieldDefinitions()}
8179
}
8280
83-
${this.typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype);
81+
${typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype);
8482
85-
${this.typeName}.prototype.detectChangesInRecords = function(throwOnChange) {
83+
${typeName}.prototype.detectChangesInRecords = function(throwOnChange) {
8684
if (!this.hydrated()) {
8785
${UTIL}.throwDehydrated();
8886
}
@@ -99,11 +97,11 @@ export class ChangeDetectorJITGenerator {
9997
${ALREADY_CHECKED_ACCESSOR} = true;
10098
}
10199
102-
${this.typeName}.prototype.callOnAllChangesDone = function() {
100+
${typeName}.prototype.callOnAllChangesDone = function() {
103101
${this._genCallOnAllChangesDoneBody()}
104102
}
105103
106-
${this.typeName}.prototype.hydrate = function(context, locals, directives) {
104+
${typeName}.prototype.hydrate = function(context, locals, directives) {
107105
${MODE_ACCESSOR} = "${ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy)}";
108106
${CONTEXT_ACCESSOR} = context;
109107
${LOCALS_ACCESSOR} = locals;
@@ -112,21 +110,20 @@ export class ChangeDetectorJITGenerator {
112110
${ALREADY_CHECKED_ACCESSOR} = false;
113111
}
114112
115-
${this.typeName}.prototype.dehydrate = function() {
113+
${typeName}.prototype.dehydrate = function() {
116114
${this._genPipeOnDestroy()}
117115
${this._genFieldDefinitions()}
118116
${LOCALS_ACCESSOR} = null;
119117
}
120118
121-
${this.typeName}.prototype.hydrated = function() {
119+
${typeName}.prototype.hydrated = function() {
122120
return ${CONTEXT_ACCESSOR} !== null;
123121
}
124122
125123
return function(dispatcher, pipeRegistry) {
126-
return new ${this.typeName}(dispatcher, pipeRegistry, protos, directiveRecords);
124+
return new ${typeName}(dispatcher, pipeRegistry, protos, directiveRecords);
127125
}
128126
`;
129-
130127
return new Function('AbstractChangeDetector', 'ChangeDetectionUtil', 'protos',
131128
'directiveRecords', classDefinition)(
132129
AbstractChangeDetector, ChangeDetectionUtil, this.records, this.directiveRecords);
@@ -444,3 +441,7 @@ export class ChangeDetectorJITGenerator {
444441
return retVal;
445442
}
446443
}
444+
445+
function _sanitizeName(s: string): string {
446+
return s.replace(new RegExp("\\W", "g"), '');
447+
}

modules/angular2/src/change_detection/dynamic_change_detector.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
2121
directives: any = null;
2222
alreadyChecked: boolean = false;
2323

24-
constructor(private changeControlStrategy: string, private dispatcher: any,
24+
constructor(id: string, private changeControlStrategy: string, private dispatcher: any,
2525
private pipeRegistry: PipeRegistry, private protos: List<ProtoRecord>,
2626
private directiveRecords: List<any>) {
27-
super();
27+
super(id);
2828
this.values = ListWrapper.createFixedSize(protos.length + 1);
2929
this.pipes = ListWrapper.createFixedSize(protos.length + 1);
3030
this.prevContexts = ListWrapper.createFixedSize(protos.length + 1);

modules/angular2/src/change_detection/interfaces.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ import {Locals} from './parser/locals';
33
import {BindingRecord} from './binding_record';
44
import {DirectiveRecord} from './directive_record';
55

6-
export class ProtoChangeDetector {
7-
instantiate(dispatcher: any): ChangeDetector { return null; }
8-
}
9-
106
/**
117
* Interface used by Angular to control the change detection strategy for an application.
128
*
@@ -39,27 +35,30 @@ export class ChangeDetection {
3935
}
4036
}
4137

42-
export class ChangeDispatcher {
43-
notifyOnBinding(bindingRecord: BindingRecord, value: any) {}
38+
export interface ChangeDispatcher {
39+
notifyOnBinding(bindingRecord: BindingRecord, value: any): void;
40+
notifyOnAllChangesDone(): void;
4441
}
4542

46-
export class ChangeDetector {
43+
export interface ChangeDetector {
4744
parent: ChangeDetector;
4845
mode: string;
4946

50-
addChild(cd: ChangeDetector): void {}
51-
addShadowDomChild(cd: ChangeDetector): void {}
52-
removeChild(cd: ChangeDetector): void {}
53-
removeShadowDomChild(cd: ChangeDetector): void {}
54-
remove(): void {}
55-
hydrate(context: any, locals: Locals, directives: any): void {}
56-
dehydrate(): void {}
57-
markPathToRootAsCheckOnce(): void {}
47+
addChild(cd: ChangeDetector): void;
48+
addShadowDomChild(cd: ChangeDetector): void;
49+
removeChild(cd: ChangeDetector): void;
50+
removeShadowDomChild(cd: ChangeDetector): void;
51+
remove(): void;
52+
hydrate(context: any, locals: Locals, directives: any): void;
53+
dehydrate(): void;
54+
markPathToRootAsCheckOnce(): void;
5855

59-
detectChanges(): void {}
60-
checkNoChanges(): void {}
56+
detectChanges(): void;
57+
checkNoChanges(): void;
6158
}
6259

60+
export interface ProtoChangeDetector { instantiate(dispatcher: any): ChangeDetector; }
61+
6362
export class ChangeDetectorDefinition {
6463
constructor(public id: string, public strategy: string, public variableNames: List<string>,
6564
public bindingRecords: List<BindingRecord>,

modules/angular2/src/change_detection/jit_proto_change_detector.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ import {ChangeDetectorJITGenerator} from './change_detection_jit_generator';
66
import {coalesce} from './coalesce';
77
import {ProtoRecordBuilder} from './proto_change_detector';
88

9-
var _jitProtoChangeDetectorClassCounter: number = 0;
10-
export class JitProtoChangeDetector extends ProtoChangeDetector {
9+
export class JitProtoChangeDetector implements ProtoChangeDetector {
1110
_factory: Function;
1211

1312
constructor(private _pipeRegistry, private definition: ChangeDetectorDefinition) {
14-
super();
1513
this._factory = this._createFactory(definition);
1614
}
1715

@@ -25,10 +23,8 @@ export class JitProtoChangeDetector extends ProtoChangeDetector {
2523
var recordBuilder = new ProtoRecordBuilder();
2624
ListWrapper.forEach(definition.bindingRecords,
2725
(b) => { recordBuilder.add(b, definition.variableNames); });
28-
var c = _jitProtoChangeDetectorClassCounter++;
2926
var records = coalesce(recordBuilder.records);
30-
var typeName = `ChangeDetector${c}`;
31-
return new ChangeDetectorJITGenerator(typeName, definition.strategy, records,
27+
return new ChangeDetectorJITGenerator(definition.id, definition.strategy, records,
3228
this.definition.directiveRecords)
3329
.generate();
3430
}

modules/angular2/src/change_detection/pregen_proto_change_detector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {coalesce} from './coalesce';
55

66
export {Function as PregenProtoChangeDetectorFactory};
77

8-
export class PregenProtoChangeDetector extends ProtoChangeDetector {
8+
export class PregenProtoChangeDetector implements ProtoChangeDetector {
99
static isSupported(): boolean { return false; }
1010

1111
instantiate(dispatcher: any): ChangeDetector {

modules/angular2/src/change_detection/proto_change_detector.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,7 @@ import {
2525
SafeMethodCall
2626
} from './parser/ast';
2727

28-
import {
29-
ChangeDispatcher,
30-
ChangeDetector,
31-
ProtoChangeDetector,
32-
ChangeDetectorDefinition
33-
} from './interfaces';
28+
import {ChangeDetector, ProtoChangeDetector, ChangeDetectorDefinition} from './interfaces';
3429
import {ChangeDetectionUtil} from './change_detection_util';
3530
import {DynamicChangeDetector} from './dynamic_change_detector';
3631
import {PipeRegistry} from './pipes/pipe_registry';
@@ -41,17 +36,17 @@ import {coalesce} from './coalesce';
4136

4237
import {ProtoRecord, RecordType} from './proto_record';
4338

44-
export class DynamicProtoChangeDetector extends ProtoChangeDetector {
39+
export class DynamicProtoChangeDetector implements ProtoChangeDetector {
4540
_records: List<ProtoRecord>;
4641

4742
constructor(private _pipeRegistry: PipeRegistry, private definition: ChangeDetectorDefinition) {
48-
super();
4943
this._records = this._createRecords(definition);
5044
}
5145

5246
instantiate(dispatcher: any) {
53-
return new DynamicChangeDetector(this.definition.strategy, dispatcher, this._pipeRegistry,
54-
this._records, this.definition.directiveRecords);
47+
return new DynamicChangeDetector(this.definition.id, this.definition.strategy, dispatcher,
48+
this._pipeRegistry, this._records,
49+
this.definition.directiveRecords);
5550
}
5651

5752
_createRecords(definition: ChangeDetectorDefinition) {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {
2+
ChangeDetector,
3+
ProtoChangeDetector,
4+
DynamicChangeDetector
5+
} from 'angular2/change_detection';
6+
import {SpyObject, proxy} from './test_lib';
7+
8+
// Remove dummy methods after https://github.com/angular/ts2dart/issues/209 is fixed.
9+
@proxy
10+
export class SpyChangeDetector extends SpyObject implements ChangeDetector {
11+
parent: ChangeDetector;
12+
mode: string;
13+
14+
constructor() { super(DynamicChangeDetector, true); }
15+
16+
addChild(cd: ChangeDetector): void { return this.spy("addChild")(cd); }
17+
18+
addShadowDomChild(cd: ChangeDetector): void { return this.spy("addShadowDomChild")(cd); }
19+
20+
removeChild(cd: ChangeDetector): void { return this.spy("removeChild")(cd); }
21+
22+
removeShadowDomChild(cd: ChangeDetector): void { return this.spy("removeShadowDomChild")(cd); }
23+
24+
remove(): void { return this.spy("remove")(); }
25+
26+
hydrate(context: any, locals: any, directives: any): void {
27+
return this.spy("hydrate")(context, locals, directives);
28+
}
29+
30+
dehydrate(): void { return this.spy("dehydrate")(); }
31+
32+
markPathToRootAsCheckOnce(): void { return this.spy("markPathToRootAsCheckOnce")(); }
33+
34+
detectChanges(): void { return this.spy("detectChanges")(); }
35+
36+
checkNoChanges(): void { return this.spy("checkNoChanges")(); }
37+
38+
noSuchMethod(m) { return super.noSuchMethod(m) }
39+
}
40+
41+
// Remove dummy methods after https://github.com/angular/ts2dart/issues/209 is fixed.
42+
@proxy
43+
export class SpyProtoChangeDetector extends SpyObject implements ProtoChangeDetector {
44+
constructor() { super(DynamicChangeDetector, true); }
45+
46+
instantiate(v: any): any { return this.spy("instantiate")(v); }
47+
}

modules/angular2/src/test_lib/test_lib.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class SpyFunction extends gns.SpyFunction {
187187
class SpyObject extends gns.SpyObject {
188188
final Map<String, SpyFunction> _spyFuncs = {};
189189

190-
SpyObject([arg]) {}
190+
SpyObject([arg, arg2]) {}
191191

192192
SpyFunction spy(String funcName) =>
193193
_spyFuncs.putIfAbsent(funcName, () => new SpyFunction(funcName));

0 commit comments

Comments
 (0)