fix(change detection): preserve memoized results from pure functions
This commit is contained in:
parent
b0e2ebda70
commit
5beaf6d735
|
@ -291,7 +291,7 @@ export class ChangeDetectorJITGenerator {
|
||||||
|
|
||||||
if (r.isPureFunction()) {
|
if (r.isPureFunction()) {
|
||||||
var condition = r.args.map((a) => this._changeNames[a]).join(" || ");
|
var condition = r.args.map((a) => this._changeNames[a]).join(" || ");
|
||||||
return `if (${condition}) { ${check} }`;
|
return `if (${condition}) { ${check} } else { ${newValue} = ${oldValue}; }`;
|
||||||
} else {
|
} else {
|
||||||
return check;
|
return check;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,12 +69,11 @@ var _rootBindings = [bind(Reflector).toValue(reflector), TestabilityRegistry];
|
||||||
|
|
||||||
function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
|
function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
|
||||||
var bestChangeDetection: Type = DynamicChangeDetection;
|
var bestChangeDetection: Type = DynamicChangeDetection;
|
||||||
// Re-enable once all e2e tests pass
|
if (PreGeneratedChangeDetection.isSupported()) {
|
||||||
// if (PreGeneratedChangeDetection.isSupported()) {
|
bestChangeDetection = PreGeneratedChangeDetection;
|
||||||
// bestChangeDetection = PreGeneratedChangeDetection;
|
} else if (JitChangeDetection.isSupported()) {
|
||||||
//} else if (JitChangeDetection.isSupported()) {
|
bestChangeDetection = JitChangeDetection;
|
||||||
// bestChangeDetection = JitChangeDetection;
|
}
|
||||||
//}
|
|
||||||
return [
|
return [
|
||||||
bind(DOCUMENT_TOKEN)
|
bind(DOCUMENT_TOKEN)
|
||||||
.toValue(DOM.defaultDoc()),
|
.toValue(DOM.defaultDoc()),
|
||||||
|
|
|
@ -352,7 +352,7 @@ class _CodegenState {
|
||||||
if (r.isPureFunction()) {
|
if (r.isPureFunction()) {
|
||||||
// Add an "if changed guard"
|
// Add an "if changed guard"
|
||||||
var condition = r.args.map((a) => _changeNames[a]).join(' || ');
|
var condition = r.args.map((a) => _changeNames[a]).join(' || ');
|
||||||
return 'if ($condition) { $check }';
|
return 'if ($condition) { $check } else { $newValue = $oldValue; }';
|
||||||
} else {
|
} else {
|
||||||
return check;
|
return check;
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,5 +303,6 @@ var _availableDefinitions = [
|
||||||
'address?.toString()',
|
'address?.toString()',
|
||||||
'sayHi("Jim")',
|
'sayHi("Jim")',
|
||||||
'a()(99)',
|
'a()(99)',
|
||||||
'a.sayHi("Jim")'
|
'a.sayHi("Jim")',
|
||||||
|
'passThrough([12])'
|
||||||
];
|
];
|
||||||
|
|
|
@ -54,8 +54,8 @@ const _DEFAULT_CONTEXT = CONST_EXPR(new Object());
|
||||||
/**
|
/**
|
||||||
* Tests in this spec run against three different implementations of `AbstractChangeDetector`,
|
* Tests in this spec run against three different implementations of `AbstractChangeDetector`,
|
||||||
* `dynamic` (which use reflection to inspect objects), `JIT` (which are generated only for
|
* `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
|
* Javascript at runtime using `eval`) and `Pregen` (which are generated only for Dart prior
|
||||||
* generated only for Dart prior to app deploy to avoid the need for reflection).
|
* 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
|
* 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
|
* 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']);
|
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('change notification', () => {
|
||||||
describe('simple checks', () => {
|
describe('simple checks', () => {
|
||||||
it('should pass a change record to the dispatcher', () => {
|
it('should pass a change record to the dispatcher', () => {
|
||||||
|
@ -948,6 +958,8 @@ class Person {
|
||||||
|
|
||||||
sayHi(m) { return `Hi, ${m}`; }
|
sayHi(m) { return `Hi, ${m}`; }
|
||||||
|
|
||||||
|
passThrough(val) { return val; }
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
var address = this.address == null ? '' : ' address=' + this.address.toString();
|
var address = this.address == null ? '' : ' address=' + this.address.toString();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue