2016-12-15 09:12:40 -08:00
|
|
|
/**
|
|
|
|
* @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
|
|
|
|
*/
|
2017-04-26 09:24:42 -07:00
|
|
|
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompileProviderMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary} from '../compile_metadata';
|
|
|
|
import * as o from '../output/output_ast';
|
2016-12-15 09:12:40 -08:00
|
|
|
import {Summary, SummaryResolver} from '../summary_resolver';
|
2017-05-16 16:30:37 -07:00
|
|
|
import {OutputContext, ValueTransformer, ValueVisitor, visitValue} from '../util';
|
2016-12-15 09:12:40 -08:00
|
|
|
|
|
|
|
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
|
|
|
|
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
|
2017-04-26 09:24:42 -07:00
|
|
|
import {summaryForJitFileName, summaryForJitName} from './util';
|
2016-12-15 09:12:40 -08:00
|
|
|
|
|
|
|
export function serializeSummaries(
|
2017-05-16 16:30:37 -07:00
|
|
|
forJitCtx: OutputContext, summaryResolver: SummaryResolver<StaticSymbol>,
|
|
|
|
symbolResolver: StaticSymbolResolver, symbols: ResolvedStaticSymbol[], types: {
|
2017-04-26 09:24:42 -07:00
|
|
|
summary: CompileTypeSummary,
|
|
|
|
metadata: CompileNgModuleMetadata | CompileDirectiveMetadata | CompilePipeMetadata |
|
|
|
|
CompileTypeMetadata
|
2017-05-16 16:30:37 -07:00
|
|
|
}[]): {json: string, exportAs: {symbol: StaticSymbol, exportAs: string}[]} {
|
2017-04-26 09:24:42 -07:00
|
|
|
const toJsonSerializer = new ToJsonSerializer(symbolResolver, summaryResolver);
|
2017-05-16 16:30:37 -07:00
|
|
|
const forJitSerializer = new ForJitSerializer(forJitCtx, symbolResolver);
|
2016-12-15 09:12:40 -08:00
|
|
|
|
|
|
|
// for symbols, we use everything except for the class metadata itself
|
|
|
|
// (we keep the statics though), as the class metadata is contained in the
|
|
|
|
// CompileTypeSummary.
|
|
|
|
symbols.forEach(
|
2017-04-26 09:24:42 -07:00
|
|
|
(resolvedSymbol) => toJsonSerializer.addOrMergeSummary(
|
2016-12-15 09:12:40 -08:00
|
|
|
{symbol: resolvedSymbol.symbol, metadata: resolvedSymbol.metadata}));
|
|
|
|
// Add summaries that are referenced by the given symbols (transitively)
|
|
|
|
// Note: the serializer.symbols array might be growing while
|
|
|
|
// we execute the loop!
|
2017-04-26 09:24:42 -07:00
|
|
|
for (let processedIndex = 0; processedIndex < toJsonSerializer.symbols.length; processedIndex++) {
|
|
|
|
const symbol = toJsonSerializer.symbols[processedIndex];
|
2016-12-27 09:36:47 -08:00
|
|
|
if (summaryResolver.isLibraryFile(symbol.filePath)) {
|
2016-12-15 09:12:40 -08:00
|
|
|
let summary = summaryResolver.resolveSummary(symbol);
|
|
|
|
if (!summary) {
|
|
|
|
// some symbols might originate from a plain typescript library
|
|
|
|
// that just exported .d.ts and .metadata.json files, i.e. where no summary
|
|
|
|
// files were created.
|
|
|
|
const resolvedSymbol = symbolResolver.resolveSymbol(symbol);
|
|
|
|
if (resolvedSymbol) {
|
|
|
|
summary = {symbol: resolvedSymbol.symbol, metadata: resolvedSymbol.metadata};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (summary) {
|
2017-04-26 09:24:42 -07:00
|
|
|
if (summary.type) {
|
|
|
|
forJitSerializer.addLibType(summary.type);
|
|
|
|
}
|
|
|
|
toJsonSerializer.addOrMergeSummary(summary);
|
2016-12-15 09:12:40 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add type summaries.
|
|
|
|
// Note: We don't add the summaries of all referenced symbols as for the ResolvedSymbols,
|
|
|
|
// as the type summaries already contain the transitive data that they require
|
|
|
|
// (in a minimal way).
|
2017-04-26 09:24:42 -07:00
|
|
|
types.forEach(({summary, metadata}) => {
|
|
|
|
forJitSerializer.addSourceType(summary, metadata);
|
|
|
|
toJsonSerializer.addOrMergeSummary(
|
|
|
|
{symbol: summary.type.reference, metadata: null, type: summary});
|
|
|
|
if (summary.summaryKind === CompileSummaryKind.NgModule) {
|
|
|
|
const ngModuleSummary = <CompileNgModuleSummary>summary;
|
2016-12-15 09:12:40 -08:00
|
|
|
ngModuleSummary.exportedDirectives.concat(ngModuleSummary.exportedPipes).forEach((id) => {
|
|
|
|
const symbol: StaticSymbol = id.reference;
|
2016-12-27 09:36:47 -08:00
|
|
|
if (summaryResolver.isLibraryFile(symbol.filePath)) {
|
|
|
|
const summary = summaryResolver.resolveSummary(symbol);
|
|
|
|
if (summary) {
|
2017-04-26 09:24:42 -07:00
|
|
|
toJsonSerializer.addOrMergeSummary(summary);
|
2016-12-27 09:36:47 -08:00
|
|
|
}
|
2016-12-15 09:12:40 -08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2017-04-26 09:24:42 -07:00
|
|
|
const {json, exportAs} = toJsonSerializer.serialize();
|
2017-05-16 16:30:37 -07:00
|
|
|
forJitSerializer.serialize(exportAs);
|
|
|
|
return {json, exportAs};
|
2016-12-15 09:12:40 -08:00
|
|
|
}
|
|
|
|
|
2016-12-27 09:36:47 -08:00
|
|
|
export function deserializeSummaries(symbolCache: StaticSymbolCache, json: string):
|
|
|
|
{summaries: Summary<StaticSymbol>[], importAs: {symbol: StaticSymbol, importAs: string}[]} {
|
2017-04-26 09:24:42 -07:00
|
|
|
const deserializer = new FromJsonDeserializer(symbolCache);
|
2016-12-15 09:12:40 -08:00
|
|
|
return deserializer.deserialize(json);
|
|
|
|
}
|
|
|
|
|
2017-05-23 13:40:50 -07:00
|
|
|
export function createForJitStub(outputCtx: OutputContext, reference: StaticSymbol) {
|
|
|
|
return createSummaryForJitFunction(outputCtx, reference, o.NULL_EXPR);
|
|
|
|
}
|
|
|
|
|
|
|
|
function createSummaryForJitFunction(
|
|
|
|
outputCtx: OutputContext, reference: StaticSymbol, value: o.Expression) {
|
|
|
|
const fnName = summaryForJitName(reference.name);
|
|
|
|
outputCtx.statements.push(
|
|
|
|
o.fn([], [new o.ReturnStatement(value)], new o.ArrayType(o.DYNAMIC_TYPE)).toDeclStmt(fnName, [
|
|
|
|
o.StmtModifier.Final, o.StmtModifier.Exported
|
|
|
|
]));
|
|
|
|
}
|
|
|
|
|
2017-04-26 09:24:42 -07:00
|
|
|
class ToJsonSerializer extends ValueTransformer {
|
2016-12-27 09:36:47 -08:00
|
|
|
// Note: This only contains symbols without members.
|
2016-12-15 09:12:40 -08:00
|
|
|
symbols: StaticSymbol[] = [];
|
|
|
|
private indexBySymbol = new Map<StaticSymbol, number>();
|
|
|
|
// This now contains a `__symbol: number` in the place of
|
|
|
|
// StaticSymbols, but otherwise has the same shape as the original objects.
|
|
|
|
private processedSummaryBySymbol = new Map<StaticSymbol, any>();
|
|
|
|
private processedSummaries: any[] = [];
|
|
|
|
|
2016-12-27 09:36:47 -08:00
|
|
|
constructor(
|
|
|
|
private symbolResolver: StaticSymbolResolver,
|
|
|
|
private summaryResolver: SummaryResolver<StaticSymbol>) {
|
|
|
|
super();
|
|
|
|
}
|
2016-12-15 09:12:40 -08:00
|
|
|
|
|
|
|
addOrMergeSummary(summary: Summary<StaticSymbol>) {
|
|
|
|
let symbolMeta = summary.metadata;
|
|
|
|
if (symbolMeta && symbolMeta.__symbolic === 'class') {
|
2017-03-30 14:51:29 -07:00
|
|
|
// For classes, we keep everything except their class decorators.
|
|
|
|
// We need to keep e.g. the ctor args, method names, method decorators
|
|
|
|
// so that the class can be extended in another compilation unit.
|
|
|
|
// We don't keep the class decorators as
|
|
|
|
// 1) they refer to data
|
|
|
|
// that should not cause a rebuild of downstream compilation units
|
|
|
|
// (e.g. inline templates of @Component, or @NgModule.declarations)
|
|
|
|
// 2) their data is already captured in TypeSummaries, e.g. DirectiveSummary.
|
|
|
|
const clone: {[key: string]: any} = {};
|
|
|
|
Object.keys(symbolMeta).forEach((propName) => {
|
|
|
|
if (propName !== 'decorators') {
|
|
|
|
clone[propName] = symbolMeta[propName];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
symbolMeta = clone;
|
2016-12-15 09:12:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
let processedSummary = this.processedSummaryBySymbol.get(summary.symbol);
|
|
|
|
if (!processedSummary) {
|
|
|
|
processedSummary = this.processValue({symbol: summary.symbol});
|
|
|
|
this.processedSummaries.push(processedSummary);
|
|
|
|
this.processedSummaryBySymbol.set(summary.symbol, processedSummary);
|
|
|
|
}
|
2017-01-30 15:32:08 -08:00
|
|
|
// Note: == on purpose to compare with undefined!
|
2016-12-15 09:12:40 -08:00
|
|
|
if (processedSummary.metadata == null && symbolMeta != null) {
|
|
|
|
processedSummary.metadata = this.processValue(symbolMeta);
|
|
|
|
}
|
2017-01-30 15:32:08 -08:00
|
|
|
// Note: == on purpose to compare with undefined!
|
2016-12-15 09:12:40 -08:00
|
|
|
if (processedSummary.type == null && summary.type != null) {
|
|
|
|
processedSummary.type = this.processValue(summary.type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-27 09:36:47 -08:00
|
|
|
serialize(): {json: string, exportAs: {symbol: StaticSymbol, exportAs: string}[]} {
|
|
|
|
const exportAs: {symbol: StaticSymbol, exportAs: string}[] = [];
|
|
|
|
const json = JSON.stringify({
|
2016-12-15 09:12:40 -08:00
|
|
|
summaries: this.processedSummaries,
|
|
|
|
symbols: this.symbols.map((symbol, index) => {
|
2016-12-27 09:36:47 -08:00
|
|
|
symbol.assertNoMembers();
|
2017-03-24 09:59:58 -07:00
|
|
|
let importAs: string = undefined !;
|
2016-12-27 09:36:47 -08:00
|
|
|
if (this.summaryResolver.isLibraryFile(symbol.filePath)) {
|
|
|
|
importAs = `${symbol.name}_${index}`;
|
|
|
|
exportAs.push({symbol, exportAs: importAs});
|
|
|
|
}
|
2016-12-15 09:12:40 -08:00
|
|
|
return {
|
|
|
|
__symbol: index,
|
|
|
|
name: symbol.name,
|
|
|
|
// We convert the source filenames tinto output filenames,
|
2017-07-07 16:55:17 -07:00
|
|
|
// as the generated summary file will be used when the current
|
2016-12-15 09:12:40 -08:00
|
|
|
// compilation unit is used as a library
|
2016-12-27 09:36:47 -08:00
|
|
|
filePath: this.summaryResolver.getLibraryFileName(symbol.filePath),
|
|
|
|
importAs: importAs
|
2016-12-15 09:12:40 -08:00
|
|
|
};
|
|
|
|
})
|
|
|
|
});
|
2016-12-27 09:36:47 -08:00
|
|
|
return {json, exportAs};
|
2016-12-15 09:12:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
private processValue(value: any): any { return visitValue(value, this, null); }
|
|
|
|
|
|
|
|
visitOther(value: any, context: any): any {
|
|
|
|
if (value instanceof StaticSymbol) {
|
2016-12-27 09:36:47 -08:00
|
|
|
const baseSymbol = this.symbolResolver.getStaticSymbol(value.filePath, value.name);
|
|
|
|
let index = this.indexBySymbol.get(baseSymbol);
|
2017-01-30 15:32:08 -08:00
|
|
|
// Note: == on purpose to compare with undefined!
|
2016-12-15 09:12:40 -08:00
|
|
|
if (index == null) {
|
|
|
|
index = this.indexBySymbol.size;
|
2016-12-27 09:36:47 -08:00
|
|
|
this.indexBySymbol.set(baseSymbol, index);
|
|
|
|
this.symbols.push(baseSymbol);
|
2016-12-15 09:12:40 -08:00
|
|
|
}
|
2016-12-27 09:36:47 -08:00
|
|
|
return {__symbol: index, members: value.members};
|
2016-12-15 09:12:40 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-26 09:24:42 -07:00
|
|
|
class ForJitSerializer {
|
|
|
|
private data = new Map<StaticSymbol, {
|
|
|
|
summary: CompileTypeSummary,
|
|
|
|
metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|CompilePipeMetadata|
|
|
|
|
CompileTypeMetadata|null,
|
|
|
|
isLibrary: boolean
|
|
|
|
}>();
|
|
|
|
|
2017-05-16 16:30:37 -07:00
|
|
|
constructor(private outputCtx: OutputContext, private symbolResolver: StaticSymbolResolver) {}
|
2017-04-26 09:24:42 -07:00
|
|
|
|
|
|
|
addSourceType(
|
|
|
|
summary: CompileTypeSummary, metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|
|
|
|
|
CompilePipeMetadata|CompileTypeMetadata) {
|
|
|
|
this.data.set(summary.type.reference, {summary, metadata, isLibrary: false});
|
|
|
|
}
|
|
|
|
|
|
|
|
addLibType(summary: CompileTypeSummary) {
|
|
|
|
this.data.set(summary.type.reference, {summary, metadata: null, isLibrary: true});
|
|
|
|
}
|
|
|
|
|
2017-05-16 16:30:37 -07:00
|
|
|
serialize(exportAs: {symbol: StaticSymbol, exportAs: string}[]): void {
|
2017-04-26 09:24:42 -07:00
|
|
|
const ngModuleSymbols = new Set<StaticSymbol>();
|
|
|
|
|
|
|
|
Array.from(this.data.values()).forEach(({summary, metadata, isLibrary}) => {
|
|
|
|
if (summary.summaryKind === CompileSummaryKind.NgModule) {
|
|
|
|
// collect the symbols that refer to NgModule classes.
|
|
|
|
// Note: we can't just rely on `summary.type.summaryKind` to determine this as
|
|
|
|
// we don't add the summaries of all referenced symbols when we serialize type summaries.
|
|
|
|
// See serializeSummaries for details.
|
|
|
|
ngModuleSymbols.add(summary.type.reference);
|
|
|
|
const modSummary = <CompileNgModuleSummary>summary;
|
|
|
|
modSummary.modules.forEach((mod) => { ngModuleSymbols.add(mod.reference); });
|
|
|
|
}
|
|
|
|
if (!isLibrary) {
|
|
|
|
const fnName = summaryForJitName(summary.type.reference.name);
|
2017-05-23 13:40:50 -07:00
|
|
|
createSummaryForJitFunction(
|
|
|
|
this.outputCtx, summary.type.reference,
|
|
|
|
this.serializeSummaryWithDeps(summary, metadata !));
|
2017-04-26 09:24:42 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
exportAs.forEach((entry) => {
|
|
|
|
const symbol = entry.symbol;
|
|
|
|
if (ngModuleSymbols.has(symbol)) {
|
|
|
|
const jitExportAsName = summaryForJitName(entry.exportAs);
|
2017-05-16 16:30:37 -07:00
|
|
|
this.outputCtx.statements.push(
|
|
|
|
o.variable(jitExportAsName).set(this.serializeSummaryRef(symbol)).toDeclStmt(null, [
|
|
|
|
o.StmtModifier.Exported
|
|
|
|
]));
|
2017-04-26 09:24:42 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private serializeSummaryWithDeps(
|
|
|
|
summary: CompileTypeSummary, metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|
|
|
|
|
CompilePipeMetadata|CompileTypeMetadata): o.Expression {
|
|
|
|
const expressions: o.Expression[] = [this.serializeSummary(summary)];
|
|
|
|
let providers: CompileProviderMetadata[] = [];
|
|
|
|
if (metadata instanceof CompileNgModuleMetadata) {
|
|
|
|
expressions.push(...
|
|
|
|
// For directives / pipes, we only add the declared ones,
|
|
|
|
// and rely on transitively importing NgModules to get the transitive
|
|
|
|
// summaries.
|
|
|
|
metadata.declaredDirectives.concat(metadata.declaredPipes)
|
|
|
|
.map(type => type.reference)
|
|
|
|
// For modules,
|
|
|
|
// we also add the summaries for modules
|
|
|
|
// from libraries.
|
|
|
|
// This is ok as we produce reexports for all transitive modules.
|
|
|
|
.concat(metadata.transitiveModule.modules.map(type => type.reference)
|
|
|
|
.filter(ref => ref !== metadata.type.reference))
|
|
|
|
.map((ref) => this.serializeSummaryRef(ref)));
|
|
|
|
// Note: We don't use `NgModuleSummary.providers`, as that one is transitive,
|
|
|
|
// and we already have transitive modules.
|
|
|
|
providers = metadata.providers;
|
|
|
|
} else if (summary.summaryKind === CompileSummaryKind.Directive) {
|
|
|
|
const dirSummary = <CompileDirectiveSummary>summary;
|
|
|
|
providers = dirSummary.providers.concat(dirSummary.viewProviders);
|
|
|
|
}
|
|
|
|
// Note: We can't just refer to the `ngsummary.ts` files for `useClass` providers (as we do for
|
|
|
|
// declaredDirectives / declaredPipes), as we allow
|
|
|
|
// providers without ctor arguments to skip the `@Injectable` decorator,
|
|
|
|
// i.e. we didn't generate .ngsummary.ts files for these.
|
|
|
|
expressions.push(
|
|
|
|
...providers.filter(provider => !!provider.useClass).map(provider => this.serializeSummary({
|
|
|
|
summaryKind: CompileSummaryKind.Injectable, type: provider.useClass
|
|
|
|
} as CompileTypeSummary)));
|
|
|
|
return o.literalArr(expressions);
|
|
|
|
}
|
|
|
|
|
|
|
|
private serializeSummaryRef(typeSymbol: StaticSymbol): o.Expression {
|
|
|
|
const jitImportedSymbol = this.symbolResolver.getStaticSymbol(
|
|
|
|
summaryForJitFileName(typeSymbol.filePath), summaryForJitName(typeSymbol.name));
|
2017-05-16 16:30:37 -07:00
|
|
|
return this.outputCtx.importExpr(jitImportedSymbol);
|
2017-04-26 09:24:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private serializeSummary(data: {[key: string]: any}): o.Expression {
|
2017-05-16 16:30:37 -07:00
|
|
|
const outputCtx = this.outputCtx;
|
|
|
|
|
2017-04-26 09:24:42 -07:00
|
|
|
class Transformer implements ValueVisitor {
|
|
|
|
visitArray(arr: any[], context: any): any {
|
|
|
|
return o.literalArr(arr.map(entry => visitValue(entry, this, context)));
|
|
|
|
}
|
|
|
|
visitStringMap(map: {[key: string]: any}, context: any): any {
|
|
|
|
return new o.LiteralMapExpr(Object.keys(map).map(
|
2017-07-05 14:51:39 -07:00
|
|
|
(key) => new o.LiteralMapEntry(key, visitValue(map[key], this, context), false)));
|
2017-04-26 09:24:42 -07:00
|
|
|
}
|
|
|
|
visitPrimitive(value: any, context: any): any { return o.literal(value); }
|
|
|
|
visitOther(value: any, context: any): any {
|
|
|
|
if (value instanceof StaticSymbol) {
|
2017-05-16 16:30:37 -07:00
|
|
|
return outputCtx.importExpr(value);
|
2017-04-26 09:24:42 -07:00
|
|
|
} else {
|
|
|
|
throw new Error(`Illegal State: Encountered value ${value}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return visitValue(data, new Transformer(), null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class FromJsonDeserializer extends ValueTransformer {
|
2016-12-15 09:12:40 -08:00
|
|
|
private symbols: StaticSymbol[];
|
|
|
|
|
|
|
|
constructor(private symbolCache: StaticSymbolCache) { super(); }
|
|
|
|
|
2016-12-27 09:36:47 -08:00
|
|
|
deserialize(json: string):
|
|
|
|
{summaries: Summary<StaticSymbol>[], importAs: {symbol: StaticSymbol, importAs: string}[]} {
|
2016-12-15 09:12:40 -08:00
|
|
|
const data: {summaries: any[], symbols: any[]} = JSON.parse(json);
|
2016-12-27 09:36:47 -08:00
|
|
|
const importAs: {symbol: StaticSymbol, importAs: string}[] = [];
|
|
|
|
this.symbols = [];
|
|
|
|
data.symbols.forEach((serializedSymbol) => {
|
|
|
|
const symbol = this.symbolCache.get(serializedSymbol.filePath, serializedSymbol.name);
|
|
|
|
this.symbols.push(symbol);
|
|
|
|
if (serializedSymbol.importAs) {
|
|
|
|
importAs.push({symbol: symbol, importAs: serializedSymbol.importAs});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const summaries = visitValue(data.summaries, this, null);
|
|
|
|
return {summaries, importAs};
|
2016-12-15 09:12:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
visitStringMap(map: {[key: string]: any}, context: any): any {
|
|
|
|
if ('__symbol' in map) {
|
2016-12-27 09:36:47 -08:00
|
|
|
const baseSymbol = this.symbols[map['__symbol']];
|
|
|
|
const members = map['members'];
|
|
|
|
return members.length ? this.symbolCache.get(baseSymbol.filePath, baseSymbol.name, members) :
|
|
|
|
baseSymbol;
|
2016-12-15 09:12:40 -08:00
|
|
|
} else {
|
|
|
|
return super.visitStringMap(map, context);
|
|
|
|
}
|
|
|
|
}
|
perf: switch angular to use StaticInjector instead of ReflectiveInjector
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes #18496
2017-08-03 12:33:29 -07:00
|
|
|
}
|