From c494d3cf60ac1415d4fa7dedf519aafd9e4b23d1 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Tue, 5 Jun 2018 22:11:47 -0700 Subject: [PATCH] Revert "feat(ivy): add support of ApplicationRef.bootstrapModuleFactory (#23811)" This reverts commit 22b58a717aad87092a7f7080805c10ef36960694. This commit causes a breakage in g3. --- packages/core/src/application_module.ts | 45 ++--- .../core/src/core_render3_private_export.ts | 2 - packages/core/src/di.ts | 2 +- packages/core/src/di/injector.ts | 9 +- packages/core/src/di/provider.ts | 8 +- packages/core/src/di/r3_injector.ts | 29 ++- packages/core/src/render3/assert.ts | 4 +- packages/core/src/render3/component.ts | 49 +++-- packages/core/src/render3/component_ref.ts | 176 ------------------ packages/core/src/render3/di.ts | 8 +- packages/core/src/render3/index.ts | 7 +- packages/core/src/render3/instructions.ts | 58 +++--- packages/core/src/render3/interfaces/view.ts | 4 +- packages/core/src/render3/ng_module_ref.ts | 73 -------- packages/core/src/render3/node_assert.ts | 6 +- .../core/src/render3/node_manipulation.ts | 2 +- .../core/src/render3/node_selector_matcher.ts | 4 +- packages/core/src/render3/query.ts | 8 +- packages/core/src/render3/view_ref.ts | 13 +- .../test/application_ref_integration_spec.ts | 95 ---------- .../hello_world/bundle.golden_symbols.json | 3 - .../hello_world_r2/bundle.golden_symbols.json | 2 +- .../bundling/todo/bundle.golden_symbols.json | 5 +- packages/core/test/di/r3_injector_spec.ts | 20 -- packages/core/test/render3/component_spec.ts | 27 +-- packages/core/test/render3/render_util.ts | 2 +- packages/platform-browser/src/browser.ts | 61 +++--- tools/public_api_guard/core/core.d.ts | 9 +- .../platform-browser/platform-browser.d.ts | 2 +- 29 files changed, 153 insertions(+), 580 deletions(-) delete mode 100644 packages/core/src/render3/component_ref.ts delete mode 100644 packages/core/src/render3/ng_module_ref.ts delete mode 100644 packages/core/test/application_ref_integration_spec.ts diff --git a/packages/core/src/application_module.ts b/packages/core/src/application_module.ts index 4cbd10b24b..55caa5d9b7 100644 --- a/packages/core/src/application_module.ts +++ b/packages/core/src/application_module.ts @@ -10,15 +10,11 @@ import {APP_INITIALIZER, ApplicationInitStatus} from './application_init'; import {ApplicationRef} from './application_ref'; import {APP_ID_RANDOM_PROVIDER} from './application_tokens'; import {IterableDiffers, KeyValueDiffers, defaultIterableDiffers, defaultKeyValueDiffers} from './change_detection/change_detection'; -import {Console} from './console'; -import {InjectionToken, Injector, StaticProvider} from './di'; +import {forwardRef} from './di/forward_ref'; import {Inject, Optional, SkipSelf} from './di/metadata'; -import {ErrorHandler} from './error_handler'; import {LOCALE_ID} from './i18n/tokens'; -import {ComponentFactoryResolver} from './linker'; import {Compiler} from './linker/compiler'; import {NgModule} from './metadata'; -import {NgZone} from './zone'; export function _iterableDiffersFactory() { return defaultIterableDiffers; @@ -32,36 +28,27 @@ export function _localeFactory(locale?: string): string { return locale || 'en-US'; } -export const APPLICATION_MODULE_PROVIDERS: StaticProvider[] = [ - { - provide: ApplicationRef, - useClass: ApplicationRef, - deps: - [NgZone, Console, Injector, ErrorHandler, ComponentFactoryResolver, ApplicationInitStatus] - }, - { - provide: ApplicationInitStatus, - useClass: ApplicationInitStatus, - deps: [[new Optional(), APP_INITIALIZER]] - }, - {provide: Compiler, useClass: Compiler, deps: []}, - APP_ID_RANDOM_PROVIDER, - {provide: IterableDiffers, useFactory: _iterableDiffersFactory, deps: []}, - {provide: KeyValueDiffers, useFactory: _keyValueDiffersFactory, deps: []}, - { - provide: LOCALE_ID, - useFactory: _localeFactory, - deps: [[new Inject(LOCALE_ID), new Optional(), new SkipSelf()]] - }, -]; - /** * This module includes the providers of @angular/core that are needed * to bootstrap components via `ApplicationRef`. * * @experimental */ -@NgModule({providers: APPLICATION_MODULE_PROVIDERS}) +@NgModule({ + providers: [ + ApplicationRef, + ApplicationInitStatus, + Compiler, + APP_ID_RANDOM_PROVIDER, + {provide: IterableDiffers, useFactory: _iterableDiffersFactory}, + {provide: KeyValueDiffers, useFactory: _keyValueDiffersFactory}, + { + provide: LOCALE_ID, + useFactory: _localeFactory, + deps: [[new Inject(LOCALE_ID), new Optional(), new SkipSelf()]] + }, + ], +}) export class ApplicationModule { // Inject ApplicationRef to make it eager... constructor(appRef: ApplicationRef) {} diff --git a/packages/core/src/core_render3_private_export.ts b/packages/core/src/core_render3_private_export.ts index 3998173ec9..ff8c7449b4 100644 --- a/packages/core/src/core_render3_private_export.ts +++ b/packages/core/src/core_render3_private_export.ts @@ -23,8 +23,6 @@ export { injectAttribute as ɵinjectAttribute, PublicFeature as ɵPublicFeature, NgOnChangesFeature as ɵNgOnChangesFeature, - NgModuleDef as ɵNgModuleDef, - NgModuleType as ɵNgModuleType, CssSelectorList as ɵCssSelectorList, markDirty as ɵmarkDirty, NC as ɵNC, diff --git a/packages/core/src/di.ts b/packages/core/src/di.ts index 1e6b201b84..62d3c4a38e 100644 --- a/packages/core/src/di.ts +++ b/packages/core/src/di.ts @@ -18,7 +18,7 @@ export {forwardRef, resolveForwardRef, ForwardRefFn} from './di/forward_ref'; export {Injectable, InjectableDecorator, InjectableProvider} from './di/injectable'; export {inject, InjectFlags, INJECTOR, Injector} from './di/injector'; export {ReflectiveInjector} from './di/reflective_injector'; -export {StaticProvider, ValueProvider, ConstructorSansProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ClassProvider} from './di/provider'; +export {StaticProvider, ValueProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ClassProvider} from './di/provider'; export {createInjector} from './di/r3_injector'; export {ResolvedReflectiveFactory, ResolvedReflectiveProvider} from './di/reflective_provider'; export {ReflectiveKey} from './di/reflective_key'; diff --git a/packages/core/src/di/injector.ts b/packages/core/src/di/injector.ts index e0286e80b4..5cbd618846 100644 --- a/packages/core/src/di/injector.ts +++ b/packages/core/src/di/injector.ts @@ -32,9 +32,6 @@ export const INJECTOR = new InjectionToken('INJECTOR'); export class NullInjector implements Injector { get(token: any, notFoundValue: any = _THROW_IF_NOT_FOUND): any { if (notFoundValue === _THROW_IF_NOT_FOUND) { - // Intentionally left behind: With dev tools open the debugger will stop here. There is no - // reason why correctly written application should cause this exception. - debugger; throw new Error(`NullInjectorError: No provider for ${stringify(token)}!`); } return notFoundValue; @@ -490,11 +487,11 @@ export function injectArgs(types: (Type| InjectionToken| any[])[]): an for (let j = 0; j < arg.length; j++) { const meta = arg[j]; - if (meta instanceof Optional || meta.ngMetadataName === 'Optional') { + if (meta instanceof Optional || meta.__proto__.ngMetadataName === 'Optional') { flags |= InjectFlags.Optional; - } else if (meta instanceof SkipSelf || meta.ngMetadataName === 'SkipSelf') { + } else if (meta instanceof SkipSelf || meta.__proto__.ngMetadataName === 'SkipSelf') { flags |= InjectFlags.SkipSelf; - } else if (meta instanceof Self || meta.ngMetadataName === 'Self') { + } else if (meta instanceof Self || meta.__proto__.ngMetadataName === 'Self') { flags |= InjectFlags.Self; } else if (meta instanceof Inject) { type = meta.token; diff --git a/packages/core/src/di/provider.ts b/packages/core/src/di/provider.ts index 447f7c2279..1b521e911a 100644 --- a/packages/core/src/di/provider.ts +++ b/packages/core/src/di/provider.ts @@ -151,6 +151,10 @@ export interface StaticClassProvider extends StaticClassSansProvider { * * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. * + * ### Example + * + * {@example core/di/ts/provider_spec.ts region='ConstructorSansProvider'} + * * @experimental */ export interface ConstructorSansProvider { @@ -449,5 +453,5 @@ export interface ClassProvider extends ClassSansProvider { * * */ -export type Provider = TypeProvider | ValueProvider | ClassProvider | ConstructorProvider | - ExistingProvider | FactoryProvider | any[]; +export type Provider = + TypeProvider | ValueProvider | ClassProvider | ExistingProvider | FactoryProvider | any[]; diff --git a/packages/core/src/di/r3_injector.ts b/packages/core/src/di/r3_injector.ts index 28742c19a2..9305d4b796 100644 --- a/packages/core/src/di/r3_injector.ts +++ b/packages/core/src/di/r3_injector.ts @@ -14,7 +14,7 @@ import {InjectableDef, InjectableType, InjectorDef, InjectorType, InjectorTypeWi import {resolveForwardRef} from './forward_ref'; import {InjectableDefToken, InjectionToken} from './injection_token'; import {INJECTOR, InjectFlags, Injector, NullInjector, THROW_IF_NOT_FOUND, USE_VALUE, inject, injectArgs, setCurrentInjector} from './injector'; -import {ClassProvider, ConstructorProvider, ExistingProvider, FactoryProvider, Provider, StaticClassProvider, StaticProvider, TypeProvider, ValueProvider} from './provider'; +import {ClassProvider, ConstructorProvider, ExistingProvider, FactoryProvider, Provider, StaticClassProvider, TypeProvider, ValueProvider} from './provider'; import {APP_ROOT} from './scope'; @@ -64,15 +64,14 @@ interface Record { } /** - * Create a new `Injector` which is configured using a `defType` of `InjectorType`s. + * Create a new `Injector` which is configured using `InjectorType`s. * * @experimental */ export function createInjector( - defType: /* InjectorType */ any, parent: Injector | null = null, - additionalProviders: StaticProvider[] | null = null): Injector { + defType: /* InjectorType */ any, parent: Injector | null = null): Injector { parent = parent || getNullInjector(); - return new R3Injector(defType, additionalProviders, parent); + return new R3Injector(defType, parent); } export class R3Injector { @@ -102,18 +101,12 @@ export class R3Injector { */ private destroyed = false; - constructor( - def: InjectorType, additionalProviders: StaticProvider[]|null, - readonly parent: Injector) { + constructor(def: InjectorType, readonly parent: Injector) { // Start off by creating Records for every provider declared in every InjectorType // included transitively in `def`. deepForEach( [def], injectorDef => this.processInjectorType(injectorDef, new Set>())); - additionalProviders && - deepForEach(additionalProviders, provider => this.processProvider(provider)); - - // Make sure the INJECTOR token provides this injector. this.records.set(INJECTOR, makeRecord(undefined, this)); @@ -291,18 +284,20 @@ export class R3Injector { throw new Error(`Mixed multi-provider for ${token}.`); } } else { + token = provider; multiRecord = makeRecord(undefined, NOT_YET, true); multiRecord.factory = () => injectArgs(multiRecord !.multi !); this.records.set(token, multiRecord); } token = provider; multiRecord.multi !.push(provider); - } else { - const existing = this.records.get(token); - if (existing && existing.multi !== undefined) { - throw new Error(`Mixed multi-provider for ${stringify(token)}`); - } } + + const existing = this.records.get(token); + if (existing && existing.multi !== undefined) { + throw new Error(`Mixed multi-provider for ${token}`); + } + this.records.set(token, record); } diff --git a/packages/core/src/render3/assert.ts b/packages/core/src/render3/assert.ts index 121217cb58..8c80e47fb6 100644 --- a/packages/core/src/render3/assert.ts +++ b/packages/core/src/render3/assert.ts @@ -46,13 +46,13 @@ export function assertGreaterThan(actual: T, expected: T, msg: string) { } } -export function assertNotDefined(actual: T, msg: string) { +export function assertNull(actual: T, msg: string) { if (actual != null) { throwError(msg); } } -export function assertDefined(actual: T, msg: string) { +export function assertNotNull(actual: T, msg: string) { if (actual == null) { throwError(msg); } diff --git a/packages/core/src/render3/component.ts b/packages/core/src/render3/component.ts index cfbc386e2d..9bc5fa88ca 100644 --- a/packages/core/src/render3/component.ts +++ b/packages/core/src/render3/component.ts @@ -13,7 +13,7 @@ import {Injector} from '../di/injector'; import {ComponentRef as viewEngine_ComponentRef} from '../linker/component_factory'; import {Sanitizer} from '../sanitization/security'; -import {assertComponentType, assertDefined} from './assert'; +import {assertComponentType, assertNotNull} from './assert'; import {queueInitHooks, queueLifecycleHooks} from './hooks'; import {CLEAN_PROMISE, ROOT_DIRECTIVE_INDICES, _getComponentHostLElementNode, baseDirectiveCreate, createLView, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, getRootView, hostElement, initChangeDetectorIfExisting, leaveView, locateHostElement, setHostBindings} from './instructions'; import {ComponentDef, ComponentType} from './interfaces/definition'; @@ -72,6 +72,31 @@ export interface CreateComponentOptions { } +/** + * Bootstraps a component, then creates and returns a `ComponentRef` for that component. + * + * @param componentType Component to bootstrap + * @param options Optional parameters which control bootstrapping + */ +export function createComponentRef( + componentType: ComponentType, opts: CreateComponentOptions): viewEngine_ComponentRef { + const component = renderComponent(componentType, opts); + const hostView = _getComponentHostLElementNode(component).data as LView; + const hostViewRef = new ViewRef(hostView, component); + return { + location: {nativeElement: getHostElement(component)}, + injector: opts.injector || NULL_INJECTOR, + instance: component, + hostView: hostViewRef, + changeDetectorRef: hostViewRef, + componentType: componentType, + // TODO: implement destroy and onDestroy + destroy: () => {}, + onDestroy: (cb: Function) => {} + }; +} + + // TODO: A hack to not pull in the NullInjector from @angular/core. export const NULL_INJECTOR: Injector = { get: (token: any, notFoundValue?: any) => { @@ -106,8 +131,12 @@ export function renderComponent( // The first index of the first selector is the tag name. const componentTag = componentDef.selectors ![0] ![0] as string; const hostNode = locateHostElement(rendererFactory, opts.host || componentTag); - const rootContext = createRootContext(opts.scheduler || requestAnimationFrame.bind(window)); - + const rootContext: RootContext = { + // Incomplete initialization due to circular reference. + component: null !, + scheduler: opts.scheduler || requestAnimationFrame.bind(window), + clean: CLEAN_PROMISE, + }; const rootView: LView = createLView( rendererFactory.createRenderer(hostNode, componentDef.rendererType), createTView(-1, null, null, null), rootContext, @@ -123,8 +152,8 @@ export function renderComponent( elementNode = hostElement(componentTag, hostNode, componentDef, sanitizer); // Create directive instance with factory() and store at index 0 in directives array - rootContext.components.push( - component = baseDirectiveCreate(0, componentDef.factory(), componentDef) as T); + component = rootContext.component = + baseDirectiveCreate(0, componentDef.factory(), componentDef) as T; initChangeDetectorIfExisting(elementNode.nodeInjector, component, elementNode.data !); opts.hostFeatures && opts.hostFeatures.forEach((feature) => feature(component, componentDef)); @@ -140,14 +169,6 @@ export function renderComponent( return component; } -export function createRootContext(scheduler: (workFn: () => void) => void): RootContext { - return { - components: [], - scheduler: scheduler, - clean: CLEAN_PROMISE, - }; -} - /** * Used to enable lifecycle hooks on the root component. * @@ -177,7 +198,7 @@ export function LifecycleHooksFeature(component: any, def: ComponentDef): v */ function getRootContext(component: any): RootContext { const rootContext = getRootView(component).context as RootContext; - ngDevMode && assertDefined(rootContext, 'rootContext'); + ngDevMode && assertNotNull(rootContext, 'rootContext'); return rootContext; } diff --git a/packages/core/src/render3/component_ref.ts b/packages/core/src/render3/component_ref.ts deleted file mode 100644 index 01222b5a3b..0000000000 --- a/packages/core/src/render3/component_ref.ts +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {ChangeDetectorRef} from '../change_detection/change_detector_ref'; -import {InjectionToken} from '../di/injection_token'; -import {Injector, inject} from '../di/injector'; -import {ComponentFactory as viewEngine_ComponentFactory, ComponentRef as viewEngine_ComponentRef} from '../linker/component_factory'; -import {ComponentFactoryResolver as viewEngine_ComponentFactoryResolver} from '../linker/component_factory_resolver'; -import {ElementRef} from '../linker/element_ref'; -import {NgModuleRef as viewEngine_NgModuleRef} from '../linker/ng_module_factory'; -import {RendererFactory2} from '../render/api'; -import {Type} from '../type'; - -import {assertComponentType, assertDefined} from './assert'; -import {createRootContext} from './component'; -import {baseDirectiveCreate, createLView, createTView, enterView, hostElement, initChangeDetectorIfExisting, leaveView, locateHostElement} from './instructions'; -import {ComponentDef, ComponentType} from './interfaces/definition'; -import {LElementNode} from './interfaces/node'; -import {RElement} from './interfaces/renderer'; -import {LView, LViewFlags, RootContext} from './interfaces/view'; -import {ViewRef} from './view_ref'; - -export class ComponentFactoryResolver extends viewEngine_ComponentFactoryResolver { - resolveComponentFactory(component: Type): viewEngine_ComponentFactory { - ngDevMode && assertComponentType(component); - const componentDef = (component as ComponentType).ngComponentDef; - return new ComponentFactory(componentDef); - } -} - -function toRefArray(map: {[key: string]: string}): {propName: string; templateName: string;}[] { - const array: {propName: string; templateName: string;}[] = []; - for (let nonMinified in map) { - if (map.hasOwnProperty(nonMinified)) { - const minified = map[nonMinified]; - array.push({propName: minified, templateName: nonMinified}); - } - } - return array; -} - -/** - * Default {@link RootContext} for all components rendered with {@link renderComponent}. - */ -export const ROOT_CONTEXT = new InjectionToken( - 'ROOT_CONTEXT_TOKEN', - {providedIn: 'root', factory: () => createRootContext(inject(SCHEDULER))}); - -/** - * A change detection scheduler token for {@link RootContext}. This token is the default value used - * for the default `RootContext` found in the {@link ROOT_CONTEXT} token. - */ -export const SCHEDULER = new InjectionToken<((fn: () => void) => void)>( - 'SCHEDULER_TOKEN', {providedIn: 'root', factory: () => requestAnimationFrame.bind(window)}); - -/** - * Render3 implementation of {@link viewEngine_ComponentFactory}. - */ -export class ComponentFactory extends viewEngine_ComponentFactory { - selector: string; - componentType: Type; - ngContentSelectors: string[]; - get inputs(): {propName: string; templateName: string;}[] { - return toRefArray(this.componentDef.inputs); - } - get outputs(): {propName: string; templateName: string;}[] { - return toRefArray(this.componentDef.outputs); - } - - constructor(private componentDef: ComponentDef) { - super(); - this.componentType = componentDef.type; - this.selector = componentDef.selectors[0][0] as string; - this.ngContentSelectors = []; - } - - create( - parentComponentInjector: Injector, projectableNodes?: any[][]|undefined, - rootSelectorOrNode?: any, - ngModule?: viewEngine_NgModuleRef|undefined): viewEngine_ComponentRef { - ngDevMode && assertDefined(ngModule, 'ngModule should always be defined'); - - const rendererFactory = ngModule ? ngModule.injector.get(RendererFactory2) : document; - const hostNode = locateHostElement(rendererFactory, rootSelectorOrNode); - - // The first index of the first selector is the tag name. - const componentTag = this.componentDef.selectors ![0] ![0] as string; - - const rootContext: RootContext = ngModule !.injector.get(ROOT_CONTEXT); - - // Create the root view. Uses empty TView and ContentTemplate. - const rootView: LView = createLView( - rendererFactory.createRenderer(hostNode, this.componentDef.rendererType), - createTView(-1, null, null, null), null, - this.componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways); - rootView.injector = ngModule && ngModule.injector || null; - - // rootView is the parent when bootstrapping - const oldView = enterView(rootView, null !); - - let component: T; - let elementNode: LElementNode; - try { - if (rendererFactory.begin) rendererFactory.begin(); - - // Create element node at index 0 in data array - elementNode = hostElement(componentTag, hostNode, this.componentDef); - - // Create directive instance with factory() and store at index 0 in directives array - rootContext.components.push( - component = baseDirectiveCreate(0, this.componentDef.factory(), this.componentDef) as T); - initChangeDetectorIfExisting(elementNode.nodeInjector, component, elementNode.data !); - - } finally { - enterView(oldView, null); - if (rendererFactory.end) rendererFactory.end(); - } - - // TODO(misko): this is the wrong injector here. - return new ComponentRef( - this.componentType, component, rootView, ngModule !.injector, hostNode !); - } -} - -/** - * Represents an instance of a Component created via a {@link ComponentFactory}. - * - * `ComponentRef` provides access to the Component Instance as well other objects related to this - * Component Instance and allows you to destroy the Component Instance via the {@link #destroy} - * method. - * - */ -export class ComponentRef extends viewEngine_ComponentRef { - destroyCbs: (() => void)[]|null = []; - location: ElementRef; - injector: Injector; - instance: T; - hostView: ViewRef; - changeDetectorRef: ChangeDetectorRef; - componentType: Type; - - constructor( - componentType: Type, instance: T, rootView: LView, injector: Injector, - hostNode: RElement) { - super(); - this.instance = instance; - /* TODO(jasonaden): This is incomplete, to be adjusted in follow-up PR. Notes from Kara:When - * ViewRef.detectChanges is called from ApplicationRef.tick, it will call detectChanges at the - * component instance level. I suspect this means that lifecycle hooks and host bindings on the - * given component won't work (as these are always called at the level above a component). - * - * In render2, ViewRef.detectChanges uses the root view instance for view checks, not the - * component instance. So passing in the root view (1 level above the component) is sufficient. - * We might want to think about creating a fake component for the top level? Or overwrite - * detectChanges with a function that calls tickRootContext? */ - this.hostView = this.changeDetectorRef = new ViewRef(rootView, instance); - this.injector = injector; - this.location = new ElementRef(hostNode); - this.componentType = componentType; - } - - destroy(): void { - ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed'); - this.destroyCbs !.forEach(fn => fn()); - this.destroyCbs = null; - } - onDestroy(callback: () => void): void { - ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed'); - this.destroyCbs !.push(callback); - } -} \ No newline at end of file diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index 4129107841..1c55e79fa6 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -18,9 +18,9 @@ import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_co import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_ViewRef} from '../linker/view_ref'; import {Type} from '../type'; -import {assertDefined, assertGreaterThan, assertLessThan} from './assert'; +import {assertGreaterThan, assertLessThan, assertNotNull} from './assert'; import {addToViewTree, assertPreviousIsParent, createLContainer, createLNodeObject, createTNode, createTView, getDirectiveInstance, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate, resolveDirective} from './instructions'; -import {ComponentTemplate, DirectiveDef, DirectiveDefList, PipeDefList} from './interfaces/definition'; +import {ComponentTemplate, DirectiveDef} from './interfaces/definition'; import {LInjector} from './interfaces/injector'; import {AttributeMarker, LContainerNode, LElementNode, LNode, LViewNode, TNodeFlags, TNodeType} from './interfaces/node'; import {LQueries, QueryReadType} from './interfaces/query'; @@ -256,7 +256,7 @@ export function injectAttribute(attrNameToInject: string): string|undefined { const lElement = getPreviousOrParentNode() as LElementNode; ngDevMode && assertNodeType(lElement, TNodeType.Element); const tElement = lElement.tNode; - ngDevMode && assertDefined(tElement, 'expecting tNode'); + ngDevMode && assertNotNull(tElement, 'expecting tNode'); const attrs = tElement.attrs; if (attrs) { for (let i = 0; i < attrs.length; i = i + 2) { @@ -707,7 +707,7 @@ export function getOrCreateTemplateRef(di: LInjector): viewEngine_TemplateRef hostTNode.tViews = createTView( -1, hostNode.data.template !, hostTView.directiveRegistry, hostTView.pipeRegistry); } - ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated'); + ngDevMode && assertNotNull(hostTNode.tViews, 'TView must be allocated'); di.templateRef = new TemplateRef( getOrCreateElementRef(di), hostTNode.tViews as TView, getRenderer(), hostNode.data.queries); } diff --git a/packages/core/src/render3/index.ts b/packages/core/src/render3/index.ts index 9d3c28b344..0e8e091bc3 100644 --- a/packages/core/src/render3/index.ts +++ b/packages/core/src/render3/index.ts @@ -6,16 +6,16 @@ * found in the LICENSE file at https://angular.io/license */ -import {LifecycleHooksFeature, getHostElement, getRenderedText, renderComponent, whenRendered} from './component'; +import {LifecycleHooksFeature, createComponentRef, getHostElement, getRenderedText, renderComponent, whenRendered} from './component'; import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective, definePipe} from './definition'; import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType, PipeDef} from './interfaces/definition'; -export {ComponentFactory, ComponentFactoryResolver, ComponentRef} from './component_ref'; export {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, directiveInject, injectAttribute, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from './di'; export {RenderFlags} from './interfaces/definition'; export {CssSelectorList} from './interfaces/projection'; + // Naming scheme: // - Capital letters are for creating things: T(Text), E(Element), D(Directive), V(View), // C(Container), L(Listener) @@ -73,8 +73,6 @@ export { tick, } from './instructions'; -export {NgModuleDef, NgModuleFactory, NgModuleRef, NgModuleType} from './ng_module_ref'; - export { AttributeMarker } from './interfaces/node'; @@ -124,6 +122,7 @@ export { defineComponent, defineDirective, definePipe, + createComponentRef, getHostElement, getRenderedText, renderComponent, diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index 509cd528bf..a004f10d81 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -8,7 +8,7 @@ import './ng_dev_mode'; -import {assertDefined, assertEqual, assertLessThan, assertNotDefined, assertNotEqual, assertSame} from './assert'; +import {assertEqual, assertLessThan, assertNotEqual, assertNotNull, assertNull, assertSame} from './assert'; import {LContainer} from './interfaces/container'; import {LInjector} from './interfaces/injector'; import {CssSelectorList, LProjection, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection'; @@ -406,8 +406,7 @@ export function createLNode( if ((type & TNodeType.ViewOrElement) === TNodeType.ViewOrElement && isState) { // Bit of a hack to bust through the readonly because there is a circular dep between // LView and LNode. - ngDevMode && - assertNotDefined((state as LView).node, 'LView.node should not have been initialized'); + ngDevMode && assertNull((state as LView).node, 'LView.node should not have been initialized'); (state as{node: LNode}).node = node; if (firstTemplatePass) (state as LView).tView.node = node.tNode; } @@ -456,7 +455,7 @@ export function renderTemplate( sanitizer)); } const hostView = host.data !; - ngDevMode && assertDefined(hostView, 'Host node should have an LView defined in host.data.'); + ngDevMode && assertNotNull(hostView, 'Host node should have an LView defined in host.data.'); renderComponentOrTemplate(host, hostView, context, template); return host; } @@ -1301,8 +1300,8 @@ export function textBinding(index: number, value: T | NO_CHANGE): void { if (value !== NO_CHANGE) { ngDevMode && assertDataInRange(index); const existingNode = data[index] as LTextNode; - ngDevMode && assertDefined(existingNode, 'LNode should exist'); - ngDevMode && assertDefined(existingNode.native, 'native element should exist'); + ngDevMode && assertNotNull(existingNode, 'LNode should exist'); + ngDevMode && assertNotNull(existingNode.native, 'native element should exist'); ngDevMode && ngDevMode.rendererSetText++; isProceduralRenderer(renderer) ? renderer.setValue(existingNode.native, stringify(value)) : existingNode.native.textContent = stringify(value); @@ -1326,7 +1325,7 @@ export function directiveCreate( index: number, directive: T, directiveDef: DirectiveDef| ComponentDef): T { const instance = baseDirectiveCreate(index, directive, directiveDef); - ngDevMode && assertDefined(previousOrParentNode.tNode, 'previousOrParentNode.tNode'); + ngDevMode && assertNotNull(previousOrParentNode.tNode, 'previousOrParentNode.tNode'); const tNode = previousOrParentNode.tNode; const isComponent = (directiveDef as ComponentDef).template; @@ -1495,7 +1494,7 @@ function generateInitialInputs( export function createLContainer( parentLNode: LNode, currentView: LView, template?: ComponentTemplate, isForViewContainerRef?: boolean): LContainer { - ngDevMode && assertDefined(parentLNode, 'containers should have a parent'); + ngDevMode && assertNotNull(parentLNode, 'containers should have a parent'); return { views: [], nextIndex: isForViewContainerRef ? null : 0, @@ -1612,7 +1611,7 @@ function refreshDynamicChildren() { const lViewNode = container.views[i]; // The directives and pipes are not needed here as an existing view is only being refreshed. const dynamicView = lViewNode.data; - ngDevMode && assertDefined(dynamicView.tView, 'TView must be allocated'); + ngDevMode && assertNotNull(dynamicView.tView, 'TView must be allocated'); renderEmbeddedTemplate(lViewNode, dynamicView.tView, dynamicView.context !, renderer); } } @@ -1700,7 +1699,7 @@ export function embeddedViewStart(viewBlockId: number): RenderFlags { function getOrCreateEmbeddedTView(viewIndex: number, parent: LContainerNode): TView { ngDevMode && assertNodeType(parent, TNodeType.Container); const containerTViews = (parent !.tNode as TContainerNode).tViews as TView[]; - ngDevMode && assertDefined(containerTViews, 'TView expected'); + ngDevMode && assertNotNull(containerTViews, 'TView expected'); ngDevMode && assertEqual(Array.isArray(containerTViews), true, 'TViews should be in an array'); if (viewIndex >= containerTViews.length || containerTViews[viewIndex] == null) { const tView = currentView.tView; @@ -1774,7 +1773,7 @@ export function componentRefresh(directiveIndex: number, elementIndex: number ngDevMode && assertDataInRange(elementIndex); const element = data ![elementIndex] as LElementNode; ngDevMode && assertNodeType(element, TNodeType.Element); - ngDevMode && assertDefined(element.data, `Component's host node should have an LView attached.`); + ngDevMode && assertNotNull(element.data, `Component's host node should have an LView attached.`); const hostView = element.data !; // Only attached CheckAlways components or attached, dirty OnPush components should be checked @@ -1929,13 +1928,13 @@ export function projection( function findComponentHost(lView: LView): LElementNode { let viewRootLNode = lView.node; while (viewRootLNode.tNode.type === TNodeType.View) { - ngDevMode && assertDefined(lView.parent, 'lView.parent'); + ngDevMode && assertNotNull(lView.parent, 'lView.parent'); lView = lView.parent !; viewRootLNode = lView.node; } ngDevMode && assertNodeType(viewRootLNode, TNodeType.Element); - ngDevMode && assertDefined(viewRootLNode.data, 'node.data'); + ngDevMode && assertNotNull(viewRootLNode.data, 'node.data'); return viewRootLNode as LElementNode; } @@ -2013,7 +2012,7 @@ export function markViewDirty(view: LView): void { } currentView.flags |= LViewFlags.Dirty; - ngDevMode && assertDefined(currentView !.context, 'rootContext'); + ngDevMode && assertNotNull(currentView !.context, 'rootContext'); scheduleTick(currentView !.context as RootContext); } @@ -2034,7 +2033,7 @@ export function scheduleTick(rootContext: RootContext) { let res: null|((val: null) => void); rootContext.clean = new Promise((r) => res = r); rootContext.scheduler(() => { - tickRootContext(rootContext); + tick(rootContext.component); res !(null); rootContext.clean = _CLEAN_PROMISE; }); @@ -2055,18 +2054,11 @@ export function scheduleTick(rootContext: RootContext) { */ export function tick(component: T): void { const rootView = getRootView(component); - const rootContext = rootView.context as RootContext; - tickRootContext(rootContext); -} + const rootComponent = (rootView.context as RootContext).component; + const hostNode = _getComponentHostLElementNode(rootComponent); -function tickRootContext(rootContext: RootContext) { - for (let i = 0; i < rootContext.components.length; i++) { - const rootComponent = rootContext.components[i]; - const hostNode = _getComponentHostLElementNode(rootComponent); - - ngDevMode && assertDefined(hostNode.data, 'Component host node should be attached to an LView'); - renderComponentOrTemplate(hostNode, getRootView(rootComponent), rootComponent); - } + ngDevMode && assertNotNull(hostNode.data, 'Component host node should be attached to an LView'); + renderComponentOrTemplate(hostNode, rootView, rootComponent); } /** @@ -2077,7 +2069,7 @@ function tickRootContext(rootContext: RootContext) { */ export function getRootView(component: any): LView { - ngDevMode && assertDefined(component, 'component'); + ngDevMode && assertNotNull(component, 'component'); const lElementNode = _getComponentHostLElementNode(component); let lView = lElementNode.view; while (lView.parent) { @@ -2101,7 +2093,7 @@ export function getRootView(component: any): LView { */ export function detectChanges(component: T): void { const hostNode = _getComponentHostLElementNode(component); - ngDevMode && assertDefined(hostNode.data, 'Component host node should be attached to an LView'); + ngDevMode && assertNotNull(hostNode.data, 'Component host node should be attached to an LView'); detectChangesInternal(hostNode.data as LView, hostNode, component); } @@ -2150,7 +2142,7 @@ export function detectChangesInternal(hostView: LView, hostNode: LElementNode * @param component Component to mark as dirty. */ export function markDirty(component: T) { - ngDevMode && assertDefined(component, 'component'); + ngDevMode && assertNotNull(component, 'component'); const lElementNode = _getComponentHostLElementNode(component); markViewDirty(lElementNode.view); } @@ -2396,7 +2388,7 @@ export function load(index: number): T { /** Retrieves a value from the `directives` array. */ export function loadDirective(index: number): T { - ngDevMode && assertDefined(directives, 'Directives array should be defined if reading a dir.'); + ngDevMode && assertNotNull(directives, 'Directives array should be defined if reading a dir.'); ngDevMode && assertDataInRange(index, directives !); return directives ![index]; } @@ -2461,7 +2453,7 @@ export function assertPreviousIsParent() { } function assertHasParent() { - assertDefined(getParentLNode(previousOrParentNode), 'previousOrParentNode should have a parent'); + assertNotNull(getParentLNode(previousOrParentNode), 'previousOrParentNode should have a parent'); } function assertDataInRange(index: number, arr?: any[]) { @@ -2492,9 +2484,9 @@ export function assertReservedSlotInitialized(slotOffset: number, numSlots: numb } export function _getComponentHostLElementNode(component: T): LElementNode { - ngDevMode && assertDefined(component, 'expecting component got null'); + ngDevMode && assertNotNull(component, 'expecting component got null'); const lElementNode = (component as any)[NG_HOST_SYMBOL] as LElementNode; - ngDevMode && assertDefined(component, 'object is not a component'); + ngDevMode && assertNotNull(component, 'object is not a component'); return lElementNode; } diff --git a/packages/core/src/render3/interfaces/view.ts b/packages/core/src/render3/interfaces/view.ts index 204c1e0960..c069e6f0ed 100644 --- a/packages/core/src/render3/interfaces/view.ts +++ b/packages/core/src/render3/interfaces/view.ts @@ -420,10 +420,10 @@ export interface RootContext { clean: Promise; /** - * RootComponents - The components that were instantiated by the call to + * RootComponent - The component which was instantiated by the call to * {@link renderComponent}. */ - components: {}[]; + component: {}; } /** diff --git a/packages/core/src/render3/ng_module_ref.ts b/packages/core/src/render3/ng_module_ref.ts deleted file mode 100644 index 1844b3b57c..0000000000 --- a/packages/core/src/render3/ng_module_ref.ts +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Injector} from '../di/injector'; -import {StaticProvider} from '../di/provider'; -import {createInjector} from '../di/r3_injector'; -import {ComponentFactoryResolver as viewEngine_ComponentFactoryResolver} from '../linker/component_factory_resolver'; -import {InternalNgModuleRef, NgModuleFactory as viewEngine_NgModuleFactory, NgModuleRef as viewEngine_NgModuleRef} from '../linker/ng_module_factory'; -import {Type} from '../type'; -import {stringify} from '../util'; -import {assertDefined} from './assert'; -import {ComponentFactoryResolver} from './component_ref'; - -export interface NgModuleType { ngModuleDef: NgModuleDef; } - -export interface NgModuleDef { bootstrap: Type[]; } - -export const COMPONENT_FACTORY_RESOLVER: StaticProvider = { - provide: viewEngine_ComponentFactoryResolver, - useFactory: () => new ComponentFactoryResolver(), - deps: [], -}; - -export class NgModuleRef extends viewEngine_NgModuleRef implements InternalNgModuleRef { - // tslint:disable-next-line:require-internal-with-underscore - _bootstrapComponents: Type[] = []; - injector: Injector; - componentFactoryResolver: viewEngine_ComponentFactoryResolver; - instance: T; - destroyCbs: (() => void)[]|null = []; - - constructor(ngModuleType: Type, parentInjector: Injector|null) { - super(); - const ngModuleDef = (ngModuleType as any as NgModuleType).ngModuleDef; - ngDevMode && assertDefined( - ngModuleDef, - `NgModule '${stringify(ngModuleType)}' is not a subtype of 'NgModuleType'.`); - - this._bootstrapComponents = ngModuleDef.bootstrap; - const additionalProviders: StaticProvider[] = [ - COMPONENT_FACTORY_RESOLVER, { - provide: viewEngine_NgModuleRef, - useValue: this, - } - ]; - this.injector = createInjector(ngModuleType, parentInjector, additionalProviders); - this.instance = this.injector.get(ngModuleType); - this.componentFactoryResolver = new ComponentFactoryResolver(); - } - - destroy(): void { - ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed'); - this.destroyCbs !.forEach(fn => fn()); - this.destroyCbs = null; - } - onDestroy(callback: () => void): void { - ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed'); - this.destroyCbs !.push(callback); - } -} - -export class NgModuleFactory extends viewEngine_NgModuleFactory { - constructor(public moduleType: Type) { super(); } - - create(parentInjector: Injector|null): viewEngine_NgModuleRef { - return new NgModuleRef(this.moduleType, parentInjector); - } -} diff --git a/packages/core/src/render3/node_assert.ts b/packages/core/src/render3/node_assert.ts index c30a0f2455..73bf9b6997 100644 --- a/packages/core/src/render3/node_assert.ts +++ b/packages/core/src/render3/node_assert.ts @@ -6,16 +6,16 @@ * found in the LICENSE file at https://angular.io/license */ -import {assertDefined, assertEqual} from './assert'; +import {assertEqual, assertNotNull} from './assert'; import {LNode, TNodeType} from './interfaces/node'; export function assertNodeType(node: LNode, type: TNodeType) { - assertDefined(node, 'should be called with a node'); + assertNotNull(node, 'should be called with a node'); assertEqual(node.tNode.type, type, `should be a ${typeName(type)}`); } export function assertNodeOfPossibleTypes(node: LNode, ...types: TNodeType[]) { - assertDefined(node, 'should be called with a node'); + assertNotNull(node, 'should be called with a node'); const found = types.some(type => node.tNode.type === type); assertEqual(found, true, `Should be one of ${types.map(typeName).join(', ')}`); } diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts index 716565fc71..db4eb95d50 100644 --- a/packages/core/src/render3/node_manipulation.ts +++ b/packages/core/src/render3/node_manipulation.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {assertDefined} from './assert'; +import {assertNotNull} from './assert'; import {callHooks} from './hooks'; import {LContainer, unusedValueExportToPlacateAjd as unused1} from './interfaces/container'; import {LContainerNode, LElementNode, LNode, LProjectionNode, LTextNode, LViewNode, TNodeFlags, TNodeType, unusedValueExportToPlacateAjd as unused2} from './interfaces/node'; diff --git a/packages/core/src/render3/node_selector_matcher.ts b/packages/core/src/render3/node_selector_matcher.ts index db94094e24..73f2ab55ec 100644 --- a/packages/core/src/render3/node_selector_matcher.ts +++ b/packages/core/src/render3/node_selector_matcher.ts @@ -8,7 +8,7 @@ import './ng_dev_mode'; -import {assertDefined} from './assert'; +import {assertNotNull} from './assert'; import {AttributeMarker, TAttributes, TNode, unusedValueExportToPlacateAjd as unused1} from './interfaces/node'; import {CssSelector, CssSelectorList, NG_PROJECT_AS_ATTR_NAME, SelectorFlags, unusedValueExportToPlacateAjd as unused2} from './interfaces/projection'; @@ -36,7 +36,7 @@ function isCssClassMatching(nodeClassAttrVal: string, cssClassToMatch: string): * @returns true if node matches the selector. */ export function isNodeMatchingSelector(tNode: TNode, selector: CssSelector): boolean { - ngDevMode && assertDefined(selector[0], 'Selector should have a tag name'); + ngDevMode && assertNotNull(selector[0], 'Selector should have a tag name'); let mode: SelectorFlags = SelectorFlags.ELEMENT; const nodeAttrs = tNode.attrs !; diff --git a/packages/core/src/render3/query.ts b/packages/core/src/render3/query.ts index c04f3f48c8..fd6a667a01 100644 --- a/packages/core/src/render3/query.ts +++ b/packages/core/src/render3/query.ts @@ -15,7 +15,7 @@ import {QueryList as viewEngine_QueryList} from '../linker/query_list'; import {Type} from '../type'; import {getSymbolIterator} from '../util'; -import {assertDefined, assertEqual} from './assert'; +import {assertEqual, assertNotNull} from './assert'; import {ReadFromInjectorFn, getOrCreateNodeInjectorForNode} from './di'; import {assertPreviousIsParent, getCurrentQueries, store, storeCleanupWithContext} from './instructions'; import {DirectiveDef, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition'; @@ -163,7 +163,7 @@ export class LQueries_ implements LQueries { let query = this.deep; while (query) { ngDevMode && - assertDefined( + assertNotNull( query.containerValues, 'View queries need to have a pointer to container values.'); query.containerValues !.splice(index, 0, query.values); query = query.next; @@ -179,7 +179,7 @@ export class LQueries_ implements LQueries { let query = this.deep; while (query) { ngDevMode && - assertDefined( + assertNotNull( query.containerValues, 'View queries need to have a pointer to container values.'); const removed = query.containerValues !.splice(index, 1); @@ -273,7 +273,7 @@ function add(query: LQuery| null, node: LNode) { if (directiveIdx !== null) { // a node is matching a predicate - determine what to read // note that queries using name selector must specify read strategy - ngDevMode && assertDefined(predicate.read, 'the node should have a predicate'); + ngDevMode && assertNotNull(predicate.read, 'the node should have a predicate'); const result = readFromNodeInjector(nodeInjector, node, predicate.read !, directiveIdx); if (result !== null) { addMatch(query, result); diff --git a/packages/core/src/render3/view_ref.ts b/packages/core/src/render3/view_ref.ts index 55c1b11e20..060f2c997b 100644 --- a/packages/core/src/render3/view_ref.ts +++ b/packages/core/src/render3/view_ref.ts @@ -6,10 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {ApplicationRef} from '../application_ref'; -import {ChangeDetectorRef as viewEngine_ChangeDetectorRef} from '../change_detection/change_detector_ref'; import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_container_ref'; -import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, InternalViewRef as viewEngine_InternalViewRef} from '../linker/view_ref'; +import {EmbeddedViewRef as viewEngine_EmbeddedViewRef} from '../linker/view_ref'; import {checkNoChanges, detectChanges, markViewDirty, storeCleanupFn} from './instructions'; import {ComponentTemplate} from './interfaces/definition'; @@ -17,10 +15,7 @@ import {LViewNode} from './interfaces/node'; import {LView, LViewFlags} from './interfaces/view'; import {destroyLView} from './node_manipulation'; -export class ViewRef implements viewEngine_EmbeddedViewRef, viewEngine_InternalViewRef, - viewEngine_ChangeDetectorRef { - private _appRef: ApplicationRef|null; - +export class ViewRef implements viewEngine_EmbeddedViewRef { context: T; rootNodes: any[]; @@ -215,10 +210,6 @@ export class ViewRef implements viewEngine_EmbeddedViewRef, viewEngine_Int * introduce other changes. */ checkNoChanges(): void { checkNoChanges(this.context); } - - detachFromAppRef() { this._appRef = null; } - - attachToAppRef(appRef: ApplicationRef) { this._appRef = appRef; } } diff --git a/packages/core/test/application_ref_integration_spec.ts b/packages/core/test/application_ref_integration_spec.ts deleted file mode 100644 index 9dee7acc17..0000000000 --- a/packages/core/test/application_ref_integration_spec.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {ApplicationModule, ApplicationRef, DoCheck, InjectFlags, InjectorType, Input, OnInit, PlatformRef, TestabilityRegistry, Type, defineInjector, inject, ɵE as elementStart, ɵNgModuleDef as NgModuleDef, ɵRenderFlags as RenderFlags, ɵT as text, ɵdefineComponent as defineComponent, ɵe as elementEnd, ɵi1 as interpolation1, ɵt as textBinding} from '@angular/core'; -import {getTestBed, withBody} from '@angular/core/testing'; -import {BrowserModule, EVENT_MANAGER_PLUGINS, platformBrowser} from '@angular/platform-browser'; - -import {BROWSER_MODULE_PROVIDERS} from '../../platform-browser/src/browser'; -import {APPLICATION_MODULE_PROVIDERS} from '../src/application_module'; -import {NgModuleFactory} from '../src/render3/ng_module_ref'; - -describe('ApplicationRef bootstrap', () => { - class HelloWorldComponent implements OnInit, DoCheck { - log: string[] = []; - name = 'World'; - static ngComponentDef = defineComponent({ - type: HelloWorldComponent, - selectors: [['hello-world']], - factory: () => new HelloWorldComponent(), - template: function(rf: RenderFlags, ctx: HelloWorldComponent): void { - if (rf & RenderFlags.Create) { - elementStart(0, 'div'); - text(1); - elementEnd(); - } - if (rf & RenderFlags.Update) { - textBinding(1, interpolation1('Hello ', ctx.name, '')); - } - } - }); - - ngOnInit(): void { this.log.push('OnInit'); } - - ngDoCheck(): void { this.log.push('DoCheck'); } - } - - class MyAppModule { - static ngInjectorDef = - defineInjector({factory: () => new MyAppModule(), imports: [BrowserModule]}); - static ngModuleDef = defineNgModule({bootstrap: [HelloWorldComponent]}); - } - - it('should bootstrap hello world', withBody('', async() => { - const MyAppModuleFactory = new NgModuleFactory(MyAppModule); - const moduleRef = - await getTestBed().platform.bootstrapModuleFactory(MyAppModuleFactory, {ngZone: 'noop'}); - const appRef = moduleRef.injector.get(ApplicationRef); - const helloWorldComponent = appRef.components[0].instance as HelloWorldComponent; - expect(document.body.innerHTML).toEqual('
Hello World
'); - // TODO(jasonaden): Get with Kara on lifecycle hooks - // expect(helloWorldComponent.log).toEqual(['OnInit', 'DoCheck']); - helloWorldComponent.name = 'Mundo'; - appRef.tick(); - expect(document.body.innerHTML).toEqual('
Hello Mundo
'); - // TODO(jasonaden): Get with Kara on lifecycle hooks - // expect(helloWorldComponent.log).toEqual(['OnInit', 'DoCheck', 'DoCheck']); - - // Cleanup TestabilityRegistry - const registry: TestabilityRegistry = getTestBed().get(TestabilityRegistry); - registry.unregisterAllApplications(); - })); - -}); - -///////////////////////////////////////////////////////// - -// These go away when Compiler is ready - -(BrowserModule as any as InjectorType).ngInjectorDef = defineInjector({ - factory: function BrowserModule_Factory() { - return new BrowserModule(inject(BrowserModule, InjectFlags.Optional | InjectFlags.SkipSelf)); - }, - imports: [ApplicationModule], - providers: BROWSER_MODULE_PROVIDERS -}); - -(ApplicationModule as any as InjectorType).ngInjectorDef = defineInjector({ - factory: function ApplicationModule_Factory() { - return new ApplicationModule(inject(ApplicationRef)); - }, - providers: APPLICATION_MODULE_PROVIDERS -}); - -export function defineNgModule({bootstrap}: {bootstrap?: Type[]}): NgModuleDef { - return { - bootstrap: bootstrap || [], - }; -} - -///////////////////////////////////////////////////////// diff --git a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json index c1c0de6f38..df06f6a31f 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -56,9 +56,6 @@ { "name": "createLView" }, - { - "name": "createRootContext" - }, { "name": "createTNode" }, diff --git a/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json index c359140b00..56d1450518 100644 --- a/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json @@ -2418,7 +2418,7 @@ "name": "assertInterpolationSymbols" }, { - "name": "assertNotNull" + "name": "assertNotNull$1" }, { "name": "assertPlatform" diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index 865432ac91..64f8a6e020 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -266,9 +266,6 @@ { "name": "createOutput" }, - { - "name": "createRootContext" - }, { "name": "createTNode" }, @@ -660,7 +657,7 @@ "name": "throwMultipleComponentError" }, { - "name": "tickRootContext" + "name": "tick" }, { "name": "trackByIdentity" diff --git a/packages/core/test/di/r3_injector_spec.ts b/packages/core/test/di/r3_injector_spec.ts index 5e690b2f86..7d08f65de5 100644 --- a/packages/core/test/di/r3_injector_spec.ts +++ b/packages/core/test/di/r3_injector_spec.ts @@ -41,8 +41,6 @@ describe('InjectorDef-based createInjector()', () => { const STATIC_TOKEN = new InjectionToken('STATIC_TOKEN'); - const LOCALE = new InjectionToken('LOCALE'); - class ServiceWithDep { constructor(readonly service: Service) {} @@ -52,15 +50,6 @@ describe('InjectorDef-based createInjector()', () => { }); } - class ServiceWithMultiDep { - constructor(readonly locale: string[]) {} - - static ngInjectableDef = defineInjectable({ - providedIn: null, - factory: () => new ServiceWithMultiDep(inject(LOCALE)), - }); - } - class ServiceTwo { static ngInjectableDef = defineInjectable({ providedIn: null, @@ -123,9 +112,6 @@ describe('InjectorDef-based createInjector()', () => { imports: [IntermediateModule], providers: [ ServiceWithDep, - ServiceWithMultiDep, - {provide: LOCALE, multi: true, useValue: 'en'}, - {provide: LOCALE, multi: true, useValue: 'es'}, Service, {provide: SERVICE_TOKEN, useExisting: Service}, CircularA, @@ -182,12 +168,6 @@ describe('InjectorDef-based createInjector()', () => { expect(instance.service).toBe(injector.get(Service)); }); - it('injects a service with dependencies on multi-providers', () => { - const instance = injector.get(ServiceWithMultiDep); - expect(instance instanceof ServiceWithMultiDep); - expect(instance.locale).toEqual(['en', 'es']); - }); - it('injects a token with useExisting', () => { const instance = injector.get(SERVICE_TOKEN); expect(instance).toBe(injector.get(Service)); diff --git a/packages/core/test/render3/component_spec.ts b/packages/core/test/render3/component_spec.ts index 148f447ded..7b7026e9a2 100644 --- a/packages/core/test/render3/component_spec.ts +++ b/packages/core/test/render3/component_spec.ts @@ -7,9 +7,9 @@ */ -import {DoCheck, ViewEncapsulation, createInjector, defineInjectable, defineInjector} from '../../src/core'; +import {ComponentFactory, DoCheck, ViewEncapsulation, createInjector, defineInjectable, defineInjector} from '../../src/core'; import {getRenderedText} from '../../src/render3/component'; -import {ComponentFactory, LifecycleHooksFeature, defineComponent, directiveInject, markDirty} from '../../src/render3/index'; +import {LifecycleHooksFeature, defineComponent, directiveInject, markDirty} from '../../src/render3/index'; import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, text, textBinding, tick} from '../../src/render3/instructions'; import {ComponentDef, DirectiveDef, RenderFlags} from '../../src/render3/interfaces/definition'; import {createRendererType2} from '../../src/view/index'; @@ -364,27 +364,4 @@ describe('recursive components', () => { tick(comp); expect(events).toEqual(['check6', 'check2', 'check0', 'check1', 'check5', 'check3', 'check4']); }); - - it('should map inputs minified & unminified names', async() => { - class TestInputsComponent { - minifiedName: string; - static ngComponentDef = defineComponent({ - type: TestInputsComponent, - selectors: [['test-inputs']], - inputs: {minifiedName: 'unminifiedName'}, - factory: () => new TestInputsComponent(), - template: function(rf: RenderFlags, ctx: TestInputsComponent): void { - // Template not needed for this test - } - }); - } - - const testInputsComponentFactory = new ComponentFactory(TestInputsComponent.ngComponentDef); - - expect([ - {propName: 'minifiedName', templateName: 'unminifiedName'} - ]).toEqual(testInputsComponentFactory.inputs); - - }); - }); diff --git a/packages/core/test/render3/render_util.ts b/packages/core/test/render3/render_util.ts index 0a68b1ead8..cb4bf297ad 100644 --- a/packages/core/test/render3/render_util.ts +++ b/packages/core/test/render3/render_util.ts @@ -135,7 +135,7 @@ export class ComponentFixture extends BaseFixture { // Fixtures above are preferred way of testing Components and Templates /////////////////////////////////////////////////////////////////////////////////// -export const document = ((typeof global == 'object' && global || window) as any).document; +export const document = ((global || window) as any).document; export let containerEl: HTMLElement = null !; let host: LElementNode|null; const isRenderer2 = diff --git a/packages/platform-browser/src/browser.ts b/packages/platform-browser/src/browser.ts index 9550029af9..dc13d2bdbb 100644 --- a/packages/platform-browser/src/browser.ts +++ b/packages/platform-browser/src/browser.ts @@ -7,7 +7,7 @@ */ import {CommonModule, PlatformLocation, ɵPLATFORM_BROWSER_ID as PLATFORM_BROWSER_ID} from '@angular/common'; -import {APP_ID, ApplicationModule, ClassProvider, ConstructorSansProvider, ErrorHandler, ExistingProvider, FactoryProvider, Inject, InjectionToken, ModuleWithProviders, NgModule, NgZone, Optional, PLATFORM_ID, PLATFORM_INITIALIZER, PlatformRef, RendererFactory2, RootRenderer, Sanitizer, SkipSelf, StaticProvider, Testability, TypeProvider, ValueProvider, createPlatformFactory, platformCore, ɵAPP_ROOT as APP_ROOT} from '@angular/core'; +import {APP_ID, ApplicationModule, ErrorHandler, ModuleWithProviders, NgModule, Optional, PLATFORM_ID, PLATFORM_INITIALIZER, PlatformRef, RendererFactory2, RootRenderer, Sanitizer, SkipSelf, StaticProvider, Testability, createPlatformFactory, platformCore, ɵAPP_ROOT as APP_ROOT} from '@angular/core'; import {BrowserDomAdapter} from './browser/browser_adapter'; import {BrowserPlatformLocation} from './browser/location/browser_platform_location'; @@ -20,7 +20,7 @@ import {getDOM} from './dom/dom_adapter'; import {DomRendererFactory2} from './dom/dom_renderer'; import {DOCUMENT} from './dom/dom_tokens'; import {DomEventsPlugin} from './dom/events/dom_events'; -import {EVENT_MANAGER_PLUGINS, EventManager, EventManagerPlugin} from './dom/events/event_manager'; +import {EVENT_MANAGER_PLUGINS, EventManager} from './dom/events/event_manager'; import {HAMMER_GESTURE_CONFIG, HammerGestureConfig, HammerGesturesPlugin} from './dom/events/hammer_gestures'; import {KeyEventsPlugin} from './dom/events/key_events'; import {DomSharedStylesHost, SharedStylesHost} from './dom/shared_styles_host'; @@ -60,47 +60,34 @@ export function _document(): any { return document; } -export const BROWSER_MODULE_PROVIDERS: StaticProvider[] = [ - BROWSER_SANITIZATION_PROVIDERS, - {provide: APP_ROOT, useValue: true}, - {provide: ErrorHandler, useFactory: errorHandler, deps: []}, - { - provide: EVENT_MANAGER_PLUGINS, - useClass: DomEventsPlugin, - multi: true, - deps: [DOCUMENT, NgZone, PLATFORM_ID] - }, - {provide: EVENT_MANAGER_PLUGINS, useClass: KeyEventsPlugin, multi: true, deps: [DOCUMENT]}, - { - provide: EVENT_MANAGER_PLUGINS, - useClass: HammerGesturesPlugin, - multi: true, - deps: [DOCUMENT, HAMMER_GESTURE_CONFIG] - }, - {provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig, deps: []}, - { - provide: DomRendererFactory2, - useClass: DomRendererFactory2, - deps: [EventManager, DomSharedStylesHost] - }, - {provide: RendererFactory2, useExisting: DomRendererFactory2}, - {provide: SharedStylesHost, useExisting: DomSharedStylesHost}, - {provide: DomSharedStylesHost, useClass: DomSharedStylesHost, deps: [DOCUMENT]}, - {provide: Testability, useClass: Testability, deps: [NgZone]}, - {provide: EventManager, useClass: EventManager, deps: [EVENT_MANAGER_PLUGINS, NgZone]}, - ELEMENT_PROBE_PROVIDERS, - {provide: Meta, useClass: Meta, deps: [DOCUMENT]}, - {provide: Title, useClass: Title, deps: [DOCUMENT]}, -]; - /** * The ng module for the browser. * * */ -@NgModule({providers: BROWSER_MODULE_PROVIDERS, exports: [CommonModule, ApplicationModule]}) +@NgModule({ + providers: [ + BROWSER_SANITIZATION_PROVIDERS, + {provide: APP_ROOT, useValue: true}, + {provide: ErrorHandler, useFactory: errorHandler, deps: []}, + {provide: EVENT_MANAGER_PLUGINS, useClass: DomEventsPlugin, multi: true}, + {provide: EVENT_MANAGER_PLUGINS, useClass: KeyEventsPlugin, multi: true}, + {provide: EVENT_MANAGER_PLUGINS, useClass: HammerGesturesPlugin, multi: true}, + {provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig}, + DomRendererFactory2, + {provide: RendererFactory2, useExisting: DomRendererFactory2}, + {provide: SharedStylesHost, useExisting: DomSharedStylesHost}, + DomSharedStylesHost, + Testability, + EventManager, + ELEMENT_PROBE_PROVIDERS, + Meta, + Title, + ], + exports: [CommonModule, ApplicationModule] +}) export class BrowserModule { - constructor(@Optional() @SkipSelf() @Inject(BrowserModule) parentModule: BrowserModule|null) { + constructor(@Optional() @SkipSelf() parentModule: BrowserModule) { if (parentModule) { throw new Error( `BrowserModule has already been loaded. If you need access to common directives such as NgIf and NgFor from a lazy loaded module, import CommonModule instead.`); diff --git a/tools/public_api_guard/core/core.d.ts b/tools/public_api_guard/core/core.d.ts index d65ed33a3c..d781017237 100644 --- a/tools/public_api_guard/core/core.d.ts +++ b/tools/public_api_guard/core/core.d.ts @@ -143,11 +143,6 @@ export declare abstract class ComponentRef { abstract onDestroy(callback: Function): void; } -/** @experimental */ -export interface ConstructorSansProvider { - deps?: any[]; -} - export declare const ContentChild: ContentChildDecorator; export interface ContentChildDecorator { @@ -173,7 +168,7 @@ export interface ContentChildrenDecorator { } /** @experimental */ -export declare function createInjector(defType: any, parent?: Injector | null, additionalProviders?: StaticProvider[] | null): Injector; +export declare function createInjector(defType: any, parent?: Injector | null): Injector; /** @experimental */ export declare function createPlatform(injector: Injector): PlatformRef; @@ -614,7 +609,7 @@ export interface Predicate { (value: T): boolean; } -export declare type Provider = TypeProvider | ValueProvider | ClassProvider | ConstructorProvider | ExistingProvider | FactoryProvider | any[]; +export declare type Provider = TypeProvider | ValueProvider | ClassProvider | ExistingProvider | FactoryProvider | any[]; export declare abstract class Query { } diff --git a/tools/public_api_guard/platform-browser/platform-browser.d.ts b/tools/public_api_guard/platform-browser/platform-browser.d.ts index 52231287f2..e1c07cbe9b 100644 --- a/tools/public_api_guard/platform-browser/platform-browser.d.ts +++ b/tools/public_api_guard/platform-browser/platform-browser.d.ts @@ -1,5 +1,5 @@ export declare class BrowserModule { - constructor(parentModule: BrowserModule | null); + constructor(parentModule: BrowserModule); /** @experimental */ static withServerTransition(params: { appId: string; }): ModuleWithProviders;