diff --git a/modules/@angular/compiler-cli/integrationtest/src/module.ts b/modules/@angular/compiler-cli/integrationtest/src/module.ts index b8c5429cae..c8469aade3 100644 --- a/modules/@angular/compiler-cli/integrationtest/src/module.ts +++ b/modules/@angular/compiler-cli/integrationtest/src/module.ts @@ -11,13 +11,16 @@ import {BrowserModule} from '@angular/platform-browser'; import {AnimateCmp} from './animate'; import {BasicComp} from './basic'; -import {CompWithPrecompile} from './precompile'; +import {CompWithAnalyzePrecompileProvider, CompWithPrecompile} from './precompile'; import {ProjectingComp} from './projection'; import {CompWithChildQuery} from './queries'; @AppModule({ modules: [BrowserModule], - precompile: [AnimateCmp, BasicComp, CompWithPrecompile, ProjectingComp, CompWithChildQuery] + precompile: [ + AnimateCmp, BasicComp, CompWithPrecompile, CompWithAnalyzePrecompileProvider, ProjectingComp, + CompWithChildQuery + ] }) export class MainModule { constructor(public appRef: ApplicationRef) {} diff --git a/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts b/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts index 1bb5791ca6..0379b0df84 100644 --- a/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts +++ b/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts @@ -7,7 +7,7 @@ */ import {LowerCasePipe, NgIf} from '@angular/common'; -import {AppModule, Component, ComponentFactoryResolver, Injectable} from '@angular/core'; +import {ANALYZE_FOR_PRECOMPILE, AppModule, Component, ComponentFactoryResolver, Inject, Injectable, OpaqueToken} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; @Injectable() @@ -53,3 +53,17 @@ export class SomeModule { }) export class SomeModuleUsingParentComp { } + +export const SOME_TOKEN = new OpaqueToken('someToken'); + +export function provideValueWithPrecompile(value: any) { + return [ + {provide: SOME_TOKEN, useValue: value}, + {provide: ANALYZE_FOR_PRECOMPILE, useValue: value, multi: true}, + ]; +} + +@AppModule({providers: [provideValueWithPrecompile([{a: 'b', component: SomeComp}])]}) +export class SomeModuleWithAnalyzePrecompileProvider { + constructor(@Inject(SOME_TOKEN) public providedValue: any) {} +} diff --git a/modules/@angular/compiler-cli/integrationtest/src/precompile.ts b/modules/@angular/compiler-cli/integrationtest/src/precompile.ts index e6cc5d31bc..0407f7ee1b 100644 --- a/modules/@angular/compiler-cli/integrationtest/src/precompile.ts +++ b/modules/@angular/compiler-cli/integrationtest/src/precompile.ts @@ -6,10 +6,30 @@ * found in the LICENSE file at https://angular.io/license */ -import {Component, ComponentFactoryResolver, Inject, OpaqueToken} from '@angular/core'; +import {ANALYZE_FOR_PRECOMPILE, Component, ComponentFactoryResolver, Inject, OpaqueToken} from '@angular/core'; + import {BasicComp} from './basic'; @Component({selector: 'cmp-precompile', template: '', precompile: [BasicComp]}) export class CompWithPrecompile { constructor(public cfr: ComponentFactoryResolver) {} } + +export const SOME_TOKEN = new OpaqueToken('someToken'); + +export function provideValueWithPrecompile(value: any) { + return [ + {provide: SOME_TOKEN, useValue: value}, + {provide: ANALYZE_FOR_PRECOMPILE, useValue: value, multi: true}, + ]; +} + +@Component({ + selector: 'comp-precompile-provider', + template: '', + providers: [provideValueWithPrecompile([{a: 'b', component: BasicComp}])] +}) +export class CompWithAnalyzePrecompileProvider { + constructor(public cfr: ComponentFactoryResolver, @Inject(SOME_TOKEN) public providedValue: any) { + } +} diff --git a/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts index 8c58578deb..a965f3745b 100644 --- a/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts +++ b/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts @@ -7,7 +7,7 @@ */ import './init'; import {NestedModule, NestedService, ParentComp, SomeComp, SomeModule, SomeService} from '../src/module_fixtures'; -import {SomeModuleNgFactory, SomeModuleUsingParentCompNgFactory} from '../src/module_fixtures.ngfactory'; +import {SomeModuleNgFactory, SomeModuleUsingParentCompNgFactory, SomeModuleWithAnalyzePrecompileProviderNgFactory} from '../src/module_fixtures.ngfactory'; import {createComponent, createModule} from './util'; describe('AppModule', () => { @@ -26,6 +26,15 @@ describe('AppModule', () => { expect(compRef.instance instanceof SomeComp).toBe(true); }); + it('should support precompile via the ANALYZE_FOR_PRECOMPILE provider and function providers in components', + () => { + const moduleRef = createModule(SomeModuleWithAnalyzePrecompileProviderNgFactory); + const cf = moduleRef.componentFactoryResolver.resolveComponentFactory(SomeComp); + expect(cf.componentType).toBe(SomeComp); + // check that the function call that created the provider for ANALYZE_FOR_PRECOMPILE worked. + expect(moduleRef.instance.providedValue).toEqual([{a: 'b', component: SomeComp}]); + }); + it('should support module directives and pipes', () => { var compFixture = createComponent(SomeComp, SomeModuleNgFactory); var debugElement = compFixture.debugElement; diff --git a/modules/@angular/compiler-cli/integrationtest/test/precompile_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/precompile_spec.ts index c9dc1679ac..d606cd9a3c 100644 --- a/modules/@angular/compiler-cli/integrationtest/test/precompile_spec.ts +++ b/modules/@angular/compiler-cli/integrationtest/test/precompile_spec.ts @@ -7,14 +7,27 @@ */ import './init'; + import {BasicComp} from '../src/basic'; -import {CompWithPrecompile} from '../src/precompile'; +import {CompWithAnalyzePrecompileProvider, CompWithPrecompile} from '../src/precompile'; + import {createComponent} from './util'; describe('content projection', () => { - it('should support basic content projection', () => { + it('should support precompile in components', () => { var compFixture = createComponent(CompWithPrecompile); var cf = compFixture.componentInstance.cfr.resolveComponentFactory(BasicComp); expect(cf.componentType).toBe(BasicComp); }); + + it('should support precompile via the ANALYZE_FOR_PRECOMPILE provider and function providers in components', + () => { + const compFixture = createComponent(CompWithAnalyzePrecompileProvider); + const cf = compFixture.componentInstance.cfr.resolveComponentFactory(BasicComp); + expect(cf.componentType).toBe(BasicComp); + // check that the function call that created the provider for ANALYZE_FOR_PRECOMPILE worked. + expect(compFixture.componentInstance.providedValue).toEqual([ + {a: 'b', component: BasicComp} + ]); + }); }); diff --git a/modules/@angular/compiler/src/identifiers.ts b/modules/@angular/compiler/src/identifiers.ts index 0f72d3b24c..f97f6d3e91 100644 --- a/modules/@angular/compiler/src/identifiers.ts +++ b/modules/@angular/compiler/src/identifiers.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {AppModuleFactory, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core'; +import {ANALYZE_FOR_PRECOMPILE, AppModuleFactory, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core'; import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppModuleInjector, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles, uninitialized} from '../core_private'; @@ -58,6 +58,11 @@ var impNoOpAnimationPlayer = NoOpAnimationPlayer_; var ANIMATION_STYLE_UTIL_ASSET_URL = assetUrl('core', 'animation/animation_style_util'); export class Identifiers { + static ANALYZE_FOR_PRECOMPILE = new CompileIdentifierMetadata({ + name: 'ANALYZE_FOR_PRECOMPILE', + moduleUrl: assetUrl('core', 'metadata/di'), + runtime: ANALYZE_FOR_PRECOMPILE + }); static ViewUtils = new CompileIdentifierMetadata( {name: 'ViewUtils', moduleUrl: assetUrl('core', 'linker/view_utils'), runtime: impViewUtils}); static AppView = new CompileIdentifierMetadata( diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts index 5f50985bfe..eb2623491e 100644 --- a/modules/@angular/compiler/src/metadata_resolver.ts +++ b/modules/@angular/compiler/src/metadata_resolver.ts @@ -18,6 +18,7 @@ import * as cpl from './compile_metadata'; import {CompilerConfig} from './config'; import {hasLifecycleHook} from './directive_lifecycle_reflector'; import {DirectiveResolver} from './directive_resolver'; +import {Identifiers, identifierToken} from './identifiers'; import {PipeResolver} from './pipe_resolver'; import {getUrlScheme} from './url_resolver'; import {MODULE_SUFFIX, ValueTransformer, sanitizeIdentifier, visitValue} from './util'; @@ -137,7 +138,7 @@ export class CompileMetadataResolver { changeDetectionStrategy = cmpMeta.changeDetection; if (isPresent(dirMeta.viewProviders)) { viewProviders = this.getProvidersMetadata( - verifyNonBlankProviders(directiveType, dirMeta.viewProviders, 'viewProviders')); + verifyNonBlankProviders(directiveType, dirMeta.viewProviders, 'viewProviders'), []); } moduleUrl = componentModuleUrl(this._reflector, directiveType, cmpMeta); if (cmpMeta.precompile) { @@ -149,10 +150,11 @@ export class CompileMetadataResolver { var providers: any[] /** TODO #9100 */ = []; if (isPresent(dirMeta.providers)) { providers = this.getProvidersMetadata( - verifyNonBlankProviders(directiveType, dirMeta.providers, 'providers')); + verifyNonBlankProviders(directiveType, dirMeta.providers, 'providers'), + precompileTypes); } - var queries: any[] /** TODO #9100 */ = []; - var viewQueries: any[] /** TODO #9100 */ = []; + var queries: cpl.CompileQueryMetadata[] = []; + var viewQueries: cpl.CompileQueryMetadata[] = []; if (isPresent(dirMeta.queries)) { queries = this.getQueriesMetadata(dirMeta.queries, false, directiveType); viewQueries = this.getQueriesMetadata(dirMeta.queries, true, directiveType); @@ -214,7 +216,7 @@ export class CompileMetadataResolver { } if (meta.providers) { - providers.push(...this.getProvidersMetadata(meta.providers)); + providers.push(...this.getProvidersMetadata(meta.providers, precompile)); } if (meta.directives) { directives.push(...flattenArray(meta.directives) @@ -410,23 +412,54 @@ export class CompileMetadataResolver { return compileToken; } - getProvidersMetadata(providers: any[]): + getProvidersMetadata(providers: any[], targetPrecompileComponents: cpl.CompileTypeMetadata[]): Array { - return providers.map((provider) => { + const compileProviders: Array = []; + providers.forEach((provider) => { provider = resolveForwardRef(provider); + if (isProviderLiteral(provider)) { + provider = createProvider(provider); + } + let compileProvider: cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]; if (isArray(provider)) { - return this.getProvidersMetadata(provider); + compileProvider = this.getProvidersMetadata(provider, targetPrecompileComponents); } else if (provider instanceof Provider) { - return this.getProviderMetadata(provider); - } else if (isProviderLiteral(provider)) { - return this.getProviderMetadata(createProvider(provider)); + let tokenMeta = this.getTokenMetadata(provider.token); + if (tokenMeta.equalsTo(identifierToken(Identifiers.ANALYZE_FOR_PRECOMPILE))) { + targetPrecompileComponents.push(...this.getPrecompileComponentsFromProvider(provider)); + } else { + compileProvider = this.getProviderMetadata(provider); + } } else if (isValidType(provider)) { - return this.getTypeMetadata(provider, staticTypeModuleUrl(provider)); + compileProvider = this.getTypeMetadata(provider, staticTypeModuleUrl(provider)); } else { throw new BaseException( `Invalid provider - only instances of Provider and Type are allowed, got: ${stringify(provider)}`); } + if (compileProvider) { + compileProviders.push(compileProvider); + } }); + return compileProviders; + } + + getPrecompileComponentsFromProvider(provider: Provider): cpl.CompileTypeMetadata[] { + let components: cpl.CompileTypeMetadata[] = []; + let collectedIdentifiers: cpl.CompileIdentifierMetadata[] = []; + if (provider.useFactory || provider.useExisting || provider.useClass) { + throw new BaseException(`The ANALYZE_FOR_PRECOMPILE token only supports useValue!`); + } + if (!provider.multi) { + throw new BaseException(`The ANALYZE_FOR_PRECOMPILE token only supports 'multi = true'!`); + } + convertToCompileValue(provider.useValue, collectedIdentifiers); + collectedIdentifiers.forEach((identifier) => { + let dirMeta = this.maybeGetDirectiveMetadata(identifier.runtime); + if (dirMeta) { + components.push(dirMeta.type); + } + }); + return components; } getProviderMetadata(provider: Provider): cpl.CompileProviderMetadata { @@ -447,7 +480,7 @@ export class CompileMetadataResolver { return new cpl.CompileProviderMetadata({ token: this.getTokenMetadata(provider.token), useClass: compileTypeMetadata, - useValue: convertToCompileValue(provider.useValue), + useValue: convertToCompileValue(provider.useValue, []), useFactory: compileFactoryMetadata, useExisting: isPresent(provider.useExisting) ? this.getTokenMetadata(provider.useExisting) : null, @@ -566,17 +599,21 @@ function componentModuleUrl( return reflector.importUri(type); } -// Only fill CompileIdentifierMetadata.runtime if needed... -function convertToCompileValue(value: any): any { - return visitValue(value, new _CompileValueConverter(), null); +function convertToCompileValue( + value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]): any { + return visitValue(value, new _CompileValueConverter(), targetIdentifiers); } class _CompileValueConverter extends ValueTransformer { - visitOther(value: any, context: any): any { + visitOther(value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]): any { + let identifier: cpl.CompileIdentifierMetadata; if (cpl.isStaticSymbol(value)) { - return new cpl.CompileIdentifierMetadata({name: value.name, moduleUrl: value.filePath}); + identifier = new cpl.CompileIdentifierMetadata( + {name: value.name, moduleUrl: value.filePath, runtime: value}); } else { - return new cpl.CompileIdentifierMetadata({runtime: value}); + identifier = new cpl.CompileIdentifierMetadata({runtime: value}); } + targetIdentifiers.push(identifier); + return identifier; } } diff --git a/modules/@angular/core/src/metadata.ts b/modules/@angular/core/src/metadata.ts index bdf52d8405..99d8c384c2 100644 --- a/modules/@angular/core/src/metadata.ts +++ b/modules/@angular/core/src/metadata.ts @@ -20,7 +20,7 @@ import {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerM import {ViewEncapsulation, ViewMetadata} from './metadata/view'; export {AppModuleMetadata} from './metadata/app_module'; -export {AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di'; +export {ANALYZE_FOR_PRECOMPILE, AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di'; export {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata} from './metadata/directives'; export {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, DoCheck, OnChanges, OnDestroy, OnInit} from './metadata/lifecycle_hooks'; export {ViewEncapsulation, ViewMetadata} from './metadata/view'; diff --git a/modules/@angular/core/src/metadata/di.ts b/modules/@angular/core/src/metadata/di.ts index 7eb2ac002d..58666a1ded 100644 --- a/modules/@angular/core/src/metadata/di.ts +++ b/modules/@angular/core/src/metadata/di.ts @@ -8,8 +8,44 @@ import {resolveForwardRef} from '../di/forward_ref'; import {DependencyMetadata} from '../di/metadata'; +import {OpaqueToken} from '../di/opaque_token'; import {StringWrapper, Type, isString, stringify} from '../facade/lang'; +/** + * This token can be used to create a virtual provider that will populate the + * `precompile` fields of components and app modules based on its `useValue`. + * All components that are referenced in the `useValue` value (either directly + * or in a nested array or map) will be added to the `precompile` property. + * + * ### Example + * The following example shows how the router can populate the `precompile` + * field of an AppModule based on the router configuration which refers + * to components. + * + * ```typescript + * // helper function inside the router + * function provideRoutes(routes) { + * return [ + * {provide: ROUTES, useValue: routes}, + * {provide: ANALYZE_FOR_PRECOMPILE, useValue: routes, multi: true} + * ]; + * } + * + * // user code + * let routes = [ + * {path: '/root', component: RootComp}, + * {path: /teams', component: TeamsComp} + * ]; + * + * @AppModule({ + * providers: [provideRoutes(routes)] + * }) + * class ModuleWithRoutes {} + * ``` + * + * @experimental + */ +export const ANALYZE_FOR_PRECOMPILE = new OpaqueToken('AnalyzeForPrecompile'); /** * Specifies that a constant attribute value should be injected. diff --git a/modules/@angular/core/test/linker/app_module_integration_spec.ts b/modules/@angular/core/test/linker/app_module_integration_spec.ts index fa64a8b021..5d3a551165 100644 --- a/modules/@angular/core/test/linker/app_module_integration_spec.ts +++ b/modules/@angular/core/test/linker/app_module_integration_spec.ts @@ -1,6 +1,6 @@ import {LowerCasePipe, NgIf} from '@angular/common'; import {CompilerConfig} from '@angular/compiler'; -import {AppModule, AppModuleMetadata, Compiler, Component, ComponentFactoryResolver, ComponentRef, ComponentResolver, DebugElement, Host, Inject, Injectable, Injector, OpaqueToken, Optional, Provider, ReflectiveInjector, SelfMetadata, SkipSelf, SkipSelfMetadata, forwardRef, getDebugNode, provide} from '@angular/core'; +import {ANALYZE_FOR_PRECOMPILE, AppModule, AppModuleMetadata, Compiler, Component, ComponentFactoryResolver, ComponentRef, ComponentResolver, DebugElement, Host, Inject, Injectable, Injector, OpaqueToken, Optional, Provider, ReflectiveInjector, SelfMetadata, SkipSelf, SkipSelfMetadata, forwardRef, getDebugNode, provide} from '@angular/core'; import {ComponentFixture, configureCompiler} from '@angular/core/testing'; import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal'; @@ -87,6 +87,14 @@ class SomeComp { class ModuleWithPrecompile { } +@AppModule({ + providers: + [{provide: ANALYZE_FOR_PRECOMPILE, multi: true, useValue: [{a: 'b', component: SomeComp}]}] +}) +class ModuleWithAnalyzePrecompileProvider { +} + + @Component({ selector: 'comp', template: `
` @@ -137,6 +145,16 @@ function declareTests({useJit}: {useJit: boolean}) { .toBe(SomeComp); }); + it('should resolve ComponentFactories via ANALYZE_FOR_PRECOMPILE', () => { + let appModule = compiler.compileAppModuleSync(ModuleWithAnalyzePrecompileProvider).create(); + expect(appModule.componentFactoryResolver.resolveComponentFactory(SomeComp).componentType) + .toBe(SomeComp); + expect(appModule.injector.get(ComponentFactoryResolver) + .resolveComponentFactory(SomeComp) + .componentType) + .toBe(SomeComp); + }); + it('should resolve ComponentFactories for nested modules', () => { let appModule = compiler diff --git a/modules/@angular/core/test/linker/precompile_integration_spec.ts b/modules/@angular/core/test/linker/precompile_integration_spec.ts index aa6305bce2..1cf19d0ff4 100644 --- a/modules/@angular/core/test/linker/precompile_integration_spec.ts +++ b/modules/@angular/core/test/linker/precompile_integration_spec.ts @@ -10,7 +10,7 @@ import {beforeEach, ddescribe, xdescribe, describe, expect, iit, inject, beforeE import {TestComponentBuilder} from '@angular/compiler/testing'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; -import {Component, ViewChild, ViewContainerRef, ComponentFactoryResolver, NoComponentFactoryError, ComponentRef, forwardRef} from '@angular/core'; +import {Component, ViewChild, ViewContainerRef, ComponentFactoryResolver, NoComponentFactoryError, ComponentRef, forwardRef, ANALYZE_FOR_PRECOMPILE} from '@angular/core'; import {CompilerConfig} from '@angular/compiler'; export function main() { @@ -34,6 +34,17 @@ function declareTests({useJit}: {useJit: boolean}) { }); })); + + it('should resolve ComponentFactories via ANALYZE_FOR_PRECOMPILE', + inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + let compFixture = tcb.createSync(CompWithAnalyzePrecompileProvider); + let mainComp: CompWithAnalyzePrecompileProvider = compFixture.componentInstance; + let cfr: ComponentFactoryResolver = + compFixture.debugElement.injector.get(ComponentFactoryResolver); + expect(cfr.resolveComponentFactory(ChildComp).componentType).toBe(ChildComp); + expect(cfr.resolveComponentFactory(NestedChildComp).componentType).toBe(NestedChildComp); + })); + it('should be able to get a component form a parent component (view hiearchy)', inject( [TestComponentBuilder, AsyncTestCompleter], @@ -70,6 +81,7 @@ function declareTests({useJit}: {useJit: boolean}) { async.done(); }); })); + }); } @@ -98,3 +110,18 @@ class ChildComp { class MainComp { constructor(public cfr: ComponentFactoryResolver) {} } + +@Component({ + selector: 'comp-with-analyze', + template: '', + providers: [{ + provide: ANALYZE_FOR_PRECOMPILE, + multi: true, + useValue: [ + {a: 'b', component: ChildComp}, + {b: 'c', anotherComponent: NestedChildComp}, + ] + }] +}) +class CompWithAnalyzePrecompileProvider { +} diff --git a/tools/public_api_guard/core/index.d.ts b/tools/public_api_guard/core/index.d.ts index 453f3be29d..ac362694cf 100644 --- a/tools/public_api_guard/core/index.d.ts +++ b/tools/public_api_guard/core/index.d.ts @@ -25,6 +25,9 @@ export declare abstract class AfterViewInit { abstract ngAfterViewInit(): any; } +/** @experimental */ +export declare const ANALYZE_FOR_PRECOMPILE: OpaqueToken; + /** @experimental */ export declare function animate(timing: string | number, styles?: AnimationStyleMetadata | AnimationKeyframesSequenceMetadata): AnimationAnimateMetadata;