refactor(view_compiler): codegen DI and Queries

BREAKING CHANGE:
- Renderer:
  * renderComponent method is removed form `Renderer`, only present on `RootRenderer`
  * Renderer.setDebugInfo is removed. Renderer.createElement / createText / createTemplateAnchor
    now take the DebugInfo directly.
- Query semantics:
  * Queries don't work with dynamically loaded components.
  * e.g. for router-outlet: loaded components can't be queries via @ViewQuery,
    but router-outlet emits an event `activate` now that emits the activated component
- Exception classes and the context inside changed (renamed fields)
- DebugElement.attributes is an Object and not a Map in JS any more
- ChangeDetectorGenConfig was renamed into CompilerConfig
- AppViewManager.createEmbeddedViewInContainer / AppViewManager.createHostViewInContainer
  are removed, use the methods in ViewContainerRef instead
- Change detection order changed:
  * 1. dirty check component inputs
  * 2. dirty check content children
  * 3. update render nodes

Closes #6301
Closes #6567
This commit is contained in:
Tobias Bosch
2016-01-06 14:13:44 -08:00
parent 45f09ba686
commit 2b34c88b69
312 changed files with 14271 additions and 16566 deletions

View File

@ -16,8 +16,8 @@ import {Injector, provide} from 'angular2/core';
import {CONST_EXPR} from 'angular2/src/facade/lang';
import {parseRouterLinkExpression} from 'angular2/src/router/directives/router_link_transform';
import {Unparser} from '../../core/change_detection/parser/unparser';
import {Parser} from 'angular2/src/core/change_detection/parser/parser';
import {Unparser} from '../../compiler/expression_parser/unparser';
import {Parser} from 'angular2/src/compiler/expression_parser/parser';
export function main() {
function check(parser: Parser, input: string, expectedValue: string) {

View File

@ -18,7 +18,7 @@ import {bootstrap} from 'angular2/platform/browser';
import {Component, Directive} from 'angular2/src/core/metadata';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {Console} from 'angular2/src/core/console';
import {provide, ViewChild, AfterViewInit} from 'angular2/core';
import {provide} from 'angular2/core';
import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
import {
RouteConfig,
@ -214,7 +214,7 @@ export function main() {
}));
});
describe('retrieving components loaded via outlet via @ViewChild', () => {
describe('activate event on outlet', () => {
let tcb: TestComponentBuilder = null;
beforeEachProviders(() => [provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppCmp})]);
@ -224,7 +224,7 @@ export function main() {
it('should get a reference and pass data to components loaded inside of outlets',
inject([AsyncTestCompleter], (async) => {
tcb.createAsync(AppWithViewChildren)
tcb.createAsync(AppWithOutletListeners)
.then(fixture => {
let appInstance = fixture.debugElement.componentInstance;
let router = appInstance.router;
@ -272,21 +272,26 @@ class AppCmp {
selector: 'app-cmp',
template: `
Hello routing!
<router-outlet></router-outlet>
<router-outlet name="pony"></router-outlet>`,
<router-outlet (activate)="activateHello($event)"></router-outlet>
<router-outlet (activate)="activateHello2($event)" name="pony"></router-outlet>`,
directives: ROUTER_DIRECTIVES
})
@RouteConfig([
new Route({path: '/rainbow', component: HelloCmp}),
new AuxRoute({name: 'pony', path: 'pony', component: Hello2Cmp})
])
class AppWithViewChildren implements AfterViewInit {
@ViewChild(HelloCmp) helloCmp: HelloCmp;
@ViewChild(Hello2Cmp) hello2Cmp: Hello2Cmp;
class AppWithOutletListeners {
helloCmp: HelloCmp;
hello2Cmp: Hello2Cmp;
constructor(public router: Router, public location: LocationStrategy) {}
ngAfterViewInit() { this.helloCmp.message = 'Ahoy'; }
activateHello(cmp: HelloCmp) {
this.helloCmp = cmp;
this.helloCmp.message = 'Ahoy';
}
activateHello2(cmp: Hello2Cmp) { this.hello2Cmp = cmp; }
}
@Component({

View File

@ -16,7 +16,7 @@ import {
} from 'angular2/testing_internal';
import {provide, Component, Injector, Inject} from 'angular2/core';
import {PromiseWrapper} from 'angular2/src/facade/async';
import {PromiseWrapper, TimerWrapper} from 'angular2/src/facade/async';
import {Router, RouterOutlet, RouterLink, RouteParams, RouteData, Location} from 'angular2/router';
import {
@ -216,6 +216,24 @@ export function main() {
async.done();
});
}));
it('should fire an event for each activated component',
inject([AsyncTestCompleter], (async) => {
compile(tcb, '<router-outlet (activate)="activatedCmp = $event"></router-outlet>')
.then((rtc) => {fixture = rtc})
.then((_) => rtr.config([new Route({path: '/test', component: HelloCmp})]))
.then((_) => rtr.navigateByUrl('/test'))
.then((_) => {
// Note: need a timeout so that all promises are flushed
var completer = PromiseWrapper.completer();
TimerWrapper.setTimeout(() => { completer.resolve(null); }, 0);
return completer.promise;
})
.then((_) => {
expect(fixture.componentInstance.activatedCmp).toBeAnInstanceOf(HelloCmp);
async.done();
});
}));
});
}

View File

@ -22,7 +22,7 @@ import {NumberWrapper} from 'angular2/src/facade/lang';
import {PromiseWrapper} from 'angular2/src/facade/async';
import {ListWrapper} from 'angular2/src/facade/collection';
import {provide, Component, DirectiveResolver} from 'angular2/core';
import {provide, Component} from 'angular2/core';
import {SpyLocation} from 'angular2/src/mock/location_mock';
import {
@ -54,7 +54,6 @@ export function main() {
beforeEachProviders(() => [
RouteRegistry,
DirectiveResolver,
provide(Location, {useClass: SpyLocation}),
provide(ROUTER_PRIMARY_COMPONENT, {useValue: MyComp}),
provide(Router, {useClass: RootRouter}),

View File

@ -23,7 +23,6 @@ import {Router, ROUTER_DIRECTIVES, ROUTER_PRIMARY_COMPONENT} from 'angular2/rout
import {SpyLocation} from 'angular2/src/mock/location_mock';
import {Location} from 'angular2/src/router/location/location';
import {RouteRegistry} from 'angular2/src/router/route_registry';
import {DirectiveResolver} from 'angular2/src/core/linker/directive_resolver';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
export {ComponentFixture} from 'angular2/testing_internal';
@ -39,6 +38,7 @@ export {ComponentFixture} from 'angular2/testing_internal';
})
export class RootCmp {
name: string;
activatedCmp: any;
}
export function compile(tcb: TestComponentBuilder,
@ -48,7 +48,6 @@ export function compile(tcb: TestComponentBuilder,
export var TEST_ROUTER_PROVIDERS = [
RouteRegistry,
DirectiveResolver,
provide(Location, {useClass: SpyLocation}),
provide(ROUTER_PRIMARY_COMPONENT, {useValue: RootCmp}),
provide(Router, {useClass: RootRouter})

View File

@ -27,7 +27,6 @@ import {
Route,
Redirect
} from 'angular2/src/router/route_config/route_config_decorator';
import {DirectiveResolver} from 'angular2/src/core/linker/directive_resolver';
import {provide} from 'angular2/core';
import {RouterOutlet} from 'angular2/src/router/directives/router_outlet';
@ -39,7 +38,6 @@ export function main() {
beforeEachProviders(() => [
RouteRegistry,
DirectiveResolver,
provide(Location, {useClass: SpyLocation}),
provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppCmp}),
provide(Router, {useClass: RootRouter})