Skip to content

Commit c58b0ff

Browse files
author
Tim Blasi
committed
refactor(change_detect): Share more codegen logic
Move more logic in our codegen into a shared util which is called by the Jit & Prege change detector code.
1 parent 392de4a commit c58b0ff

File tree

6 files changed

+148
-173
lines changed

6 files changed

+148
-173
lines changed

modules/angular2/src/change_detection/change_detection_jit_generator.ts

Lines changed: 4 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {DirectiveIndex, DirectiveRecord} from './directive_record';
77

88
import {ProtoRecord, RecordType} from './proto_record';
99
import {CodegenNameUtil, sanitizeName} from './codegen_name_util';
10+
import {CodegenLogicUtil} from './codegen_logic_util';
1011

1112

1213
/**
@@ -24,13 +25,15 @@ var IS_CHANGED_LOCAL = "isChanged";
2425
var CHANGES_LOCAL = "changes";
2526

2627
export class ChangeDetectorJITGenerator {
28+
_logic: CodegenLogicUtil;
2729
_names: CodegenNameUtil;
2830
_typeName: string;
2931

3032
constructor(public id: string, private changeDetectionStrategy: string,
3133
public records: List<ProtoRecord>, public directiveRecords: List<any>,
3234
private generateCheckNoChanges: boolean) {
3335
this._names = new CodegenNameUtil(this.records, this.directiveRecords, UTIL);
36+
this._logic = new CodegenLogicUtil(this._names, UTIL);
3437
this._typeName = sanitizeName(`ChangeDetector_${this.id}`);
3538
}
3639

@@ -206,7 +209,7 @@ export class ChangeDetectorJITGenerator {
206209
var oldValue = this._names.getFieldName(r.selfIndex);
207210
var newValue = this._names.getLocalName(r.selfIndex);
208211
var read = `
209-
${this._genUpdateCurrentValue(r)}
212+
${this._logic.genUpdateCurrentValue(r)}
210213
`;
211214

212215
var check = `
@@ -232,80 +235,6 @@ export class ChangeDetectorJITGenerator {
232235
}
233236
}
234237

235-
_genUpdateCurrentValue(r: ProtoRecord): string {
236-
var context = (r.contextIndex == -1) ? this._names.getDirectiveName(r.directiveIndex) :
237-
this._names.getLocalName(r.contextIndex);
238-
var newValue = this._names.getLocalName(r.selfIndex);
239-
var argString = r.args.map((arg) => this._names.getLocalName(arg)).join(", ");
240-
241-
var rhs;
242-
switch (r.mode) {
243-
case RecordType.SELF:
244-
rhs = context;
245-
break;
246-
247-
case RecordType.CONST:
248-
rhs = JSON.stringify(r.funcOrValue);
249-
break;
250-
251-
case RecordType.PROPERTY:
252-
rhs = `${context}.${r.name}`;
253-
break;
254-
255-
case RecordType.SAFE_PROPERTY:
256-
rhs = `${UTIL}.isValueBlank(${context}) ? null : ${context}.${r.name}`;
257-
break;
258-
259-
case RecordType.LOCAL:
260-
rhs = `${this._names.getLocalsAccessorName()}.get('${r.name}')`;
261-
break;
262-
263-
case RecordType.INVOKE_METHOD:
264-
rhs = `${context}.${r.name}(${argString})`;
265-
break;
266-
267-
case RecordType.SAFE_INVOKE_METHOD:
268-
rhs = `${UTIL}.isValueBlank(${context}) ? null : ${context}.${r.name}(${argString})`;
269-
break;
270-
271-
case RecordType.INVOKE_CLOSURE:
272-
rhs = `${context}(${argString})`;
273-
break;
274-
275-
case RecordType.PRIMITIVE_OP:
276-
rhs = `${UTIL}.${r.name}(${argString})`;
277-
break;
278-
279-
case RecordType.COLLECTION_LITERAL:
280-
rhs = `${UTIL}.${r.name}(${argString})`;
281-
break;
282-
283-
case RecordType.INTERPOLATE:
284-
rhs = this._genInterpolation(r);
285-
break;
286-
287-
case RecordType.KEYED_ACCESS:
288-
rhs = `${context}[${this._names.getLocalName(r.args[0])}]`;
289-
break;
290-
291-
default:
292-
throw new BaseException(`Unknown operation ${r.mode}`);
293-
}
294-
return `${newValue} = ${rhs}`;
295-
}
296-
297-
_genInterpolation(r: ProtoRecord): string {
298-
var res = "";
299-
for (var i = 0; i < r.args.length; ++i) {
300-
res += JSON.stringify(r.fixedArgs[i]);
301-
res += " + ";
302-
res += `${UTIL}.s(${this._names.getLocalName(r.args[i])})`;
303-
res += " + ";
304-
}
305-
res += JSON.stringify(r.fixedArgs[r.args.length]);
306-
return res;
307-
}
308-
309238
_genChangeMarker(r: ProtoRecord): string {
310239
return r.argumentToPureFunction ? `${this._names.getChangeName(r.selfIndex)} = true` : ``;
311240
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
library angular2.src.change_detection.codegen_facade;
2+
3+
import 'dart:convert' show JSON;
4+
5+
/// Converts `funcOrValue` to a string which can be used in generated code.
6+
String codify(funcOrValue) => JSON.encode(funcOrValue).replaceAll(r'$', r'\$');
7+
8+
/// Combine the strings of generated code into a single interpolated string.
9+
/// Each element of `vals` is expected to be a string literal or a codegen'd
10+
/// call to a method returning a string.
11+
/// The return format interpolates each value as an expression which reads
12+
/// poorly, but the resulting code is easily flattened by dart2js.
13+
String combineGeneratedStrings(List<String> vals) {
14+
return '"${vals.map((v) => '\${$v}').join('')}"';
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {List} from 'angular2/src/facade/collection';
2+
3+
/**
4+
* Converts `funcOrValue` to a string which can be used in generated code.
5+
*/
6+
export function codify(obj: any): string {
7+
return JSON.stringify(obj);
8+
}
9+
10+
/**
11+
* Combine the strings of generated code into a single interpolated string.
12+
* Each element of `vals` is expected to be a string literal or a codegen'd
13+
* call to a method returning a string.
14+
*/
15+
export function combineGeneratedStrings(vals: string[]): string {
16+
return vals.join(' + ');
17+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import {ListWrapper} from 'angular2/src/facade/collection';
2+
import {BaseException, Json} from 'angular2/src/facade/lang';
3+
import {CodegenNameUtil} from './codegen_name_util';
4+
import {codify, combineGeneratedStrings} from './codegen_facade';
5+
import {ProtoRecord, RecordType} from './proto_record';
6+
7+
/**
8+
* Class responsible for providing change detection logic for chagne detector classes.
9+
*/
10+
export class CodegenLogicUtil {
11+
constructor(private _names: CodegenNameUtil, private _utilName: string) {}
12+
13+
/**
14+
* Generates a statement which updates the local variable representing `protoRec` with the current
15+
* value of the record.
16+
*/
17+
genUpdateCurrentValue(protoRec: ProtoRecord): string {
18+
var context = (protoRec.contextIndex == -1) ?
19+
this._names.getDirectiveName(protoRec.directiveIndex) :
20+
this._names.getLocalName(protoRec.contextIndex);
21+
var argString =
22+
ListWrapper.map(protoRec.args, (arg) => this._names.getLocalName(arg)).join(", ");
23+
24+
var rhs: string;
25+
switch (protoRec.mode) {
26+
case RecordType.SELF:
27+
rhs = context;
28+
break;
29+
30+
case RecordType.CONST:
31+
rhs = codify(protoRec.funcOrValue);
32+
break;
33+
34+
case RecordType.PROPERTY:
35+
rhs = `${context}.${protoRec.name}`;
36+
break;
37+
38+
case RecordType.SAFE_PROPERTY:
39+
rhs = `${this._utilName}.isValueBlank(${context}) ? null : ${context}.${protoRec.name}`;
40+
break;
41+
42+
case RecordType.LOCAL:
43+
rhs = `${this._names.getLocalsAccessorName()}.get('${protoRec.name}')`;
44+
break;
45+
46+
case RecordType.INVOKE_METHOD:
47+
rhs = `${context}.${protoRec.name}(${argString})`;
48+
break;
49+
50+
case RecordType.SAFE_INVOKE_METHOD:
51+
rhs =
52+
`${this._utilName}.isValueBlank(${context}) ? null : ${context}.${protoRec.name}(${argString})`;
53+
break;
54+
55+
case RecordType.INVOKE_CLOSURE:
56+
rhs = `${context}(${argString})`;
57+
break;
58+
59+
case RecordType.PRIMITIVE_OP:
60+
rhs = `${this._utilName}.${protoRec.name}(${argString})`;
61+
break;
62+
63+
case RecordType.COLLECTION_LITERAL:
64+
rhs = `${this._utilName}.${protoRec.name}(${argString})`;
65+
break;
66+
67+
case RecordType.INTERPOLATE:
68+
rhs = this._genInterpolation(protoRec);
69+
break;
70+
71+
case RecordType.KEYED_ACCESS:
72+
rhs = `${context}[${this._names.getLocalName(protoRec.args[0])}]`;
73+
break;
74+
75+
default:
76+
throw new BaseException(`Unknown operation ${protoRec.mode}`);
77+
}
78+
return `${this._names.getLocalName(protoRec.selfIndex)} = ${rhs};`;
79+
}
80+
81+
_genInterpolation(protoRec: ProtoRecord): string {
82+
var iVals = [];
83+
for (var i = 0; i < protoRec.args.length; ++i) {
84+
iVals.push(codify(protoRec.fixedArgs[i]));
85+
iVals.push(`${this._utilName}.s(${this._names.getLocalName(protoRec.args[i])})`);
86+
}
87+
iVals.push(codify(protoRec.fixedArgs[protoRec.args.length]));
88+
return combineGeneratedStrings(iVals);
89+
}
90+
}

0 commit comments

Comments
 (0)