fix(change_detection): update the right change detector when using ON_PUSH mode
Previously, in a case where you have a mix of ON_PUSH and DEFAULT detectors, Angular would update the status of a wrong detector.
This commit is contained in:
@@ -183,24 +183,25 @@ class _ExpressionWithMode {
|
||||
var directiveRecords = [];
|
||||
var eventRecords = [];
|
||||
|
||||
var dirRecordWithDefault =
|
||||
new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0), changeDetection: DEFAULT});
|
||||
var dirRecordWithOnPush =
|
||||
new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 1), changeDetection: ON_PUSH});
|
||||
|
||||
if (this._withRecords) {
|
||||
var dirRecordWithOnPush =
|
||||
new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0), changeDetection: ON_PUSH});
|
||||
var updateDirWithOnDefaultRecord =
|
||||
BindingRecord.createForDirective(_getParser().parseBinding('42', 'location'), 'a',
|
||||
(o, v) => (<any>o).a = v, dirRecordWithDefault);
|
||||
var updateDirWithOnPushRecord =
|
||||
BindingRecord.createForDirective(_getParser().parseBinding('42', 'location'), 'a',
|
||||
(o, v) => (<any>o).a = v, dirRecordWithOnPush);
|
||||
bindingRecords = [updateDirWithOnPushRecord];
|
||||
directiveRecords = [dirRecordWithOnPush];
|
||||
} else {
|
||||
bindingRecords = [];
|
||||
directiveRecords = [];
|
||||
|
||||
directiveRecords = [dirRecordWithDefault, dirRecordWithOnPush];
|
||||
bindingRecords = [updateDirWithOnDefaultRecord, updateDirWithOnPushRecord];
|
||||
}
|
||||
|
||||
if (this._withEvents) {
|
||||
var dirRecordWithOnPush =
|
||||
new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0), changeDetection: ON_PUSH});
|
||||
directiveRecords = [dirRecordWithOnPush];
|
||||
|
||||
directiveRecords = [dirRecordWithDefault, dirRecordWithOnPush];
|
||||
eventRecords =
|
||||
ListWrapper.concat(_createEventRecords("(event)='false'"),
|
||||
_createHostEventRecords("(host-event)='false'", dirRecordWithOnPush))
|
||||
|
||||
@@ -704,29 +704,36 @@ export function main() {
|
||||
});
|
||||
|
||||
describe('marking ON_PUSH detectors as CHECK_ONCE after an update', () => {
|
||||
var checkedDetector;
|
||||
var childDirectiveDetectorRegular;
|
||||
var childDirectiveDetectorOnPush;
|
||||
var directives;
|
||||
|
||||
beforeEach(() => {
|
||||
checkedDetector = _createWithoutHydrate('emptyUsingOnPushStrategy').changeDetector;
|
||||
checkedDetector.hydrate(_DEFAULT_CONTEXT, null, null, null);
|
||||
checkedDetector.mode = CHECKED;
|
||||
childDirectiveDetectorRegular = _createWithoutHydrate('10').changeDetector;
|
||||
childDirectiveDetectorRegular.hydrate(_DEFAULT_CONTEXT, null, null, null);
|
||||
childDirectiveDetectorRegular.mode = CHECK_ALWAYS;
|
||||
|
||||
var targetDirective = new TestData(null);
|
||||
directives = new FakeDirectives([targetDirective], [checkedDetector]);
|
||||
childDirectiveDetectorOnPush =
|
||||
_createWithoutHydrate('emptyUsingOnPushStrategy').changeDetector;
|
||||
childDirectiveDetectorOnPush.hydrate(_DEFAULT_CONTEXT, null, null, null);
|
||||
childDirectiveDetectorOnPush.mode = CHECKED;
|
||||
|
||||
directives =
|
||||
new FakeDirectives([new TestData(null), new TestData(null)],
|
||||
[childDirectiveDetectorRegular, childDirectiveDetectorOnPush]);
|
||||
});
|
||||
|
||||
it('should set the mode to CHECK_ONCE when a binding is updated', () => {
|
||||
var cd = _createWithoutHydrate('onPushRecordsUsingDefaultStrategy').changeDetector;
|
||||
cd.hydrate(_DEFAULT_CONTEXT, null, directives, null);
|
||||
var parentDetector =
|
||||
_createWithoutHydrate('onPushRecordsUsingDefaultStrategy').changeDetector;
|
||||
parentDetector.hydrate(_DEFAULT_CONTEXT, null, directives, null);
|
||||
|
||||
expect(checkedDetector.mode).toEqual(CHECKED);
|
||||
parentDetector.detectChanges();
|
||||
|
||||
// evaluate the record, update the targetDirective, and mark its detector as
|
||||
// CHECK_ONCE
|
||||
cd.detectChanges();
|
||||
// making sure that we only change the status of ON_PUSH components
|
||||
expect(childDirectiveDetectorRegular.mode).toEqual(CHECK_ALWAYS);
|
||||
|
||||
expect(checkedDetector.mode).toEqual(CHECK_ONCE);
|
||||
expect(childDirectiveDetectorOnPush.mode).toEqual(CHECK_ONCE);
|
||||
});
|
||||
|
||||
it('should mark ON_PUSH detectors as CHECK_ONCE after an event', () => {
|
||||
@@ -745,7 +752,7 @@ export function main() {
|
||||
|
||||
cd.handleEvent("host-event", 0, null);
|
||||
|
||||
expect(checkedDetector.mode).toEqual(CHECK_ONCE);
|
||||
expect(childDirectiveDetectorOnPush.mode).toEqual(CHECK_ONCE);
|
||||
});
|
||||
|
||||
if (IS_DART) {
|
||||
|
||||
Reference in New Issue
Block a user