diff --git a/modules/@angular/compiler/src/compile_metadata.ts b/modules/@angular/compiler/src/compile_metadata.ts index 17b5f45c66..57ddb1b1e6 100644 --- a/modules/@angular/compiler/src/compile_metadata.ts +++ b/modules/@angular/compiler/src/compile_metadata.ts @@ -410,7 +410,7 @@ export class CompileTemplateMetadata { export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier { static create( {type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host, providers, - viewProviders, queries, viewQueries, entryComponents, viewDirectives, viewPipes, template}: { + viewProviders, queries, viewQueries, entryComponents, template}: { type?: CompileTypeMetadata, isComponent?: boolean, selector?: string, @@ -479,8 +479,6 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier { queries, viewQueries, entryComponents, - viewDirectives, - viewPipes, template, }); } @@ -500,17 +498,13 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier { viewQueries: CompileQueryMetadata[]; // Note: Need to keep types here to prevent cycles! entryComponents: CompileTypeMetadata[]; - // Note: Need to keep types here to prevent cycles! - viewDirectives: CompileTypeMetadata[]; - // Note: Need to keep types here to prevent cycles! - viewPipes: CompileTypeMetadata[]; template: CompileTemplateMetadata; constructor( {type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners, hostProperties, hostAttributes, providers, viewProviders, queries, viewQueries, - entryComponents, viewDirectives, viewPipes, template}: { + entryComponents, template}: { type?: CompileTypeMetadata, isComponent?: boolean, selector?: string, @@ -547,8 +541,6 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier { this.queries = _normalizeArray(queries); this.viewQueries = _normalizeArray(viewQueries); this.entryComponents = _normalizeArray(entryComponents); - this.viewDirectives = _normalizeArray(viewDirectives); - this.viewPipes = _normalizeArray(viewPipes); this.template = template; } diff --git a/modules/@angular/compiler/src/directive_resolver.ts b/modules/@angular/compiler/src/directive_resolver.ts index 52a5d83cca..e20280cdbb 100644 --- a/modules/@angular/compiler/src/directive_resolver.ts +++ b/modules/@angular/compiler/src/directive_resolver.ts @@ -142,8 +142,6 @@ export class DirectiveResolver { providers: dm.providers, viewProviders: dm.viewProviders, entryComponents: dm.entryComponents, - directives: dm.directives, - pipes: dm.pipes, template: dm.template, templateUrl: dm.templateUrl, styles: dm.styles, diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts index 1e36b659c7..273c5c8021 100644 --- a/modules/@angular/compiler/src/metadata_resolver.ts +++ b/modules/@angular/compiler/src/metadata_resolver.ts @@ -8,12 +8,11 @@ import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, AttributeMetadata, ChangeDetectionStrategy, ComponentMetadata, HostMetadata, InjectMetadata, Injectable, ModuleWithProviders, OptionalMetadata, Provider, QueryMetadata, SchemaMetadata, SelfMetadata, SkipSelfMetadata, Type, ViewQueryMetadata, resolveForwardRef} from '@angular/core'; -import {Console, LIFECYCLE_HOOKS_VALUES, ReflectorReader, reflector} from '../core_private'; +import {LIFECYCLE_HOOKS_VALUES, ReflectorReader, reflector} from '../core_private'; import {StringMapWrapper} from '../src/facade/collection'; import {assertArrayOfStrings, assertInterpolationSymbols} from './assertions'; import * as cpl from './compile_metadata'; -import {CompilerConfig} from './config'; import {DirectiveResolver} from './directive_resolver'; import {BaseException} from './facade/exceptions'; import {isArray, isBlank, isPresent, isString, stringify} from './facade/lang'; @@ -36,8 +35,7 @@ export class CompileMetadataResolver { constructor( private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver, - private _pipeResolver: PipeResolver, private _config: CompilerConfig, - private _console: Console, private _schemaRegistry: ElementSchemaRegistry, + private _pipeResolver: PipeResolver, private _schemaRegistry: ElementSchemaRegistry, private _reflector: ReflectorReader = reflector) {} private sanitizeTokenName(token: any): string { @@ -124,9 +122,7 @@ export class CompileMetadataResolver { var changeDetectionStrategy: ChangeDetectionStrategy = null; var viewProviders: Array = []; var moduleUrl = staticTypeModuleUrl(directiveType); - var viewDirectiveTypes: cpl.CompileTypeMetadata[] = []; - var viewPipeTypes: cpl.CompileTypeMetadata[] = []; - var entryComponentTypes: cpl.CompileTypeMetadata[] = []; + var entryComponentMetadata: cpl.CompileTypeMetadata[] = []; let selector = dirMeta.selector; if (dirMeta instanceof ComponentMetadata) { var cmpMeta = dirMeta; @@ -150,32 +146,15 @@ export class CompileMetadataResolver { changeDetectionStrategy = cmpMeta.changeDetection; if (isPresent(dirMeta.viewProviders)) { viewProviders = this.getProvidersMetadata( - verifyNonBlankProviders(directiveType, dirMeta.viewProviders, 'viewProviders'), []); + verifyNonBlankProviders(directiveType, dirMeta.viewProviders, 'viewProviders'), + entryComponentMetadata); } moduleUrl = componentModuleUrl(this._reflector, directiveType, cmpMeta); if (cmpMeta.entryComponents) { - entryComponentTypes = + entryComponentMetadata = flattenArray(cmpMeta.entryComponents) - .map((type) => this.getTypeMetadata(type, staticTypeModuleUrl(type))); - } - if (cmpMeta.directives) { - viewDirectiveTypes = flattenArray(cmpMeta.directives).map((type) => { - if (!type) { - throw new BaseException( - `Unexpected directive value '${type}' on the View of component '${stringify(directiveType)}'`); - } - - return this.getTypeMetadata(type, staticTypeModuleUrl(type)); - }); - } - if (cmpMeta.pipes) { - viewPipeTypes = flattenArray(cmpMeta.pipes).map((type) => { - if (!type) { - throw new BaseException( - `Unexpected pipe value '${type}' on the View of component '${stringify(directiveType)}'`); - } - return this.getTypeMetadata(type, staticTypeModuleUrl(type)); - }); + .map((type) => this.getTypeMetadata(type, staticTypeModuleUrl(type))) + .concat(entryComponentMetadata); } if (!selector) { selector = this._schemaRegistry.getDefaultComponentElementName(); @@ -191,7 +170,7 @@ export class CompileMetadataResolver { if (isPresent(dirMeta.providers)) { providers = this.getProvidersMetadata( verifyNonBlankProviders(directiveType, dirMeta.providers, 'providers'), - entryComponentTypes); + entryComponentMetadata); } var queries: cpl.CompileQueryMetadata[] = []; var viewQueries: cpl.CompileQueryMetadata[] = []; @@ -213,9 +192,7 @@ export class CompileMetadataResolver { viewProviders: viewProviders, queries: queries, viewQueries: viewQueries, - viewDirectives: viewDirectiveTypes, - viewPipes: viewPipeTypes, - entryComponents: entryComponentTypes + entryComponents: entryComponentMetadata }); this._directiveCache.set(directiveType, meta); } @@ -359,19 +336,6 @@ export class CompileMetadataResolver { return compileMeta; } - addComponentToModule(moduleType: Type, compType: Type) { - const moduleMeta = this.getNgModuleMetadata(moduleType); - // Collect @Component.directives/pipes/entryComponents into our declared directives/pipes. - const compMeta = this.getDirectiveMetadata(compType, false); - this._addDirectiveToModule( - compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule, - moduleMeta.declaredDirectives); - - moduleMeta.transitiveModule.entryComponents.push(compMeta.type); - moduleMeta.entryComponents.push(compMeta.type); - - this._verifyModule(moduleMeta); - } private _verifyModule(moduleMeta: cpl.CompileNgModuleMetadata) { moduleMeta.exportedDirectives.forEach((dirMeta) => { @@ -386,17 +350,6 @@ export class CompileMetadataResolver { `Can't export pipe ${stringify(pipeMeta.type.runtime)} from ${stringify(moduleMeta.type.runtime)} as it was neither declared nor imported!`); } }); - moduleMeta.entryComponents.forEach((entryComponentType) => { - if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) { - throw new BaseException( - `NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(entryComponentType.runtime)} via "entryComponents" but it was neither declared nor imported! If ${stringify(entryComponentType.runtime)} is declared in an imported module, make sure it is exported.`); - } - }); - // Collect @Component.directives/pipes/entryComponents into our declared - // directives/pipes. Do this last so that directives added by previous steps - // are considered as well! - moduleMeta.declaredDirectives.forEach( - (dirMeta) => { this._getTransitiveViewDirectivesAndPipes(dirMeta, moduleMeta); }); } private _getTypeDescriptor(type: Type): string { @@ -422,41 +375,6 @@ export class CompileMetadataResolver { this._ngModuleOfTypes.set(type, moduleType); } - - private _getTransitiveViewDirectivesAndPipes( - compMeta: cpl.CompileDirectiveMetadata, moduleMeta: cpl.CompileNgModuleMetadata) { - if (!compMeta.isComponent) { - return; - } - const addPipe = (pipeType: Type) => { - const pipeMeta = this.getPipeMetadata(pipeType); - this._addPipeToModule( - pipeMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule, moduleMeta.declaredPipes); - }; - - const addDirective = (dirType: Type) => { - const dirMeta = this.getDirectiveMetadata(dirType); - if (this._addDirectiveToModule( - dirMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule, - moduleMeta.declaredDirectives)) { - this._getTransitiveViewDirectivesAndPipes(dirMeta, moduleMeta); - } - }; - if (compMeta.viewPipes) { - compMeta.viewPipes.forEach((cplType) => addPipe(cplType.runtime)); - } - if (compMeta.viewDirectives) { - compMeta.viewDirectives.forEach((cplType) => addDirective(cplType.runtime)); - } - compMeta.entryComponents.forEach((entryComponentType) => { - if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) { - this._console.warn( - `Component ${stringify(compMeta.type.runtime)} in NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(entryComponentType.runtime)} via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final.`); - addDirective(entryComponentType.runtime); - } - }); - } - private _getTransitiveNgModuleMetadata( importedModules: cpl.CompileNgModuleMetadata[], exportedModules: cpl.CompileNgModuleMetadata[]): cpl.TransitiveCompileNgModuleMetadata { diff --git a/modules/@angular/compiler/src/runtime_compiler.ts b/modules/@angular/compiler/src/runtime_compiler.ts index 7aae1ed20b..180358d1bc 100644 --- a/modules/@angular/compiler/src/runtime_compiler.ts +++ b/modules/@angular/compiler/src/runtime_compiler.ts @@ -46,8 +46,7 @@ export class RuntimeCompiler implements Compiler { private _injector: Injector, private _metadataResolver: CompileMetadataResolver, private _templateNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler, - private _ngModuleCompiler: NgModuleCompiler, private _compilerConfig: CompilerConfig, - private _console: Console) {} + private _ngModuleCompiler: NgModuleCompiler, private _compilerConfig: CompilerConfig) {} get injector(): Injector { return this._injector; } @@ -68,23 +67,6 @@ export class RuntimeCompiler implements Compiler { return this._compileModuleAndAllComponents(moduleType, false).asyncResult; } - compileComponentAsync(compType: Type, ngModule: Type = null): - Promise> { - if (!ngModule) { - throw new BaseException( - `Calling compileComponentAsync on the root compiler without a module is not allowed! (Compiling component ${stringify(compType)})`); - } - return this._compileComponentInModule(compType, false, ngModule).asyncResult; - } - - compileComponentSync(compType: Type, ngModule: Type = null): ComponentFactory { - if (!ngModule) { - throw new BaseException( - `Calling compileComponentSync on the root compiler without a module is not allowed! (Compiling component ${stringify(compType)})`); - } - return this._compileComponentInModule(compType, true, ngModule).syncResult; - } - private _compileModuleAndComponents(moduleType: Type, isSync: boolean): SyncAsyncResult> { const componentPromise = this._compileComponents(moduleType, isSync); @@ -146,17 +128,6 @@ export class RuntimeCompiler implements Compiler { return ngModuleFactory; } - private _compileComponentInModule(compType: Type, isSync: boolean, moduleType: Type): - SyncAsyncResult> { - this._metadataResolver.addComponentToModule(moduleType, compType); - - const componentPromise = this._compileComponents(moduleType, isSync); - const componentFactory: ComponentFactory = - this._assertComponentKnown(compType, true).proxyComponentFactory; - - return new SyncAsyncResult(componentFactory, componentPromise.then(() => componentFactory)); - } - /** * @internal */ @@ -172,10 +143,13 @@ export class RuntimeCompiler implements Compiler { dirMeta.entryComponents.forEach((entryComponentType) => { templates.add(this._createCompiledHostTemplate(entryComponentType.runtime)); }); + // TODO: what about entryComponents of entryComponents? maybe skip here and just do the + // below? } }); localModuleMeta.entryComponents.forEach((entryComponentType) => { templates.add(this._createCompiledHostTemplate(entryComponentType.runtime)); + // TODO: what about entryComponents of entryComponents? }); }); templates.forEach((template) => { @@ -248,8 +222,13 @@ export class RuntimeCompiler implements Compiler { const compiledTemplate = isHost ? this._compiledHostTemplateCache.get(compType) : this._compiledTemplateCache.get(compType); if (!compiledTemplate) { - throw new BaseException( - `Illegal state: CompiledTemplate for ${stringify(compType)} (isHost: ${isHost}) does not exist!`); + if (isHost) { + throw new BaseException( + `Illegal state: Compiled view for component ${stringify(compType)} does not exist!`); + } else { + throw new BaseException( + `Component ${stringify(compType)} is not part of any NgModule or the module has not been imported into your module.`); + } } return compiledTemplate; } @@ -403,15 +382,6 @@ class ModuleBoundCompiler implements Compiler { get _injector(): Injector { return this._delegate.injector; } - compileComponentAsync(compType: Type, ngModule: Type = null): - Promise> { - return this._delegate.compileComponentAsync(compType, ngModule ? ngModule : this._ngModule); - } - - compileComponentSync(compType: Type, ngModule: Type = null): ComponentFactory { - return this._delegate.compileComponentSync(compType, ngModule ? ngModule : this._ngModule); - } - compileModuleSync(moduleType: Type): NgModuleFactory { return this._delegate.compileModuleSync(moduleType); } diff --git a/modules/@angular/compiler/test/directive_resolver_mock_spec.ts b/modules/@angular/compiler/test/directive_resolver_mock_spec.ts index 12491fd751..9855ee4f97 100644 --- a/modules/@angular/compiler/test/directive_resolver_mock_spec.ts +++ b/modules/@angular/compiler/test/directive_resolver_mock_spec.ts @@ -6,17 +6,21 @@ * found in the LICENSE file at https://angular.io/license */ -import {Component, ComponentMetadata, Injector} from '@angular/core'; -import {beforeEach, ddescribe, describe, expect, iit, inject, it} from '@angular/core/testing/testing_internal'; +import {Component, ComponentMetadata, Directive, Injector} from '@angular/core'; +import {TestBed, inject} from '@angular/core/testing'; import {ViewMetadata} from '../core_private'; -import {isBlank, stringify} from '../src/facade/lang'; import {MockDirectiveResolver} from '../testing'; export function main() { describe('MockDirectiveResolver', () => { var dirResolver: MockDirectiveResolver; + beforeEach(() => { + TestBed.configureTestingModule( + {declarations: [SomeDirective, SomeOtherDirective, SomeComponent]}); + }); + beforeEach(inject([Injector], (injector: Injector) => { dirResolver = new MockDirectiveResolver(injector); })); @@ -40,14 +44,12 @@ export function main() { it('should fallback to the default ViewResolver when templates are not overridden', () => { var view = dirResolver.resolve(SomeComponent); expect(view.template).toEqual('template'); - expect(view.directives).toEqual([SomeDirective]); }); it('should allow overriding the @View', () => { dirResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'})); var view = dirResolver.resolve(SomeComponent); expect(view.template).toEqual('overridden template'); - expect(isBlank(view.directives)).toBe(true); }); it('should allow overriding a view after it has been resolved', () => { @@ -55,7 +57,6 @@ export function main() { dirResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'})); var view = dirResolver.resolve(SomeComponent); expect(view.template).toEqual('overridden template'); - expect(isBlank(view.directives)).toBe(true); }); }); @@ -64,7 +65,6 @@ export function main() { dirResolver.setInlineTemplate(SomeComponent, 'overridden template'); var view = dirResolver.resolve(SomeComponent); expect(view.template).toEqual('overridden template'); - expect(view.directives).toEqual([SomeDirective]); }); it('should allow overriding an overridden @View', () => { @@ -81,50 +81,17 @@ export function main() { expect(view.template).toEqual('overridden template'); }); }); - - - describe('Directive overriding', () => { - it('should allow overriding a directive from the default view', () => { - dirResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective); - var view = dirResolver.resolve(SomeComponent); - expect(view.directives.length).toEqual(1); - expect(view.directives[0]).toBe(SomeOtherDirective); - }); - - it('should allow overriding a directive from an overridden @View', () => { - dirResolver.setView(SomeComponent, new ViewMetadata({directives: [SomeOtherDirective]})); - dirResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeComponent); - var view = dirResolver.resolve(SomeComponent); - expect(view.directives.length).toEqual(1); - expect(view.directives[0]).toBe(SomeComponent); - }); - - it('should throw when the overridden directive is not present', () => { - dirResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeDirective); - expect(() => { dirResolver.resolve(SomeComponent); }) - .toThrowError( - `Overriden directive ${stringify(SomeOtherDirective)} not found in the template of ${stringify(SomeComponent)}`); - }); - - it('should allow overriding a directive after its view has been resolved', () => { - dirResolver.resolve(SomeComponent); - dirResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective); - var view = dirResolver.resolve(SomeComponent); - expect(view.directives.length).toEqual(1); - expect(view.directives[0]).toBe(SomeOtherDirective); - }); - }); }); } -class SomeDirective {} +@Directive({selector: 'some-directive'}) +class SomeDirective { +} -@Component({ - selector: 'cmp', - template: 'template', - directives: [SomeDirective], -}) +@Component({selector: 'cmp', template: 'template'}) class SomeComponent { } -class SomeOtherDirective {} +@Directive({selector: 'some-other-directive'}) +class SomeOtherDirective { +} diff --git a/modules/@angular/compiler/test/directive_resolver_spec.ts b/modules/@angular/compiler/test/directive_resolver_spec.ts index ca514e8a4e..ab53062f00 100644 --- a/modules/@angular/compiler/test/directive_resolver_spec.ts +++ b/modules/@angular/compiler/test/directive_resolver_spec.ts @@ -104,16 +104,7 @@ class SomeDirectiveWithViewChild { c: any; } -class SomeDir {} -class SomePipe {} - -@Component({ - selector: 'sample', - template: 'some template', - directives: [SomeDir], - pipes: [SomePipe], - styles: ['some styles'] -}) +@Component({selector: 'sample', template: 'some template', styles: ['some styles']}) class ComponentWithTemplate { } @@ -236,8 +227,6 @@ export function main() { it('should read out the template related metadata from the Component metadata', () => { var compMetadata = resolver.resolve(ComponentWithTemplate); expect(compMetadata.template).toEqual('some template'); - expect(compMetadata.directives).toEqual([SomeDir]); - expect(compMetadata.pipes).toEqual([SomePipe]); expect(compMetadata.styles).toEqual(['some styles']); }); }); diff --git a/modules/@angular/compiler/test/runtime_compiler_spec.ts b/modules/@angular/compiler/test/runtime_compiler_spec.ts index ead188388b..d48e09bb99 100644 --- a/modules/@angular/compiler/test/runtime_compiler_spec.ts +++ b/modules/@angular/compiler/test/runtime_compiler_spec.ts @@ -140,12 +140,12 @@ export function main() { it('should throw when using a templateUrl in a nested component that has not been compiled before', () => { - @NgModule({declarations: [SomeComp], entryComponents: [SomeComp]}) + @NgModule({declarations: [SomeComp, ChildComp], entryComponents: [SomeComp]}) class SomeModule { } resourceLoader.spy('get').andCallFake(() => Promise.resolve('')); - dirResolver.setView(SomeComp, new ViewMetadata({template: '', directives: [ChildComp]})); + dirResolver.setView(SomeComp, new ViewMetadata({template: ''})); dirResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'})); expect(() => compiler.compileModuleSync(SomeModule)) .toThrowError( diff --git a/modules/@angular/compiler/testing.ts b/modules/@angular/compiler/testing.ts index 3eea8b3309..236b6de5e1 100644 --- a/modules/@angular/compiler/testing.ts +++ b/modules/@angular/compiler/testing.ts @@ -7,7 +7,6 @@ */ export * from './testing/schema_registry_mock'; -export * from './testing/test_component_builder'; export * from './testing/directive_resolver_mock'; export * from './testing/ng_module_resolver_mock'; export * from './testing/pipe_resolver_mock'; @@ -39,13 +38,7 @@ export class TestingCompilerImpl implements TestingCompiler { private _compiler: RuntimeCompiler, private _directiveResolver: MockDirectiveResolver, private _pipeResolver: MockPipeResolver, private _moduleResolver: MockNgModuleResolver) {} get injector(): Injector { return this._compiler.injector; } - compileComponentAsync(component: Type, ngModule: Type = null): - Promise> { - return this._compiler.compileComponentAsync(component, ngModule); - } - compileComponentSync(component: Type, ngModule: Type = null): ComponentFactory { - return this._compiler.compileComponentSync(component, ngModule); - } + compileModuleSync(moduleType: Type): NgModuleFactory { return this._compiler.compileModuleSync(moduleType); } diff --git a/modules/@angular/compiler/testing/directive_resolver_mock.ts b/modules/@angular/compiler/testing/directive_resolver_mock.ts index 66a9183781..ae888a6f29 100644 --- a/modules/@angular/compiler/testing/directive_resolver_mock.ts +++ b/modules/@angular/compiler/testing/directive_resolver_mock.ts @@ -11,8 +11,7 @@ import {ViewMetadata} from '../core_private'; import {DirectiveResolver} from '../src/directive_resolver'; import {Map} from '../src/facade/collection'; -import {BaseException} from '../src/facade/exceptions'; -import {isArray, isPresent, stringify} from '../src/facade/lang'; +import {isArray, isPresent} from '../src/facade/lang'; @@ -28,7 +27,6 @@ export class MockDirectiveResolver extends DirectiveResolver { private _views = new Map, ViewMetadata>(); private _inlineTemplates = new Map, string>(); private _animations = new Map, AnimationEntryMetadata[]>(); - private _directiveOverrides = new Map, Map, Type>>(); constructor(private _injector: Injector) { super(); } @@ -67,13 +65,8 @@ export class MockDirectiveResolver extends DirectiveResolver { view = metadata; } - const directives: any[] = []; - if (isPresent(view.directives)) { - flattenArray(view.directives, directives); - } let animations = view.animations; let templateUrl = view.templateUrl; - const directiveOverrides = this._directiveOverrides.get(type); const inlineAnimations = this._animations.get(type); if (isPresent(inlineAnimations)) { @@ -87,17 +80,6 @@ export class MockDirectiveResolver extends DirectiveResolver { inlineTemplate = view.template; } - if (isPresent(directiveOverrides) && isPresent(view.directives)) { - directiveOverrides.forEach((to, from) => { - var srcIndex = directives.indexOf(from); - if (srcIndex == -1) { - throw new BaseException( - `Overriden directive ${stringify(from)} not found in the template of ${stringify(type)}`); - } - directives[srcIndex] = to; - }); - } - return new ComponentMetadata({ selector: metadata.selector, inputs: metadata.inputs, @@ -112,11 +94,9 @@ export class MockDirectiveResolver extends DirectiveResolver { entryComponents: metadata.entryComponents, template: inlineTemplate, templateUrl: templateUrl, - directives: directives.length > 0 ? directives : null, animations: animations, styles: view.styles, styleUrls: view.styleUrls, - pipes: view.pipes, encapsulation: view.encapsulation, interpolation: view.interpolation }); @@ -170,21 +150,6 @@ export class MockDirectiveResolver extends DirectiveResolver { this._animations.set(component, animations); this._clearCacheFor(component); } - - /** - * Overrides a directive from the component {@link ViewMetadata}. - */ - overrideViewDirective(component: Type, from: Type, to: Type): void { - var overrides = this._directiveOverrides.get(component); - - if (!overrides) { - overrides = new Map, Type>(); - this._directiveOverrides.set(component, overrides); - } - - overrides.set(from, to); - this._clearCacheFor(component); - } } function flattenArray(tree: any[], out: Array|any[]>): void { diff --git a/modules/@angular/core/src/application_ref.ts b/modules/@angular/core/src/application_ref.ts index a9986fb5dd..b60325ae14 100644 --- a/modules/@angular/core/src/application_ref.ts +++ b/modules/@angular/core/src/application_ref.ts @@ -304,11 +304,23 @@ export class PlatformRef_ extends PlatformRef { } private _bootstrapModuleWithZone( - moduleType: Type, compilerOptions: CompilerOptions|CompilerOptions[] = [], - ngZone: NgZone): Promise> { + moduleType: Type, compilerOptions: CompilerOptions|CompilerOptions[] = [], ngZone: NgZone, + componentFactoryCallback?: any): Promise> { const compilerFactory: CompilerFactory = this.injector.get(CompilerFactory); const compiler = compilerFactory.createCompiler( compilerOptions instanceof Array ? compilerOptions : [compilerOptions]); + + // ugly internal api hack: generate host component factories for all declared components and + // pass the factories into the callback - this is used by UpdateAdapter to get hold of all + // factories. + if (componentFactoryCallback) { + return compiler.compileModuleAndAllComponentsAsync(moduleType) + .then(({ngModuleFactory, componentFactories}) => { + componentFactoryCallback(componentFactories); + return this._bootstrapModuleFactoryWithZone(ngModuleFactory, ngZone); + }); + } + return compiler.compileModuleAsync(moduleType) .then((moduleFactory) => this._bootstrapModuleFactoryWithZone(moduleFactory, ngZone)); } diff --git a/modules/@angular/core/src/linker/compiler.ts b/modules/@angular/core/src/linker/compiler.ts index 8368dd8502..b0d483d142 100644 --- a/modules/@angular/core/src/linker/compiler.ts +++ b/modules/@angular/core/src/linker/compiler.ts @@ -45,7 +45,7 @@ function _throwError() { } /** - * Low-level service for running the angular compiler duirng runtime + * Low-level service for running the angular compiler during runtime * to create {@link ComponentFactory}s, which * can later be used to create and render a Component instance. * @@ -55,20 +55,6 @@ function _throwError() { * @stable */ export class Compiler { - /** - * Loads the template and styles of a component and returns the associated `ComponentFactory`. - */ - compileComponentAsync(component: Type, ngModule: Type = null): - Promise> { - throw _throwError(); - } - /** - * Compiles the given component. All templates have to be either inline or compiled via - * `compileComponentAsync` before. Otherwise throws a {@link ComponentStillLoadingError}. - */ - compileComponentSync(component: Type, ngModule: Type = null): ComponentFactory { - throw _throwError(); - } /** * Compiles the given NgModule and all of its components. All templates of the components listed * in `entryComponents` diff --git a/modules/@angular/core/src/metadata/directives.ts b/modules/@angular/core/src/metadata/directives.ts index 2662f9f2f2..c317a3fcdc 100644 --- a/modules/@angular/core/src/metadata/directives.ts +++ b/modules/@angular/core/src/metadata/directives.ts @@ -481,8 +481,7 @@ export class DirectiveMetadata extends InjectableMetadata implements DirectiveMe * selector: 'app', * template: ` * - * `, - * directives: [BankAccount] + * ` * }) * class App {} * ``` @@ -525,8 +524,7 @@ export class DirectiveMetadata extends InjectableMetadata implements DirectiveMe * template: ` * * - * `, - * directives: [IntervalDir] + * ` * }) * class App { * everySecond() { console.log('second'); } @@ -578,8 +576,7 @@ export class DirectiveMetadata extends InjectableMetadata implements DirectiveMe * * @Component({ * selector: 'app', - * template: ``, - * directives: [CountClicks] + * template: `` * }) * class App {} * ``` @@ -612,8 +609,7 @@ export class DirectiveMetadata extends InjectableMetadata implements DirectiveMe * * @Component({ * selector: 'app', - * template: ``, - * directives: [FORM_DIRECTIVES, NgModelStatus] + * template: `` * }) * class App { * prop; @@ -690,8 +686,7 @@ export class DirectiveMetadata extends InjectableMetadata implements DirectiveMe * * @Component({ * selector: 'main', - * template: ``, - * directives: [ChildDir] + * template: `` * }) * class MainComponent { * } @@ -716,8 +711,7 @@ export class DirectiveMetadata extends InjectableMetadata implements DirectiveMe * contentChildren: new ContentChildren(ChildDirective), * viewChildren: new ViewChildren(ChildDirective) * }, - * template: '', - * directives: [ChildDirective] + * template: '' * }) * class SomeDir { * contentChildren: QueryList, @@ -761,8 +755,6 @@ export interface ComponentMetadataType extends DirectiveMetadataType { styleUrls?: string[]; styles?: string[]; animations?: AnimationEntryMetadata[]; - directives?: Array|any[]>; - pipes?: Array|any[]>; encapsulation?: ViewEncapsulation; interpolation?: [string, string]; entryComponents?: Array|any[]>; @@ -836,8 +828,7 @@ export class ComponentMetadata extends DirectiveMetadata implements ComponentMet * viewProviders: [ * Greeter * ], - * template: ``, - * directives: [NeedsGreeter] + * template: `` * }) * class HelloWorld { * } @@ -969,10 +960,6 @@ export class ComponentMetadata extends DirectiveMetadata implements ComponentMet */ animations: AnimationEntryMetadata[]; - directives: Array|any[]>; - - pipes: Array|any[]>; - /** * Specify how the template and the styles should be encapsulated. * The default is {@link ViewEncapsulation#Emulated `ViewEncapsulation.Emulated`} if the view @@ -991,13 +978,11 @@ export class ComponentMetadata extends DirectiveMetadata implements ComponentMet */ entryComponents: Array|any[]>; - constructor({selector, inputs, outputs, - host, exportAs, moduleId, - providers, viewProviders, changeDetection = ChangeDetectionStrategy.Default, - queries, templateUrl, template, - styleUrls, styles, animations, - directives, pipes, encapsulation, - interpolation, entryComponents}: ComponentMetadataType = {}) { + constructor( + {selector, inputs, outputs, host, exportAs, moduleId, providers, viewProviders, + changeDetection = ChangeDetectionStrategy.Default, queries, templateUrl, template, styleUrls, + styles, animations, encapsulation, interpolation, + entryComponents}: ComponentMetadataType = {}) { super({ selector: selector, inputs: inputs, @@ -1014,8 +999,6 @@ export class ComponentMetadata extends DirectiveMetadata implements ComponentMet this.template = template; this.styleUrls = styleUrls; this.styles = styles; - this.directives = directives; - this.pipes = pipes; this.encapsulation = encapsulation; this.moduleId = moduleId; this.animations = animations; @@ -1092,9 +1075,9 @@ export class PipeMetadata extends InjectableMetadata implements PipeMetadataType * selector: 'app', * template: ` * - * `, - * directives: [BankAccount] + * ` * }) + * * class App {} * ``` * @stable @@ -1138,8 +1121,7 @@ export class InputMetadata { * template: ` * * - * `, - * directives: [IntervalDir] + * ` * }) * class App { * everySecond() { console.log('second'); } @@ -1177,8 +1159,7 @@ export class OutputMetadata { * * @Component({ * selector: 'app', - * template: ``, - * directives: [FORM_DIRECTIVES, NgModelStatus] + * template: `` * }) * class App { * prop; @@ -1216,8 +1197,7 @@ export class HostBindingMetadata { * * @Component({ * selector: 'app', - * template: ``, - * directives: [CountClicks] + * template: `` * }) * class App {} * ``` diff --git a/modules/@angular/core/src/metadata/view.ts b/modules/@angular/core/src/metadata/view.ts index 2778892905..ef7ad3e1a4 100644 --- a/modules/@angular/core/src/metadata/view.ts +++ b/modules/@angular/core/src/metadata/view.ts @@ -103,30 +103,6 @@ export class ViewMetadata { */ styles: string[]; - /** - * Specifies a list of directives that can be used within a template. - * - * Directives must be listed explicitly to provide proper component encapsulation. - * - * ### Example - * - * ```javascript - * @Component({ - * selector: 'my-component', - * directives: [NgFor] - * template: ' - *
    - *
  • {{item}}
  • - *
' - * }) - * class MyComponent { - * } - * ``` - */ - directives: Array|any[]>; - - pipes: Array|any[]>; - /** * Specify how the template and the styles should be encapsulated. * The default is {@link ViewEncapsulation#Emulated `ViewEncapsulation.Emulated`} if the view @@ -140,12 +116,9 @@ export class ViewMetadata { interpolation: [string, string]; constructor( - {templateUrl, template, directives, pipes, encapsulation, styles, styleUrls, animations, - interpolation}: { + {templateUrl, template, encapsulation, styles, styleUrls, animations, interpolation}: { templateUrl?: string, template?: string, - directives?: Array|any[]>, - pipes?: Array|any[]>, encapsulation?: ViewEncapsulation, styles?: string[], styleUrls?: string[], @@ -156,8 +129,6 @@ export class ViewMetadata { this.template = template; this.styleUrls = styleUrls; this.styles = styles; - this.directives = directives; - this.pipes = pipes; this.encapsulation = encapsulation; this.animations = animations; this.interpolation = interpolation; diff --git a/modules/@angular/core/test/linker/ng_module_integration_spec.ts b/modules/@angular/core/test/linker/ng_module_integration_spec.ts index c778e56aa4..cf086a2854 100644 --- a/modules/@angular/core/test/linker/ng_module_integration_spec.ts +++ b/modules/@angular/core/test/linker/ng_module_integration_spec.ts @@ -8,8 +8,7 @@ import {ANALYZE_FOR_ENTRY_COMPONENTS, CUSTOM_ELEMENTS_SCHEMA, Compiler, Component, ComponentFactoryResolver, Directive, HostBinding, Inject, Injectable, Injector, Input, NgModule, NgModuleRef, Optional, Pipe, SelfMetadata, Type, forwardRef} from '@angular/core'; import {Console} from '@angular/core/src/console'; -import {ComponentFixture, TestBed} from '@angular/core/testing'; -import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal'; +import {ComponentFixture, TestBed, inject} from '@angular/core/testing'; import {expect} from '@angular/platform-browser/testing/matchers'; import {BaseException} from '../../src/facade/exceptions'; @@ -263,20 +262,35 @@ function declareTests({useJit}: {useJit: boolean}) { .toBe(SomeComp); }); - it('should throw when using an entryComponent that was neither declared nor imported', () => { - @Component({template: '', entryComponents: [SomeComp]}) + it('should throw if we cannot find a module associated with a module-level entryComponent', () => { + @Component({template: ''}) class SomeCompWithEntryComponents { } - @NgModule({entryComponents: [SomeCompWithEntryComponents]}) + @NgModule({declarations: [], entryComponents: [SomeCompWithEntryComponents]}) class SomeModule { } expect(() => createModule(SomeModule)) .toThrowError( - `NgModule ${stringify(SomeModule)} uses ${stringify(SomeCompWithEntryComponents)} via "entryComponents" but it was neither declared nor imported! If ${stringify(SomeCompWithEntryComponents)} is declared in an imported module, make sure it is exported.`); + 'Component SomeCompWithEntryComponents is not part of any NgModule or the module has not been imported into your module.'); }); + it('should throw if we cannot find a module associated with a component-level entryComponent', + () => { + @Component({template: '', entryComponents: [SomeComp]}) + class SomeCompWithEntryComponents { + } + + @NgModule({declarations: [SomeCompWithEntryComponents]}) + class SomeModule { + } + + expect(() => createModule(SomeModule)) + .toThrowError( + 'Component SomeComp is not part of any NgModule or the module has not been imported into your module.'); + }); + it('should create ComponentFactories via ANALYZE_FOR_ENTRY_COMPONENTS', () => { @NgModule({ declarations: [SomeComp], @@ -417,61 +431,6 @@ function declareTests({useJit}: {useJit: boolean}) { expect(compFixture.debugElement.children[0].children[0].properties['title']) .toBe('transformed someValue'); }); - - it('should hoist @Component.directives/pipes into the module', () => { - @Component({ - selector: 'parent', - template: '', - directives: [CompUsingModuleDirectiveAndPipe, SomeDirective], - pipes: [SomePipe] - }) - class ParentCompUsingModuleDirectiveAndPipe { - } - - @NgModule({ - declarations: [ParentCompUsingModuleDirectiveAndPipe], - entryComponents: [ParentCompUsingModuleDirectiveAndPipe] - }) - class SomeModule { - } - - const compFixture = createComp(ParentCompUsingModuleDirectiveAndPipe, SomeModule); - compFixture.detectChanges(); - expect(compFixture.debugElement.children[0].children[0].properties['title']) - .toBe('transformed someValue'); - }); - - it('should allow to use directives/pipes via @Component.directives/pipes that were already imported from another module', - () => { - @Component({ - selector: 'parent', - template: '', - directives: [CompUsingModuleDirectiveAndPipe, SomeDirective], - pipes: [SomePipe] - }) - class ParentCompUsingModuleDirectiveAndPipe { - } - - @NgModule({ - declarations: [SomeDirective, SomePipe, CompUsingModuleDirectiveAndPipe], - exports: [SomeDirective, SomePipe, CompUsingModuleDirectiveAndPipe] - }) - class SomeImportedModule { - } - - @NgModule({ - declarations: [ParentCompUsingModuleDirectiveAndPipe], - imports: [SomeImportedModule], - entryComponents: [ParentCompUsingModuleDirectiveAndPipe] - }) - class SomeModule { - } - - const compFixture = createComp(ParentCompUsingModuleDirectiveAndPipe, SomeModule); - compFixture.detectChanges(); - expect(compFixture.debugElement.children[0].children[0].properties['title']) - .toBe('transformed someValue'); - }); }); describe('import/export', () => { @@ -603,24 +562,6 @@ function declareTests({useJit}: {useJit: boolean}) { }); }); - describe('bound compiler', () => { - it('should provide a Compiler instance that uses the directives/pipes of the module', () => { - @NgModule({declarations: [SomeDirective, SomePipe]}) - class SomeModule { - } - - const ngModule = createModule(SomeModule); - const boundCompiler: Compiler = ngModule.injector.get(Compiler); - const cf = boundCompiler.compileComponentSync(CompUsingModuleDirectiveAndPipe); - const compFixture = new ComponentFixture(cf.create(injector), null, false); - compFixture.detectChanges(); - expect(compFixture.debugElement.children[0].properties['title']) - .toBe('transformed someValue'); - - // compile again should produce the same result - expect(boundCompiler.compileComponentSync(CompUsingModuleDirectiveAndPipe)).toBe(cf); - }); - }); describe('providers', function() { let moduleType: any = null; diff --git a/modules/@angular/upgrade/src/upgrade_adapter.ts b/modules/@angular/upgrade/src/upgrade_adapter.ts index 83ab164067..a3ae7d5dcf 100644 --- a/modules/@angular/upgrade/src/upgrade_adapter.ts +++ b/modules/@angular/upgrade/src/upgrade_adapter.ts @@ -6,8 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {BaseException, Compiler, ComponentFactory, Injector, NgModule, NgModuleRef, NgZone, Provider, Testability, Type} from '@angular/core'; -import {BrowserModule} from '@angular/platform-browser'; +import {BaseException, Compiler, ComponentFactory, ComponentFactoryResolver, Injector, NgModule, NgModuleRef, NgZone, Provider, Testability, Type} from '@angular/core'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import * as angular from './angular_js'; @@ -117,10 +116,10 @@ export class UpgradeAdapter { // the ng2AppModule param should be required once the deprecated @Component.directives prop is // removed - constructor(private ng2AppModule?: Type) { - if (arguments.length && !ng2AppModule) { + constructor(private ng2AppModule: Type) { + if (!ng2AppModule) { throw new BaseException( - 'UpgradeAdapter constructor called with undefined instead of a ng module type'); + 'UpgradeAdapter cannot be instantiated without an NgModule of the Angular 2 app.'); } } @@ -394,10 +393,21 @@ export class UpgradeAdapter { {provide: NG1_COMPILE, useFactory: () => ng1Injector.get(NG1_COMPILE)}, this.providers ], - imports: this.ng2AppModule ? [this.ng2AppModule] : [BrowserModule] - }).Class({constructor: function() {}, ngDoBootstrap: function() {}}); + imports: [this.ng2AppModule] + }).Class({ + constructor: function DynamicNgUpgradeModule() {}, + ngDoBootstrap: function() {} + }); + (platformBrowserDynamic() as any) - ._bootstrapModuleWithZone(DynamicNgUpgradeModule, undefined, ngZone) + ._bootstrapModuleWithZone( + DynamicNgUpgradeModule, undefined, ngZone, + (componentFactories: ComponentFactory[]) => { + componentFactories.forEach((componentFactory) => { + componentFactoryRefMap[getComponentInfo(componentFactory.componentType) + .selector] = componentFactory; + }); + }) .then((ref: NgModuleRef) => { moduleRef = ref; angular.element(element).data( @@ -417,7 +427,7 @@ export class UpgradeAdapter { windowAngular.resumeBootstrap = undefined; ngZone.run(() => { angular.bootstrap(element, [this.idPrefix], config); }); - ng1BootstrapPromise = new Promise((resolve, reject) => { + ng1BootstrapPromise = new Promise((resolve) => { if (windowAngular.resumeBootstrap) { var originalResumeBootstrap: () => void = windowAngular.resumeBootstrap; windowAngular.resumeBootstrap = function() { @@ -430,23 +440,18 @@ export class UpgradeAdapter { } }); - Promise.all([ng1BootstrapPromise, ng1compilePromise]) - .then(() => { - return this.compileNg2Components( - moduleRef.injector.get(Compiler), componentFactoryRefMap); - }) - .then(() => { - moduleRef.injector.get(NgZone).run(() => { - if (rootScopePrototype) { - rootScopePrototype.$apply = original$applyFn; // restore original $apply - while (delayApplyExps.length) { - rootScope.$apply(delayApplyExps.shift()); - } - (upgrade)._bootstrapDone(moduleRef, ng1Injector); - rootScopePrototype = null; - } - }); - }, onError); + Promise.all([ng1BootstrapPromise, ng1compilePromise]).then(() => { + moduleRef.injector.get(NgZone).run(() => { + if (rootScopePrototype) { + rootScopePrototype.$apply = original$applyFn; // restore original $apply + while (delayApplyExps.length) { + rootScope.$apply(delayApplyExps.shift()); + } + (upgrade)._bootstrapDone(moduleRef, ng1Injector); + rootScopePrototype = null; + } + }); + }, onError); return upgrade; } @@ -518,23 +523,6 @@ export class UpgradeAdapter { (factory).$inject = [NG2_INJECTOR]; return factory; } - - /* @internal */ - private compileNg2Components(compiler: Compiler, componentFactoryRefMap: ComponentFactoryRefMap): - Promise { - var promises: Array>> = []; - var types = this.upgradedComponents; - for (var i = 0; i < types.length; i++) { - promises.push(compiler.compileComponentAsync(types[i], this.ng2AppModule)); - } - return Promise.all(promises).then((componentFactories: Array>) => { - var types = this.upgradedComponents; - for (var i = 0; i < componentFactories.length; i++) { - componentFactoryRefMap[getComponentInfo(types[i]).selector] = componentFactories[i]; - } - return componentFactoryRefMap; - }, onError); - } } interface ComponentFactoryRefMap { diff --git a/modules/@angular/upgrade/test/upgrade_spec.ts b/modules/@angular/upgrade/test/upgrade_spec.ts index 3163b4f35a..2e9ba94ac8 100644 --- a/modules/@angular/upgrade/test/upgrade_spec.ts +++ b/modules/@angular/upgrade/test/upgrade_spec.ts @@ -6,9 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {Class, Component, EventEmitter, Inject, NgModule, OpaqueToken, Testability, destroyPlatform} from '@angular/core'; +import {Class, Component, EventEmitter, Inject, NgModule, OpaqueToken, Testability, destroyPlatform, forwardRef} from '@angular/core'; import {async} from '@angular/core/testing'; -import {AsyncTestCompleter, ddescribe, describe, expect, iit, inject, it} from '@angular/core/testing/testing_internal'; import {BrowserModule} from '@angular/platform-browser'; import {UpgradeAdapter} from '@angular/upgrade'; import * as angular from '@angular/upgrade/src/angular_js'; @@ -20,34 +19,40 @@ export function main() { it('should have angular 1 loaded', () => expect(angular.version.major).toBe(1)); - it('should instantiate ng2 in ng1 template and project content', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + it('should instantiate ng2 in ng1 template and project content', async(() => { var ng1Module = angular.module('ng1', []); + var Ng2 = Component({selector: 'ng2', template: `{{ 'NG2' }}()`}) .Class({constructor: function() {}}); + var Ng2Module = NgModule({declarations: [Ng2], imports: [BrowserModule]}).Class({ + constructor: function() {} + }); + var element = html('
{{ \'ng1[\' }}~{{ \'ng-content\' }}~{{ \']\' }}
'); - var adapter: UpgradeAdapter = new UpgradeAdapter(); + const adapter: UpgradeAdapter = new UpgradeAdapter(Ng2Module); ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(document.body.textContent).toEqual('ng1[NG2(~ng-content~)]'); ref.dispose(); - async.done(); }); })); - it('should instantiate ng1 in ng2 template and project content', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter: UpgradeAdapter = new UpgradeAdapter(); + it('should instantiate ng1 in ng2 template and project content', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var Ng2 = Component({ selector: 'ng2', template: `{{ 'ng2(' }}{{'transclude'}}{{ ')' }}`, - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + }).Class({constructor: function Ng2() {}}); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function Ng2Module() {}}); ng1Module.directive('ng1', () => { return {transclude: true, template: '{{ "ng1" }}()'}; @@ -59,19 +64,17 @@ export function main() { adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(document.body.textContent).toEqual('ng1(ng2(ng1(transclude)))'); ref.dispose(); - async.done(); }); })); describe('scope/component change-detection', () => { - it('should interleave scope and component expressions', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + it('should interleave scope and component expressions', async(() => { var ng1Module = angular.module('ng1', []); var log: any[] /** TODO #9100 */ = []; var l = function(value: any /** TODO #9100 */) { log.push(value); return value + ';'; }; - var adapter: UpgradeAdapter = new UpgradeAdapter(); + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); ng1Module.directive('ng1a', () => { return {template: '{{ l(\'ng1a\') }}'}; }); ng1Module.directive('ng1b', () => { return {template: '{{ l(\'ng1b\') }}'}; }); @@ -80,13 +83,18 @@ export function main() { $rootScope.reset = () => log.length = 0; }); - var Ng2 = - Component({ - selector: 'ng2', - template: `{{l('2A')}}{{l('2B')}}{{l('2C')}}`, - directives: - [adapter.upgradeNg1Component('ng1a'), adapter.upgradeNg1Component('ng1b')] - }).Class({constructor: function() { this.l = l; }}); + var Ng2 = Component({ + selector: 'ng2', + template: `{{l('2A')}}{{l('2B')}}{{l('2C')}}` + }).Class({constructor: function() { this.l = l; }}); + + var Ng2Module = + NgModule({ + declarations: [ + adapter.upgradeNg1Component('ng1a'), adapter.upgradeNg1Component('ng1b'), Ng2 + ], + imports: [BrowserModule] + }).Class({constructor: function() {}}); ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); @@ -97,15 +105,13 @@ export function main() { // https://github.com/angular/angular.js/issues/12983 expect(log).toEqual(['1A', '1B', '1C', '2A', '2B', '2C', 'ng1a', 'ng1b']); ref.dispose(); - async.done(); }); })); }); describe('downgrade ng2 component', () => { - it('should bind properties, events', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter: UpgradeAdapter = new UpgradeAdapter(); + it('should bind properties, events', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); ng1Module.run(($rootScope: any /** TODO #9100 */) => { @@ -189,6 +195,11 @@ export function main() { } }); ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); + + var Ng2Module = NgModule({declarations: [Ng2], imports: [BrowserModule]}).Class({ + constructor: function() {} + }); + var element = html(`
{ - var adapter: UpgradeAdapter = new UpgradeAdapter(); + it('should properly run cleanup when ng1 directive is destroyed', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var onDestroyed: EventEmitter = new EventEmitter(); @@ -229,20 +238,21 @@ export function main() { constructor: function() {}, ngOnDestroy: function() { onDestroyed.emit('destroyed'); } }); + + var Ng2Module = NgModule({declarations: [Ng2], imports: [BrowserModule]}).Class({ + constructor: function() {} + }); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(''); adapter.bootstrap(element, ['ng1']).ready((ref) => { - onDestroyed.subscribe(() => { - ref.dispose(); - async.done(); - }); + onDestroyed.subscribe(() => { ref.dispose(); }); }); })); - it('should fallback to the root ng2.injector when compiled outside the dom', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter: UpgradeAdapter = new UpgradeAdapter(); + it('should fallback to the root ng2.injector when compiled outside the dom', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); ng1Module.directive('ng1', [ @@ -262,12 +272,16 @@ export function main() { var Ng2 = Component({selector: 'ng2', template: 'test'}).Class({constructor: function() {}}); + + var Ng2Module = NgModule({declarations: [Ng2], imports: [BrowserModule]}).Class({ + constructor: function() {} + }); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(''); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('test'); ref.dispose(); - async.done(); }); })); @@ -308,9 +322,8 @@ export function main() { }); describe('upgrade ng1 component', () => { - it('should bind properties, events', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should bind properties, events', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = function() { @@ -338,8 +351,7 @@ export function main() { '' + '' + - '{{event}}-{{last}}, {{first}}', - directives: [adapter.upgradeNg1Component('ng1')] + '{{event}}-{{last}}, {{first}}' }).Class({ constructor: function() { this.first = 'Victor'; @@ -347,6 +359,12 @@ export function main() { this.event = '?'; } }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { @@ -357,14 +375,13 @@ export function main() { .toEqual( 'Hello SAVKIN, Victor; A: VICTOR; B: SAVKIN; | Hello TEST; A: First; B: Last; | WORKS-SAVKIN, Victor'); ref.dispose(); - async.done(); }, 0); }); })); it('should bind properties, events in controller when bindToController is not used', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = function() { @@ -383,8 +400,7 @@ export function main() { Component({ selector: 'ng2', template: - '{{someText}} - Length: {{dataList.length}} | ', - directives: [adapter.upgradeNg1Component('ng1')], + '{{someText}} - Length: {{dataList.length}} | ' }).Class({ constructor: function() { @@ -392,6 +408,12 @@ export function main() { this.someText = 'ng2'; } }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { @@ -401,14 +423,12 @@ export function main() { expect(multiTrim(document.body.textContent)) .toEqual('ng2 - Length: 3 | ng1 - Data: 1,2,3 - Length: 3'); ref.dispose(); - async.done(); }, 0); }); })); - it('should bind properties, events in link function', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should bind properties, events in link function', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = function() { @@ -427,8 +447,7 @@ export function main() { Component({ selector: 'ng2', template: - '{{someText}} - Length: {{dataList.length}} | ', - directives: [adapter.upgradeNg1Component('ng1')], + '{{someText}} - Length: {{dataList.length}} | ' }).Class({ constructor: function() { @@ -436,6 +455,12 @@ export function main() { this.someText = 'ng2'; } }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { @@ -445,14 +470,12 @@ export function main() { expect(multiTrim(document.body.textContent)) .toEqual('ng2 - Length: 3 | ng1 - Data: 1,2,3 - Length: 3'); ref.dispose(); - async.done(); }, 0); }); })); - it('should support templateUrl fetched from $httpBackend', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support templateUrl fetched from $httpBackend', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); ng1Module.value( '$httpBackend', (method: any /** TODO #9100 */, url: any /** TODO #9100 */, @@ -461,23 +484,25 @@ export function main() { var ng1 = function() { return {templateUrl: 'url.html'}; }; ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('GET:url.html'); ref.dispose(); - async.done(); }); })); - it('should support templateUrl as a function', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support templateUrl as a function', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); ng1Module.value( '$httpBackend', (method: any /** TODO #9100 */, url: any /** TODO #9100 */, @@ -486,88 +511,100 @@ export function main() { var ng1 = function() { return {templateUrl() { return 'url.html'; }}; }; ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('GET:url.html'); ref.dispose(); - async.done(); }); })); - it('should support empty template', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support empty template', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = function() { return {template: ''}; }; ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual(''); ref.dispose(); - async.done(); }); })); - it('should support template as a function', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support template as a function', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = function() { return {template() { return ''; }}; }; ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual(''); ref.dispose(); - async.done(); }); })); - it('should support templateUrl fetched from $templateCache', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support templateUrl fetched from $templateCache', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); ng1Module.run( ($templateCache: any /** TODO #9100 */) => $templateCache.put('url.html', 'WORKS')); var ng1 = function() { return {templateUrl: 'url.html'}; }; ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('WORKS'); ref.dispose(); - async.done(); }); })); - it('should support controller with controllerAs', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support controller with controllerAs', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = function() { @@ -592,23 +629,26 @@ export function main() { }; }; ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('scope; isClass; NG1; published'); ref.dispose(); - async.done(); }); })); - it('should support bindToController', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support bindToController', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = function() { @@ -621,23 +661,26 @@ export function main() { }; }; ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('WORKS'); ref.dispose(); - async.done(); }); })); - it('should support bindToController with bindings', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support bindToController with bindings', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = function() { @@ -650,23 +693,26 @@ export function main() { }; }; ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('WORKS'); ref.dispose(); - async.done(); }); })); - it('should support single require in linking fn', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support single require in linking fn', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = function($rootScope: any /** TODO #9100 */) { @@ -688,23 +734,26 @@ export function main() { }; }; ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('WORKS'); ref.dispose(); - async.done(); }); })); - it('should support array require in linking fn', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support array require in linking fn', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var parent = function() { @@ -731,23 +780,26 @@ export function main() { }; ng1Module.directive('parent', parent); ng1Module.directive('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('PARENT:WORKS'); ref.dispose(); - async.done(); }); })); - it('should call $onInit of components', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should call $onInit of components', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var valueToFind = '$onInit'; @@ -759,24 +811,26 @@ export function main() { }; ng1Module.component('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); + var Ng2 = Component({selector: 'ng2', template: ''}).Class({ + constructor: function() {} + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual(valueToFind); ref.dispose(); - async.done(); }); })); - it('should bind input properties (<) of components', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should bind input properties (<) of components', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = { @@ -786,26 +840,27 @@ export function main() { }; ng1Module.component('ng1', ng1); - var Ng2 = Component({ - selector: 'ng2', - template: '', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({ - constructor: function() { this.goku = {firstName: 'GOKU', lastName: 'SAN'}; } - }); + var Ng2 = + Component({selector: 'ng2', template: ''}).Class({ + constructor: function() { this.goku = {firstName: 'GOKU', lastName: 'SAN'}; } + }); + + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual(`Hello GOKU SAN`); ref.dispose(); - async.done(); }); })); - it('should support ng2 > ng1 > ng2', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should support ng2 > ng1 > ng2', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var ng1Module = angular.module('ng1', []); var ng1 = { @@ -813,22 +868,23 @@ export function main() { }; ng1Module.component('ng1', ng1); - var Ng2a = Component({ - selector: 'ng2a', - template: 'ng2a()', - directives: [adapter.upgradeNg1Component('ng1')] - }).Class({constructor: function() {}}); - ng1Module.directive('ng2a', adapter.downgradeNg2Component(Ng2a)); - - var Ng2b = Component({selector: 'ng2b', template: 'ng2b', directives: []}).Class({ + var Ng2a = Component({selector: 'ng2a', template: 'ng2a()'}).Class({ constructor: function() {} }); + ng1Module.directive('ng2a', adapter.downgradeNg2Component(Ng2a)); + + var Ng2b = + Component({selector: 'ng2b', template: 'ng2b'}).Class({constructor: function() {}}); ng1Module.directive('ng2b', adapter.downgradeNg2Component(Ng2b)); + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2a, Ng2b], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + var element = html(`
`); adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(multiTrim(document.body.textContent)).toEqual('ng2a(ng1(ng2b))'); - async.done(); }); })); }); @@ -837,12 +893,12 @@ export function main() { function SomeToken() {} it('should export ng2 instance to ng1', async(() => { - var MyModule = NgModule({ - providers: [{provide: SomeToken, useValue: 'correct_value'}], - imports: [BrowserModule] - }).Class({constructor: function() {}}); + var MyNg2Module = NgModule({ + providers: [{provide: SomeToken, useValue: 'correct_value'}], + imports: [BrowserModule] + }).Class({constructor: function() {}}); - var adapter = new UpgradeAdapter(MyModule); + const adapter: UpgradeAdapter = new UpgradeAdapter(MyNg2Module); var module = angular.module('myExample', []); module.factory('someToken', adapter.downgradeNg2Provider(SomeToken)); adapter.bootstrap(html('
'), ['myExample']).ready((ref) => { @@ -851,9 +907,11 @@ export function main() { }); })); - it('should export ng1 instance to ng2', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should export ng1 instance to ng2', async(() => { + var MyNg2Module = + NgModule({imports: [BrowserModule]}).Class({constructor: function() {}}); + + const adapter: UpgradeAdapter = new UpgradeAdapter(MyNg2Module); var module = angular.module('myExample', []); module.value('testValue', 'secreteToken'); adapter.upgradeNg1Provider('testValue'); @@ -864,15 +922,16 @@ export function main() { expect(ref.ng2Injector.get(String)).toBe('secreteToken'); expect(ref.ng2Injector.get('testToken')).toBe('secreteToken'); ref.dispose(); - async.done(); }); })); }); describe('testability', () => { - it('should handle deferred bootstrap', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter: UpgradeAdapter = new UpgradeAdapter(); + it('should handle deferred bootstrap', async(() => { + var MyNg2Module = + NgModule({imports: [BrowserModule]}).Class({constructor: function() {}}); + + const adapter: UpgradeAdapter = new UpgradeAdapter(MyNg2Module); var ng1Module = angular.module('ng1', []); var bootstrapResumed: boolean = false; @@ -882,7 +941,6 @@ export function main() { adapter.bootstrap(element, ['ng1']).ready((ref) => { expect(bootstrapResumed).toEqual(true); ref.dispose(); - async.done(); }); setTimeout(() => { @@ -891,9 +949,11 @@ export function main() { }, 100); })); - it('should wait for ng2 testability', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter: UpgradeAdapter = new UpgradeAdapter(); + it('should wait for ng2 testability', async(() => { + var MyNg2Module = + NgModule({imports: [BrowserModule]}).Class({constructor: function() {}}); + + const adapter: UpgradeAdapter = new UpgradeAdapter(MyNg2Module); var ng1Module = angular.module('ng1', []); var element = html('
'); adapter.bootstrap(element, ['ng1']).ready((ref) => { @@ -904,7 +964,6 @@ export function main() { angular.getTestability(element).whenStable(function() { expect(ng2Stable).toEqual(true); ref.dispose(); - async.done(); }); setTimeout(() => { @@ -916,9 +975,8 @@ export function main() { }); describe('examples', () => { - it('should verify UpgradeAdapter example', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var adapter = new UpgradeAdapter(); + it('should verify UpgradeAdapter example', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); var module = angular.module('myExample', []); module.directive('ng1', function() { @@ -929,15 +987,18 @@ export function main() { }; }); - var Ng2 = Component({ selector: 'ng2', inputs: ['name'], - template: 'ng2[transclude]()', - directives: [adapter.upgradeNg1Component('ng1')] + template: 'ng2[transclude]()' }).Class({constructor: function() {}}); + var Ng2Module = NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule] + }).Class({constructor: function() {}}); + module.directive('ng2', adapter.downgradeNg2Component(Ng2)); document.body.innerHTML = 'project'; @@ -946,7 +1007,6 @@ export function main() { expect(multiTrim(document.body.textContent)) .toEqual('ng2[ng1[Hello World!](transclude)](project)'); ref.dispose(); - async.done(); }); })); }); diff --git a/tools/public_api_guard/core/index.d.ts b/tools/public_api_guard/core/index.d.ts index 7c04a3fd9c..72c1e66625 100644 --- a/tools/public_api_guard/core/index.d.ts +++ b/tools/public_api_guard/core/index.d.ts @@ -227,8 +227,6 @@ export declare class CollectionChangeRecord { export declare class Compiler { clearCache(): void; clearCacheFor(type: Type): void; - compileComponentAsync(component: Type, ngModule?: Type): Promise>; - compileComponentSync(component: Type, ngModule?: Type): ComponentFactory; compileModuleAndAllComponentsAsync(moduleType: Type): Promise>; compileModuleAndAllComponentsSync(moduleType: Type): ModuleWithComponentFactories; compileModuleAsync(moduleType: Type): Promise>; @@ -276,18 +274,16 @@ export declare abstract class ComponentFactoryResolver { export declare class ComponentMetadata extends DirectiveMetadata implements ComponentMetadataType { animations: AnimationEntryMetadata[]; changeDetection: ChangeDetectionStrategy; - directives: Array | any[]>; encapsulation: ViewEncapsulation; entryComponents: Array | any[]>; interpolation: [string, string]; moduleId: string; - pipes: Array | any[]>; styleUrls: string[]; styles: string[]; template: string; templateUrl: string; viewProviders: any[]; - constructor({selector, inputs, outputs, host, exportAs, moduleId, providers, viewProviders, changeDetection, queries, templateUrl, template, styleUrls, styles, animations, directives, pipes, encapsulation, interpolation, entryComponents}?: ComponentMetadataType); + constructor({selector, inputs, outputs, host, exportAs, moduleId, providers, viewProviders, changeDetection, queries, templateUrl, template, styleUrls, styles, animations, encapsulation, interpolation, entryComponents}?: ComponentMetadataType); } /** @stable */ @@ -300,12 +296,10 @@ export interface ComponentMetadataFactory { export interface ComponentMetadataType extends DirectiveMetadataType { animations?: AnimationEntryMetadata[]; changeDetection?: ChangeDetectionStrategy; - directives?: Array | any[]>; encapsulation?: ViewEncapsulation; entryComponents?: Array | any[]>; interpolation?: [string, string]; moduleId?: string; - pipes?: Array | any[]>; styleUrls?: string[]; styles?: string[]; template?: string; diff --git a/tools/public_api_guard/upgrade/index.d.ts b/tools/public_api_guard/upgrade/index.d.ts index ed3f3be1c9..ffd2cbbf6e 100644 --- a/tools/public_api_guard/upgrade/index.d.ts +++ b/tools/public_api_guard/upgrade/index.d.ts @@ -1,6 +1,6 @@ /** @experimental */ export declare class UpgradeAdapter { - constructor(ng2AppModule?: Type); + constructor(ng2AppModule: Type); bootstrap(element: Element, modules?: any[], config?: angular.IAngularBootstrapConfig): UpgradeAdapterRef; downgradeNg2Component(type: Type): Function; downgradeNg2Provider(token: any): Function;