feat(change_detection): added changeDetection to Component

This commit is contained in:
vsavkin
2015-03-30 16:54:10 -07:00
parent a11f683e7b
commit 514ba54282
20 changed files with 210 additions and 194 deletions
+3 -3
View File
@@ -18,7 +18,7 @@ import {PromiseWrapper} from 'angular2/src/facade/async';
import {Injector, bind} from 'angular2/di';
import {Lexer, Parser, dynamicChangeDetection,
DynamicChangeDetection, Pipe, PipeRegistry, BindingPropagationConfig} from 'angular2/change_detection';
DynamicChangeDetection, Pipe, PipeRegistry, BindingPropagationConfig, ON_PUSH} from 'angular2/change_detection';
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
@@ -723,7 +723,8 @@ class MyDir {
selector: 'push-cmp',
bind: {
'prop': 'prop'
}
},
changeDetection:ON_PUSH
})
@Template({inline: '{{field}}'})
class PushBasedComp {
@@ -734,7 +735,6 @@ class PushBasedComp {
constructor(bpc:BindingPropagationConfig) {
this.numberOfChecks = 0;
this.bpc = bpc;
bpc.shouldBePropagated();
}
get field(){
@@ -71,7 +71,7 @@ export function main() {
current.isViewRoot = true;
current.inheritedProtoView = new ProtoView(
current.element,
new DynamicProtoChangeDetector(normalizeBlank(registry)),
new DynamicProtoChangeDetector(normalizeBlank(registry), null),
new NativeShadowDomStrategy(null));
} else if (isPresent(parent)) {
current.inheritedProtoView = parent.inheritedProtoView;
@@ -467,7 +467,7 @@ export function main() {
var results = pipeline.process(el('<div viewroot prop-binding directives></div>'));
var pv = results[0].inheritedProtoView;
results[0].inheritedElementBinder.nestedProtoView = new ProtoView(
el('<div></div>'), new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null));
el('<div></div>'), new DynamicProtoChangeDetector(null, null), new NativeShadowDomStrategy(null));
instantiateView(pv);
evalContext.prop1 = 'a';
@@ -503,7 +503,7 @@ export function main() {
var results = pipeline.process(el('<div viewroot prop-binding directives></div>'));
var pv = results[0].inheritedProtoView;
results[0].inheritedElementBinder.nestedProtoView = new ProtoView(
el('<div></div>'), new DynamicProtoChangeDetector(registry), new NativeShadowDomStrategy(null));
el('<div></div>'), new DynamicProtoChangeDetector(registry, null), new NativeShadowDomStrategy(null));
instantiateView(pv);
evalContext.prop1 = 'a';
@@ -4,16 +4,20 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
import {dynamicChangeDetection} from 'angular2/change_detection';
import {ElementBinder} from 'angular2/src/core/compiler/element_binder';
import {ProtoViewBuilder} from 'angular2/src/core/compiler/pipeline/proto_view_builder';
import {Component} from 'angular2/annotations';
import {CompilePipeline} from 'angular2/src/core/compiler/pipeline/compile_pipeline';
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step'
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
import {MapWrapper} from 'angular2/src/facade/collection';
export function main() {
describe('ProtoViewBuilder', () => {
function createPipeline(variableBindings = null) {
var component = new DirectiveMetadata(null, new Component());
return new CompilePipeline([new MockStep((parent, current, control) => {
if (isPresent(DOM.getAttribute(current.element, 'viewroot'))) {
current.isViewRoot = true;
@@ -22,7 +26,7 @@ export function main() {
current.variableBindings = MapWrapper.createFromStringMap(variableBindings);
}
current.inheritedElementBinder = new ElementBinder(0, null, 0, null, null, null);
}), new ProtoViewBuilder(dynamicChangeDetection, new NativeShadowDomStrategy(null))]);
}), new ProtoViewBuilder(component, dynamicChangeDetection, new NativeShadowDomStrategy(null))]);
}
it('should not create a ProtoView when the isViewRoot flag is not set', () => {
@@ -47,7 +47,7 @@ export function main() {
it('should attach the view nodes to the shadow root', () => {
var host = el('<div></div>');
var nodes = el('<div>view</div>');
var pv = new ProtoView(nodes, new DynamicProtoChangeDetector(null), null);
var pv = new ProtoView(nodes, new DynamicProtoChangeDetector(null, null), null);
var view = pv.instantiate(null, null);
strategy.attachTemplate(host, view);
@@ -89,7 +89,7 @@ export function main() {
it('should attach the view nodes as child of the host element', () => {
var host = el('<div><span>original content</span></div>');
var nodes = el('<div>view</div>');
var pv = new ProtoView(nodes, new DynamicProtoChangeDetector(null), null);
var pv = new ProtoView(nodes, new DynamicProtoChangeDetector(null, null), null);
var view = pv.instantiate(null, null);
strategy.attachTemplate(host, view);
@@ -224,7 +224,7 @@ export function main() {
it('should attach the view nodes as child of the host element', () => {
var host = el('<div><span>original content</span></div>');
var nodes = el('<div>view</div>');
var pv = new ProtoView(nodes, new DynamicProtoChangeDetector(null), null);
var pv = new ProtoView(nodes, new DynamicProtoChangeDetector(null, null), null);
var view = pv.instantiate(null, null);
strategy.attachTemplate(host, view);
+3 -3
View File
@@ -11,7 +11,7 @@ import {DynamicProtoChangeDetector, ChangeDetector, Lexer, Parser} from 'angular
function createView(nodes) {
var view = new View(null, nodes, MapWrapper.create());
var cd = new DynamicProtoChangeDetector(null).instantiate(view, [], null, []);
var cd = new DynamicProtoChangeDetector(null, null).instantiate(view, [], null, []);
view.init(cd, [], [], [], [], [], [], [], [], []);
return view;
}
@@ -71,7 +71,7 @@ export function main() {
dom = el(`<div><stuff></stuff><div insert-after-me></div><stuff></stuff></div>`);
var insertionElement = dom.childNodes[1];
parentView = createView([dom.childNodes[0]]);
protoView = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector(null),
protoView = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector(null, null),
new NativeShadowDomStrategy(null));
elementInjector = new ElementInjector(null, null, null);
viewContainer = new ViewContainer(parentView, insertionElement, protoView, elementInjector,
@@ -217,7 +217,7 @@ export function main() {
viewContainer.hydrate(new Injector([]), null, null);
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null));
new DynamicProtoChangeDetector(null, null), new NativeShadowDomStrategy(null));
pv.bindElement(null, 0, new ProtoElementInjector(null, 1, [SomeDirective]));
pv.bindTextNode(0, parser.parseBinding('foo', null));
fancyView = pv.instantiate(null, null);
+37 -37
View File
@@ -63,7 +63,7 @@ export function main() {
describe('instantiated from protoView', () => {
var view;
beforeEach(() => {
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector(null), null);
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector(null, null), null);
view = pv.instantiate(null, null);
});
@@ -90,7 +90,7 @@ export function main() {
});
it('should use the view pool to reuse views', () => {
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector(null), null);
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector(null, null), null);
var fakeView = new FakeView();
pv.returnToPool(fakeView);
@@ -101,7 +101,7 @@ export function main() {
describe('with locals', function() {
var view;
beforeEach(() => {
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector(null), null);
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector(null, null), null);
pv.bindVariable('context-foo', 'template-foo');
view = createView(pv);
});
@@ -138,7 +138,7 @@ export function main() {
it('should collect the root node in the ProtoView element', () => {
var pv = new ProtoView(templateAwareCreateElement('<div id="1"></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
var view = pv.instantiate(null, null);
view.hydrate(null, null, null, null, null);
expect(view.nodes.length).toBe(1);
@@ -149,7 +149,7 @@ export function main() {
it('should collect property bindings on the root element if it has the ng-binding class', () => {
var pv = new ProtoView(templateAwareCreateElement('<div [prop]="a" class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, null);
pv.bindElementProperty(parser.parseBinding('a', null), 'prop', reflector.setter('prop'));
@@ -161,7 +161,7 @@ export function main() {
it('should collect property bindings on child elements with ng-binding class', () => {
var pv = new ProtoView(templateAwareCreateElement('<div><span></span><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, null);
pv.bindElementProperty(parser.parseBinding('b', null), 'a', reflector.setter('a'));
@@ -177,7 +177,7 @@ export function main() {
it('should collect text nodes under the root element', () => {
var pv = new ProtoView(templateAwareCreateElement('<div class="ng-binding">{{}}<span></span>{{}}</div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, null);
pv.bindTextNode(0, parser.parseBinding('a', null));
pv.bindTextNode(2, parser.parseBinding('b', null));
@@ -191,7 +191,7 @@ export function main() {
it('should collect text nodes with bindings on child elements with ng-binding class', () => {
var pv = new ProtoView(templateAwareCreateElement('<div><span> </span><span class="ng-binding">{{}}</span></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, null);
pv.bindTextNode(0, parser.parseBinding('b', null));
@@ -207,7 +207,7 @@ export function main() {
describe('inplace instantiation', () => {
it('should be supported.', () => {
var template = el('<div></div>');
var pv = new ProtoView(template, new DynamicProtoChangeDetector(null),
var pv = new ProtoView(template, new DynamicProtoChangeDetector(null, null),
new NativeShadowDomStrategy(null));
pv.instantiateInPlace = true;
var view = pv.instantiate(null, null);
@@ -217,7 +217,7 @@ export function main() {
it('should be off by default.', () => {
var template = el('<div></div>')
var pv = new ProtoView(template, new DynamicProtoChangeDetector(null),
var pv = new ProtoView(template, new DynamicProtoChangeDetector(null, null),
new NativeShadowDomStrategy(null))
var view = pv.instantiate(null, null);
view.hydrate(null, null, null, null, null);
@@ -236,7 +236,7 @@ export function main() {
describe('create ElementInjectors', () => {
it('should use the directives of the ProtoElementInjector', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new ProtoElementInjector(null, 1, [SomeDirective]));
var view = pv.instantiate(null, null);
@@ -247,7 +247,7 @@ export function main() {
it('should use the correct parent', () => {
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
pv.bindElement(null, 0, protoParent);
pv.bindElement(null, 0, new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
@@ -261,7 +261,7 @@ export function main() {
it('should not pass the host injector when a parent injector exists', () => {
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
pv.bindElement(null, 0, protoParent);
var testProtoElementInjector = new TestProtoElementInjector(protoParent, 1, [AnotherDirective]);
@@ -277,7 +277,7 @@ export function main() {
it('should pass the host injector when there is no parent injector', () => {
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeDirective]));
var testProtoElementInjector = new TestProtoElementInjector(null, 1, [AnotherDirective]);
pv.bindElement(null, 0, testProtoElementInjector);
@@ -294,7 +294,7 @@ export function main() {
it('should collect a single root element injector', () => {
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
pv.bindElement(null, 0, protoParent);
pv.bindElement(null, 0, new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
@@ -307,7 +307,7 @@ export function main() {
it('should collect multiple root element injectors', () => {
var pv = new ProtoView(el('<div><span class="ng-binding"></span><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new ProtoElementInjector(null, 1, [SomeDirective]));
pv.bindElement(null, 0, new ProtoElementInjector(null, 2, [AnotherDirective]));
@@ -325,7 +325,7 @@ export function main() {
function createComponentWithSubPV(subProtoView) {
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'),
new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null));
new DynamicProtoChangeDetector(null, null), new NativeShadowDomStrategy(null));
var binder = pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeComponent], true));
binder.componentDirective = someComponentDirective;
binder.nestedProtoView = subProtoView;
@@ -340,7 +340,7 @@ export function main() {
}
it('should expose component services to the component', () => {
var subpv = new ProtoView(el('<span></span>'), new DynamicProtoChangeDetector(null), null);
var subpv = new ProtoView(el('<span></span>'), new DynamicProtoChangeDetector(null, null), null);
var pv = createComponentWithSubPV(subpv);
var view = createNestedView(pv);
@@ -353,7 +353,7 @@ export function main() {
() => {
var subpv = new ProtoView(
el('<div dec class="ng-binding">hello shadow dom</div>'),
new DynamicProtoChangeDetector(null),
new DynamicProtoChangeDetector(null, null),
null);
subpv.bindElement(null, 0,
new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
@@ -378,7 +378,7 @@ export function main() {
it('dehydration should dehydrate child component views too', () => {
var subpv = new ProtoView(
el('<div dec class="ng-binding">hello shadow dom</div>'),
new DynamicProtoChangeDetector(null),
new DynamicProtoChangeDetector(null, null),
null);
subpv.bindElement(null, 0,
new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
@@ -395,7 +395,7 @@ export function main() {
it('should create shadow dom (Native Strategy)', () => {
var subpv = new ProtoView(el('<span>hello shadow dom</span>'),
new DynamicProtoChangeDetector(null),
new DynamicProtoChangeDetector(null, null),
null);
var pv = createComponentWithSubPV(subpv);
@@ -406,10 +406,10 @@ export function main() {
it('should emulate shadow dom (Emulated Strategy)', () => {
var subpv = new ProtoView(el('<span>hello shadow dom</span>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'),
new DynamicProtoChangeDetector(null), new EmulatedScopedShadowDomStrategy(null, null, null));
new DynamicProtoChangeDetector(null, null), new EmulatedScopedShadowDomStrategy(null, null, null));
var binder = pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeComponent], true));
binder.componentDirective = new DirectiveMetadataReader().read(SomeComponent);
binder.nestedProtoView = subpv;
@@ -423,9 +423,9 @@ export function main() {
describe('with template views', () => {
function createViewWithViewport() {
var templateProtoView = new ProtoView(
el('<div id="1"></div>'), new DynamicProtoChangeDetector(null), null);
el('<div id="1"></div>'), new DynamicProtoChangeDetector(null, null), null);
var pv = new ProtoView(el('<someTmpl class="ng-binding"></someTmpl>'),
new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null));
new DynamicProtoChangeDetector(null, null), new NativeShadowDomStrategy(null));
var binder = pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeViewport]));
binder.viewportDirective = someViewportDirective;
binder.nestedProtoView = templateProtoView;
@@ -471,7 +471,7 @@ export function main() {
function createProtoView() {
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new TestProtoElementInjector(null, 0, []));
pv.bindEvent('click', parser.parseBinding('callMe($event)', null));
return pv;
@@ -506,7 +506,7 @@ export function main() {
it('should support custom event emitters', () => {
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new TestProtoElementInjector(null, 0, [EventEmitterDirective]));
pv.bindEvent('click', parser.parseBinding('callMe($event)', null));
@@ -527,7 +527,7 @@ export function main() {
it('should bind to directive events', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeDirectiveWithEventHandler]));
pv.bindEvent('click', parser.parseAction('onEvent($event)', null), 0);
view = createView(pv, new EventManager([new DomEventsPlugin()], new FakeVmTurnZone()));
@@ -552,7 +552,7 @@ export function main() {
it('should consume text node changes', () => {
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, null);
pv.bindTextNode(0, parser.parseBinding('foo', null));
createViewAndChangeDetector(pv);
@@ -564,7 +564,7 @@ export function main() {
it('should consume element binding changes', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, null);
pv.bindElementProperty(parser.parseBinding('foo', null), 'id', reflector.setter('id'));
createViewAndChangeDetector(pv);
@@ -576,7 +576,7 @@ export function main() {
it('should consume directive watch expression change', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeDirective]));
pv.bindDirectiveProperty(0, parser.parseBinding('foo', null), 'prop', reflector.setter('prop'));
createViewAndChangeDetector(pv);
@@ -588,7 +588,7 @@ export function main() {
it('should notify a directive about changes after all its properties have been set', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [
DirectiveBinding.createFromType(DirectiveImplementingOnChange,
@@ -608,7 +608,7 @@ export function main() {
it('should provide a map of updated properties using onChange callback', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [
DirectiveBinding.createFromType(DirectiveImplementingOnChange,
@@ -636,7 +636,7 @@ export function main() {
it('should invoke the onAllChangesDone callback', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
new DynamicProtoChangeDetector(null, null), null);
pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [
DirectiveBinding.createFromType(DirectiveImplementingOnAllChangesDone,
@@ -656,13 +656,13 @@ export function main() {
var element, pv;
beforeEach(() => {
element = DOM.createElement('div');
pv = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector(null),
pv = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector(null, null),
new NativeShadowDomStrategy(null));
});
it('should create the root component when instantiated', () => {
var rootProtoView = ProtoView.createRootProtoView(pv, element,
someComponentDirective, new DynamicProtoChangeDetector(null),
someComponentDirective, new DynamicProtoChangeDetector(null, null),
new NativeShadowDomStrategy(null));
var view = rootProtoView.instantiate(null, null);
view.hydrate(new Injector([]), null, null, null, null);
@@ -671,7 +671,7 @@ export function main() {
it('should inject the protoView into the shadowDom', () => {
var rootProtoView = ProtoView.createRootProtoView(pv, element,
someComponentDirective, new DynamicProtoChangeDetector(null),
someComponentDirective, new DynamicProtoChangeDetector(null, null),
new NativeShadowDomStrategy(null));
var view = rootProtoView.instantiate(null, null);
view.hydrate(new Injector([]), null, null, null, null);