diff --git a/integration/hello_world__render3__closure/src/index.ts b/integration/hello_world__render3__closure/src/index.ts index 2e35907c2a..64358031e5 100644 --- a/integration/hello_world__render3__closure/src/index.ts +++ b/integration/hello_world__render3__closure/src/index.ts @@ -14,6 +14,7 @@ export class HelloWorld { /** @nocollapse */ static ngComponentDef: ComponentDef = defineComponent({ + type: HelloWorld, tag: 'hello-world', template: function (ctx: HelloWorld, cm: boolean) { if (cm) { diff --git a/modules/benchmarks/src/largetable/render3/table.ts b/modules/benchmarks/src/largetable/render3/table.ts index 5e62f6dca1..ba70e62002 100644 --- a/modules/benchmarks/src/largetable/render3/table.ts +++ b/modules/benchmarks/src/largetable/render3/table.ts @@ -16,6 +16,7 @@ export class LargeTableComponent { /** @nocollapse */ static ngComponentDef: ComponentDef = defineComponent({ + type: LargeTableComponent, tag: 'largetable', template: function(ctx: LargeTableComponent, cm: boolean) { if (cm) { diff --git a/packages/compiler/test/render3/r3_view_compiler_spec.ts b/packages/compiler/test/render3/r3_view_compiler_spec.ts index d3573814aa..57b4342953 100644 --- a/packages/compiler/test/render3/r3_view_compiler_spec.ts +++ b/packages/compiler/test/render3/r3_view_compiler_spec.ts @@ -205,8 +205,8 @@ describe('r3_view_compiler', () => { IDENT.ɵe(); IDENT.ɵT(3, '!'); } - r(1, 0); - r(2, 0); + ChildComponent.ngComponentDef.r(1, 0); + SomeDirective.ngDirectiveDef.r(2, 0); } }); `; @@ -267,7 +267,7 @@ describe('r3_view_compiler', () => { } const IDENT = IDENT.ɵm(1); IDENT.ɵcR(2); - r(3,2); + IfDirective.ngDirectiveDef.r(3,2); IDENT.ɵcr(); function MyComponent_IfDirective_Template_2(ctx0: IDENT, cm: IDENT) { diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index 1238a83540..65458202a2 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -46,10 +46,14 @@ export function defineComponent(componentDefinition: ComponentDefArgs): Co methods: invertObject(componentDefinition.methods), rendererType: resolveRendererType2(componentDefinition.rendererType) || null, exportAs: componentDefinition.exportAs, - lifecycleHooks: getLifecyleHooksMap(componentDefinition.type) + lifecycleHooks: null ! }; const feature = componentDefinition.features; feature && feature.forEach((fn) => fn(def)); + + // These must be set after feature functions are run, so ngOnChanges can be + // properly set up. + def.lifecycleHooks = getLifecyleHooksMap(componentDefinition.type); return def; } @@ -62,7 +66,7 @@ type OnChangesExpando = OnChanges & { }; export function NgOnChangesFeature(type: Type): (definition: DirectiveDef) => void { - return function (definition: DirectiveDef): void { + return function(definition: DirectiveDef): void { const inputs = definition.inputs; const proto = type.prototype; // Place where we will store SimpleChanges if there is a change @@ -77,11 +81,11 @@ export function NgOnChangesFeature(type: Type): (definition: DirectiveDef< // create a getter and setter for property Object.defineProperty(proto, minKey, { - get: function (this: OnChangesExpando) { + get: function(this: OnChangesExpando) { return (existingDesc && existingDesc.get) ? existingDesc.get.call(this) : - this[privateMinKey]; + this[privateMinKey]; }, - set: function (this: OnChangesExpando, value: any) { + set: function(this: OnChangesExpando, value: any) { let simpleChanges = this[PRIVATE_PREFIX]; let isFirstChange = simpleChanges === undefined; if (simpleChanges == null) { @@ -89,12 +93,12 @@ export function NgOnChangesFeature(type: Type): (definition: DirectiveDef< } simpleChanges[pubKey] = new SimpleChange(this[privateMinKey], value, isFirstChange); (existingDesc && existingDesc.set) ? existingDesc.set.call(this, value) : - this[privateMinKey] = value; + this[privateMinKey] = value; } }); } - proto.ngDoCheck = (function (delegateDoCheck) { - return function (this: OnChangesExpando) { + proto.ngDoCheck = (function(delegateDoCheck) { + return function(this: OnChangesExpando) { let simpleChanges = this[PRIVATE_PREFIX]; if (simpleChanges != null) { this.ngOnChanges(simpleChanges); diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index 4e8dd39147..0fbf633fca 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -167,7 +167,7 @@ export function diPublicInInjector(di: LInjector, def: DirectiveDef): void * * @param def The definition of the directive to be made public */ -export function diPublic(def: TypedDirectiveDef): void { +export function diPublic(def: DirectiveDef): void { diPublicInInjector(getOrCreateNodeInjector(), def); } diff --git a/packages/core/src/render3/hooks.ts b/packages/core/src/render3/hooks.ts index 37de184889..7a9215c518 100644 --- a/packages/core/src/render3/hooks.ts +++ b/packages/core/src/render3/hooks.ts @@ -1,3 +1,10 @@ +/** + * @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 {DirectiveDef, LifecycleHooksMap} from './interfaces/definition'; import {LNodeFlags} from './interfaces/node'; @@ -5,14 +12,12 @@ import {HookData, LView, TView} from './interfaces/view'; -/** - * Enum used by the lifecycle (l) instruction to determine which lifecycle hook is requesting - * processing. - */ -export const enum LifecycleHook {ON_INIT = 0b00, ON_CHECK = 0b01, ON_CHANGES = 0b10} - /** Constants used by lifecycle hooks to determine when and how a hook should be called. */ -export const enum LifecycleHookUtils { +export const enum LifecycleHook { + ON_INIT = 0b00, + ON_CHECK = 0b01, + ON_CHANGES = 0b10, + /* Mask used to get the type of the lifecycle hook from flags in hook queue */ TYPE_MASK = 0b00000000000000000000000000000001, @@ -21,70 +26,8 @@ export const enum LifecycleHookUtils { } /** - * Loops through the directives on a node and queues their all hooks except ngOnInit - * and ngDoCheck, which are queued separately in E. - */ -export function queueLifecycleHooks(flags: number, currentView: LView): void { - const tView = currentView.tView; - if (tView.firstTemplatePass === true) { - const size = (flags & LNodeFlags.SIZE_MASK) >> LNodeFlags.SIZE_SHIFT; - const start = flags >> LNodeFlags.INDX_SHIFT; - - // It's necessary to loop through the directives at elementEnd() (rather than storing - // the hooks at creation time) so we can preserve the current hook order. All hooks - // for projected components and directives must be called *before* their hosts. - for (let i = start, end = start + size; i < end; i++) { - const hooks = (tView.data[i] as DirectiveDef).lifecycleHooks; - queueContentHooks(hooks, tView, i); - queueViewHooks(hooks, tView, i); - } - } - - const size = (flags & LNodeFlags.SIZE_MASK) >> LNodeFlags.SIZE_SHIFT; - const start = flags >> LNodeFlags.INDX_SHIFT; - let cleanup = currentView.cleanup; - - for (let i = start, end = start + size; i < end; i++) { - const instance = currentView.data[i]; - if (instance.ngOnDestroy != null) { - (cleanup || (currentView.cleanup = cleanup = [])).push(instance.ngOnDestroy, instance); - } - } -} - -function queueContentHooks(hooks: LifecycleHooksMap, tView: TView, i: number): void { - if (hooks.afterContentInit != null) { - (tView.contentHooks || (tView.contentHooks = [])).push(getInitFlags(i), hooks.afterContentInit); - } - - if (hooks.afterContentChecked != null) { - (tView.contentHooks || (tView.contentHooks = [ - ])).push(getCheckFlags(i), hooks.afterContentChecked); - } -} -function queueViewHooks(hooks: LifecycleHooksMap, tView: TView, i: number): void { - if (hooks.afterViewInit != null) { - (tView.viewHooks || (tView.viewHooks = [])).push(getInitFlags(i), hooks.afterViewInit); - } - - if (hooks.afterViewChecked != null) { - (tView.viewHooks || (tView.viewHooks = [])).push(getCheckFlags(i), hooks.afterViewChecked); - } -} - -/** Generates flags for init-only hooks */ -function getInitFlags(index: number): number { - return index << LifecycleHookUtils.INDX_SHIFT; -} - -/** Generates flags for hooks called every change detection run */ -function getCheckFlags(index: number): number { - return (index << LifecycleHookUtils.INDX_SHIFT) | LifecycleHook.ON_CHECK; -} - -/** - * If this is the first template pass, any ngOnInit or ngDoCheck hooks on the current directive - * will be queued on TView.initHooks. + * If this is the first template pass, any ngOnInit or ngDoCheck hooks will be queued into + * TView.initHooks during directiveCreate. * * The directive index and hook type are encoded into one number (1st bit: type, remaining bits: * directive index), then saved in the even indices of the initHooks array. The odd indices @@ -95,22 +38,82 @@ function getCheckFlags(index: number): number { * @param tView The current TView */ export function queueInitHooks(index: number, hooks: LifecycleHooksMap, tView: TView): void { - if (tView.firstTemplatePass === true && hooks.onInit != null) { - const hookFlags = index << LifecycleHookUtils.INDX_SHIFT; - (tView.initHooks || (tView.initHooks = [])).push(hookFlags, hooks.onInit); + const firstTemplatePass = tView.firstTemplatePass; + if (firstTemplatePass === true && hooks.onInit != null) { + (tView.initHooks || (tView.initHooks = [])).push(getInitFlags(index), hooks.onInit); } - if (tView.firstTemplatePass === true && hooks.doCheck != null) { - const hookFlags = (index << LifecycleHookUtils.INDX_SHIFT) | LifecycleHook.ON_CHECK; - (tView.initHooks || (tView.initHooks = [])).push(hookFlags, hooks.doCheck); + if (firstTemplatePass === true && hooks.doCheck != null) { + (tView.initHooks || (tView.initHooks = [])).push(getCheckFlags(index), hooks.doCheck); } } +/** + * Loops through the directives on a node and queues all their hooks except ngOnInit + * and ngDoCheck, which are queued separately in directiveCreate. + */ +export function queueLifecycleHooks(flags: number, currentView: LView): void { + const tView = currentView.tView; + if (tView.firstTemplatePass === true) { + const size = (flags & LNodeFlags.SIZE_MASK) >> LNodeFlags.SIZE_SHIFT; + const start = flags >> LNodeFlags.INDX_SHIFT; + + // It's necessary to loop through the directives at elementEnd() (rather than processing in + // directiveCreate) so we can preserve the current hook order. Content, view, and destroy + // hooks for projected components and directives must be called *before* their hosts. + for (let i = start, end = start + size; i < end; i++) { + const hooks = (tView.data[i] as DirectiveDef).lifecycleHooks; + queueContentHooks(hooks, tView, i); + queueViewHooks(hooks, tView, i); + queueDestroyHooks(hooks, tView, i); + } + } +} + +/** Queues afterContentInit and afterContentChecked hooks on TView */ +function queueContentHooks(hooks: LifecycleHooksMap, tView: TView, i: number): void { + if (hooks.afterContentInit != null) { + (tView.contentHooks || (tView.contentHooks = [])).push(getInitFlags(i), hooks.afterContentInit); + } + + if (hooks.afterContentChecked != null) { + (tView.contentHooks || (tView.contentHooks = [ + ])).push(getCheckFlags(i), hooks.afterContentChecked); + } +} + +/** Queues afterViewInit and afterViewChecked hooks on TView */ +function queueViewHooks(hooks: LifecycleHooksMap, tView: TView, i: number): void { + if (hooks.afterViewInit != null) { + (tView.viewHooks || (tView.viewHooks = [])).push(getInitFlags(i), hooks.afterViewInit); + } + + if (hooks.afterViewChecked != null) { + (tView.viewHooks || (tView.viewHooks = [])).push(getCheckFlags(i), hooks.afterViewChecked); + } +} + +/** Queues onDestroy hooks on TView */ +function queueDestroyHooks(hooks: LifecycleHooksMap, tView: TView, i: number): void { + if (hooks.onDestroy != null) { + (tView.destroyHooks || (tView.destroyHooks = [])).push(i, hooks.onDestroy); + } +} + +/** Generates flags for init-only hooks */ +function getInitFlags(index: number): number { + return index << LifecycleHook.INDX_SHIFT; +} + +/** Generates flags for hooks called every change detection run */ +function getCheckFlags(index: number): number { + return (index << LifecycleHook.INDX_SHIFT) | LifecycleHook.ON_CHECK; +} + /** * Calls onInit and doCheck calls if they haven't already been called. * * @param currentView The current view - * @param initHooks The init hooks for this view */ export function executeInitHooks(currentView: LView): void { const initHooks = currentView.tView.initHooks; @@ -121,7 +124,11 @@ export function executeInitHooks(currentView: LView): void { } } -/** Iterates over view hook functions and calls them. */ +/** + * Iterates over afterViewInit and afterViewChecked functions and calls them. + * + * @param currentView The current view + */ export function executeViewHooks(currentView: LView): void { const viewHooks = currentView.tView.viewHooks; @@ -133,6 +140,8 @@ export function executeViewHooks(currentView: LView): void { /** * Calls all afterContentInit and afterContentChecked hooks for the view, then splices * out afterContentInit hooks to prep for the next run in update mode. + * + * @param currentView The current view */ export function executeContentHooks(currentView: LView): void { const contentHooks = currentView.tView.contentHooks; @@ -157,8 +166,8 @@ function executeLifecycleHooks(currentView: LView, arr: HookData): void { for (let i = 0; i < arr.length; i += 2) { const flags = arr[i] as number; const hook = arr[i | 1] as() => void; - const initOnly = (flags & LifecycleHookUtils.TYPE_MASK) === LifecycleHook.ON_INIT; - const instance = data[flags >> LifecycleHookUtils.INDX_SHIFT]; + const initOnly = (flags & LifecycleHook.TYPE_MASK) === LifecycleHook.ON_INIT; + const instance = data[flags >> LifecycleHook.INDX_SHIFT]; if (initOnly === false || creationMode) { hook.call(instance); } diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index 69ab5589bb..32e45391c3 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -101,10 +101,11 @@ let data: any[]; let bindingIndex: number; /** - * When a view is destroyed, listeners need to be released - * and onDestroy callbacks need to be called. This cleanup array - * stores both listener data (in chunks of 4) and onDestroy data - * (in chunks of 2), as they'll be processed at the same time. + * When a view is destroyed, listeners need to be released and outputs need to be + * unsubscribed. This cleanup array stores both listener data (in chunks of 4) + * and output data (in chunks of 2) for a particular view. Combining the arrays + * saves on memory (70 bytes per array) and on a few bytes of code size (for two + * separate for loops). * * If it's a listener being stored: * 1st index is: event name to remove @@ -112,8 +113,8 @@ let bindingIndex: number; * 3rd index is: listener function * 4th index is: useCapture boolean * - * If it's an onDestroy function: - * 1st index is: onDestroy function + * If it's an output subscription: + * 1st index is: unsubscribe function * 2nd index is: context for function */ let cleanup: any[]|null; @@ -158,7 +159,7 @@ export function leaveView(newView: LView): void { currentView.creationMode = false; currentView.initHooksCalled = false; currentView.contentHooksCalled = false; - if (currentView.tView.firstTemplatePass) currentView.tView.firstTemplatePass = false; + currentView.tView.firstTemplatePass = false; enterView(newView, null); } @@ -181,8 +182,8 @@ export function createLView( template: template, context: context, dynamicViewCount: 0, - contentHooksCalled: false, - initHooksCalled: false + initHooksCalled: false, + contentHooksCalled: false }; return newView; @@ -310,7 +311,7 @@ export function renderEmbeddedTemplate( previousOrParentNode = null !; let cm: boolean = false; if (viewNode == null) { - const view = createLView(-1, renderer, {data: []}, template, context); + const view = createLView(-1, renderer, createTView(), template, context); viewNode = createLNode(null, LNodeFlags.View, null, view); cm = true; } @@ -483,8 +484,16 @@ function getOrCreateTView(template: ComponentTemplate): TView { return template.ngPrivateData || (template.ngPrivateData = createTView() as never); } +/** Creates a TView instance */ export function createTView(): TView { - return {data: [], firstTemplatePass: true, initHooks: null, contentHooks: null, viewHooks: null}; + return { + data: [], + firstTemplatePass: true, + initHooks: null, + contentHooks: null, + viewHooks: null, + destroyHooks: null + }; } function setUpAttributes(native: RElement, attrs: string[]): void { @@ -1183,7 +1192,7 @@ export function componentRefresh(directiveIndex: number, elementIndex: number leaveView(oldView); } } -}; +} /** * Instruction to distribute projectable nodes among occurrences in a given template. diff --git a/packages/core/src/render3/interfaces/view.ts b/packages/core/src/render3/interfaces/view.ts index 87c4226d6d..14a24b18af 100644 --- a/packages/core/src/render3/interfaces/view.ts +++ b/packages/core/src/render3/interfaces/view.ts @@ -69,9 +69,9 @@ export interface LView { bindingStartIndex: number|null; /** - * When a view is destroyed, listeners need to be released and onDestroy callbacks - * need to be called. This cleanup array stores both listener data (in chunks of 4) - * and onDestroy data (in chunks of 2) for a particular view. Combining the arrays + * When a view is destroyed, listeners need to be released and outputs need to be + * unsubscribed. This cleanup array stores both listener data (in chunks of 4) + * and output data (in chunks of 2) for a particular view. Combining the arrays * saves on memory (70 bytes per array) and on a few bytes of code size (for two * separate for loops). * @@ -81,9 +81,9 @@ export interface LView { * 3rd index is: listener function * 4th index is: useCapture boolean * - * If it's an onDestroy function: - * 1st index is: onDestroy function - * 2nd index is; context for function + * If it's an output subscription: + * 1st index is: unsubscribe function + * 2nd index is: context for function */ cleanup: any[]|null; @@ -92,13 +92,14 @@ export interface LView { * detection run. * * These two hooks are executed by the first Comp.r() instruction that runs OR the - * first cR instruction that runs (so inits are run for the top level view before + * first cR() instruction that runs (so inits are run for the top level view before * any embedded views). For this reason, the call must be tracked. */ initHooksCalled: boolean; /** - * Whether or not the content hooks have been called in this change detection run. + * Whether or not the afterContentInit and afterContentChecked hooks have been called + * in this change detection run. * * Content hooks are executed by the first Comp.r() instruction that runs (to avoid * adding to the code size), so it needs to be able to check whether or not they should @@ -220,10 +221,18 @@ export interface TView { * Odd indices: Hook function */ viewHooks: HookData|null; + + /** + * Array of ngOnDestroy hooks that should be executed when this view is destroyed. + * + * Even indices: Directive index + * Odd indices: Hook function + */ + destroyHooks: HookData|null; } /** - * Array of init hooks that should be executed for a view. + * Array of hooks that should be executed for a view and their directive indices. * * Even indices: Flags (1st bit: hook type, remaining: directive index) * Odd indices: Hook function diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts index cdfbe741c3..73dc4daa5e 100644 --- a/packages/core/src/render3/node_manipulation.ts +++ b/packages/core/src/render3/node_manipulation.ts @@ -11,7 +11,7 @@ import {LContainer, unusedValueExportToPlacateAjd as unused1} from './interfaces import {LContainerNode, LElementNode, LNode, LNodeFlags, LProjectionNode, LTextNode, LViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node'; import {LProjection, unusedValueExportToPlacateAjd as unused3} from './interfaces/projection'; import {ProceduralRenderer3, RComment, RElement, RNode, RText, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer'; -import {LView, LViewOrLContainer, unusedValueExportToPlacateAjd as unused5} from './interfaces/view'; +import {HookData, LView, LViewOrLContainer, TView, unusedValueExportToPlacateAjd as unused5} from './interfaces/view'; import {assertNodeType} from './node_assert'; const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5; @@ -295,17 +295,36 @@ export function getParentState(state: LViewOrLContainer, rootView: LView): LView * @param view The LView to clean up */ function cleanUpView(view: LView): void { - if (!view.cleanup) return; + removeListeners(view); + executeOnDestroys(view); +} + +/** Removes listeners and unsubscribes from output subscriptions */ +function removeListeners(view: LView): void { const cleanup = view.cleanup !; - for (let i = 0; i < cleanup.length - 1; i += 2) { - if (typeof cleanup[i] === 'string') { - cleanup ![i + 1].removeEventListener(cleanup[i], cleanup[i + 2], cleanup[i + 3]); - i += 2; - } else { - cleanup[i].call(cleanup[i + 1]); + if (cleanup != null) { + for (let i = 0; i < cleanup.length - 1; i += 2) { + if (typeof cleanup[i] === 'string') { + cleanup ![i + 1].removeEventListener(cleanup[i], cleanup[i + 2], cleanup[i + 3]); + i += 2; + } else { + cleanup[i].call(cleanup[i + 1]); + } + } + view.cleanup = null; + } +} + +/** Calls onDestroy hooks for this view */ +function executeOnDestroys(view: LView): void { + const tView = view.tView; + let destroyHooks: HookData|null; + if (tView != null && (destroyHooks = tView.destroyHooks) != null) { + for (let i = 0; i < destroyHooks.length; i += 2) { + const instance = view.data[destroyHooks[i] as number]; + (destroyHooks[i | 1] as() => void).call(instance); } } - view.cleanup = null; } /** diff --git a/packages/core/test/render3/common_integration_spec.ts b/packages/core/test/render3/common_integration_spec.ts index 2be5b561e0..fceb38427f 100644 --- a/packages/core/test/render3/common_integration_spec.ts +++ b/packages/core/test/render3/common_integration_spec.ts @@ -8,7 +8,7 @@ import {NgForOfContext} from '@angular/common'; -import {C, E, T, b, cR, cr, defineComponent, e, p, t} from '../../src/render3/index'; +import {C, E, T, b, cR, cr, defineComponent, e, p, r, t} from '../../src/render3/index'; import {NgForOf} from './common_with_def'; import {renderComponent, toHtml} from './render_util'; @@ -20,6 +20,7 @@ describe('@angular/common integration', () => { items: string[] = ['first', 'second']; static ngComponentDef = defineComponent({ + type: MyApp, factory: () => new MyApp(), tag: 'my-app', //
    @@ -33,7 +34,7 @@ describe('@angular/common integration', () => { } p(1, 'ngForOf', b(myApp.items)); cR(1); - NgForOf.ngDirectiveDef.r(2, 0); + r(2, 0); cr(); function liTemplate(row: NgForOfContext, cm: boolean) { diff --git a/packages/core/test/render3/common_with_def.ts b/packages/core/test/render3/common_with_def.ts index d07803c8e4..2b40b4fe94 100644 --- a/packages/core/test/render3/common_with_def.ts +++ b/packages/core/test/render3/common_with_def.ts @@ -15,13 +15,11 @@ import {DirectiveType, InjectFlags, NgOnChangesFeature, defineDirective, inject, export const NgForOf: DirectiveType> = NgForOfDef as any; NgForOf.ngDirectiveDef = defineDirective({ + type: NgForOfDef, factory: () => new NgForOfDef( injectViewContainerRef(), injectTemplateRef(), inject(IterableDiffers, InjectFlags.Default, defaultIterableDiffers)), features: [NgOnChangesFeature(NgForOf)], - refresh: (directiveIndex: number, elementIndex: number) => { - m>(directiveIndex).ngDoCheck(); - }, inputs: { ngForOf: 'ngForOf', ngForTrackBy: 'ngForTrackBy', diff --git a/packages/core/test/render3/compiler_canonical_spec.ts b/packages/core/test/render3/compiler_canonical_spec.ts index e18af8f4f4..65d77d5f20 100644 --- a/packages/core/test/render3/compiler_canonical_spec.ts +++ b/packages/core/test/render3/compiler_canonical_spec.ts @@ -311,14 +311,12 @@ describe('compiler specification', () => { // NORMATIVE static ngDirectiveDef = r3.defineDirective({ + type: ForOfDirective, factory: function ForOfDirective_Factory() { return new ForOfDirective(r3.injectViewContainerRef(), r3.injectTemplateRef()); }, // TODO(chuckj): Enable when ngForOf enabling lands. // features: [NgOnChangesFeature(NgForOf)], - refresh: function ForOfDirective_Refresh(directiveIndex: number, elementIndex: number) { - r3.m(directiveIndex).ngDoCheck(); - }, inputs: {forOf: 'forOf'} }); // /NORMATIVE @@ -340,6 +338,7 @@ describe('compiler specification', () => { // NORMATIVE static ngComponentDef = r3.defineComponent({ + type: MyComponent, tag: 'my-component', factory: function MyComponent_Factory() { return new MyComponent(); }, template: function MyComponentTemplate(ctx: MyComponent, cm: boolean) { @@ -350,7 +349,7 @@ describe('compiler specification', () => { } r3.p(1, 'forOf', r3.b(ctx.items)); r3.cR(1); - ForOfDirective.ngDirectiveDef.r(2, 1); + r3.r(2, 1); r3.cr(); function MyComponent_ForOfDirective_Template_1(ctx1: any, cm: boolean) { @@ -404,6 +403,7 @@ describe('compiler specification', () => { // NORMATIVE static ngComponentDef = r3.defineComponent({ + type: MyComponent, tag: 'my-component', factory: function MyComponent_Factory() { return new MyComponent(); }, template: function MyComponent_Template(ctx: MyComponent, cm: boolean) { @@ -414,7 +414,7 @@ describe('compiler specification', () => { } r3.p(1, 'forOf', r3.b(ctx.items)); r3.cR(1); - ForOfDirective.ngDirectiveDef.r(2, 1); + r3.r(2, 1); r3.cr(); function MyComponent_ForOfDirective_Template_1(ctx1: any, cm: boolean) { @@ -430,7 +430,7 @@ describe('compiler specification', () => { r3.t(1, r3.b1('', l0_item.name, '')); r3.p(4, 'forOf', r3.b(ctx.items)); r3.cR(3); - ForOfDirective.ngDirectiveDef.r(4, 3); + r3.r(4, 3); r3.cr(); function MyComponent_ForOfDirective_ForOfDirective_Template_3( diff --git a/packages/core/test/render3/define_spec.ts b/packages/core/test/render3/define_spec.ts index 2d9e0e821a..d27483bed4 100644 --- a/packages/core/test/render3/define_spec.ts +++ b/packages/core/test/render3/define_spec.ts @@ -28,6 +28,7 @@ describe('define', () => { } static ngDirectiveDef = defineDirective({ + type: MyDirective, factory: () => new MyDirective(), features: [NgOnChangesFeature(MyDirective)], inputs: {valA: 'valA', valB: 'valB'} diff --git a/packages/core/test/render3/di_spec.ts b/packages/core/test/render3/di_spec.ts index 0b1f83a5bb..638a514844 100644 --- a/packages/core/test/render3/di_spec.ts +++ b/packages/core/test/render3/di_spec.ts @@ -240,7 +240,7 @@ describe('di', () => { constructor(public value: string) {} static ngComponentDef = defineComponent({ - // type: MyApp, + type: MyApp, tag: 'my-app', factory: () => new MyApp(inject(String as any, InjectFlags.Default, 'DefaultValue')), template: () => null diff --git a/packages/core/test/render3/view_container_ref_spec.ts b/packages/core/test/render3/view_container_ref_spec.ts index 33be3d439e..986b2a5a21 100644 --- a/packages/core/test/render3/view_container_ref_spec.ts +++ b/packages/core/test/render3/view_container_ref_spec.ts @@ -7,7 +7,7 @@ */ import {TemplateRef, ViewContainerRef} from '../../src/core'; -import {C, T, b, cR, cr, defineComponent, defineDirective, injectTemplateRef, injectViewContainerRef, m, t} from '../../src/render3/index'; +import {C, T, b, cR, cr, defineComponent, defineDirective, injectTemplateRef, injectViewContainerRef, m, r, t} from '../../src/render3/index'; import {renderComponent, toHtml} from './render_util'; @@ -16,6 +16,7 @@ describe('ViewContainerRef', () => { constructor(public viewContainer: ViewContainerRef, public template: TemplateRef, ) {} static ngDirectiveDef = defineDirective({ + type: TestDirective, factory: () => new TestDirective(injectViewContainerRef(), injectTemplateRef(), ), }); } @@ -24,6 +25,7 @@ describe('ViewContainerRef', () => { testDir: TestDirective; static ngComponentDef = defineComponent({ + type: TestComponent, tag: 'test-cmp', factory: () => new TestComponent(), template: (cmp: TestComponent, cm: boolean) => { @@ -38,7 +40,8 @@ describe('ViewContainerRef', () => { } cR(0); cmp.testDir = m(1) as TestDirective; - TestDirective.ngDirectiveDef.r(1, 0); + TestDirective.ngDirectiveDef.h(1, 0); + r(1, 0); cr(); }, });