refactor(proto_view_factory): expose data for generating change detectors
Also consolidates metadata handling in `ElementInjector` BREAKING CHANGE: - renames `DirectiveMetadataReader` into `DirectiveResolver` and removes `src/core/compiler/directive_metadata`. Fixes #1712 Fixes #1713
This commit is contained in:
+1
-2
@@ -11,7 +11,6 @@ import {
|
||||
xit,
|
||||
} from 'angular2/test_lib';
|
||||
import {bootstrap} from 'angular2/src/core/application';
|
||||
import {appComponentAnnotatedTypeToken} from 'angular2/src/core/application_tokens';
|
||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
@@ -114,7 +113,7 @@ export function main() {
|
||||
it('should resolve an injector promise and contain bindings', inject([AsyncTestCompleter], (async) => {
|
||||
var refPromise = bootstrap(HelloRootCmp, testBindings);
|
||||
refPromise.then((ref) => {
|
||||
expect(ref.injector.get(appComponentAnnotatedTypeToken).type).toBe(HelloRootCmp);
|
||||
expect(ref.injector.get(HelloRootCmp)).toBeAnInstanceOf(HelloRootCmp);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
+35
-32
@@ -20,7 +20,7 @@ import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||
import {AppProtoView} from 'angular2/src/core/compiler/view';
|
||||
import {ElementBinder} from 'angular2/src/core/compiler/element_binder';
|
||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {Attribute} from 'angular2/src/core/annotations_impl/di';
|
||||
import {View} from 'angular2/src/core/annotations_impl/view';
|
||||
@@ -37,10 +37,10 @@ import {RenderCompiler} from 'angular2/src/render/api';
|
||||
|
||||
export function main() {
|
||||
describe('compiler', function() {
|
||||
var reader, tplResolver, renderCompiler, protoViewFactory, cmpUrlMapper, renderCompileRequests;
|
||||
var directiveResolver, tplResolver, renderCompiler, protoViewFactory, cmpUrlMapper, renderCompileRequests;
|
||||
|
||||
beforeEach(() => {
|
||||
reader = new DirectiveMetadataReader();
|
||||
directiveResolver = new DirectiveResolver();
|
||||
tplResolver = new FakeTemplateResolver();
|
||||
cmpUrlMapper = new RuntimeComponentUrlMapper();
|
||||
renderCompiler = new SpyRenderCompiler();
|
||||
@@ -56,7 +56,7 @@ export function main() {
|
||||
|
||||
protoViewFactory = new FakeProtoViewFactory(protoViewFactoryResults)
|
||||
return new Compiler(
|
||||
reader,
|
||||
directiveResolver,
|
||||
new CompilerCache(),
|
||||
tplResolver,
|
||||
cmpUrlMapper,
|
||||
@@ -70,7 +70,7 @@ export function main() {
|
||||
|
||||
function captureTemplate(template:View):Promise<renderApi.ViewDefinition> {
|
||||
tplResolver.setView(MainComponent, template);
|
||||
var compiler = createCompiler([createRenderProtoView()], [createProtoView()]);
|
||||
var compiler = createCompiler([createRenderProtoView()], [[createProtoView()]]);
|
||||
return compiler.compile(MainComponent).then( (_) => {
|
||||
expect(renderCompileRequests.length).toBe(1);
|
||||
return renderCompileRequests[0];
|
||||
@@ -219,7 +219,7 @@ export function main() {
|
||||
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
|
||||
var renderProtoView = createRenderProtoView();
|
||||
var expectedProtoView = createProtoView();
|
||||
var compiler = createCompiler([renderProtoView], [expectedProtoView]);
|
||||
var compiler = createCompiler([renderProtoView], [[expectedProtoView]]);
|
||||
compiler.compile(MainComponent).then( (_) => {
|
||||
var request = protoViewFactory.requests[0];
|
||||
expect(request[1]).toBe(renderProtoView);
|
||||
@@ -229,7 +229,7 @@ export function main() {
|
||||
|
||||
it('should pass the component binding', inject([AsyncTestCompleter], (async) => {
|
||||
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
|
||||
var compiler = createCompiler([createRenderProtoView()], [createProtoView()]);
|
||||
var compiler = createCompiler([createRenderProtoView()], [[createProtoView()]]);
|
||||
compiler.compile(MainComponent).then( (_) => {
|
||||
var request = protoViewFactory.requests[0];
|
||||
expect(request[0].key.token).toBe(MainComponent);
|
||||
@@ -244,7 +244,7 @@ export function main() {
|
||||
directives: [SomeDirective]
|
||||
})
|
||||
);
|
||||
var compiler = createCompiler([createRenderProtoView()], [createProtoView()]);
|
||||
var compiler = createCompiler([createRenderProtoView()], [[createProtoView()]]);
|
||||
compiler.compile(MainComponent).then( (_) => {
|
||||
var request = protoViewFactory.requests[0];
|
||||
var binding = request[2][0];
|
||||
@@ -257,7 +257,7 @@ export function main() {
|
||||
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
|
||||
var renderProtoView = createRenderProtoView();
|
||||
var expectedProtoView = createProtoView();
|
||||
var compiler = createCompiler([renderProtoView], [expectedProtoView]);
|
||||
var compiler = createCompiler([renderProtoView], [[expectedProtoView]]);
|
||||
compiler.compile(MainComponent).then( (protoViewRef) => {
|
||||
expect(internalProtoView(protoViewRef)).toBe(expectedProtoView);
|
||||
async.done();
|
||||
@@ -270,7 +270,7 @@ export function main() {
|
||||
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
|
||||
tplResolver.setView(NestedComponent, new View({template: '<div></div>'}));
|
||||
var mainProtoView = createProtoView([
|
||||
createComponentElementBinder(reader, NestedComponent)
|
||||
createComponentElementBinder(directiveResolver, NestedComponent)
|
||||
]);
|
||||
var nestedProtoView = createProtoView();
|
||||
var compiler = createCompiler(
|
||||
@@ -278,7 +278,7 @@ export function main() {
|
||||
createRenderProtoView([createRenderComponentElementBinder(0)]),
|
||||
createRenderProtoView()
|
||||
],
|
||||
[mainProtoView, nestedProtoView]
|
||||
[[mainProtoView], [nestedProtoView]]
|
||||
);
|
||||
compiler.compile(MainComponent).then( (protoViewRef) => {
|
||||
expect(internalProtoView(protoViewRef)).toBe(mainProtoView);
|
||||
@@ -294,7 +294,7 @@ export function main() {
|
||||
createViewportElementBinder(null)
|
||||
]);
|
||||
var viewportProtoView = createProtoView([
|
||||
createComponentElementBinder(reader, NestedComponent)
|
||||
createComponentElementBinder(directiveResolver, NestedComponent)
|
||||
]);
|
||||
var nestedProtoView = createProtoView();
|
||||
var compiler = createCompiler(
|
||||
@@ -303,16 +303,15 @@ export function main() {
|
||||
createRenderViewportElementBinder(
|
||||
createRenderProtoView([
|
||||
createRenderComponentElementBinder(0)
|
||||
])
|
||||
], renderApi.ProtoViewDto.EMBEDDED_VIEW_TYPE)
|
||||
)
|
||||
]),
|
||||
createRenderProtoView()
|
||||
],
|
||||
[mainProtoView, viewportProtoView, nestedProtoView]
|
||||
[[mainProtoView, viewportProtoView], [nestedProtoView]]
|
||||
);
|
||||
compiler.compile(MainComponent).then( (protoViewRef) => {
|
||||
expect(internalProtoView(protoViewRef)).toBe(mainProtoView);
|
||||
expect(mainProtoView.elementBinders[0].nestedProtoView).toBe(viewportProtoView);
|
||||
expect(viewportProtoView.elementBinders[0].nestedProtoView).toBe(nestedProtoView);
|
||||
|
||||
async.done();
|
||||
@@ -323,7 +322,7 @@ export function main() {
|
||||
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
|
||||
var renderProtoView = createRenderProtoView();
|
||||
var expectedProtoView = createProtoView();
|
||||
var compiler = createCompiler([renderProtoView], [expectedProtoView]);
|
||||
var compiler = createCompiler([renderProtoView], [[expectedProtoView]]);
|
||||
compiler.compile(MainComponent).then( (protoViewRef) => {
|
||||
expect(internalProtoView(protoViewRef)).toBe(expectedProtoView);
|
||||
return compiler.compile(MainComponent);
|
||||
@@ -337,7 +336,7 @@ export function main() {
|
||||
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
|
||||
var renderProtoViewCompleter = PromiseWrapper.completer();
|
||||
var expectedProtoView = createProtoView();
|
||||
var compiler = createCompiler([renderProtoViewCompleter.promise], [expectedProtoView]);
|
||||
var compiler = createCompiler([renderProtoViewCompleter.promise], [[expectedProtoView]]);
|
||||
renderProtoViewCompleter.resolve(createRenderProtoView());
|
||||
PromiseWrapper.all([
|
||||
compiler.compile(MainComponent),
|
||||
@@ -352,13 +351,13 @@ export function main() {
|
||||
it('should allow recursive components', inject([AsyncTestCompleter], (async) => {
|
||||
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
|
||||
var mainProtoView = createProtoView([
|
||||
createComponentElementBinder(reader, MainComponent)
|
||||
createComponentElementBinder(directiveResolver, MainComponent)
|
||||
]);
|
||||
var compiler = createCompiler(
|
||||
[createRenderProtoView([
|
||||
createRenderComponentElementBinder(0)
|
||||
])],
|
||||
[mainProtoView]
|
||||
[[mainProtoView]]
|
||||
);
|
||||
compiler.compile(MainComponent).then( (protoViewRef) => {
|
||||
expect(internalProtoView(protoViewRef)).toBe(mainProtoView);
|
||||
@@ -370,19 +369,19 @@ export function main() {
|
||||
it('should create host proto views', inject([AsyncTestCompleter], (async) => {
|
||||
renderCompiler.spy('compileHost').andCallFake( (componentId) => {
|
||||
return PromiseWrapper.resolve(
|
||||
createRenderProtoView([createRenderComponentElementBinder(0)])
|
||||
createRenderProtoView([createRenderComponentElementBinder(0)], renderApi.ProtoViewDto.HOST_VIEW_TYPE)
|
||||
);
|
||||
});
|
||||
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
|
||||
var rootProtoView = createProtoView([
|
||||
createComponentElementBinder(reader, MainComponent)
|
||||
createComponentElementBinder(directiveResolver, MainComponent)
|
||||
]);
|
||||
var mainProtoView = createProtoView();
|
||||
var compiler = createCompiler(
|
||||
[
|
||||
createRenderProtoView()
|
||||
],
|
||||
[rootProtoView, mainProtoView]
|
||||
[[rootProtoView], [mainProtoView]]
|
||||
);
|
||||
compiler.compileInHost(MainComponent).then( (protoViewRef) => {
|
||||
expect(internalProtoView(protoViewRef)).toBe(rootProtoView);
|
||||
@@ -400,13 +399,13 @@ export function main() {
|
||||
});
|
||||
}
|
||||
|
||||
function createDirectiveBinding(reader, type) {
|
||||
var meta = reader.read(type);
|
||||
return DirectiveBinding.createFromType(meta.type, meta.annotation);
|
||||
function createDirectiveBinding(directiveResolver, type) {
|
||||
var annotation = directiveResolver.resolve(type);
|
||||
return DirectiveBinding.createFromType(type, annotation);
|
||||
}
|
||||
|
||||
function createProtoView(elementBinders = null) {
|
||||
var pv = new AppProtoView(null, null, null, null, null);
|
||||
var pv = new AppProtoView(null, null, MapWrapper.create());
|
||||
if (isBlank(elementBinders)) {
|
||||
elementBinders = [];
|
||||
}
|
||||
@@ -414,8 +413,8 @@ function createProtoView(elementBinders = null) {
|
||||
return pv;
|
||||
}
|
||||
|
||||
function createComponentElementBinder(reader, type) {
|
||||
var binding = createDirectiveBinding(reader, type);
|
||||
function createComponentElementBinder(directiveResolver, type) {
|
||||
var binding = createDirectiveBinding(directiveResolver, type);
|
||||
return new ElementBinder(
|
||||
0, null, 0,
|
||||
null, binding
|
||||
@@ -431,12 +430,16 @@ function createViewportElementBinder(nestedProtoView) {
|
||||
return elBinder;
|
||||
}
|
||||
|
||||
function createRenderProtoView(elementBinders = null) {
|
||||
function createRenderProtoView(elementBinders = null, type:number = null) {
|
||||
if (isBlank(type)) {
|
||||
type = renderApi.ProtoViewDto.COMPONENT_VIEW_TYPE;
|
||||
}
|
||||
if (isBlank(elementBinders)) {
|
||||
elementBinders = [];
|
||||
}
|
||||
return new renderApi.ProtoViewDto({
|
||||
elementBinders: elementBinders
|
||||
elementBinders: elementBinders,
|
||||
type: type
|
||||
});
|
||||
}
|
||||
|
||||
@@ -549,8 +552,8 @@ class FakeProtoViewFactory extends ProtoViewFactory {
|
||||
this._results = results;
|
||||
}
|
||||
|
||||
createProtoView(parentProtoView, componentBinding:DirectiveBinding, renderProtoView: renderApi.ProtoViewDto,
|
||||
directives:List<DirectiveBinding>):AppProtoView {
|
||||
createAppProtoViews(componentBinding:DirectiveBinding, renderProtoView: renderApi.ProtoViewDto,
|
||||
directives:List<DirectiveBinding>):List<AppProtoView> {
|
||||
ListWrapper.push(this.requests, [componentBinding, renderProtoView, directives]);
|
||||
return ListWrapper.removeAt(this._results, 0);
|
||||
}
|
||||
|
||||
@@ -1,57 +1,29 @@
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {ddescribe, describe, it, iit, expect, beforeEach} from 'angular2/test_lib';
|
||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||
import {Directive, Component} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||
import {Injectable, Injector} from 'angular2/di';
|
||||
|
||||
@Injectable()
|
||||
class SomeInjectable {}
|
||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||
import {Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||
|
||||
@Directive({selector: 'someDirective'})
|
||||
class SomeDirective {}
|
||||
|
||||
@Component({selector: 'someComponent', injectables: [SomeInjectable]})
|
||||
class SomeComponent {}
|
||||
|
||||
class SomeDirectiveWithoutAnnotation {
|
||||
}
|
||||
|
||||
export function main() {
|
||||
describe("DirectiveMetadataReader", () => {
|
||||
describe("DirectiveResolver", () => {
|
||||
var reader;
|
||||
|
||||
beforeEach(() => {
|
||||
reader = new DirectiveMetadataReader();
|
||||
reader = new DirectiveResolver();
|
||||
});
|
||||
|
||||
it('should read out the Directive annotation', () => {
|
||||
var directiveMetadata = reader.read(SomeDirective);
|
||||
expect(directiveMetadata).toEqual(
|
||||
new DirectiveMetadata(SomeDirective, new Directive({selector: 'someDirective'}), null));
|
||||
});
|
||||
|
||||
it('should read out the Component annotation', () => {
|
||||
var m = reader.read(SomeComponent);
|
||||
// For some reason `toEqual` fails to compare ResolvedBinding objects.
|
||||
// Have to decompose and compare.
|
||||
expect(m.type).toEqual(SomeComponent);
|
||||
expect(m.annotation)
|
||||
.toEqual(new Component({selector: 'someComponent', injectables: [SomeInjectable]}));
|
||||
var resolvedList = ListWrapper.reduce(m.resolvedInjectables, function(prev, elem) {
|
||||
if (isPresent(elem)) {
|
||||
ListWrapper.push(prev, elem);
|
||||
}
|
||||
return prev;
|
||||
}, []);
|
||||
expect(resolvedList.length).toBe(1);
|
||||
expect(resolvedList[0].key.token).toBe(SomeInjectable);
|
||||
var directiveMetadata = reader.resolve(SomeDirective);
|
||||
expect(directiveMetadata).toEqual(new Directive({selector: 'someDirective'}));
|
||||
});
|
||||
|
||||
it('should throw if not matching annotation is found', () => {
|
||||
expect(() => {
|
||||
reader.read(SomeDirectiveWithoutAnnotation);
|
||||
reader.resolve(SomeDirectiveWithoutAnnotation);
|
||||
}).toThrowError('No Directive annotation found on SomeDirectiveWithoutAnnotation');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -506,7 +506,7 @@ export function main() {
|
||||
});
|
||||
|
||||
it("should instantiate directives that depend on pre built objects", function () {
|
||||
var protoView = new AppProtoView(null, null, null, null, null);
|
||||
var protoView = new AppProtoView(null, null, null);
|
||||
var inj = injector([NeedsProtoViewRef], null, false, new PreBuiltObjects(null, null, protoView));
|
||||
|
||||
expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView));
|
||||
@@ -800,7 +800,7 @@ export function main() {
|
||||
});
|
||||
|
||||
it("should inject ProtoViewRef", function () {
|
||||
var protoView = new AppProtoView(null, null, null, null, null);
|
||||
var protoView = new AppProtoView(null, null, null);
|
||||
var inj = injector([NeedsProtoViewRef], null, false, new PreBuiltObjects(null, null, protoView));
|
||||
|
||||
expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView));
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
import {
|
||||
AsyncTestCompleter,
|
||||
beforeEach,
|
||||
xdescribe,
|
||||
ddescribe,
|
||||
describe,
|
||||
el,
|
||||
expect,
|
||||
iit,
|
||||
inject,
|
||||
IS_DARTIUM,
|
||||
it,
|
||||
SpyObject, proxy
|
||||
} from 'angular2/test_lib';
|
||||
|
||||
import {isBlank} from 'angular2/src/facade/lang';
|
||||
import {MapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import {ChangeDetection, ChangeDetectorDefinition} from 'angular2/change_detection';
|
||||
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
|
||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||
import {DirectiveBinding} from 'angular2/src/core/compiler/element_injector';
|
||||
import * as renderApi from 'angular2/src/render/api';
|
||||
|
||||
export function main() {
|
||||
// TODO(tbosch): add missing tests
|
||||
|
||||
describe('ProtoViewFactory', () => {
|
||||
var changeDetection;
|
||||
var protoViewFactory;
|
||||
var directiveResolver;
|
||||
|
||||
beforeEach( () => {
|
||||
directiveResolver = new DirectiveResolver();
|
||||
changeDetection = new ChangeDetectionSpy();
|
||||
protoViewFactory = new ProtoViewFactory(changeDetection);
|
||||
});
|
||||
|
||||
function bindDirective(type) {
|
||||
return DirectiveBinding.createFromType(type, directiveResolver.resolve(type));
|
||||
}
|
||||
|
||||
describe('getChangeDetectorDefinitions', () => {
|
||||
|
||||
it('should create a ChangeDetectorDefinition for the root render proto view', () => {
|
||||
var renderPv = createRenderProtoView();
|
||||
var defs = protoViewFactory.getChangeDetectorDefinitions(bindDirective(MainComponent).metadata,
|
||||
renderPv, []);
|
||||
expect(defs.length).toBe(1);
|
||||
expect(defs[0].id).toEqual('MainComponent_comp_0');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('createAppProtoViews', () => {
|
||||
|
||||
it('should create an AppProtoView for the root render proto view', () => {
|
||||
var renderPv = createRenderProtoView();
|
||||
var pvs = protoViewFactory.createAppProtoViews(bindDirective(MainComponent),
|
||||
renderPv, []);
|
||||
expect(pvs.length).toBe(1);
|
||||
expect(pvs[0].render).toBe(renderPv.render);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function createRenderProtoView(elementBinders = null, type:number = null) {
|
||||
if (isBlank(type)) {
|
||||
type = renderApi.ProtoViewDto.COMPONENT_VIEW_TYPE;
|
||||
}
|
||||
if (isBlank(elementBinders)) {
|
||||
elementBinders = [];
|
||||
}
|
||||
return new renderApi.ProtoViewDto({
|
||||
elementBinders: elementBinders,
|
||||
type: type,
|
||||
variableBindings: MapWrapper.create()
|
||||
});
|
||||
}
|
||||
|
||||
function createRenderComponentElementBinder(directiveIndex) {
|
||||
return new renderApi.ElementBinder({
|
||||
directives: [new renderApi.DirectiveBinder({
|
||||
directiveIndex: directiveIndex
|
||||
})]
|
||||
});
|
||||
}
|
||||
|
||||
function createRenderViewportElementBinder(nestedProtoView) {
|
||||
return new renderApi.ElementBinder({
|
||||
nestedProtoView: nestedProtoView
|
||||
});
|
||||
}
|
||||
|
||||
@proxy
|
||||
@IMPLEMENTS(ChangeDetection)
|
||||
class ChangeDetectionSpy extends SpyObject {
|
||||
constructor(){super(ChangeDetection);}
|
||||
noSuchMethod(m){return super.noSuchMethod(m)}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'main-comp'
|
||||
})
|
||||
class MainComponent {}
|
||||
@@ -37,7 +37,7 @@ export function main() {
|
||||
}
|
||||
|
||||
function createProtoView() {
|
||||
return new AppProtoView(null, null, null, null, null);
|
||||
return new AppProtoView(null, null, null);
|
||||
}
|
||||
|
||||
function createView() {
|
||||
|
||||
@@ -24,7 +24,7 @@ import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
||||
import {Renderer, RenderViewRef, RenderProtoViewRef, RenderViewContainerRef} from 'angular2/src/render/api';
|
||||
import {ElementBinder} from 'angular2/src/core/compiler/element_binder';
|
||||
import {DirectiveBinding, ElementInjector} from 'angular2/src/core/compiler/element_injector';
|
||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||
import {Component} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
||||
import {AppViewManagerUtils} from 'angular2/src/core/compiler/view_manager_utils';
|
||||
@@ -38,7 +38,7 @@ export function main() {
|
||||
var utils;
|
||||
var viewPool;
|
||||
var manager;
|
||||
var reader;
|
||||
var directiveResolver;
|
||||
var createdViews;
|
||||
var createdRenderViews;
|
||||
|
||||
@@ -55,8 +55,8 @@ export function main() {
|
||||
}
|
||||
|
||||
function createDirectiveBinding(type) {
|
||||
var meta = reader.read(type);
|
||||
return DirectiveBinding.createFromType(meta.type, meta.annotation);
|
||||
var annotation = directiveResolver.resolve(type);
|
||||
return DirectiveBinding.createFromType(type, annotation);
|
||||
}
|
||||
|
||||
function createEmptyElBinder() {
|
||||
@@ -80,7 +80,7 @@ export function main() {
|
||||
staticChildComponentCount++;
|
||||
}
|
||||
}
|
||||
var res = new AppProtoView(new MockProtoViewRef(staticChildComponentCount), null, null, null, null);
|
||||
var res = new AppProtoView(new MockProtoViewRef(staticChildComponentCount), null, null);
|
||||
res.elementBinders = binders;
|
||||
return res;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ export function main() {
|
||||
}
|
||||
|
||||
beforeEach( () => {
|
||||
reader = new DirectiveMetadataReader();
|
||||
directiveResolver = new DirectiveResolver();
|
||||
renderer = new SpyRenderer();
|
||||
utils = new SpyAppViewManagerUtils();
|
||||
viewPool = new SpyAppViewPool();
|
||||
|
||||
@@ -24,7 +24,7 @@ import {AppProtoView, AppView} from 'angular2/src/core/compiler/view';
|
||||
import {ChangeDetector} from 'angular2/change_detection';
|
||||
import {ElementBinder} from 'angular2/src/core/compiler/element_binder';
|
||||
import {DirectiveBinding, ElementInjector, PreBuiltObjects} from 'angular2/src/core/compiler/element_injector';
|
||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||
import {Component} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {AppViewManagerUtils} from 'angular2/src/core/compiler/view_manager_utils';
|
||||
|
||||
@@ -34,7 +34,7 @@ export function main() {
|
||||
|
||||
describe('AppViewManagerUtils', () => {
|
||||
|
||||
var metadataReader;
|
||||
var directiveResolver;
|
||||
var utils;
|
||||
|
||||
function createInjector() {
|
||||
@@ -42,8 +42,8 @@ export function main() {
|
||||
}
|
||||
|
||||
function createDirectiveBinding(type) {
|
||||
var meta = metadataReader.read(type);
|
||||
return DirectiveBinding.createFromType(meta.type, meta.annotation);
|
||||
var annotation = directiveResolver.resolve(type);
|
||||
return DirectiveBinding.createFromType(type, annotation);
|
||||
}
|
||||
|
||||
function createEmptyElBinder() {
|
||||
@@ -61,7 +61,7 @@ export function main() {
|
||||
if (isBlank(binders)) {
|
||||
binders = [];
|
||||
}
|
||||
var res = new AppProtoView(null, null, null, null, null);
|
||||
var res = new AppProtoView(null, null, null);
|
||||
res.elementBinders = binders;
|
||||
return res;
|
||||
}
|
||||
@@ -100,8 +100,8 @@ export function main() {
|
||||
}
|
||||
|
||||
beforeEach( () => {
|
||||
metadataReader = new DirectiveMetadataReader();
|
||||
utils = new AppViewManagerUtils(metadataReader);
|
||||
directiveResolver = new DirectiveResolver();
|
||||
utils = new AppViewManagerUtils(directiveResolver);
|
||||
});
|
||||
|
||||
describe('hydrateDynamicComponentInElementInjector', () => {
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ export function main() {
|
||||
}
|
||||
|
||||
function createProtoView() {
|
||||
return new AppProtoView(null, null, null, null, null);
|
||||
return new AppProtoView(null, null, null);
|
||||
}
|
||||
|
||||
function createView(pv) {
|
||||
|
||||
+123
-90
@@ -41,99 +41,126 @@ export function runCompilerCommonTests() {
|
||||
return new DomCompiler(mockStepFactory, tplLoader);
|
||||
}
|
||||
|
||||
it('should run the steps and build the AppProtoView of the root element', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler((parent, current, control) => {
|
||||
current.inheritedProtoView.bindVariable('b', 'a');
|
||||
});
|
||||
compiler.compile(new ViewDefinition({
|
||||
componentId: 'someComponent',
|
||||
template: '<div></div>'
|
||||
})).then( (protoView) => {
|
||||
expect(protoView.variableBindings).toEqual(MapWrapper.createFromStringMap({
|
||||
'a': 'b'
|
||||
}));
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
describe('compile', () => {
|
||||
|
||||
it('should run the steps and build the proto view', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler((parent, current, control) => {
|
||||
current.inheritedProtoView.bindVariable('b', 'a');
|
||||
});
|
||||
|
||||
var dirMetadata = new DirectiveMetadata({id: 'id', selector: 'CUSTOM', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||
compiler.compileHost(dirMetadata).then( (protoView) => {
|
||||
expect(DOM.tagName(resolveInternalDomProtoView(protoView.render).element)).toEqual('CUSTOM')
|
||||
expect(mockStepFactory.viewDef.directives).toEqual([dirMetadata]);
|
||||
expect(protoView.variableBindings).toEqual(MapWrapper.createFromStringMap({
|
||||
'a': 'b'
|
||||
}));
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should use the inline template and compile in sync', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler(EMPTY_STEP);
|
||||
compiler.compile(new ViewDefinition({
|
||||
componentId: 'someId',
|
||||
template: 'inline component'
|
||||
})).then( (protoView) => {
|
||||
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element)).toEqual('inline component');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should load url templates', inject([AsyncTestCompleter], (async) => {
|
||||
var urlData = MapWrapper.createFromStringMap({
|
||||
'someUrl': 'url component'
|
||||
});
|
||||
var compiler = createCompiler(EMPTY_STEP, urlData);
|
||||
compiler.compile(new ViewDefinition({
|
||||
componentId: 'someId',
|
||||
absUrl: 'someUrl'
|
||||
})).then( (protoView) => {
|
||||
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element)).toEqual('url component');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should report loading errors', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler(EMPTY_STEP, MapWrapper.create());
|
||||
PromiseWrapper.catchError(compiler.compile(new ViewDefinition({
|
||||
componentId: 'someId',
|
||||
absUrl: 'someUrl'
|
||||
})), (e) => {
|
||||
expect(e.message).toContain(`Failed to load the template "someId"`);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should wait for async subtasks to be resolved', inject([AsyncTestCompleter], (async) => {
|
||||
var subTasksCompleted = false;
|
||||
|
||||
var completer = PromiseWrapper.completer();
|
||||
|
||||
var compiler = createCompiler( (parent, current, control) => {
|
||||
ListWrapper.push(mockStepFactory.subTaskPromises, completer.promise.then((_) => {
|
||||
subTasksCompleted = true;
|
||||
}));
|
||||
});
|
||||
|
||||
// It should always return a Promise because the subtask is async
|
||||
var pvPromise = compiler.compile(new ViewDefinition({
|
||||
componentId: 'someId',
|
||||
template: 'some component'
|
||||
it('should run the steps and build the AppProtoView of the root element', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler((parent, current, control) => {
|
||||
current.inheritedProtoView.bindVariable('b', 'a');
|
||||
});
|
||||
compiler.compile(new ViewDefinition({
|
||||
componentId: 'someComponent',
|
||||
template: '<div></div>'
|
||||
})).then( (protoView) => {
|
||||
expect(protoView.variableBindings).toEqual(MapWrapper.createFromStringMap({
|
||||
'a': 'b'
|
||||
}));
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
expect(pvPromise).toBePromise();
|
||||
expect(subTasksCompleted).toEqual(false);
|
||||
|
||||
// The Promise should resolve after the subtask is ready
|
||||
completer.resolve(null);
|
||||
pvPromise.then((protoView) => {
|
||||
expect(subTasksCompleted).toEqual(true);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
it('should run the steps and build the proto view', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler((parent, current, control) => {
|
||||
current.inheritedProtoView.bindVariable('b', 'a');
|
||||
});
|
||||
|
||||
var dirMetadata = new DirectiveMetadata({id: 'id', selector: 'CUSTOM', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||
compiler.compileHost(dirMetadata).then( (protoView) => {
|
||||
expect(DOM.tagName(resolveInternalDomProtoView(protoView.render).element)).toEqual('CUSTOM')
|
||||
expect(mockStepFactory.viewDef.directives).toEqual([dirMetadata]);
|
||||
expect(protoView.variableBindings).toEqual(MapWrapper.createFromStringMap({
|
||||
'a': 'b'
|
||||
}));
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should use the inline template and compile in sync', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler(EMPTY_STEP);
|
||||
compiler.compile(new ViewDefinition({
|
||||
componentId: 'someId',
|
||||
template: 'inline component'
|
||||
})).then( (protoView) => {
|
||||
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element)).toEqual('inline component');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should load url templates', inject([AsyncTestCompleter], (async) => {
|
||||
var urlData = MapWrapper.createFromStringMap({
|
||||
'someUrl': 'url component'
|
||||
});
|
||||
var compiler = createCompiler(EMPTY_STEP, urlData);
|
||||
compiler.compile(new ViewDefinition({
|
||||
componentId: 'someId',
|
||||
absUrl: 'someUrl'
|
||||
})).then( (protoView) => {
|
||||
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element)).toEqual('url component');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should report loading errors', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler(EMPTY_STEP, MapWrapper.create());
|
||||
PromiseWrapper.catchError(compiler.compile(new ViewDefinition({
|
||||
componentId: 'someId',
|
||||
absUrl: 'someUrl'
|
||||
})), (e) => {
|
||||
expect(e.message).toContain(`Failed to load the template "someId"`);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should wait for async subtasks to be resolved', inject([AsyncTestCompleter], (async) => {
|
||||
var subTasksCompleted = false;
|
||||
|
||||
var completer = PromiseWrapper.completer();
|
||||
|
||||
var compiler = createCompiler( (parent, current, control) => {
|
||||
ListWrapper.push(mockStepFactory.subTaskPromises, completer.promise.then((_) => {
|
||||
subTasksCompleted = true;
|
||||
}));
|
||||
});
|
||||
|
||||
// It should always return a Promise because the subtask is async
|
||||
var pvPromise = compiler.compile(new ViewDefinition({
|
||||
componentId: 'someId',
|
||||
template: 'some component'
|
||||
}));
|
||||
expect(pvPromise).toBePromise();
|
||||
expect(subTasksCompleted).toEqual(false);
|
||||
|
||||
// The Promise should resolve after the subtask is ready
|
||||
completer.resolve(null);
|
||||
pvPromise.then((protoView) => {
|
||||
expect(subTasksCompleted).toEqual(true);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should return ProtoViews of type COMPONENT_VIEW_TYPE', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler(EMPTY_STEP);
|
||||
compiler.compile(new ViewDefinition({
|
||||
componentId: 'someId',
|
||||
template: 'inline component'
|
||||
})).then( (protoView) => {
|
||||
expect(protoView.type).toEqual(ProtoViewDto.COMPONENT_VIEW_TYPE);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('compileHost', () => {
|
||||
|
||||
it('should return ProtoViews of type HOST_VIEW_TYPE', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler = createCompiler(EMPTY_STEP);
|
||||
compiler.compileHost(someComponent).then( (protoView) => {
|
||||
expect(protoView.type).toEqual(ProtoViewDto.HOST_VIEW_TYPE);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -195,3 +222,9 @@ class FakeTemplateLoader extends TemplateLoader {
|
||||
return PromiseWrapper.reject('Load failed');
|
||||
}
|
||||
}
|
||||
|
||||
var someComponent = new DirectiveMetadata({
|
||||
selector: 'some-comp',
|
||||
id: 'someComponent',
|
||||
type: DirectiveMetadata.COMPONENT_TYPE
|
||||
});
|
||||
|
||||
@@ -204,6 +204,14 @@ export function main() {
|
||||
);
|
||||
}).toThrowError(new RegExp('Only one component directive is allowed per element' ));
|
||||
});
|
||||
|
||||
it('should sort the directives and store the component as the first directive', () => {
|
||||
var results = process(
|
||||
el('<some-comp some-decor></some-comp>')
|
||||
);
|
||||
expect(annotatedDirectives[results[0].directives[0].directiveIndex].id).toEqual('someComponent');
|
||||
expect(annotatedDirectives[results[0].directives[1].directiveIndex].id).toEqual('someDirective');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -239,6 +247,7 @@ var someComponent2 = new DirectiveMetadata({
|
||||
|
||||
var someDirective = new DirectiveMetadata({
|
||||
selector: '[some-decor]',
|
||||
id: 'someDirective',
|
||||
type: DirectiveMetadata.DIRECTIVE_TYPE
|
||||
});
|
||||
|
||||
@@ -303,4 +312,4 @@ var componentWithNonElementSelector = new DirectiveMetadata({
|
||||
id: 'componentWithNonElementSelector',
|
||||
selector: '[attr]',
|
||||
type: DirectiveMetadata.COMPONENT_TYPE
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step'
|
||||
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
||||
|
||||
import {ProtoViewBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
||||
import {ProtoViewDto} from 'angular2/src/render/api';
|
||||
|
||||
export function main() {
|
||||
describe('compile_pipeline', () => {
|
||||
@@ -39,7 +40,7 @@ export function main() {
|
||||
var element = el('<div><div><span viewroot><span></span></span></div></div>');
|
||||
var pipeline = new CompilePipeline([new MockStep((parent, current, control) => {
|
||||
if (isPresent(DOM.getAttribute(current.element, 'viewroot'))) {
|
||||
current.inheritedProtoView = new ProtoViewBuilder(current.element);
|
||||
current.inheritedProtoView = new ProtoViewBuilder(current.element, ProtoViewDto.EMBEDDED_VIEW_TYPE);
|
||||
}
|
||||
})]);
|
||||
var results = pipeline.process(element);
|
||||
|
||||
@@ -3,6 +3,7 @@ import {MapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import {ViewSplitter} from 'angular2/src/render/dom/compiler/view_splitter';
|
||||
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
|
||||
import {ProtoViewDto} from 'angular2/src/render/api';
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
|
||||
import {Lexer, Parser} from 'angular2/change_detection';
|
||||
@@ -56,6 +57,7 @@ export function main() {
|
||||
var results = createPipeline().process(rootElement);
|
||||
expect(results[2].inheritedProtoView).not.toBe(null);
|
||||
expect(results[2].inheritedProtoView).toBe(results[1].inheritedElementBinder.nestedProtoView);
|
||||
expect(results[2].inheritedProtoView.type).toBe(ProtoViewDto.EMBEDDED_VIEW_TYPE);
|
||||
expect(DOM.getOuterHTML(results[2].inheritedProtoView.rootElement)).toEqual('<template>a</template>');
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
import {SpyLocation} from 'angular2/src/mock/location_mock';
|
||||
import {Location} from 'angular2/src/router/location';
|
||||
import {RouteRegistry} from 'angular2/src/router/route_registry';
|
||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||
|
||||
var teamCmpCount;
|
||||
|
||||
@@ -41,7 +41,7 @@ export function main() {
|
||||
beforeEachBindings(() => [
|
||||
Pipeline,
|
||||
RouteRegistry,
|
||||
DirectiveMetadataReader,
|
||||
DirectiveResolver,
|
||||
bind(Location).toClass(SpyLocation),
|
||||
bind(Router).toFactory((registry, pipeline, location) => {
|
||||
return new RootRouter(registry, pipeline, location, MyComp);
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ import {SpyLocation} from 'angular2/src/mock/location_mock'
|
||||
import {Location} from 'angular2/src/router/location';
|
||||
|
||||
import {RouteRegistry} from 'angular2/src/router/route_registry';
|
||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||
|
||||
import {bind} from 'angular2/di';
|
||||
|
||||
@@ -28,7 +28,7 @@ export function main() {
|
||||
beforeEachBindings(() => [
|
||||
Pipeline,
|
||||
RouteRegistry,
|
||||
DirectiveMetadataReader,
|
||||
DirectiveResolver,
|
||||
bind(Location).toClass(SpyLocation),
|
||||
bind(Router).toFactory((registry, pipeline, location) => {
|
||||
return new RootRouter(registry, pipeline, location, AppCmp);
|
||||
|
||||
Reference in New Issue
Block a user