fix(change detection): preserve memoized results from pure functions

This commit is contained in:
Yegor Jbanov 2015-06-17 12:56:11 -07:00
parent b0e2ebda70
commit 5beaf6d735
5 changed files with 23 additions and 11 deletions

View File

@ -291,7 +291,7 @@ export class ChangeDetectorJITGenerator {
if (r.isPureFunction()) {
var condition = r.args.map((a) => this._changeNames[a]).join(" || ");
return `if (${condition}) { ${check} }`;
return `if (${condition}) { ${check} } else { ${newValue} = ${oldValue}; }`;
} else {
return check;
}

View File

@ -69,12 +69,11 @@ var _rootBindings = [bind(Reflector).toValue(reflector), TestabilityRegistry];
function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
var bestChangeDetection: Type = DynamicChangeDetection;
// Re-enable once all e2e tests pass
// if (PreGeneratedChangeDetection.isSupported()) {
// bestChangeDetection = PreGeneratedChangeDetection;
//} else if (JitChangeDetection.isSupported()) {
// bestChangeDetection = JitChangeDetection;
//}
if (PreGeneratedChangeDetection.isSupported()) {
bestChangeDetection = PreGeneratedChangeDetection;
} else if (JitChangeDetection.isSupported()) {
bestChangeDetection = JitChangeDetection;
}
return [
bind(DOCUMENT_TOKEN)
.toValue(DOM.defaultDoc()),

View File

@ -352,7 +352,7 @@ class _CodegenState {
if (r.isPureFunction()) {
// Add an "if changed guard"
var condition = r.args.map((a) => _changeNames[a]).join(' || ');
return 'if ($condition) { $check }';
return 'if ($condition) { $check } else { $newValue = $oldValue; }';
} else {
return check;
}

View File

@ -303,5 +303,6 @@ var _availableDefinitions = [
'address?.toString()',
'sayHi("Jim")',
'a()(99)',
'a.sayHi("Jim")'
'a.sayHi("Jim")',
'passThrough([12])'
];

View File

@ -54,8 +54,8 @@ const _DEFAULT_CONTEXT = CONST_EXPR(new Object());
/**
* Tests in this spec run against three different implementations of `AbstractChangeDetector`,
* `dynamic` (which use reflection to inspect objects), `JIT` (which are generated only for
* Javascript at runtime using `eval` to avoid the need for reflection) and `Pregen` (which are
* generated only for Dart prior to app deploy to avoid the need for reflection).
* Javascript at runtime using `eval`) and `Pregen` (which are generated only for Dart prior
* to app deploy to avoid the need for reflection).
*
* Pre-generated classes require knowledge of the shape of the change detector at the time of Dart
* transformation, so in these tests we abstract a `ChangeDetectorDefinition` out into the
@ -304,6 +304,16 @@ export function main() {
expect(val.dispatcher.log).toEqual(['propName=BvalueA']);
});
describe('pure functions', () => {
it('should preserve memoized result', () => {
var person = new Person('bob');
var val = _createChangeDetector('passThrough([12])', person);
val.changeDetector.detectChanges();
val.changeDetector.detectChanges();
expect(val.dispatcher.loggedValues).toEqual([[12]]);
});
});
describe('change notification', () => {
describe('simple checks', () => {
it('should pass a change record to the dispatcher', () => {
@ -948,6 +958,8 @@ class Person {
sayHi(m) { return `Hi, ${m}`; }
passThrough(val) { return val; }
toString(): string {
var address = this.address == null ? '' : ' address=' + this.address.toString();