feat(ChangeDetector): Add support for short-circuiting

This commit is contained in:
Victor Berchet
2015-10-16 10:55:21 -07:00
parent b91351469f
commit 7e92d2e6b7
10 changed files with 582 additions and 113 deletions

View File

@ -14,6 +14,7 @@ import 'package:angular2/src/core/change_detection/binding_record.dart';
import 'package:angular2/src/core/change_detection/codegen_facade.dart'
show codify;
import 'package:angular2/src/core/facade/exceptions.dart' show BaseException;
import 'package:angular2/src/core/facade/collection.dart' show ListWrapper;
/// Responsible for generating change detector classes for Angular 2.
///
@ -90,6 +91,7 @@ class _CodegenState {
final CodegenNameUtil _names;
final ChangeDetectorGenConfig _genConfig;
final List<BindingTarget> _propertyBindingTargets;
final List<int> _endOfBlockIdxs = [];
String get _changeDetectionStrategyAsCode => _changeDetectionStrategy == null
? 'null'
@ -156,7 +158,7 @@ class _CodegenState {
var $_IS_CHANGED_LOCAL = false;
var $_CHANGES_LOCAL = null;
${_records.map(_genRecord).join('')}
${_genAllRecords()}
}
${_maybeGenHandleEventInternal()}
@ -186,6 +188,15 @@ class _CodegenState {
''');
}
String _genAllRecords() {
_endOfBlockIdxs.clear();
List<String> res = [];
for (int i = 0; i < _records.length; i++) {
res.add(_genRecord(_records[i], i));
}
return res.join('');
}
String _genPropertyBindingTargets() {
var targets = _logic.genPropertyBindingTargets(
_propertyBindingTargets, this._genConfig.genDebugInfo);
@ -215,10 +226,29 @@ class _CodegenState {
}
String _genEventBinding(EventBinding eb) {
var recs = eb.records.map((r) => _genEventBindingEval(eb, r)).join("\n");
List<String> codes = [];
_endOfBlockIdxs.clear();
ListWrapper.forEachWithIndex(eb.records, (r, i) {
var code;
var r = eb.records[i];
if (r.isConditionalSkipRecord()) {
code = _genConditionalSkip(r, _names.getEventLocalName(eb, i));
} else if (r.isUnconditionalSkipRecord()) {
code = _genUnconditionalSkip(r);
} else {
code = _genEventBindingEval(eb, r);
}
code += this._genEndOfSkipBlock(i);
codes.add(code);
});
return '''
if (eventName == "${eb.eventName}" && elIndex == ${eb.elIndex}) {
${recs}
${codes.join("\n")}
}''';
}
@ -315,20 +345,53 @@ class _CodegenState {
return 'var ${declareNames.join(', ')};';
}
String _genRecord(ProtoRecord r) {
var rec = null;
String _genRecord(ProtoRecord r, int index) {
var code = null;
if (r.isLifeCycleRecord()) {
rec = _genDirectiveLifecycle(r);
code = _genDirectiveLifecycle(r);
} else if (r.isPipeRecord()) {
rec = _genPipeCheck(r);
code = _genPipeCheck(r);
} else if (r.isConditionalSkipRecord()) {
code = _genConditionalSkip(r, _names.getLocalName(r.contextIndex));
} else if (r.isUnconditionalSkipRecord()) {
code = _genUnconditionalSkip(r);
} else {
rec = _genReferenceCheck(r);
code = _genReferenceCheck(r);
}
return '''
code = '''
${this._maybeFirstInBinding(r)}
${rec}
${code}
${this._maybeGenLastInDirective(r)}
${this._genEndOfSkipBlock(index)}
''';
return code;
}
String _genConditionalSkip(ProtoRecord r, String condition) {
var maybeNegate = r.mode == RecordType.SkipRecordsIf ? '!' : '';
_endOfBlockIdxs.add(r.fixedArgs[0] - 1);
return 'if ($maybeNegate$condition) {';
}
String _genUnconditionalSkip(ProtoRecord r) {
_endOfBlockIdxs.removeLast();
_endOfBlockIdxs.add(r.fixedArgs[0] - 1);
return '} else {';
}
String _genEndOfSkipBlock(int protoIndex) {
if (!ListWrapper.isEmpty(this._endOfBlockIdxs)) {
var endOfBlock = ListWrapper.last(this._endOfBlockIdxs);
if (protoIndex == endOfBlock) {
this._endOfBlockIdxs.removeLast();
return '}';
}
}
return '';
}
String _genDirectiveLifecycle(ProtoRecord r) {