From 2fee5cc0958e08d16d6e549a056f3289138d5739 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Sun, 4 Mar 2018 20:21:23 -0800 Subject: [PATCH] test(ivy): add injection canonical specs (#22595) PR Close #22595 --- .../core/src/core_render3_private_export.ts | 2 +- packages/core/src/render3/definition.ts | 1 - packages/core/src/render3/di.ts | 9 +- packages/core/src/render3/index.ts | 2 +- .../core/src/render3/interfaces/definition.ts | 182 ++++++++++++- packages/core/test/render3/common_with_def.ts | 4 +- .../back_patch_types_specs.ts | 8 +- .../compiler_canonical/injection_spec.ts | 239 ++++++++++++------ .../compiler_canonical/ng_module_spec.ts | 7 +- .../compiler_canonical/patch_types_spec.ts | 8 +- .../compiler_canonical/pending_api_spec.ts | 28 ++ .../compiler_canonical/small_app_spec.ts | 21 +- packages/core/test/render3/component_spec.ts | 1 - packages/core/test/render3/di_spec.ts | 19 +- 14 files changed, 403 insertions(+), 128 deletions(-) create mode 100644 packages/core/test/render3/compiler_canonical/pending_api_spec.ts diff --git a/packages/core/src/core_render3_private_export.ts b/packages/core/src/core_render3_private_export.ts index 65c59d14b6..1d179a2632 100644 --- a/packages/core/src/core_render3_private_export.ts +++ b/packages/core/src/core_render3_private_export.ts @@ -14,7 +14,7 @@ export { detectChanges as ɵdetectChanges, renderComponent as ɵrenderComponent, ComponentType as ɵComponentType, - inject as ɵinject, + directiveInject as ɵdirectiveInject, injectTemplateRef as ɵinjectTemplateRef, injectViewContainerRef as ɵinjectViewContainerRef, injectChangeDetectorRef as ɵinjectChangeDetectorRef, diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index d675b5612e..9f57886967 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -47,7 +47,6 @@ export function defineComponent(componentDefinition: ComponentDefArgs): Co inputs: invertObject(componentDefinition.inputs), inputsPropertyName: componentDefinition.inputsPropertyName || null, outputs: invertObject(componentDefinition.outputs), - methods: invertObject(componentDefinition.methods), rendererType: resolveRendererType2(componentDefinition.rendererType) || null, exportAs: componentDefinition.exportAs, onInit: type.prototype.ngOnInit || null, diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index 120b7d00e2..abf5394acb 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -174,7 +174,7 @@ export function diPublic(def: DirectiveDef): void { } /** - * Searches for an instance of the given directive type up the injector tree and returns + * Searches for an instance of the given type up the injector tree and returns * that instance if found. * * If not found, it will propagate up to the next parent injector until the token @@ -187,15 +187,18 @@ export function diPublic(def: DirectiveDef): void { * * static ngDirectiveDef = defineDirective({ * type: SomeDirective, - * factory: () => new SomeDirective(inject(DirectiveA)) + * factory: () => new SomeDirective(directiveInject(DirectiveA)) * }); * } * + * NOTE: use `directiveInject` with `@Directive`, `@Component`, and `@Pipe`. For + * all other injection use `inject` which does not walk the DOM render tree. + * * @param token The directive type to search for * @param flags Injection flags (e.g. CheckParent) * @returns The instance found */ -export function inject(token: Type, flags?: InjectFlags, defaultValue?: T): T { +export function directiveInject(token: Type, flags?: InjectFlags, defaultValue?: T): T { return getOrCreateInjectable(getOrCreateNodeInjector(), token, flags, defaultValue); } diff --git a/packages/core/src/render3/index.ts b/packages/core/src/render3/index.ts index 134414a94a..8e4d48473b 100644 --- a/packages/core/src/render3/index.ts +++ b/packages/core/src/render3/index.ts @@ -11,7 +11,7 @@ import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective, def import {InjectFlags} from './di'; import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType} from './interfaces/definition'; -export {InjectFlags, QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, inject, injectAttribute, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from './di'; +export {InjectFlags, 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 {CssSelector} from './interfaces/projection'; diff --git a/packages/core/src/render3/interfaces/definition.ts b/packages/core/src/render3/interfaces/definition.ts index 45d6d7a054..9050baec7e 100644 --- a/packages/core/src/render3/interfaces/definition.ts +++ b/packages/core/src/render3/interfaces/definition.ts @@ -8,10 +8,13 @@ import {ChangeDetectionStrategy} from '../../change_detection/constants'; import {PipeTransform} from '../../change_detection/pipe_transform'; +import {Provider} from '../../core'; import {RendererType2} from '../../render/api'; import {Type} from '../../type'; import {resolveRendererType2} from '../../view/util'; + + /** * Definition of what a template rendering function should look like. */ @@ -19,16 +22,37 @@ export type ComponentTemplate = { (ctx: T, creationMode: boolean): void; ngPrivateData?: never; }; +/** + * A subclass of `Type` which has a static `ngComponentDef`:`ComponentDef` field making it + * consumable for rendering. + */ export interface ComponentType extends Type { ngComponentDef: ComponentDef; } +/** + * A subclass of `Type` which has a static `ngDirectiveDef`:`DirectiveDef` field making it + * consumable for rendering. + */ export interface DirectiveType extends Type { ngDirectiveDef: DirectiveDef; } export const enum DirectiveDefFlags {ContentQuery = 0b10} +/** + * A subclass of `Type` which has a static `ngPipeDef`:`PipeDef` field making it + * consumable for rendering. + */ export interface PipeType extends Type { ngPipeDef: PipeDef; } /** - * `DirectiveDef` is a compiled version of the Directive used by the renderer instructions. + * Runtime link information for Directives. + * + * This is internal data structure used by the render to link + * directives into templates. + * + * NOTE: Always use `defineDirective` function to create this object, + * never create the object directly since the shape of this object + * can change between versions. + * + * See: {@link defineDirective} */ export interface DirectiveDef { /** Token representing the directive. Used by DI. */ @@ -59,11 +83,6 @@ export interface DirectiveDef { */ readonly outputs: {[P in keyof T]: P}; - /** - * A dictionary mapping the methods' minified names to their original unminified ones. - */ - readonly methods: {[P in keyof T]: P}; - /** * Name under which the directive is exported (for use with local references in template) */ @@ -104,6 +123,18 @@ export interface DirectiveDef { onDestroy: (() => void)|null; } +/** + * Runtime link information for Components. + * + * This is internal data structure used by the render to link + * components into templates. + * + * NOTE: Always use `defineComponent` function to create this object, + * never create the object directly since the shape of this object + * can change between versions. + * + * See: {@link defineComponent} + */ export interface ComponentDef extends DirectiveDef { /** * The tag name which should be used by the component. @@ -128,10 +159,31 @@ export interface ComponentDef extends DirectiveDef { /** Whether or not this component's ChangeDetectionStrategy is OnPush */ readonly onPush: boolean; + + /** + * Defines the set of injectable providers that are visible to a Directive and its content DOM + * children. + */ + readonly providers?: Provider[]; + + /** + * Defines the set of injectable providers that are visible to a Directive and its view DOM + * children only. + */ + readonly viewProviders?: Provider[]; } /** + * Runtime link information for Pipes. * + * This is internal data structure used by the renderer to link + * pipes into templates. + * + * NOTE: Always use `definePipe` function to create this object, + * never create the object directly since the shape of this object + * can change between versions. + * + * See: {@link definePipe} */ export interface PipeDef { /** @@ -154,30 +206,142 @@ export interface PipeDef { onDestroy: (() => void)|null; } - +/** + * Arguments for `defineDirective` + */ export interface DirectiveDefArgs { + /** + * Directive type, needed to configure the injector. + */ type: Type; + + /** + * Factory method used to create an instance of directive. + */ factory: () => T | [T]; + + /** + * Static attributes to set on host element. + * + * Even indices: attribute name + * Odd indices: attribute value + */ attributes?: string[]; + + /** + * A map of input names. + * + * The format is in: `{[actualPropertyName: string]:string}`. + * + * Which the minifier may translate to: `{[minifiedPropertyName: string]:string}`. + * + * This allows the render to re-construct the minified and non-minified names + * of properties. + */ inputs?: {[P in keyof T]?: string}; + + /** + * TODO: Remove per https://github.com/angular/angular/issues/22591 + */ inputsPropertyName?: {[P in keyof T]?: string}; + + /** + * A map of output names. + * + * The format is in: `{[actualPropertyName: string]:string}`. + * + * Which the minifier may translate to: `{[minifiedPropertyName: string]:string}`. + * + * This allows the render to re-construct the minified and non-minified names + * of properties. + */ outputs?: {[P in keyof T]?: string}; - methods?: {[P in keyof T]?: string}; + + /** + * A list of optional features to apply. + * + * See: {@link NgOnChangesFeature}, {@link PublicFeature} + */ features?: DirectiveDefFeature[]; + + /** + * Function executed by the parent template to allow child directive to apply host bindings. + */ hostBindings?: (directiveIndex: number, elementIndex: number) => void; + + /** + * Defines the name that can be used in the template to assign this directive to a variable. + * + * See: {@link Directive.exportAs} + */ exportAs?: string; } +/** + * Arguments for `defineComponent`. + */ export interface ComponentDefArgs extends DirectiveDefArgs { + /** + * HTML tag name to use in place where this component should be instantiated. + */ tag: string; + + /** + * Template function use for rendering DOM. + * + * This function has following structure. + * + * ``` + * function Template(ctx:T, creationMode: boolean) { + * if (creationMode) { + * // Contains creation mode instructions. + * } + * // Contains binding update instructions + * } + * ``` + * + * Common instructions are: + * Creation mode instructions: + * - `elementStart`, `elementEnd` + * - `text` + * - `container` + * - `listener` + * + * Binding update instructions: + * - `bind` + * - `elementAttribute` + * - `elementProperty` + * - `elementClass` + * - `elementStyle` + * + */ template: ComponentTemplate; + + /** + * A list of optional features to apply. + * + * See: {@link NgOnChancesFeature}, {@link PublicFeature} + */ features?: ComponentDefFeature[]; + rendererType?: RendererType2; + changeDetection?: ChangeDetectionStrategy; + + /** + * Defines the set of injectable objects that are visible to a Directive and its light DOM + * children. + */ + providers?: Provider[]; + + /** + * Defines the set of injectable objects that are visible to its view DOM children. + */ + viewProviders?: Provider[]; } export type DirectiveDefFeature = (directiveDef: DirectiveDef) => void; -export type ComponentDefFeature = (directiveDef: DirectiveDef) => void; +export type ComponentDefFeature = (componentDef: ComponentDef) => void; // Note: This hack is necessary so we don't erroneously get a circular dependency // failure based on types. diff --git a/packages/core/test/render3/common_with_def.ts b/packages/core/test/render3/common_with_def.ts index 06feef5f1c..ca75a201b3 100644 --- a/packages/core/test/render3/common_with_def.ts +++ b/packages/core/test/render3/common_with_def.ts @@ -10,7 +10,7 @@ import {NgForOf as NgForOfDef} from '@angular/common'; import {IterableDiffers} from '@angular/core'; import {defaultIterableDiffers} from '../../src/change_detection/change_detection'; -import {DirectiveType, InjectFlags, NgOnChangesFeature, defineDirective, inject, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index'; +import {DirectiveType, InjectFlags, NgOnChangesFeature, defineDirective, directiveInject, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index'; export const NgForOf: DirectiveType> = NgForOfDef as any; @@ -18,7 +18,7 @@ NgForOf.ngDirectiveDef = defineDirective({ type: NgForOfDef, factory: () => new NgForOfDef( injectViewContainerRef(), injectTemplateRef(), - inject(IterableDiffers, InjectFlags.Default, defaultIterableDiffers)), + directiveInject(IterableDiffers, InjectFlags.Default, defaultIterableDiffers)), features: [NgOnChangesFeature], inputs: { ngForOf: 'ngForOf', diff --git a/packages/core/test/render3/compiler_canonical/back_patch_types_specs.ts b/packages/core/test/render3/compiler_canonical/back_patch_types_specs.ts index 7c3e597dfe..a97e726a1f 100644 --- a/packages/core/test/render3/compiler_canonical/back_patch_types_specs.ts +++ b/packages/core/test/render3/compiler_canonical/back_patch_types_specs.ts @@ -9,7 +9,7 @@ import {Component, ContentChild, Directive, Injectable, Injector, Input, NgModule, NgModuleFactory, NgModuleRef, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef} from '../../../src/core'; import * as r3 from '../../../src/render3/index'; -import {pending_pull_22005} from './small_app_spec'; +import {$pending_pr_22458$} from './pending_api_spec'; const details_elided = { type: Object, @@ -60,7 +60,7 @@ export class LibBComponent { @NgModule({declarations: [LibAComponent], imports: []}) export class LibBModule { // COMPILER GENERATED - static ngInjectorDef = pending_pull_22005.defineInjector(details_elided); + static ngInjectorDef = $pending_pr_22458$.defineInjector(details_elided); } // END FILE: node_modules/libB/module.ts // BEGIN FILE: node_modules/libB/module.metadata.json @@ -92,7 +92,7 @@ export class AppComponent { @NgModule({declarations: [LibAComponent], imports: []}) export class AppModule { // COMPILER GENERATED - static ngInjectorDef = pending_pull_22005.defineInjector(details_elided); + static ngInjectorDef = $pending_pr_22458$.defineInjector(details_elided); } // END FILE: src/app.ts @@ -113,7 +113,7 @@ function ngBackPatch_node_modules_libB_module_LibAComponent() { } function ngBackPatch_node_modules_libB_module_LibAModule() { - (LibAModule as any).ngInjectorDef = pending_pull_22005.defineInjector(details_elided); + (LibAModule as any).ngInjectorDef = $pending_pr_22458$.defineInjector(details_elided); } export const AppModuleFactory: NgModuleFactory&{patchedDeps: boolean} = { diff --git a/packages/core/test/render3/compiler_canonical/injection_spec.ts b/packages/core/test/render3/compiler_canonical/injection_spec.ts index 5e69202be0..53a4e179da 100644 --- a/packages/core/test/render3/compiler_canonical/injection_spec.ts +++ b/packages/core/test/render3/compiler_canonical/injection_spec.ts @@ -6,103 +6,194 @@ * found in the LICENSE file at https://angular.io/license */ -import {Attribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core'; +import {Attribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Inject, InjectFlags, Injectable, Injector, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, SkipSelf, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core'; import * as $r3$ from '../../../src/core_render3_private_export'; import {renderComponent, toHtml} from '../render_util'; +import {$pending_pr_22458$} from './pending_api_spec'; + + + /// See: `normative.md` describe('injection', () => { type $boolean$ = boolean; - it('should inject ChangeDetectorRef', () => { - type $MyComp$ = MyComp; - type $MyApp$ = MyApp; + describe('directives', () => { + // Directives (and Components) should use `directiveInject` + it('should inject ChangeDetectorRef', () => { + type $MyComp$ = MyComp; + type $MyApp$ = MyApp; - @Component({selector: 'my-comp', template: `{{ value }}`}) - class MyComp { - value: string; - constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; } + @Component({selector: 'my-comp', template: `{{ value }}`}) + class MyComp { + value: string; + constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; } - // NORMATIVE - static ngComponentDef = $r3$.ɵdefineComponent({ - type: MyComp, - tag: 'my-comp', - factory: function MyComp_Factory() { return new MyComp($r3$.ɵinjectChangeDetectorRef()); }, - template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) { - if (cm) { - $r3$.ɵT(0); + // NORMATIVE + static ngComponentDef = $r3$.ɵdefineComponent({ + type: MyComp, + tag: 'my-comp', + factory: function MyComp_Factory() { + return new MyComp($r3$.ɵinjectChangeDetectorRef()); + }, + template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) { + if (cm) { + $r3$.ɵT(0); + } + $r3$.ɵt(0, $r3$.ɵb(ctx.value)); } - $r3$.ɵt(0, $r3$.ɵb(ctx.value)); - } - }); - // /NORMATIVE - } + }); + // /NORMATIVE + } - class MyApp { - static ngComponentDef = $r3$.ɵdefineComponent({ - type: MyApp, - tag: 'my-app', - factory: function MyApp_Factory() { return new MyApp(); }, - /** */ - template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { - if (cm) { - $r3$.ɵE(0, MyComp); - $r3$.ɵe(); + class MyApp { + static ngComponentDef = $r3$.ɵdefineComponent({ + type: MyApp, + tag: 'my-app', + factory: function MyApp_Factory() { return new MyApp(); }, + /** */ + template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { + if (cm) { + $r3$.ɵE(0, MyComp); + $r3$.ɵe(); + } + MyComp.ngComponentDef.h(1, 0); + $r3$.ɵr(1, 0); } - MyComp.ngComponentDef.h(1, 0); - $r3$.ɵr(1, 0); - } - }); - } + }); + } - const app = renderComponent(MyApp); - // ChangeDetectorRef is the token, ViewRef is historically the constructor - expect(toHtml(app)).toEqual('ViewRef'); + const app = renderComponent(MyApp); + // ChangeDetectorRef is the token, ViewRef is historically the constructor + expect(toHtml(app)).toEqual('ViewRef'); + }); + + it('should inject attributes', () => { + type $MyComp$ = MyComp; + type $MyApp$ = MyApp; + + @Component({selector: 'my-comp', template: `{{ title }}`}) + class MyComp { + constructor(@Attribute('title') public title: string|undefined) {} + + // NORMATIVE + static ngComponentDef = $r3$.ɵdefineComponent({ + type: MyComp, + tag: 'my-comp', + factory: function MyComp_Factory() { return new MyComp($r3$.ɵinjectAttribute('title')); }, + template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) { + if (cm) { + $r3$.ɵT(0); + } + $r3$.ɵt(0, $r3$.ɵb(ctx.title)); + } + }); + // /NORMATIVE + } + + class MyApp { + static ngComponentDef = $r3$.ɵdefineComponent({ + type: MyApp, + tag: 'my-app', + factory: function MyApp_Factory() { return new MyApp(); }, + /** */ + template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { + if (cm) { + $r3$.ɵE(0, MyComp, e0_attrs); + $r3$.ɵe(); + } + MyComp.ngComponentDef.h(1, 0); + $r3$.ɵr(1, 0); + } + }); + } + const e0_attrs = ['title', 'WORKS']; + const app = renderComponent(MyApp); + // ChangeDetectorRef is the token, ViewRef is historically the constructor + expect(toHtml(app)).toEqual('WORKS'); + }); + + // TODO(misko): enable once `providers` and `viewProvdires` are implemented. + xit('should inject into an injectable', () => { + type $MyApp$ = MyApp; + + @Injectable() + class ServiceA { + // NORMATIVE + static ngInjectableDef = $pending_pr_22458$.defineInjectable({ + factory: function ServiceA_Factory() { return new ServiceA(); }, + }); + // /NORMATIVE + } + + @Injectable() + class ServiceB { + // NORMATIVE + static ngInjectableDef = $pending_pr_22458$.defineInjectable({ + factory: function ServiceA_Factory() { return new ServiceB(); }, + }); + // /NORMATIVE + } + + @Component({ + template: '', + providers: [ServiceA], + viewProviders: [ServiceB], + }) + class MyApp { + constructor(serviceA: ServiceA, serviceB: ServiceB, injector: Injector) {} + + static ngComponentDef = $r3$.ɵdefineComponent({ + type: MyApp, + tag: 'my-app', + factory: function MyApp_Factory() { + return new MyApp( + $r3$.ɵdirectiveInject(ServiceA), $r3$.ɵdirectiveInject(ServiceB), + $pending_pr_22458$.injectInjector()); + }, + /** */ + template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {}, + providers: [ServiceA], + viewProviders: [ServiceB], + }); + } + const e0_attrs = ['title', 'WORKS']; + const app = renderComponent(MyApp); + // ChangeDetectorRef is the token, ViewRef is historically the constructor + expect(toHtml(app)).toEqual('WORKS'); + }); }); - it('should inject attributes', () => { - type $MyComp$ = MyComp; - type $MyApp$ = MyApp; - - @Component({selector: 'my-comp', template: `{{ title }}`}) - class MyComp { - constructor(@Attribute('title') public title: string|undefined) {} + describe('services', () => { + // Services should use `inject` + @Injectable() + class ServiceA { + constructor(@Inject(String) name: String, injector: Injector) {} // NORMATIVE - static ngComponentDef = $r3$.ɵdefineComponent({ - type: MyComp, - tag: 'my-comp', - factory: function MyComp_Factory() { return new MyComp($r3$.ɵinjectAttribute('title')); }, - template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) { - if (cm) { - $r3$.ɵT(0); - } - $r3$.ɵt(0, $r3$.ɵb(ctx.title)); - } + static ngInjectableDef = $pending_pr_22458$.defineInjectable({ + factory: function ServiceA_Factory() { + return new ServiceA( + $pending_pr_22458$.inject(String), $pending_pr_22458$.injectInjector()); + }, }); // /NORMATIVE } - class MyApp { - static ngComponentDef = $r3$.ɵdefineComponent({ - type: MyApp, - tag: 'my-app', - factory: function MyApp_Factory() { return new MyApp(); }, - /** */ - template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { - if (cm) { - $r3$.ɵE(0, MyComp, e0_attrs); - $r3$.ɵe(); - } - MyComp.ngComponentDef.h(1, 0); - $r3$.ɵr(1, 0); - } + @Injectable() + class ServiceB { + constructor(serviceA: ServiceA, @SkipSelf() injector: Injector) {} + // NORMATIVE + static ngInjectableDef = $pending_pr_22458$.defineInjectable({ + factory: function ServiceA_Factory() { + return new ServiceB( + $pending_pr_22458$.inject(ServiceA), + $pending_pr_22458$.injectInjector(InjectFlags.SkipSelf)); + }, }); + // /NORMATIVE } - const e0_attrs = ['title', 'WORKS']; - const app = renderComponent(MyApp); - // ChangeDetectorRef is the token, ViewRef is historically the constructor - expect(toHtml(app)).toEqual('WORKS'); + }); }); \ No newline at end of file diff --git a/packages/core/test/render3/compiler_canonical/ng_module_spec.ts b/packages/core/test/render3/compiler_canonical/ng_module_spec.ts index 554b5cad39..b69c3e08ab 100644 --- a/packages/core/test/render3/compiler_canonical/ng_module_spec.ts +++ b/packages/core/test/render3/compiler_canonical/ng_module_spec.ts @@ -32,7 +32,7 @@ xdescribe('NgModule', () => { constructor(name: String) {} // NORMATIVE static ngInjectableDef = defineInjectable({ - factory: () => new Toast($r3$.ɵinject(String)), + factory: () => new Toast($r3$.ɵdirectiveInject(String)), }); // /NORMATIVE } @@ -51,7 +51,7 @@ xdescribe('NgModule', () => { constructor(toast: Toast) {} // NORMATIVE static ngInjectorDef = defineInjector({ - factory: () => new MyModule($r3$.ɵinject(Toast)), + factory: () => new MyModule($r3$.ɵdirectiveInject(Toast)), provider: [ {provide: Toast, deps: [String]}, // If Toast has metadata generate this line Toast, // If Toast has no metadata generate this line. @@ -69,7 +69,8 @@ xdescribe('NgModule', () => { static ngInjectableDef = defineInjectable({ scope: MyModule, factory: () => new BurntToast( - $r3$.ɵinject(Toast, $r3$.ɵInjectFlags.Optional), $r3$.ɵinject(String)), + $r3$.ɵdirectiveInject(Toast, $r3$.ɵInjectFlags.Optional), + $r3$.ɵdirectiveInject(String)), }); // /NORMATIVE } diff --git a/packages/core/test/render3/compiler_canonical/patch_types_spec.ts b/packages/core/test/render3/compiler_canonical/patch_types_spec.ts index ca4e37374c..bb63645229 100644 --- a/packages/core/test/render3/compiler_canonical/patch_types_spec.ts +++ b/packages/core/test/render3/compiler_canonical/patch_types_spec.ts @@ -8,7 +8,7 @@ import {Component, ContentChild, Directive, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef} from '../../../src/core'; import * as r3 from '../../../src/render3/index'; -import {pending_pull_22005} from './small_app_spec'; +import {$pending_pr_22458$} from './pending_api_spec'; /** * GOALS: @@ -29,7 +29,7 @@ class ThirdPartyClass { @Injectable() class CompiledWithIvy { // NORMATIVE - static ngInjectableDef = pending_pull_22005.defineInjectable( + static ngInjectableDef = $pending_pr_22458$.defineInjectable( {factory: function CompileWithIvy_Factory() { return new CompiledWithIvy(); }}); // /NORMATIVE } @@ -38,7 +38,7 @@ class CompiledWithIvy { @NgModule({providers: [ThirdPartyClass, CompiledWithIvy]}) class CompiledWithIvyModule { // NORMATIVE - static ngInjectorDef = pending_pull_22005.defineInjector({ + static ngInjectorDef = $pending_pr_22458$.defineInjector({ providers: [ThirdPartyClass, CompiledWithIvy], factory: function CompiledWithIvyModule_Factory() { return new CompiledWithIvyModule(); } }); @@ -72,7 +72,7 @@ function ngPatch_depsOf_CompiledWithIvyModule() { } function ngPatch_node_modules_some_library_path_public_CompileWithIvy() { /** @__BUILD_OPTIMIZER_COLOCATE__ */ - (ThirdPartyClass as any).ngInjectableDef = pending_pull_22005.defineInjectable( + (ThirdPartyClass as any).ngInjectableDef = $pending_pr_22458$.defineInjectable( {factory: function CompileWithIvy_Factory() { return new ThirdPartyClass(); }}); } // /NORMATIVE diff --git a/packages/core/test/render3/compiler_canonical/pending_api_spec.ts b/packages/core/test/render3/compiler_canonical/pending_api_spec.ts new file mode 100644 index 0000000000..9e69b29b76 --- /dev/null +++ b/packages/core/test/render3/compiler_canonical/pending_api_spec.ts @@ -0,0 +1,28 @@ +/** + * @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 {InjectFlags, InjectionToken, Injector, Type} from '@angular/core'; + + + +// TODO: remove once https://github.com/angular/angular/pull/22458 lands +export class $pending_pr_22458$ { + static defineInjectable({providerFor, factory}: {providerFor?: Type, factory: () => T}): + {providerFor: Type| null, factory: () => T} { + return {providerFor: providerFor || null, factory: factory}; + } + + static defineInjector({factory, providers}: {factory: () => T, providers: any[]}): + {factory: () => T, providers: any[]} { + return {factory: factory, providers: providers}; + } + + static injectInjector(flags?: InjectFlags): Injector { return null !; } + + static inject(token: Type|InjectionToken, flags?: InjectFlags): T { return null as any; } +} diff --git a/packages/core/test/render3/compiler_canonical/small_app_spec.ts b/packages/core/test/render3/compiler_canonical/small_app_spec.ts index 4c094cb3e6..ec70c726d8 100644 --- a/packages/core/test/render3/compiler_canonical/small_app_spec.ts +++ b/packages/core/test/render3/compiler_canonical/small_app_spec.ts @@ -11,24 +11,11 @@ import {Component, ContentChild, Directive, EventEmitter, Injectable, Input, NgM import {withBody} from '@angular/core/testing'; import * as r3 from '../../../src/render3/index'; +import {$pending_pr_22458$} from './pending_api_spec'; /// See: `normative.md` -// TODO: remove once https://github.com/angular/angular/pull/22005 lands -export class pending_pull_22005 { - static defineInjectable({scope, factory}: {scope?: Type, factory: () => T}): - {scope: Type| null, factory: () => T} { - return {scope: scope || null, factory: factory}; - } - - static defineInjector({factory, providers}: {factory: () => T, providers: any[]}): - {factory: () => T, providers: any[]} { - return {factory: factory, providers: providers}; - } -} - - interface ToDo { text: string; @@ -46,7 +33,7 @@ class AppState { ]; // NORMATIVE - static ngInjectableDef = pending_pull_22005.defineInjectable({factory: () => new AppState()}); + static ngInjectableDef = $pending_pr_22458$.defineInjectable({factory: () => new AppState()}); // /NORMATIVE } @@ -74,7 +61,7 @@ class ToDoAppComponent { type: ToDoAppComponent, tag: 'todo-app', factory: function ToDoAppComponent_Factory() { - return new ToDoAppComponent(r3.inject(AppState)); + return new ToDoAppComponent(r3.directiveInject(AppState)); }, template: function ToDoAppComponent_Template(ctx: ToDoAppComponent, cm: boolean) { if (cm) { @@ -171,7 +158,7 @@ const e1_attrs = ['type', 'checkbox']; }) class ToDoAppModule { // NORMATIVE - static ngInjectorDef = pending_pull_22005.defineInjector({ + static ngInjectorDef = $pending_pr_22458$.defineInjector({ factory: () => new ToDoAppModule(), providers: [AppState], }); diff --git a/packages/core/test/render3/component_spec.ts b/packages/core/test/render3/component_spec.ts index ce1aefe3c2..471849cf25 100644 --- a/packages/core/test/render3/component_spec.ts +++ b/packages/core/test/render3/component_spec.ts @@ -32,7 +32,6 @@ describe('component', () => { }, factory: () => new CounterComponent, inputs: {count: 'count'}, - methods: {increment: 'increment'} }); } diff --git a/packages/core/test/render3/di_spec.ts b/packages/core/test/render3/di_spec.ts index 33b97de204..7f3414ffde 100644 --- a/packages/core/test/render3/di_spec.ts +++ b/packages/core/test/render3/di_spec.ts @@ -10,7 +10,7 @@ import {ChangeDetectorRef, ElementRef, TemplateRef, ViewContainerRef} from '@ang import {defineComponent} from '../../src/render3/definition'; import {InjectFlags, bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di'; -import {NgOnChangesFeature, PublicFeature, defineDirective, inject, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index'; +import {NgOnChangesFeature, PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index'; import {bind, container, containerRefreshEnd, containerRefreshStart, createLNode, createLView, createTView, directiveRefresh, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, load, projection, projectionDef, text, textBinding} from '../../src/render3/instructions'; import {LInjector} from '../../src/render3/interfaces/injector'; import {LNodeFlags} from '../../src/render3/interfaces/node'; @@ -59,7 +59,7 @@ describe('di', () => { constructor(a: DirectiveA, b: DirectiveB) { this.value = a.value + b.value; } static ngDirectiveDef = defineDirective({ type: DirectiveC, - factory: () => new DirectiveC(inject(DirectiveA), inject(DirectiveB)) + factory: () => new DirectiveC(directiveInject(DirectiveA), directiveInject(DirectiveB)) }); } @@ -101,7 +101,7 @@ describe('di', () => { } static ngDirectiveDef = defineDirective({ type: DirectiveSameInstance, - factory: () => new DirectiveSameInstance(injectElementRef(), inject(Directive)) + factory: () => new DirectiveSameInstance(injectElementRef(), directiveInject(Directive)) }); } @@ -141,7 +141,7 @@ describe('di', () => { } static ngDirectiveDef = defineDirective({ type: DirectiveSameInstance, - factory: () => new DirectiveSameInstance(injectTemplateRef(), inject(Directive)) + factory: () => new DirectiveSameInstance(injectTemplateRef(), directiveInject(Directive)) }); } @@ -181,7 +181,8 @@ describe('di', () => { } static ngDirectiveDef = defineDirective({ type: DirectiveSameInstance, - factory: () => new DirectiveSameInstance(injectViewContainerRef(), inject(Directive)) + factory: + () => new DirectiveSameInstance(injectViewContainerRef(), directiveInject(Directive)) }); } @@ -540,7 +541,8 @@ describe('di', () => { static ngComponentDef = defineComponent({ type: MyApp, tag: 'my-app', - factory: () => new MyApp(inject(String as any, InjectFlags.Default, 'DefaultValue')), + factory: () => new MyApp( + directiveInject(String as any, InjectFlags.Default, 'DefaultValue')), template: () => null }); } @@ -565,7 +567,7 @@ describe('di', () => { } static ngDirectiveDef = defineDirective({ type: ChildDirective, - factory: () => new ChildDirective(inject(ParentDirective)), + factory: () => new ChildDirective(directiveInject(ParentDirective)), features: [PublicFeature] }); } @@ -577,7 +579,8 @@ describe('di', () => { } static ngDirectiveDef = defineDirective({ type: Child2Directive, - factory: () => new Child2Directive(inject(ParentDirective), inject(ChildDirective)) + factory: () => new Child2Directive( + directiveInject(ParentDirective), directiveInject(ChildDirective)) }); }