refactor(core): introduce ComponentFactory.

Each compile template now exposes a `<CompName>NgFactory` variable
with an instance of a `ComponentFactory`.
Calling `ComponentFactory.create` returns a `ComponentRef` that can
be used directly.

BREAKING CHANGE:
- `Compiler` is renamed to `ComponentResolver`,
  `Compiler.compileInHost` has been renamed to `ComponentResolver.resolveComponent`.
- `ComponentRef.dispose` is renamed to `ComponentRef.destroy`
- `ViewContainerRef.createHostView` is renamed to `ViewContainerRef.createComponent`
- `ComponentFixture_` has been removed, the class `ComponentFixture`
  can now be created directly as it is no more using private APIs.
This commit is contained in:
Tobias Bosch
2016-04-13 17:05:17 -07:00
parent 41404057cf
commit 0c600cf6e3
66 changed files with 611 additions and 849 deletions

View File

@ -4,6 +4,7 @@ export {TEMPLATE_TRANSFORMS} from 'angular2/src/compiler/template_parser';
export {CompilerConfig, RenderTypes} from './config';
export * from './compile_metadata';
export * from './offline_compiler';
export {RuntimeCompiler} from './runtime_compiler';
export * from 'angular2/src/compiler/url_resolver';
export * from 'angular2/src/compiler/xhr';
@ -20,7 +21,7 @@ import {RuntimeMetadataResolver} from 'angular2/src/compiler/runtime_metadata';
import {StyleCompiler} from 'angular2/src/compiler/style_compiler';
import {ViewCompiler} from 'angular2/src/compiler/view_compiler/view_compiler';
import {CompilerConfig} from './config';
import {Compiler} from 'angular2/src/core/linker/compiler';
import {ComponentResolver} from 'angular2/src/core/linker/component_resolver';
import {RuntimeCompiler} from 'angular2/src/compiler/runtime_compiler';
import {ElementSchemaRegistry} from 'angular2/src/compiler/schema/element_schema_registry';
import {DomElementSchemaRegistry} from 'angular2/src/compiler/schema/dom_element_schema_registry';
@ -51,7 +52,7 @@ export const COMPILER_PROVIDERS: Array<Type | Provider | any[]> = CONST_EXPR([
ViewCompiler,
new Provider(CompilerConfig, {useFactory: _createCompilerConfig, deps: []}),
RuntimeCompiler,
new Provider(Compiler, {useExisting: RuntimeCompiler}),
new Provider(ComponentResolver, {useExisting: RuntimeCompiler}),
DomElementSchemaRegistry,
new Provider(ElementSchemaRegistry, {useExisting: DomElementSchemaRegistry}),
UrlResolver,

View File

@ -13,16 +13,16 @@ import {TemplateParser} from './template_parser';
import {DirectiveNormalizer} from './directive_normalizer';
import {OutputEmitter} from './output/abstract_emitter';
import * as o from './output/output_ast';
import {HostViewFactory} from 'angular2/src/core/linker/view';
import {ComponentFactory} from 'angular2/src/core/linker/component_factory';
import {
MODULE_SUFFIX,
} from './util';
var _HOST_VIEW_FACTORY_IDENTIFIER = new CompileIdentifierMetadata({
name: 'HostViewFactory',
runtime: HostViewFactory,
moduleUrl: `asset:angular2/lib/src/core/linker/view${MODULE_SUFFIX}`
var _COMPONENT_FACTORY_IDENTIFIER = new CompileIdentifierMetadata({
name: 'ComponentFactory',
runtime: ComponentFactory,
moduleUrl: `asset:angular2/lib/src/core/linker/component_factory${MODULE_SUFFIX}`
});
export class SourceModule {
@ -59,17 +59,20 @@ export class OfflineCompiler {
exportedVars.push(compViewFactoryVar);
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
var compHostViewFactoryVar = this._compileComponent(hostMeta, [compMeta], [], statements);
var hostViewFactoryVar = `hostViewFactory_${compMeta.type.name}`;
statements.push(
o.variable(hostViewFactoryVar)
.set(o.importExpr(_HOST_VIEW_FACTORY_IDENTIFIER)
.instantiate(
[o.literal(compMeta.selector), o.variable(compHostViewFactoryVar)],
o.importType(_HOST_VIEW_FACTORY_IDENTIFIER, null,
[o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]));
exportedVars.push(hostViewFactoryVar);
var hostViewFactoryVar = this._compileComponent(hostMeta, [compMeta], [], statements);
var compFactoryVar = `${compMeta.type.name}NgFactory`;
statements.push(o.variable(compFactoryVar)
.set(o.importExpr(_COMPONENT_FACTORY_IDENTIFIER)
.instantiate(
[
o.literal(compMeta.selector),
o.variable(hostViewFactoryVar),
o.importExpr(compMeta.type)
],
o.importType(_COMPONENT_FACTORY_IDENTIFIER, null,
[o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]));
exportedVars.push(compFactoryVar);
});
return this._codegenSourceModule(moduleUrl, statements, exportedVars);
}

View File

@ -1,5 +1,6 @@
import {isPresent} from 'angular2/src/facade/lang';
import {AppView} from 'angular2/src/core/linker/view';
import {AppElement} from 'angular2/src/core/linker/element';
import {BaseException} from 'angular2/src/facade/exceptions';
import {InstanceFactory, DynamicInstance} from './output_interpreter';
@ -19,12 +20,12 @@ class _InterpretiveAppView extends AppView<any> implements DynamicInstance {
super(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9],
args[10]);
}
createInternal(rootSelector: string): void {
createInternal(rootSelector: string | any): AppElement {
var m = this.methods.get('createInternal');
if (isPresent(m)) {
m(rootSelector);
return m(rootSelector);
} else {
super.createInternal(rootSelector);
return super.createInternal(rootSelector);
}
}
injectorGetInternal(token: any, nodeIndex: number, notFoundResult: any): any {

View File

@ -46,9 +46,11 @@ import {ViewCompiler} from './view_compiler/view_compiler';
import {TemplateParser} from './template_parser';
import {DirectiveNormalizer} from './directive_normalizer';
import {RuntimeMetadataResolver} from './runtime_metadata';
import {HostViewFactory} from 'angular2/src/core/linker/view';
import {HostViewFactoryRef, HostViewFactoryRef_} from 'angular2/src/core/linker/view_ref';
import {Compiler, Compiler_} from 'angular2/src/core/linker/compiler';
import {ComponentFactory} from 'angular2/src/core/linker/component_factory';
import {
ComponentResolver,
ReflectorComponentResolver
} from 'angular2/src/core/linker/component_resolver';
import {CompilerConfig} from './config';
import * as ir from './output/output_ast';
@ -64,7 +66,7 @@ import {XHR} from 'angular2/src/compiler/xhr';
* ready for linking into an application.
*/
@Injectable()
export class RuntimeCompiler extends Compiler_ {
export class RuntimeCompiler implements ComponentResolver {
private _styleCache: Map<string, Promise<string>> = new Map<string, Promise<string>>();
private _hostCacheKeys = new Map<Type, any>();
private _compiledTemplateCache = new Map<any, CompiledTemplate>();
@ -74,11 +76,9 @@ export class RuntimeCompiler extends Compiler_ {
private _templateNormalizer: DirectiveNormalizer,
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
private _viewCompiler: ViewCompiler, private _xhr: XHR,
private _genConfig: CompilerConfig) {
super();
}
private _genConfig: CompilerConfig) {}
compileInHost(componentType: Type): Promise<HostViewFactoryRef_> {
resolveComponent(componentType: Type): Promise<ComponentFactory> {
var compMeta: CompileDirectiveMetadata =
this._runtimeMetadataResolver.getDirectiveMetadata(componentType);
var hostCacheKey = this._hostCacheKeys.get(componentType);
@ -92,8 +92,8 @@ export class RuntimeCompiler extends Compiler_ {
this._loadAndCompileComponent(hostCacheKey, hostMeta, [compMeta], [], []);
}
return this._compiledTemplateDone.get(hostCacheKey)
.then((compiledTemplate: CompiledTemplate) => new HostViewFactoryRef_(
new HostViewFactory(compMeta.selector, compiledTemplate.viewFactory)));
.then((compiledTemplate: CompiledTemplate) => new ComponentFactory(
compMeta.selector, compiledTemplate.viewFactory, componentType));
}
clearCache() {

View File

@ -1,77 +0,0 @@
var nodeDebugInfos_MyComp1 = [
new jit_StaticNodeDebugInfo0([],null,{}),
new jit_StaticNodeDebugInfo0([],null,{})
]
;
function _View_MyComp1(viewManager,renderer,parentInjector,declarationEl,projectableNodes) {
var self = this;
jit_AppView1.call(this, './MyComp',_View_MyComp1,jit_ViewType_EMBEDDED2,{'some-tmpl': null},renderer,viewManager,parentInjector,projectableNodes,declarationEl,jit_ChangeDetectionStrategy_Default3,nodeDebugInfos_MyComp1);
}
_View_MyComp1.prototype = Object.create(jit_AppView1.prototype);
_View_MyComp1.prototype.createInternal = function(rootSelector) {
var self = this;
self._el_0 = self.renderer.createElement(null,'copy-me',self.debug(0,0,49));
self._text_1 = self.renderer.createText(self._el_0,'',self.debug(1,0,58));
self._expr_0 = jit_uninitialized4;
self.init([].concat([self._el_0]),[
self._el_0,
self._text_1
]
,{},[],[]);
};
_View_MyComp1.prototype.detectChangesInternal = function(throwOnChange) {
var self = this;
var currVal = null;
self.debug(1,0,58);
currVal = jit_interpolate5(1,'',self.locals['some-tmpl'],'');
if (jit_checkBinding6(throwOnChange,self._expr_0,currVal)) {
self.renderer.setText(self._text_1,currVal);
self._expr_0 = currVal;
}
self.detectContentChildrenChanges(throwOnChange); }
self.detectViewChildrenChanges(throwOnChange); }
};
function viewFactory_MyComp1(viewManager,parentInjector,declarationEl,projectableNodes,rootSelector) {
projectableNodes = jit_ensureSlotCount7(projectableNodes,0);
var renderer = declarationEl.parentView.renderer;
var view = new _View_MyComp1(viewManager,renderer,parentInjector,declarationEl,projectableNodes);
view.create(rootSelector);
return view;
}
var nodeDebugInfos_MyComp0 = [new jit_StaticNodeDebugInfo0([
jit_TemplateRef8,
jit_SomeViewport9
]
,null,{})];
var renderType_MyComp = null;
function _View_MyComp0(viewManager,renderer,parentInjector,declarationEl,projectableNodes) {
var self = this;
jit_AppView1.call(this, './MyComp',_View_MyComp0,jit_ViewType_COMPONENT10,{},renderer,viewManager,parentInjector,projectableNodes,declarationEl,jit_ChangeDetectionStrategy_Default3,nodeDebugInfos_MyComp0);
}
_View_MyComp0.prototype = Object.create(jit_AppView1.prototype);
_View_MyComp0.prototype.createInternal = function(rootSelector) {
var self = this;
var parentRenderNode = self.renderer.createViewRoot(self.declarationAppElement.nativeElement);
self._anchor_0 = self.renderer.createTemplateAnchor(parentRenderNode,self.debug(0,0,0));
self.debug(null,null,null);
self._appEl_0 = new jit_AppElement11(0,null,self,self._anchor_0);
self._TemplateRef_0_0 = new jit_TemplateRef_12(self._appEl_0,viewFactory_MyComp1);
self._SomeViewport_0_1 = new jit_SomeViewport9(self._appEl_0.vcRef,self._TemplateRef_0_0);
self.init([],[self._anchor_0],{},[],[]);
};
_View_MyComp0.prototype.injectorGetInternal = function(token,requestNodeIndex,notFoundResult) {
var self = this;
if (((token === jit_TemplateRef8) && (0 === requestNodeIndex))) { return self._TemplateRef_0_0; }
if (((token === jit_SomeViewport9) && (0 === requestNodeIndex))) { return self._SomeViewport_0_1; }
return notFoundResult;
};
function viewFactory_MyComp0(viewManager,parentInjector,declarationEl,projectableNodes,rootSelector) {
if ((renderType_MyComp === null)) { (renderType_MyComp = viewManager.createRenderComponentType(jit_ViewType_EMBEDDED2,jit_undefined13)); }
projectableNodes = jit_ensureSlotCount7(projectableNodes,0);
var renderer = viewManager.renderComponent(renderType_MyComp);
var view = new _View_MyComp0(viewManager,renderer,parentInjector,declarationEl,projectableNodes);
view.create(rootSelector);
return view;
}
return viewFactory_MyComp0
//# sourceURL=MyComp.template.js

View File

@ -43,7 +43,6 @@ import {getViewFactoryName, createFlatArray, createDiTokenExpression} from './ut
import {ViewType} from 'angular2/src/core/linker/view_type';
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
import {HOST_VIEW_ELEMENT_NAME} from 'angular2/src/core/linker/view';
import {
CompileIdentifierMetadata,
@ -185,17 +184,13 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
var nodeIndex = this.view.nodes.length;
var createRenderNodeExpr;
var debugContextExpr = this.view.createMethod.resetDebugInfoExpr(nodeIndex, ast);
var createElementExpr = ViewProperties.renderer.callMethod(
'createElement',
[this._getParentRenderNode(parent), o.literal(ast.name), debugContextExpr]);
if (nodeIndex === 0 && this.view.viewType === ViewType.HOST) {
createRenderNodeExpr =
rootSelectorVar.identical(o.NULL_EXPR)
.conditional(createElementExpr,
ViewProperties.renderer.callMethod('selectRootElement',
[rootSelectorVar, debugContextExpr]));
createRenderNodeExpr = o.THIS_EXPR.callMethod(
'selectOrCreateHostElement', [o.literal(ast.name), rootSelectorVar, debugContextExpr]);
} else {
createRenderNodeExpr = createElementExpr;
createRenderNodeExpr = ViewProperties.renderer.callMethod(
'createElement',
[this._getParentRenderNode(parent), o.literal(ast.name), debugContextExpr]);
}
var fieldName = `_el_${nodeIndex}`;
this.view.fields.push(
@ -342,9 +337,6 @@ function _readHtmlAndDirectiveVariables(elementExportAsVars: VariableAst[],
elementExportAsVars.forEach((varAst) => {
variables[varAst.name] = isPresent(component) ? identifierToken(component.type) : null;
});
if (viewType === ViewType.HOST) {
variables[HOST_VIEW_ELEMENT_NAME] = null;
}
return variables;
}
@ -444,7 +436,7 @@ function createViewClass(view: CompileView, renderCompTypeVar: o.ReadVarExpr,
var viewMethods = [
new o.ClassMethod('createInternal', [new o.FnParam(rootSelectorVar.name, o.STRING_TYPE)],
generateCreateMethod(view)),
generateCreateMethod(view), o.importType(Identifiers.AppElement)),
new o.ClassMethod(
'injectorGetInternal',
[
@ -519,6 +511,12 @@ function generateCreateMethod(view: CompileView): o.Statement[] {
.toDeclStmt(o.importType(view.genConfig.renderTypes.renderNode), [o.StmtModifier.Final])
];
}
var resultExpr: o.Expression;
if (view.viewType === ViewType.HOST) {
resultExpr = (<CompileElement>view.nodes[0]).getOrCreateAppElement();
} else {
resultExpr = o.NULL_EXPR;
}
return parentRenderNodeStmts.concat(view.createMethod.finish())
.concat([
o.THIS_EXPR.callMethod('init',
@ -529,7 +527,8 @@ function generateCreateMethod(view: CompileView): o.Statement[] {
o.literalArr(view.disposables),
o.literalArr(view.subscriptions)
])
.toStmt()
.toStmt(),
new o.ReturnStatement(resultExpr)
]);
}