feat(change_detection): added support for observable components and directives

This commit is contained in:
vsavkin
2015-08-21 14:45:38 -07:00
parent 85ec34d1d9
commit e8e430e630
11 changed files with 202 additions and 105 deletions
@@ -12,6 +12,7 @@ import {
Parser,
ChangeDetectorGenConfig
} from 'angular2/src/change_detection/change_detection';
import {ON_PUSH_OBSERVE} from 'angular2/src/change_detection/constants';
import {reflector} from 'angular2/src/reflection/reflection';
import {ReflectionCapabilities} from 'angular2/src/reflection/reflection_capabilities';
@@ -106,11 +107,19 @@ export function getDefinition(id: string): TestDefinition {
[_DirectiveUpdating.basicRecords[0]], genConfig);
testDef = new TestDefinition(id, cdDef, null);
} else if (id == "onPushObserve") {
} else if (id == "onPushObserveBinding") {
var records = _createBindingRecords("a");
let cdDef = new ChangeDetectorDefinition(id, "ON_PUSH_OBSERVE", [], records, [], [], genConfig);
let cdDef = new ChangeDetectorDefinition(id, ON_PUSH_OBSERVE, [], records, [], [], genConfig);
testDef = new TestDefinition(id, cdDef, null);
} else if (id == "onPushObserveComponent") {
let cdDef = new ChangeDetectorDefinition(id, ON_PUSH_OBSERVE, [], [], [], [], genConfig);
testDef = new TestDefinition(id, cdDef, null);
} else if (id == "onPushObserveDirective") {
let cdDef = new ChangeDetectorDefinition(id, ON_PUSH_OBSERVE, [], [], [],
[_DirectiveUpdating.recordNoCallbacks], genConfig);
testDef = new TestDefinition(id, cdDef, null);
} else if (id == "updateElementProduction") {
var genConfig = new ChangeDetectorGenConfig(false, false, false);
var records = _createBindingRecords("name");
@@ -118,7 +127,6 @@ export function getDefinition(id: string): TestDefinition {
testDef = new TestDefinition(id, cdDef, null);
}
if (isBlank(testDef)) {
throw `No ChangeDetectorDefinition for ${id} available. Please modify this file if necessary.`;
}
@@ -144,7 +152,12 @@ export function getAllDefinitions(): List<TestDefinition> {
ListWrapper.concat(allDefs, StringMapWrapper.keys(_DirectiveUpdating.availableDefinitions));
allDefs = ListWrapper.concat(allDefs, _availableEventDefinitions);
allDefs = ListWrapper.concat(allDefs, _availableHostEventDefinitions);
allDefs = ListWrapper.concat(allDefs, ["onPushObserve", "updateElementProduction"]);
allDefs = ListWrapper.concat(allDefs, [
"onPushObserveBinding",
"onPushObserveComponent",
"onPushObserveDirective",
"updateElementProduction"
]);
return ListWrapper.map(allDefs, (id) => getDefinition(id));
}
@@ -781,64 +781,100 @@ export function main() {
});
if (IS_DART) {
it('should mark ON_PUSH_OBSERVE detectors as CHECK_ONCE when an observable fires an event',
fakeAsync(() => {
var context = new TestDirective();
context.a = createObservableModel();
describe('ON_PUSH_OBSERVE', () => {
it('should mark ON_PUSH_OBSERVE detectors as CHECK_ONCE when an observable fires an event',
fakeAsync(() => {
var context = new TestDirective();
context.a = createObservableModel();
var cd = _createWithoutHydrate('onPushObserve').changeDetector;
cd.hydrate(context, null, directives, null);
cd.detectChanges();
var cd = _createWithoutHydrate('onPushObserveBinding').changeDetector;
cd.hydrate(context, null, directives, null);
cd.detectChanges();
expect(cd.mode).toEqual(CHECKED);
expect(cd.mode).toEqual(CHECKED);
context.a.pushUpdate();
tick();
context.a.pushUpdate();
tick();
expect(cd.mode).toEqual(CHECK_ONCE);
}));
expect(cd.mode).toEqual(CHECK_ONCE);
}));
it('should unsubscribe from an old observable when an object changes', fakeAsync(() => {
var originalModel = createObservableModel();
var context = new TestDirective();
context.a = originalModel;
it('should mark ON_PUSH_OBSERVE detectors as CHECK_ONCE when an observable context fires an event',
fakeAsync(() => {
var context = createObservableModel();
var cd = _createWithoutHydrate('onPushObserve').changeDetector;
cd.hydrate(context, null, directives, null);
cd.detectChanges();
var cd = _createWithoutHydrate('onPushObserveComponent').changeDetector;
cd.hydrate(context, null, directives, null);
cd.detectChanges();
context.a = createObservableModel();
cd.mode = CHECK_ONCE;
cd.detectChanges();
expect(cd.mode).toEqual(CHECKED);
// Updating this model will not reenable the detector. This model is not longer
// used.
originalModel.pushUpdate();
tick();
expect(cd.mode).toEqual(CHECKED);
}));
context.pushUpdate();
tick();
it('should unsubscribe from observables when dehydrating', fakeAsync(() => {
var originalModel = createObservableModel();
var context = new TestDirective();
context.a = originalModel;
expect(cd.mode).toEqual(CHECK_ONCE);
}));
var cd = _createWithoutHydrate('onPushObserve').changeDetector;
cd.hydrate(context, null, directives, null);
cd.detectChanges();
it('should mark ON_PUSH_OBSERVE detectors as CHECK_ONCE when an observable directive fires an event',
fakeAsync(() => {
var dir = createObservableModel();
var directives = new FakeDirectives([dir], []);
cd.dehydrate();
var cd = _createWithoutHydrate('onPushObserveDirective').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, directives, null);
cd.detectChanges();
context.a = "not an observable model";
cd.hydrate(context, null, directives, null);
cd.detectChanges();
expect(cd.mode).toEqual(CHECKED);
// Updating this model will not reenable the detector. This model is not longer
// used.
originalModel.pushUpdate();
tick();
expect(cd.mode).toEqual(CHECKED);
}));
dir.pushUpdate();
tick();
expect(cd.mode).toEqual(CHECK_ONCE);
}));
it('should unsubscribe from an old observable when an object changes',
fakeAsync(() => {
var originalModel = createObservableModel();
var context = new TestDirective();
context.a = originalModel;
var cd = _createWithoutHydrate('onPushObserveBinding').changeDetector;
cd.hydrate(context, null, directives, null);
cd.detectChanges();
context.a = createObservableModel();
cd.mode = CHECK_ONCE;
cd.detectChanges();
// Updating this model will not reenable the detector. This model is not longer
// used.
originalModel.pushUpdate();
tick();
expect(cd.mode).toEqual(CHECKED);
}));
it('should unsubscribe from observables when dehydrating', fakeAsync(() => {
var originalModel = createObservableModel();
var context = new TestDirective();
context.a = originalModel;
var cd = _createWithoutHydrate('onPushObserveBinding').changeDetector;
cd.hydrate(context, null, directives, null);
cd.detectChanges();
cd.dehydrate();
context.a = "not an observable model";
cd.hydrate(context, null, directives, null);
cd.detectChanges();
// Updating this model will not reenable the detector. This model is not longer
// used.
originalModel.pushUpdate();
tick();
expect(cd.mode).toEqual(CHECKED);
}));
});
}
});
});
@@ -29,7 +29,7 @@ class _MyComponent_ChangeDetector0
_MyComponent_ChangeDetector0(dispatcher) : super(
"MyComponent_comp_0", dispatcher, 2,
_MyComponent_ChangeDetector0.gen_propertyBindingTargets,
_MyComponent_ChangeDetector0.gen_directiveIndices, 'ALWAYS_CHECK') {
_MyComponent_ChangeDetector0.gen_directiveIndices,null) {
dehydrateDirectives(false);
}