parent
6ff164be0e
commit
a19e018439
|
@ -22,7 +22,6 @@ import * as o from '../output/output_ast';
|
|||
import {ParseError} from '../parse_util';
|
||||
import {compileNgModule as compileIvyModule} from '../render3/r3_module_compiler';
|
||||
import {compilePipe as compileIvyPipe} from '../render3/r3_pipe_compiler';
|
||||
import {OutputMode} from '../render3/r3_types';
|
||||
import {compileComponent as compileIvyComponent, compileDirective as compileIvyDirective} from '../render3/r3_view_compiler';
|
||||
import {CompiledStylesheet, StyleCompiler} from '../style_compiler';
|
||||
import {SummaryResolver} from '../summary_resolver';
|
||||
|
@ -389,17 +388,16 @@ export class AotCompiler {
|
|||
this._parseTemplate(directiveMetadata, module, module.transitiveModule.directives);
|
||||
compileIvyComponent(
|
||||
context, directiveMetadata, parsedPipes, parsedTemplate, this.reflector,
|
||||
hostBindingParser, OutputMode.PartialClass);
|
||||
hostBindingParser);
|
||||
} else {
|
||||
compileIvyDirective(
|
||||
context, directiveMetadata, this.reflector, hostBindingParser, OutputMode.PartialClass);
|
||||
compileIvyDirective(context, directiveMetadata, this.reflector, hostBindingParser);
|
||||
}
|
||||
});
|
||||
|
||||
pipes.forEach(pipeType => {
|
||||
const pipeMetadata = this._metadataResolver.getPipeMetadata(pipeType);
|
||||
if (pipeMetadata) {
|
||||
compileIvyPipe(context, pipeMetadata, this.reflector, OutputMode.PartialClass);
|
||||
compileIvyPipe(context, pipeMetadata, this.reflector);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {StaticReflector} from '../aot/static_reflector';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeSummary, CompileTypeMetadata} from '../compile_metadata';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG, DomElementSchemaRegistry, Lexer, ParseError, Parser} from '../compiler';
|
||||
import {CompileMetadataResolver} from '../metadata_resolver';
|
||||
import * as o from '../output/output_ast';
|
||||
import {BindingParser} from '../template_parser/binding_parser';
|
||||
import {TemplateAst} from '../template_parser/template_ast';
|
||||
import {OutputContext} from '../util';
|
||||
|
||||
import {compilePipe} from './r3_pipe_compiler';
|
||||
import {BUILD_OPTIMIZER_REMOVE, OutputMode} from './r3_types';
|
||||
import {compileComponent, compileDirective} from './r3_view_compiler';
|
||||
|
||||
export const enum ModuleKind {
|
||||
Renderer2,
|
||||
Renderer3,
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce the back-patching function for the given module to the output context.
|
||||
*/
|
||||
export function compileModuleBackPatch(
|
||||
outputCtx: OutputContext, name: string, module: CompileNgModuleMetadata, kind: ModuleKind,
|
||||
backPatchReferenceOf: (module: CompileTypeMetadata) => o.Expression,
|
||||
parseTemplate: (
|
||||
compMeta: CompileDirectiveMetadata, ngModule: CompileNgModuleMetadata,
|
||||
directiveIdentifiers: CompileIdentifierMetadata[]) => {
|
||||
template: TemplateAst[],
|
||||
pipes: CompilePipeSummary[]
|
||||
},
|
||||
reflector: StaticReflector, resolver: CompileMetadataResolver) {
|
||||
const imports: o.Statement[] = [];
|
||||
let statements: o.Statement[] = [];
|
||||
|
||||
// Call dependent back patching
|
||||
for (const importedModule of module.importedModules) {
|
||||
const importBackPatchFunction = backPatchReferenceOf(importedModule.type);
|
||||
|
||||
// e.g. // @BUILD_OPTIMIZER_REMOVE
|
||||
imports.push(new o.CommentStmt(BUILD_OPTIMIZER_REMOVE));
|
||||
|
||||
// e.g. ngBackPatch_some_other_module_Module();
|
||||
imports.push(importBackPatchFunction.callFn([]).toStmt());
|
||||
}
|
||||
|
||||
// The local output context allows collecting the back-patch statements that
|
||||
// are generated by the various compilers which allows putting placing them
|
||||
// into the body of a function instead of at global scope.
|
||||
const localCtx: OutputContext = {
|
||||
statements,
|
||||
constantPool: outputCtx.constantPool,
|
||||
genFilePath: outputCtx.genFilePath,
|
||||
importExpr: outputCtx.importExpr
|
||||
};
|
||||
|
||||
// e.g. export function ngBackPatch_some_module_Lib1Module()
|
||||
if (kind === ModuleKind.Renderer2) {
|
||||
// For all Renderer2 modules generate back-patching code for all the components, directives,
|
||||
// pipes, and injectables as well as the injector def for the module itself.
|
||||
|
||||
const expressionParser = new Parser(new Lexer());
|
||||
const elementSchemaRegistry = new DomElementSchemaRegistry();
|
||||
const errors: ParseError[] = [];
|
||||
const hostBindingParser = new BindingParser(
|
||||
expressionParser, DEFAULT_INTERPOLATION_CONFIG, elementSchemaRegistry, [], errors);
|
||||
|
||||
// Back-patch all declared directive and components
|
||||
for (const declaredDirective of module.declaredDirectives) {
|
||||
const declaredDirectiveMetadata = resolver.getDirectiveMetadata(declaredDirective.reference);
|
||||
if (declaredDirectiveMetadata.isComponent) {
|
||||
const {template: parsedTemplate, pipes: parsedPipes} =
|
||||
parseTemplate(declaredDirectiveMetadata, module, module.transitiveModule.directives);
|
||||
compileComponent(
|
||||
localCtx, declaredDirectiveMetadata, parsedPipes, parsedTemplate, reflector,
|
||||
hostBindingParser, OutputMode.BackPatch);
|
||||
} else {
|
||||
compileDirective(
|
||||
localCtx, declaredDirectiveMetadata, reflector, hostBindingParser,
|
||||
OutputMode.BackPatch);
|
||||
}
|
||||
}
|
||||
|
||||
// Back-patch all pipes declared in the module.
|
||||
for (const pipeType of module.declaredPipes) {
|
||||
const pipeMetadata = resolver.getPipeMetadata(pipeType.reference);
|
||||
if (pipeMetadata) {
|
||||
compilePipe(localCtx, pipeMetadata, reflector, OutputMode.BackPatch);
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
throw new Error(errors.map(e => e.toString()).join('\n'));
|
||||
}
|
||||
}
|
||||
|
||||
outputCtx.statements.push(new o.DeclareFunctionStmt(
|
||||
name, [], [...imports, ...statements], o.INFERRED_TYPE, [o.StmtModifier.Exported]));
|
||||
}
|
|
@ -13,15 +13,14 @@ import * as o from '../output/output_ast';
|
|||
import {OutputContext, error} from '../util';
|
||||
|
||||
import {Identifiers as R3} from './r3_identifiers';
|
||||
import {BUILD_OPTIMIZER_COLOCATE, OutputMode} from './r3_types';
|
||||
import {BUILD_OPTIMIZER_COLOCATE} from './r3_types';
|
||||
import {createFactory} from './r3_view_compiler';
|
||||
|
||||
/**
|
||||
* Write a pipe definition to the output context.
|
||||
*/
|
||||
export function compilePipe(
|
||||
outputCtx: OutputContext, pipe: CompilePipeMetadata, reflector: CompileReflector,
|
||||
mode: OutputMode) {
|
||||
outputCtx: OutputContext, pipe: CompilePipeMetadata, reflector: CompileReflector) {
|
||||
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
|
||||
|
||||
// e.g. `name: 'myPipe'`
|
||||
|
@ -47,7 +46,6 @@ export function compilePipe(
|
|||
const definitionFunction =
|
||||
o.importExpr(R3.definePipe).callFn([o.literalMap(definitionMapValues)]);
|
||||
|
||||
if (mode === OutputMode.PartialClass) {
|
||||
outputCtx.statements.push(new o.ClassStmt(
|
||||
/* name */ className,
|
||||
/* parent */ null,
|
||||
|
@ -59,13 +57,4 @@ export function compilePipe(
|
|||
/* getters */[],
|
||||
/* constructorMethod */ new o.ClassMethod(null, [], []),
|
||||
/* methods */[]));
|
||||
} else {
|
||||
// Create back-patch definition.
|
||||
const classReference = outputCtx.importExpr(pipe.type.reference);
|
||||
|
||||
// Create the back-patch statement
|
||||
outputCtx.statements.push(
|
||||
new o.CommentStmt(BUILD_OPTIMIZER_COLOCATE),
|
||||
classReference.prop(definitionField).set(definitionFunction).toStmt());
|
||||
}
|
||||
}
|
|
@ -6,14 +6,6 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* The statement mode for the render, either as a class back-patch or as a partial class
|
||||
*/
|
||||
export const enum OutputMode {
|
||||
PartialClass,
|
||||
BackPatch,
|
||||
}
|
||||
|
||||
/**
|
||||
* Comment to insert above back-patch
|
||||
*/
|
||||
|
|
|
@ -22,7 +22,7 @@ import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventA
|
|||
import {OutputContext, error} from '../util';
|
||||
|
||||
import {Identifiers as R3} from './r3_identifiers';
|
||||
import {BUILD_OPTIMIZER_COLOCATE, OutputMode} from './r3_types';
|
||||
import {BUILD_OPTIMIZER_COLOCATE} from './r3_types';
|
||||
|
||||
|
||||
/** Name of the context parameter passed into a template function */
|
||||
|
@ -50,7 +50,7 @@ const ID_SEPARATOR = '@@';
|
|||
|
||||
export function compileDirective(
|
||||
outputCtx: OutputContext, directive: CompileDirectiveMetadata, reflector: CompileReflector,
|
||||
bindingParser: BindingParser, mode: OutputMode) {
|
||||
bindingParser: BindingParser) {
|
||||
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
|
||||
|
||||
const field = (key: string, value: o.Expression | null) => {
|
||||
|
@ -87,7 +87,6 @@ export function compileDirective(
|
|||
const definitionFunction =
|
||||
o.importExpr(R3.defineDirective).callFn([o.literalMap(definitionMapValues)]);
|
||||
|
||||
if (mode === OutputMode.PartialClass) {
|
||||
// Create the partial class to be merged with the actual class.
|
||||
outputCtx.statements.push(new o.ClassStmt(
|
||||
/* name */ className,
|
||||
|
@ -100,21 +99,12 @@ export function compileDirective(
|
|||
/* getters */[],
|
||||
/* constructorMethod */ new o.ClassMethod(null, [], []),
|
||||
/* methods */[]));
|
||||
} else {
|
||||
// Create back-patch definition.
|
||||
const classReference = outputCtx.importExpr(directive.type.reference);
|
||||
|
||||
// Create the back-patch statement
|
||||
outputCtx.statements.push(new o.CommentStmt(BUILD_OPTIMIZER_COLOCATE));
|
||||
outputCtx.statements.push(
|
||||
classReference.prop(definitionField).set(definitionFunction).toStmt());
|
||||
}
|
||||
}
|
||||
|
||||
export function compileComponent(
|
||||
outputCtx: OutputContext, component: CompileDirectiveMetadata,
|
||||
pipeSummaries: CompilePipeSummary[], template: TemplateAst[], reflector: CompileReflector,
|
||||
bindingParser: BindingParser, mode: OutputMode) {
|
||||
bindingParser: BindingParser) {
|
||||
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
|
||||
|
||||
// Pipes and Directives found in the template
|
||||
|
@ -200,7 +190,6 @@ export function compileComponent(
|
|||
const definitionField = outputCtx.constantPool.propertyNameOf(DefinitionKind.Component);
|
||||
const definitionFunction =
|
||||
o.importExpr(R3.defineComponent).callFn([o.literalMap(definitionMapValues)]);
|
||||
if (mode === OutputMode.PartialClass) {
|
||||
const className = identifierName(component.type) !;
|
||||
className || error(`Cannot resolver the name of ${component.type}`);
|
||||
|
||||
|
@ -216,14 +205,6 @@ export function compileComponent(
|
|||
/* getters */[],
|
||||
/* constructorMethod */ new o.ClassMethod(null, [], []),
|
||||
/* methods */[]));
|
||||
} else {
|
||||
const classReference = outputCtx.importExpr(component.type.reference);
|
||||
|
||||
// Create the back-patch statement
|
||||
outputCtx.statements.push(
|
||||
new o.CommentStmt(BUILD_OPTIMIZER_COLOCATE),
|
||||
classReference.prop(definitionField).set(definitionFunction).toStmt());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove these when the things are fully supported
|
||||
|
|
|
@ -6,19 +6,18 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AotCompilerHost, AotCompilerOptions, AotSummaryResolver, CompileDirectiveMetadata, CompileIdentifierMetadata, CompileMetadataResolver, CompileNgModuleMetadata, CompilePipeSummary, CompileTypeMetadata, CompilerConfig, DEFAULT_INTERPOLATION_CONFIG, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, HtmlParser, Lexer, NgModuleResolver, ParseError, Parser, PipeResolver, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, TemplateParser, TypeScriptEmitter, analyzeNgModules, createAotUrlResolver, templateSourceUrl} from '@angular/compiler';
|
||||
import {AotCompilerOptions, AotSummaryResolver, CompileMetadataResolver, CompilerConfig, DEFAULT_INTERPOLATION_CONFIG, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, HtmlParser, Lexer, NgModuleResolver, ParseError, Parser, PipeResolver, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, TemplateParser, TypeScriptEmitter, analyzeNgModules, createAotUrlResolver} from '@angular/compiler';
|
||||
import {ViewEncapsulation} from '@angular/core';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {NgAnalyzedModules} from '../../src/aot/compiler';
|
||||
import {ConstantPool} from '../../src/constant_pool';
|
||||
import {ParserError} from '../../src/expression_parser/ast';
|
||||
import * as html from '../../src/ml_parser/ast';
|
||||
import {removeWhitespaces} from '../../src/ml_parser/html_whitespaces';
|
||||
import * as o from '../../src/output/output_ast';
|
||||
import {ModuleKind, compileModuleBackPatch} from '../../src/render3/r3_back_patch_compiler';
|
||||
import {compileModuleFactory} from '../../src/render3/r3_module_factory_compiler';
|
||||
import {compilePipe} from '../../src/render3/r3_pipe_compiler';
|
||||
import {OutputMode} from '../../src/render3/r3_types';
|
||||
import {compileComponent, compileDirective} from '../../src/render3/r3_view_compiler';
|
||||
import {HtmlToTemplateTransform} from '../../src/render3/r3_template_transform';
|
||||
import {compileComponent, compileDirective} from '../../src/render3/r3_view_compiler_local';
|
||||
import {BindingParser} from '../../src/template_parser/binding_parser';
|
||||
import {OutputContext, escapeRegExp} from '../../src/util';
|
||||
import {MockAotCompilerHost, MockCompilerHost, MockData, MockDirectory, arrayToMockDir, expectNoDiagnostics, settings, toMockFileArray} from '../aot/test_util';
|
||||
|
@ -252,9 +251,6 @@ function doCompile(
|
|||
|
||||
const emitter = new TypeScriptEmitter();
|
||||
|
||||
const moduleName = compilerHost.fileNameToModuleName(
|
||||
fakeOutputContext.genFilePath, fakeOutputContext.genFilePath);
|
||||
|
||||
const result = emitter.emitStatementsAndContext(
|
||||
fakeOutputContext.genFilePath, fakeOutputContext.statements, '', false,
|
||||
/* referenceFilter */ undefined,
|
||||
|
@ -294,81 +290,18 @@ export function compile(
|
|||
const parsedTemplate = templateParser.parse(
|
||||
metadata, htmlAst, directives, pipes, module.schemas, fakeUrl, false);
|
||||
compileComponent(
|
||||
outputCtx, metadata, pipes, parsedTemplate.template, reflector, hostBindingParser,
|
||||
OutputMode.PartialClass);
|
||||
outputCtx, metadata, pipes, parsedTemplate.template, reflector, hostBindingParser);
|
||||
} else {
|
||||
compileDirective(
|
||||
outputCtx, metadata, reflector, hostBindingParser, OutputMode.PartialClass);
|
||||
outputCtx, metadata, reflector, hostBindingParser);
|
||||
}
|
||||
} else if (resolver.isPipe(pipeOrDirective)) {
|
||||
const metadata = resolver.getPipeMetadata(pipeOrDirective);
|
||||
if (metadata) {
|
||||
compilePipe(outputCtx, metadata, reflector, OutputMode.PartialClass);
|
||||
compilePipe(outputCtx, metadata, reflector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
const DTS = /\.d\.ts$/;
|
||||
const EXT = /(\.\w+)+$/;
|
||||
const NONE_WORD = /\W/g;
|
||||
const NODE_MODULES = /^.*\/node_modules\//;
|
||||
|
||||
function getBackPatchFunctionName(type: CompileTypeMetadata) {
|
||||
const filePath = (type.reference.filePath as string)
|
||||
.replace(EXT, '')
|
||||
.replace(NODE_MODULES, '')
|
||||
.replace(NONE_WORD, '_');
|
||||
return `ngBackPatch_${filePath.split('/').filter(s => !!s).join('_')}_${type.reference.name}`;
|
||||
}
|
||||
|
||||
function getBackPatchReference(type: CompileTypeMetadata): o.Expression {
|
||||
return o.variable(getBackPatchFunctionName(type));
|
||||
}
|
||||
|
||||
export function backPatch(
|
||||
data: MockDirectory, angularFiles: MockData, options: AotCompilerOptions = {},
|
||||
errorCollector: (error: any, fileName?: string) => void = error => { throw error;}) {
|
||||
return doCompile(
|
||||
data, angularFiles, options, errorCollector,
|
||||
(outputCtx: OutputContext, analyzedModules: NgAnalyzedModules,
|
||||
resolver: CompileMetadataResolver, htmlParser: HtmlParser, templateParser: TemplateParser,
|
||||
hostBindingParser: BindingParser, reflector: StaticReflector) => {
|
||||
|
||||
const parseTemplate =
|
||||
(compMeta: CompileDirectiveMetadata, ngModule: CompileNgModuleMetadata,
|
||||
directiveIdentifiers: CompileIdentifierMetadata[]) => {
|
||||
const directives =
|
||||
directiveIdentifiers.map(dir => resolver.getDirectiveSummary(dir.reference));
|
||||
const pipes = ngModule.transitiveModule.pipes.map(
|
||||
pipe => resolver.getPipeSummary(pipe.reference));
|
||||
return templateParser.parse(
|
||||
compMeta, compMeta.template !.htmlAst !, directives, pipes, ngModule.schemas,
|
||||
templateSourceUrl(ngModule.type, compMeta, compMeta.template !), true);
|
||||
};
|
||||
|
||||
for (const module of analyzedModules.ngModules) {
|
||||
compileModuleBackPatch(
|
||||
outputCtx, getBackPatchFunctionName(module.type), module,
|
||||
DTS.test(module.type.reference.filePath) ? ModuleKind.Renderer2 :
|
||||
ModuleKind.Renderer3,
|
||||
getBackPatchReference, parseTemplate, reflector, resolver);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function createFactories(
|
||||
data: MockDirectory, context: MockData, options: AotCompilerOptions = {},
|
||||
errorCollector: (error: any, fileName?: string) => void = error => { throw error;}) {
|
||||
return doCompile(
|
||||
data, context, options, errorCollector,
|
||||
(outputCtx: OutputContext, analyzedModules: NgAnalyzedModules,
|
||||
resolver: CompileMetadataResolver, htmlParser: HtmlParser, templateParser: TemplateParser,
|
||||
hostBindingParser: BindingParser, reflector: StaticReflector) => {
|
||||
for (const module of analyzedModules.ngModules) {
|
||||
compileModuleFactory(outputCtx, module, getBackPatchReference, resolver);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,218 +0,0 @@
|
|||
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {MockDirectory, emitLibrary, mergeMaps, setup} from '../aot/test_util';
|
||||
|
||||
import {backPatch, expectEmit} from './mock_compile';
|
||||
|
||||
describe('r3_back_patch_compiler', () => {
|
||||
const angularFiles = setup({
|
||||
compileAngular: true,
|
||||
compileAnimations: false,
|
||||
compileCommon: true,
|
||||
});
|
||||
|
||||
it('should back-patch a component in a library', () => {
|
||||
const libraries = {
|
||||
lib1: {
|
||||
src: {
|
||||
'component.ts': `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'lib1-cmp',
|
||||
template: '<h1> Hello, {{name}}!</h1>'
|
||||
})
|
||||
export class Lib1Component {
|
||||
name: string;
|
||||
}
|
||||
`,
|
||||
'directive.ts': `
|
||||
import {Directive, HostBinding} from '@angular/core';
|
||||
|
||||
@Directive({selector: '[lib1-dir]'})
|
||||
export class Lib1Directive {
|
||||
@HostBinding('id') dirId = 'some id';
|
||||
}
|
||||
`,
|
||||
'service.ts': `
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class Lib1Service {
|
||||
getSomeInfo() { return 'some info'; }
|
||||
}
|
||||
`,
|
||||
'pipe.ts': `
|
||||
import {Pipe} from '@angular/core';
|
||||
|
||||
@Pipe({name: 'lib1Pipe', pure: true})
|
||||
export class Lib1Pipe {
|
||||
transform(v: any) { return v; }
|
||||
}
|
||||
`,
|
||||
'module.ts': `
|
||||
import {NgModule} from '@angular/core';
|
||||
|
||||
import {Lib1Component} from './component';
|
||||
import {Lib1Directive} from './directive';
|
||||
import {Lib1Service} from './service';
|
||||
import {Lib1Pipe} from './pipe';
|
||||
|
||||
@NgModule({
|
||||
exports: [Lib1Component, Lib1Directive, Lib1Pipe],
|
||||
declarations: [Lib1Component, Lib1Directive, Lib1Pipe],
|
||||
providers: [Lib1Service]
|
||||
})
|
||||
export class Lib1Module {}
|
||||
`
|
||||
}
|
||||
},
|
||||
lib2: {
|
||||
src: {
|
||||
'component.ts': `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'lib2-cmp',
|
||||
template: '<h1> Hello, {{name}}!</h1>'
|
||||
})
|
||||
export class Lib2Component {
|
||||
name: string;
|
||||
}
|
||||
`,
|
||||
'directive.ts': `
|
||||
import {Directive, HostBinding} from '@angular/core';
|
||||
|
||||
@Directive({selector: '[lib2-dir]'})
|
||||
export class Lib2Directive {
|
||||
@HostBinding('id') dirId = 'some id';
|
||||
}
|
||||
`,
|
||||
'service.ts': `
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class Lib2Service {
|
||||
getSomeInfo() { return 'some info'; }
|
||||
}
|
||||
`,
|
||||
'pipe.ts': `
|
||||
import {Pipe} from '@angular/core';
|
||||
|
||||
@Pipe({name: 'lib2Pipe', pure: true})
|
||||
export class Lib2Pipe {
|
||||
transform(v: any) { return v; }
|
||||
}
|
||||
`,
|
||||
'module.ts': `
|
||||
import {NgModule} from '@angular/core';
|
||||
|
||||
import {Lib1Module} from '../../lib1/src/module';
|
||||
import {Lib2Component} from './component';
|
||||
import {Lib2Directive} from './directive';
|
||||
import {Lib2Service} from './service';
|
||||
import {Lib2Pipe} from './pipe';
|
||||
|
||||
@NgModule({
|
||||
imports: [Lib1Module],
|
||||
exports: [Lib2Component, Lib2Directive, Lib2Pipe],
|
||||
declarations: [Lib2Component, Lib2Directive, Lib2Pipe],
|
||||
providers: [Lib2Service]
|
||||
})
|
||||
export class Lib2Module {}
|
||||
`
|
||||
}
|
||||
},
|
||||
};
|
||||
const app = {
|
||||
app: {
|
||||
src: {
|
||||
'app.component.ts': `
|
||||
import {Component} from '@angular/core';
|
||||
import {Lib1Service} from '../../lib1/src/service';
|
||||
import {Lib2Service} from '../../lib2/src/service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-cmp',
|
||||
template: \`
|
||||
<lib1-cmp lib2-dir>{{'v' | lib1Pipe | lib2Pipe}}</lib1-cmp>
|
||||
<lib2-cmp lib1-dir>{{'v' | lib2Pipe | lib2Pipe}}</lib2-cmp>
|
||||
\`
|
||||
})
|
||||
export class AppComponent {
|
||||
constructor(public lib1s: Lib1Service, public lib2s: Lib2Service) {}
|
||||
}
|
||||
`,
|
||||
'app.module.ts': `
|
||||
import {NgModule} from '@angular/core';
|
||||
import {Lib1Module} from '../../lib1/src/module';
|
||||
import {Lib2Module} from '../../lib2/src/module';
|
||||
|
||||
import {AppComponent} from './app.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [Lib1Module, Lib2Module],
|
||||
declarations: [AppComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const lib1_module_back_patch = `
|
||||
export function ngBackPatch__lib1_src_module_Lib1Module() {
|
||||
// @__BUILD_OPTIMIZER_COLOCATE__
|
||||
$lib1_c$.Lib1Component.ngComponentDef = $r3$.ɵdefineComponent(…);
|
||||
|
||||
// @__BUILD_OPTIMIZER_COLOCATE__
|
||||
$lib1_d$.Lib1Directive.ngDirectiveDef = $r3$.ɵdefineDirective(…);
|
||||
|
||||
// @__BUILD_OPTIMIZER_COLOCATE__
|
||||
$lib1_p$.Lib1Pipe.ngPipeDef = $r3$.ɵdefinePipe(…);
|
||||
}
|
||||
`;
|
||||
|
||||
const lib2_module_back_patch = `
|
||||
export function ngBackPatch__lib2_src_module_Lib2Module() {
|
||||
// @__BUILD_OPTIMIZER_REMOVE__
|
||||
ngBackPatch__lib1_src_module_Lib1Module();
|
||||
|
||||
// @__BUILD_OPTIMIZER_COLOCATE__
|
||||
$lib2_c$.Lib2Component.ngComponentDef = $r3$.ɵdefineComponent(…);
|
||||
|
||||
// @__BUILD_OPTIMIZER_COLOCATE__
|
||||
$lib2_d$.Lib2Directive.ngDirectiveDef = $r3$.ɵdefineDirective(…);
|
||||
|
||||
// @__BUILD_OPTIMIZER_COLOCATE__
|
||||
$lib1_p$.Lib2Pipe.ngPipeDef = $r3$.ɵdefinePipe(…);
|
||||
}
|
||||
`;
|
||||
|
||||
const app_module_back_patch = `
|
||||
export function ngBackPatch__app_src_app_AppModule() {
|
||||
// @__BUILD_OPTIMIZER_REMOVE__
|
||||
ngBackPatch__lib1_src_module_Lib1Module();
|
||||
// @__BUILD_OPTIMIZER_REMOVE__
|
||||
ngBackPatch__lib2_src_module_Lib2Module();
|
||||
}
|
||||
`;
|
||||
|
||||
const context = mergeMaps(emitLibrary(angularFiles, libraries), angularFiles);
|
||||
|
||||
const result = backPatch(app, context);
|
||||
|
||||
expectEmit(result.source, lib1_module_back_patch, 'Invalid lib1 back-patch');
|
||||
expectEmit(result.source, lib2_module_back_patch, 'Invalid lib2 back-patch');
|
||||
expectEmit(result.source, app_module_back_patch, 'Invalid app module back-patch');
|
||||
});
|
||||
|
||||
});
|
|
@ -1,202 +0,0 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {MockDirectory, emitLibrary, mergeMaps, setup} from '../aot/test_util';
|
||||
import {createFactories, expectEmit} from './mock_compile';
|
||||
|
||||
describe('r3_factory_compiler', () => {
|
||||
const angularFiles = setup({
|
||||
compileAngular: true,
|
||||
compileAnimations: false,
|
||||
compileCommon: true,
|
||||
});
|
||||
|
||||
it('should generate factories for all modules', () => {
|
||||
const libraries = {
|
||||
lib1: {
|
||||
src: {
|
||||
'component.ts': `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'lib1-cmp',
|
||||
template: '<h1> Hello, {{name}}!</h1>'
|
||||
})
|
||||
export class Lib1Component {
|
||||
name: string;
|
||||
}
|
||||
`,
|
||||
'directive.ts': `
|
||||
import {Directive, HostBinding} from '@angular/core';
|
||||
|
||||
@Directive({selector: '[lib1-dir]'})
|
||||
export class Lib1Directive {
|
||||
@HostBinding('id') dirId = 'some id';
|
||||
}
|
||||
`,
|
||||
'service.ts': `
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class Lib1Service {
|
||||
getSomeInfo() { return 'some info'; }
|
||||
}
|
||||
`,
|
||||
'module.ts': `
|
||||
import {NgModule} from '@angular/core';
|
||||
|
||||
import {Lib1Component} from './component';
|
||||
import {Lib1Directive} from './directive';
|
||||
import {Lib1Service} from './service';
|
||||
|
||||
@NgModule({
|
||||
exports: [Lib1Component, Lib1Directive],
|
||||
declarations: [Lib1Component, Lib1Directive],
|
||||
providers: [Lib1Service]
|
||||
})
|
||||
export class Lib1Module {}
|
||||
`
|
||||
}
|
||||
},
|
||||
lib2: {
|
||||
src: {
|
||||
'component.ts': `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'lib2-cmp',
|
||||
template: '<h1> Hello, {{name}}!</h1>'
|
||||
})
|
||||
export class Lib2Component {
|
||||
name: string;
|
||||
}
|
||||
`,
|
||||
'directive.ts': `
|
||||
import {Directive, HostBinding} from '@angular/core';
|
||||
|
||||
@Directive({selector: '[lib2-dir]'})
|
||||
export class Lib2Directive {
|
||||
@HostBinding('id') dirId = 'some id';
|
||||
}
|
||||
`,
|
||||
'service.ts': `
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class Lib2Service {
|
||||
getSomeInfo() { return 'some info'; }
|
||||
}
|
||||
`,
|
||||
'module.ts': `
|
||||
import {NgModule} from '@angular/core';
|
||||
|
||||
import {Lib1Module} from '../../lib1/src/module';
|
||||
import {Lib2Component} from './component';
|
||||
import {Lib2Directive} from './directive';
|
||||
import {Lib2Service} from './service';
|
||||
|
||||
@NgModule({
|
||||
imports: [Lib1Module],
|
||||
exports: [Lib2Component, Lib2Directive],
|
||||
declarations: [Lib2Component, Lib2Directive],
|
||||
providers: [Lib2Service]
|
||||
})
|
||||
export class Lib2Module {}
|
||||
`
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const app = {
|
||||
app: {
|
||||
src: {
|
||||
'app.component.ts': `
|
||||
import {Component} from '@angular/core';
|
||||
import {Lib1Service} from '../../lib1/src/service';
|
||||
import {Lib2Service} from '../../lib2/src/service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-cmp',
|
||||
template: \`
|
||||
<lib1-cmp lib2-dir></lib1-cmp>
|
||||
<lib2-cmp lib1-dir></lib2-cmp>
|
||||
\`
|
||||
})
|
||||
export class AppComponent {
|
||||
constructor(public lib1s: Lib1Service, public lib2s: Lib2Service) {}
|
||||
}
|
||||
`,
|
||||
'app.module.ts': `
|
||||
import {NgModule} from '@angular/core';
|
||||
import {Lib1Module} from '../../lib1/src/module';
|
||||
import {Lib2Module} from '../../lib2/src/module';
|
||||
|
||||
import {AppComponent} from './app.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [Lib1Module, Lib2Module],
|
||||
declarations: [AppComponent],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const lib1_module_factory = `
|
||||
export const Lib1ModuleNgFactory: $any$ = {
|
||||
moduleType: $i1$.Lib1Module,
|
||||
create: function Lib1ModuleNgFactory_Create(parentInjector: $any$) {
|
||||
if ((this.patchedDeps !== true)) {
|
||||
this.patchedDeps = true;
|
||||
ngBackPatch__lib1_src_module_Lib1Module();
|
||||
}
|
||||
…
|
||||
}
|
||||
};
|
||||
`;
|
||||
|
||||
const lib2_module_factory = `
|
||||
export const Lib2ModuleNgFactory: $any$ = {
|
||||
moduleType: $i2$.Lib2Module,
|
||||
create: function Lib2ModuleNgFactory_Create(parentInjector: $any$) {
|
||||
if ((this.patchedDeps !== true)) {
|
||||
this.patchedDeps = true;
|
||||
ngBackPatch__lib2_src_module_Lib2Module();
|
||||
}
|
||||
…
|
||||
}
|
||||
};
|
||||
`;
|
||||
|
||||
// TODO(chuckj): What should we do with the bootstrap components?
|
||||
const app_module_factory = `
|
||||
export const AppModuleNgFactory: $any$ = {
|
||||
moduleType: AppModule,
|
||||
create: function AppModuleNgFactory_Create(parentInjector: $any$) {
|
||||
if ((this.patchedDeps !== true)) {
|
||||
this.patchedDeps = true;
|
||||
ngBackPatch__app_src_app_AppModule();
|
||||
}
|
||||
…
|
||||
}
|
||||
};
|
||||
`;
|
||||
|
||||
const context = mergeMaps(emitLibrary(angularFiles, libraries), angularFiles);
|
||||
|
||||
const result = createFactories(app, context);
|
||||
|
||||
expectEmit(result.source, lib1_module_factory, 'Invalid module factory for lib1');
|
||||
expectEmit(result.source, lib2_module_factory, 'Invalid module factory for lib2');
|
||||
expectEmit(result.source, app_module_factory, 'Invalid module factory for app');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue