From 5beaf6d735026882757e535db26e7f80a6439c9d Mon Sep 17 00:00:00 2001 From: Yegor Jbanov Date: Wed, 17 Jun 2015 12:56:11 -0700 Subject: [PATCH] fix(change detection): preserve memoized results from pure functions --- .../change_detection_jit_generator.ts | 2 +- modules/angular2/src/core/application.ts | 11 +++++------ .../change_detector_codegen.dart | 2 +- .../change_detection/change_detector_config.ts | 3 ++- .../change_detection/change_detector_spec.ts | 16 ++++++++++++++-- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/modules/angular2/src/change_detection/change_detection_jit_generator.ts b/modules/angular2/src/change_detection/change_detection_jit_generator.ts index 8d9777a4c3..01b02c2097 100644 --- a/modules/angular2/src/change_detection/change_detection_jit_generator.ts +++ b/modules/angular2/src/change_detection/change_detection_jit_generator.ts @@ -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; } diff --git a/modules/angular2/src/core/application.ts b/modules/angular2/src/core/application.ts index 24bd004442..7fbbc9061f 100644 --- a/modules/angular2/src/core/application.ts +++ b/modules/angular2/src/core/application.ts @@ -69,12 +69,11 @@ var _rootBindings = [bind(Reflector).toValue(reflector), TestabilityRegistry]; function _injectorBindings(appComponentType): List> { 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()), diff --git a/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart b/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart index 28d93df88f..c2ba2ffa2d 100644 --- a/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart +++ b/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart @@ -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; } diff --git a/modules/angular2/test/change_detection/change_detector_config.ts b/modules/angular2/test/change_detection/change_detector_config.ts index 3b396a1b6e..213565b833 100644 --- a/modules/angular2/test/change_detection/change_detector_config.ts +++ b/modules/angular2/test/change_detection/change_detector_config.ts @@ -303,5 +303,6 @@ var _availableDefinitions = [ 'address?.toString()', 'sayHi("Jim")', 'a()(99)', - 'a.sayHi("Jim")' + 'a.sayHi("Jim")', + 'passThrough([12])' ]; diff --git a/modules/angular2/test/change_detection/change_detector_spec.ts b/modules/angular2/test/change_detection/change_detector_spec.ts index b1828dc5db..84d027dab1 100644 --- a/modules/angular2/test/change_detection/change_detector_spec.ts +++ b/modules/angular2/test/change_detection/change_detector_spec.ts @@ -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();