diff --git a/goldens/size-tracking/aio-payloads.json b/goldens/size-tracking/aio-payloads.json index 48c8029749..0e7403b502 100755 --- a/goldens/size-tracking/aio-payloads.json +++ b/goldens/size-tracking/aio-payloads.json @@ -12,7 +12,7 @@ "master": { "uncompressed": { "runtime-es2015": 3037, - "main-es2015": 448676, + "main-es2015": 448085, "polyfills-es2015": 52415 } } diff --git a/goldens/size-tracking/integration-payloads.json b/goldens/size-tracking/integration-payloads.json index e9db1e512f..8ff6309247 100644 --- a/goldens/size-tracking/integration-payloads.json +++ b/goldens/size-tracking/integration-payloads.json @@ -30,7 +30,7 @@ "master": { "uncompressed": { "runtime-es2015": 1485, - "main-es2015": 136096, + "main-es2015": 135506, "polyfills-es2015": 37248 } } @@ -39,7 +39,7 @@ "master": { "uncompressed": { "runtime-es2015": 2289, - "main-es2015": 242460, + "main-es2015": 241945, "polyfills-es2015": 36938, "5-es2015": 751 } diff --git a/packages/core/src/render3/VIEW_DATA.md b/packages/core/src/render3/VIEW_DATA.md index f93362b25d..6442566db5 100644 --- a/packages/core/src/render3/VIEW_DATA.md +++ b/packages/core/src/render3/VIEW_DATA.md @@ -198,57 +198,6 @@ The above will create the following layout: | ... | ... | ... -The `EXPANDO` section needs additional information for information stored in `TView.expandoInstructions` - -| Index | `TView.expandoInstructions` | Meaning -| ----: | ---------------------------:| ------- -| 0 | -10 | Negative numbers signify pointers to elements. In this case 10 (``) -| 1 | 2 | Injector size. Number of values to skip to get to Host Bindings. -| 2 | Child.ɵcmp.hostBindings | The function to call. (Only when `hostVars` is not `0`) -| 3 | Child.ɵcmp.hostVars | Number of host bindings to process. (Only when `hostVars` is not `0`) -| 4 | Tooltip.ɵdir.hostBindings | The function to call. (Only when `hostVars` is not `0`) -| 5 | Tooltip.ɵdir.hostVars | Number of host bindings to process. (Only when `hostVars` is not `0`) - -The reason for this layout is to make the host binding update efficient using this pseudo code: -```typescript -let currentDirectiveIndex = -1; -let currentElementIndex = -1; -// This is global state which is used internally by hostBindings to know where the offset is -let bindingRootIndex = tView.expandoStartIndex; -for(var i = 0; i < tView.expandoInstructions.length; i++) { - let instruction = tView.expandoInstructions[i]; - if (typeof instruction === 'number') { - // Numbers are used to update the indices. - if (instruction < 0) { - // Negative numbers means that we are starting new EXPANDO block and need to update current element and directive index - bindingRootIndex += BLOOM_OFFSET; - currentDirectiveIndex = bindingRootIndex; - currentElementIndex = -instruction; - } else { - bindingRootIndex += instruction; - } - } else { - // We know that we are hostBinding function so execute it. - instruction(currentDirectiveIndex, currentElementIndex); - currentDirectiveIndex++; - } -} -``` - -The above code should execute as: - -| Instruction | `bindingRootIndex` | `currentDirectiveIndex` | `currentElementIndex` -| ----------: | -----------------: | ----------------------: | --------------------: -| (initial) | `11` | `-1` | `-1` -| `-10` | `19` | `\* new Child() *\ 19` | `\* *\ 10` -| `2` | `21` | `\* new Child() *\ 19` | `\* *\ 10` -| `Child.ɵcmp.hostBindings` | invoke with => | `\* new Child() *\ 19` | `\* *\ 10` -| | `21` | `\* new Tooltip() *\ 20` | `\* *\ 10` -| `Child.ɵcmp.hostVars` | `22` | `\* new Tooltip() *\ 20` | `\* *\ 10` -| `Tooltip.ɵdir.hostBindings` | invoke with => | `\* new Tooltip() *\ 20` | `\* *\ 10` -| | `22` | `21` | `\* *\ 10` -| `Tooltip.ɵdir.hostVars` | `22` | `21` | `\* *\ 10` - ## `EXPANDO` and Injection `EXPANDO` will also store the injection information for the element. diff --git a/packages/core/src/render3/component.ts b/packages/core/src/render3/component.ts index 177bdae614..e27a6f9cdd 100644 --- a/packages/core/src/render3/component.ts +++ b/packages/core/src/render3/component.ts @@ -16,9 +16,9 @@ import {assertComponentType} from './assert'; import {getComponentDef} from './definition'; import {diPublicInInjector, getOrCreateNodeInjectorForNode} from './di'; import {registerPostOrderHooks} from './hooks'; -import {addHostBindingsToExpandoInstructions, addToViewTree, CLEAN_PROMISE, createLView, createTView, getOrCreateTComponentView, getOrCreateTNode, growHostVarsSpace, initTNodeFlags, instantiateRootComponent, invokeHostBindingsInCreationMode, locateHostElement, markAsComponentHost, refreshView, renderView} from './instructions/shared'; +import {addToViewTree, CLEAN_PROMISE, createLView, createTView, getOrCreateTComponentView, getOrCreateTNode, initTNodeFlags, instantiateRootComponent, invokeHostBindingsInCreationMode, locateHostElement, markAsComponentHost, refreshView, registerHostBindingOpCodes, renderView} from './instructions/shared'; import {ComponentDef, ComponentType, RenderFlags} from './interfaces/definition'; -import {TElementNode, TNode, TNodeType} from './interfaces/node'; +import {TElementNode, TNodeType} from './interfaces/node'; import {PlayerHandler} from './interfaces/player'; import {domRendererFactory3, RElement, Renderer3, RendererFactory3} from './interfaces/renderer'; import {CONTEXT, HEADER_OFFSET, LView, LViewFlags, RootContext, RootContextFlags, TVIEW, TViewType} from './interfaces/view'; @@ -230,7 +230,9 @@ export function createRootComponent( // We want to generate an empty QueryList for root content queries for backwards // compatibility with ViewEngine. if (componentDef.contentQueries) { - componentDef.contentQueries(RenderFlags.Create, component, rootLView.length - 1); + const tNode = getCurrentTNode()!; + ngDevMode && assertDefined(tNode, 'TNode expected'); + componentDef.contentQueries(RenderFlags.Create, component, tNode.directiveStart); } const rootTNode = getCurrentTNode()!; @@ -240,8 +242,9 @@ export function createRootComponent( setSelectedIndex(rootTNode.index); const rootTView = rootLView[TVIEW]; - addHostBindingsToExpandoInstructions(rootTView, componentDef); - growHostVarsSpace(rootTView, rootLView, componentDef.hostVars); + registerHostBindingOpCodes( + rootTView, rootTNode, rootLView, rootTNode.directiveStart, rootTNode.directiveEnd, + componentDef); invokeHostBindingsInCreationMode(componentDef, component); } @@ -274,13 +277,12 @@ export function createRootContext( * ``` */ export function LifecycleHooksFeature(component: any, def: ComponentDef): void { - const rootTView = readPatchedLView(component)![TVIEW]; - const dirIndex = rootTView.data.length - 1; - - // TODO(misko): replace `as TNode` with createTNode call. (needs refactoring to lose dep on - // LNode). - registerPostOrderHooks( - rootTView, {directiveStart: dirIndex, directiveEnd: dirIndex + 1} as TNode); + const lView = readPatchedLView(component)!; + ngDevMode && assertDefined(lView, 'LView is required'); + const tView = lView[TVIEW]; + const tNode = getCurrentTNode()!; + ngDevMode && assertDefined(tNode, 'TNode is required'); + registerPostOrderHooks(tView, tNode); } /** diff --git a/packages/core/src/render3/hooks.ts b/packages/core/src/render3/hooks.ts index bd08fdcaab..b7b41ac026 100644 --- a/packages/core/src/render3/hooks.ts +++ b/packages/core/src/render3/hooks.ts @@ -7,7 +7,7 @@ */ import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, DoCheck, OnChanges, OnDestroy, OnInit} from '../interface/lifecycle_hooks'; -import {assertEqual, assertNotEqual} from '../util/assert'; +import {assertDefined, assertEqual, assertNotEqual} from '../util/assert'; import {assertFirstCreatePass} from './assert'; import {NgOnChangesFeatureImpl} from './features/ng_onchanges_feature'; import {DirectiveDef} from './interfaces/definition'; @@ -77,6 +77,7 @@ export function registerPostOrderHooks(tView: TView, tNode: TNode): void { // hooks for projected components and directives must be called *before* their hosts. for (let i = tNode.directiveStart, end = tNode.directiveEnd; i < end; i++) { const directiveDef = tView.data[i] as DirectiveDef; + ngDevMode && assertDefined(directiveDef, 'Expecting DirectiveDef'); const lifecycleHooks: AfterContentInit&AfterContentChecked&AfterViewInit&AfterViewChecked& OnDestroy = directiveDef.type.prototype; const { diff --git a/packages/core/src/render3/i18n/i18n_parse.ts b/packages/core/src/render3/i18n/i18n_parse.ts index 2e4de13f35..837d0b0a94 100644 --- a/packages/core/src/render3/i18n/i18n_parse.ts +++ b/packages/core/src/render3/i18n/i18n_parse.ts @@ -154,7 +154,7 @@ export function i18nStartFirstCreatePass( function createTNodeAndAddOpCode( tView: TView, rootTNode: TNode|null, existingTNodes: TNode[], lView: LView, createOpCodes: I18nCreateOpCodes, text: string|null, isICU: boolean): TNode { - const i18nNodeIdx = allocExpando(tView, lView, 1); + const i18nNodeIdx = allocExpando(tView, lView, 1, null); let opCode = i18nNodeIdx << I18nCreateOpCode.SHIFT; let parentTNode = getCurrentParentTNode(); @@ -423,7 +423,7 @@ export function icuStart( let bindingMask = 0; const tIcu: TIcu = { type: icuExpression.type, - currentCaseLViewIndex: allocExpando(tView, lView, 1), + currentCaseLViewIndex: allocExpando(tView, lView, 1, null), anchorIdx, cases: [], create: [], @@ -596,7 +596,7 @@ function walkIcuTree( let bindingMask = 0; let currentNode = parentNode.firstChild; while (currentNode) { - const newIndex = allocExpando(tView, lView, 1); + const newIndex = allocExpando(tView, lView, 1, null); switch (currentNode.nodeType) { case Node.ELEMENT_NODE: const element = currentNode as Element; diff --git a/packages/core/src/render3/instructions/lview_debug.ts b/packages/core/src/render3/instructions/lview_debug.ts index ed2ed31987..c7f4f469a5 100644 --- a/packages/core/src/render3/instructions/lview_debug.ts +++ b/packages/core/src/render3/instructions/lview_debug.ts @@ -22,7 +22,7 @@ import {SelectorFlags} from '../interfaces/projection'; import {LQueries, TQueries} from '../interfaces/query'; import {RComment, RElement, Renderer3, RendererFactory3, RNode} from '../interfaces/renderer'; import {getTStylingRangeNext, getTStylingRangeNextDuplicate, getTStylingRangePrev, getTStylingRangePrevDuplicate, TStylingKey, TStylingRange} from '../interfaces/styling'; -import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DebugNode, DECLARATION_VIEW, DestroyHookData, ExpandoInstructions, FLAGS, HEADER_OFFSET, HookData, HOST, INJECTOR, LContainerDebug as ILContainerDebug, LView, LViewDebug as ILViewDebug, LViewDebugRange, LViewDebugRangeContent, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, SANITIZER, T_HOST, TData, TView as ITView, TVIEW, TView, TViewType, TViewTypeAsString} from '../interfaces/view'; +import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DebugNode, DECLARATION_VIEW, DestroyHookData, FLAGS, HEADER_OFFSET, HookData, HOST, HostBindingOpCodes, INJECTOR, LContainerDebug as ILContainerDebug, LView, LViewDebug as ILViewDebug, LViewDebugRange, LViewDebugRangeContent, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, SANITIZER, T_HOST, TData, TView as ITView, TVIEW, TView, TViewType, TViewTypeAsString} from '../interfaces/view'; import {attachDebugObject} from '../util/debug_utils'; import {getParentInjectorIndex, getParentInjectorView} from '../util/injector_utils'; import {unwrapRNode} from '../util/view_utils'; @@ -115,38 +115,38 @@ function nameSuffix(text: string|null|undefined): string { */ export const TViewConstructor = class TView implements ITView { constructor( - public type: TViewType, // - public blueprint: LView, // - public template: ComponentTemplate<{}>|null, // - public queries: TQueries|null, // - public viewQuery: ViewQueriesFunction<{}>|null, // - public declTNode: ITNode|null, // - public data: TData, // - public bindingStartIndex: number, // - public expandoStartIndex: number, // - public expandoInstructions: ExpandoInstructions|null, // - public firstCreatePass: boolean, // - public firstUpdatePass: boolean, // - public staticViewQueries: boolean, // - public staticContentQueries: boolean, // - public preOrderHooks: HookData|null, // - public preOrderCheckHooks: HookData|null, // - public contentHooks: HookData|null, // - public contentCheckHooks: HookData|null, // - public viewHooks: HookData|null, // - public viewCheckHooks: HookData|null, // - public destroyHooks: DestroyHookData|null, // - public cleanup: any[]|null, // - public contentQueries: number[]|null, // - public components: number[]|null, // - public directiveRegistry: DirectiveDefList|null, // - public pipeRegistry: PipeDefList|null, // - public firstChild: ITNode|null, // - public schemas: SchemaMetadata[]|null, // - public consts: TConstants|null, // - public incompleteFirstPass: boolean, // - public _decls: number, // - public _vars: number, // + public type: TViewType, + public blueprint: LView, + public template: ComponentTemplate<{}>|null, + public queries: TQueries|null, + public viewQuery: ViewQueriesFunction<{}>|null, + public declTNode: ITNode|null, + public data: TData, + public bindingStartIndex: number, + public expandoStartIndex: number, + public hostBindingOpCodes: HostBindingOpCodes|null, + public firstCreatePass: boolean, + public firstUpdatePass: boolean, + public staticViewQueries: boolean, + public staticContentQueries: boolean, + public preOrderHooks: HookData|null, + public preOrderCheckHooks: HookData|null, + public contentHooks: HookData|null, + public contentCheckHooks: HookData|null, + public viewHooks: HookData|null, + public viewCheckHooks: HookData|null, + public destroyHooks: DestroyHookData|null, + public cleanup: any[]|null, + public contentQueries: number[]|null, + public components: number[]|null, + public directiveRegistry: DirectiveDefList|null, + public pipeRegistry: PipeDefList|null, + public firstChild: ITNode|null, + public schemas: SchemaMetadata[]|null, + public consts: TConstants|null, + public incompleteFirstPass: boolean, + public _decls: number, + public _vars: number, ) {} diff --git a/packages/core/src/render3/instructions/shared.ts b/packages/core/src/render3/instructions/shared.ts index 9a3d22a680..d96ff9d380 100644 --- a/packages/core/src/render3/instructions/shared.ts +++ b/packages/core/src/render3/instructions/shared.ts @@ -12,7 +12,7 @@ import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../../me import {ViewEncapsulation} from '../../metadata/view'; import {validateAgainstEventAttributes, validateAgainstEventProperties} from '../../sanitization/sanitization'; import {Sanitizer} from '../../sanitization/sanitizer'; -import {assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertGreaterThanOrEqual, assertIndexInRange, assertLessThan, assertNotEqual, assertNotSame, assertSame, assertString} from '../../util/assert'; +import {assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertGreaterThanOrEqual, assertIndexInRange, assertNotEqual, assertNotSame, assertSame, assertString} from '../../util/assert'; import {createNamedArrayType} from '../../util/named_array_type'; import {initNgDevMode} from '../../util/ng_dev_mode'; import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect'; @@ -24,13 +24,13 @@ import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} f import {throwMultipleComponentError} from '../errors'; import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags} from '../hooks'; import {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS} from '../interfaces/container'; -import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, PipeDefListOrFactory, RenderFlags, ViewQueriesFunction} from '../interfaces/definition'; -import {NodeInjectorFactory, NodeInjectorOffset} from '../interfaces/injector'; -import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliases, PropertyAliasValue, TAttributes, TConstantsOrFactory, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, TProjectionNode} from '../interfaces/node'; +import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, HostBindingsFunction, PipeDefListOrFactory, RenderFlags, ViewQueriesFunction} from '../interfaces/definition'; +import {NodeInjectorFactory} from '../interfaces/injector'; +import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliases, PropertyAliasValue, TAttributes, TConstantsOrFactory, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode} from '../interfaces/node'; import {isProceduralRenderer, RComment, RElement, Renderer3, RendererFactory3, RNode, RText} from '../interfaces/renderer'; import {SanitizerFn} from '../interfaces/sanitization'; import {isComponentDef, isComponentHost, isContentQueryHost, isRootView} from '../interfaces/type_checks'; -import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, InitPhaseState, INJECTOR, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, T_HOST, TData, TRANSPLANTED_VIEWS_TO_REFRESH, TVIEW, TView, TViewType} from '../interfaces/view'; +import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, HostBindingOpCodes, InitPhaseState, INJECTOR, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, T_HOST, TData, TRANSPLANTED_VIEWS_TO_REFRESH, TVIEW, TView, TViewType} from '../interfaces/view'; import {assertPureTNodeType, assertTNodeType} from '../node_assert'; import {updateTextNode} from '../node_manipulation'; import {isInlineTemplate, isNodeMatchingSelectorList} from '../node_selector_matcher'; @@ -53,65 +53,31 @@ import {attachLContainerDebug, attachLViewDebug, cloneToLViewFromTViewBlueprint, const _CLEAN_PROMISE = (() => Promise.resolve(null))(); /** - * Process the `TView.expandoInstructions`. (Execute the `hostBindings`.) + * Invoke `HostBindingsFunction`s for view. * - * @param tView `TView` containing the `expandoInstructions` - * @param lView `LView` associated with the `TView` + * This methods executes `TView.hostBindingOpCodes`. It is used to execute the + * `HostBindingsFunction`s associated with the current `LView`. + * + * @param tView Current `TView`. + * @param lView Current `LView`. */ -export function setHostBindingsByExecutingExpandoInstructions(tView: TView, lView: LView): void { - ngDevMode && assertSame(tView, lView[TVIEW], '`LView` is not associated with the `TView`!'); +export function processHostBindingOpCodes(tView: TView, lView: LView): void { + const hostBindingOpCodes = tView.hostBindingOpCodes; + if (hostBindingOpCodes === null) return; try { - const expandoInstructions = tView.expandoInstructions; - if (expandoInstructions !== null) { - let bindingRootIndex = tView.expandoStartIndex; - let currentDirectiveIndex = -1; - let currentElementIndex = -1; - // TODO(misko): PERF It is possible to get here with `TView.expandoInstructions` containing no - // functions to execute. This is wasteful as there is no work to be done, but we still need - // to iterate over the instructions. - // In example of this is in this test: `host_binding_spec.ts` - // `fit('should not cause problems if detectChanges is called when a property updates', ...` - // In the above test we get here with expando [0, 0, 1] which requires a lot of processing but - // there is no function to execute. - for (let i = 0; i < expandoInstructions.length; i++) { - const instruction = expandoInstructions[i]; - if (typeof instruction === 'number') { - if (instruction <= 0) { - // Negative numbers mean that we are starting new EXPANDO block and need to update - // the current element and directive index. - currentElementIndex = ~instruction; - setSelectedIndex(currentElementIndex); - - // Injector block and providers are taken into account. - const providerCount = (expandoInstructions[++i] as number); - bindingRootIndex += NodeInjectorOffset.SIZE + providerCount; - - currentDirectiveIndex = bindingRootIndex; - } else { - // This is either the injector size (so the binding root can skip over directives - // and get to the first set of host bindings on this node) or the host var count - // (to get to the next set of host bindings on this node). - bindingRootIndex += instruction; - } - } else { - // If it's not a number, it's a host binding function that needs to be executed. - if (instruction !== null) { - ngDevMode && - assertLessThan( - currentDirectiveIndex, TNodeProviderIndexes.CptViewProvidersCountShifter, - 'Reached the max number of host bindings'); - setBindingRootForHostBindings(bindingRootIndex, currentDirectiveIndex); - const hostCtx = lView[currentDirectiveIndex]; - instruction(RenderFlags.Update, hostCtx); - } - // TODO(misko): PERF Relying on incrementing the `currentDirectiveIndex` here is - // sub-optimal. The implications are that if we have a lot of directives but none of them - // have host bindings we nevertheless need to iterate over the expando instructions to - // update the counter. It would be much better if we could encode the - // `currentDirectiveIndex` into the `expandoInstruction` array so that we only need to - // iterate over those directives which actually have `hostBindings`. - currentDirectiveIndex++; - } + for (let i = 0; i < hostBindingOpCodes.length; i++) { + const opCode = hostBindingOpCodes[i] as number; + if (opCode < 0) { + // Negative numbers are element indexes. + setSelectedIndex(~opCode); + } else { + // Positive numbers are NumberTuple which store bindingRootIndex and directiveIndex. + const directiveIdx = opCode; + const bindingRootIndx = hostBindingOpCodes[++i] as number; + const hostBindingFn = hostBindingOpCodes[++i] as HostBindingsFunction; + setBindingRootForHostBindings(bindingRootIndx, directiveIdx); + const context = lView[directiveIdx]; + hostBindingFn(RenderFlags.Update, context); } } } finally { @@ -119,6 +85,7 @@ export function setHostBindingsByExecutingExpandoInstructions(tView: TView, lVie } } + /** Refreshes all content queries declared by directives in a given view */ function refreshContentQueries(tView: TView, lView: LView): void { const contentQueries = tView.contentQueries; @@ -128,6 +95,7 @@ function refreshContentQueries(tView: TView, lView: LView): void { const directiveDefIdx = contentQueries[i + 1]; if (directiveDefIdx !== -1) { const directiveDef = tView.data[directiveDefIdx] as DirectiveDef; + ngDevMode && assertDefined(directiveDef, 'DirectiveDef not found.'); ngDevMode && assertDefined(directiveDef.contentQueries, 'contentQueries function should be defined'); setCurrentQueryIndex(queryStartIdx); @@ -279,10 +247,14 @@ export function createTNodeAtIndex( * @param tView `TView` associated with `LView` * @param lView The `LView` containing the blueprint to adjust * @param numSlotsToAlloc The number of slots to alloc in the LView, should be >0 + * @param initialValue Initial value to store in blueprint */ -export function allocExpando(tView: TView, lView: LView, numSlotsToAlloc: number): number { +export function allocExpando( + tView: TView, lView: LView, numSlotsToAlloc: number, initialValue: any): number { + if (numSlotsToAlloc === 0) return -1; if (ngDevMode) { - assertGreaterThan(numSlotsToAlloc, 0, 'The number of slots to alloc should be greater than 0'); + assertFirstCreatePass(tView); + assertSame(tView, lView[TVIEW], '`LView` must be associated with `TView`!'); assertEqual(tView.data.length, lView.length, 'Expecting LView to be same size as TView'); assertEqual( tView.data.length, tView.blueprint.length, 'Expecting Blueprint to be same size as TView'); @@ -290,21 +262,9 @@ export function allocExpando(tView: TView, lView: LView, numSlotsToAlloc: number } const allocIdx = lView.length; for (let i = 0; i < numSlotsToAlloc; i++) { - tView.blueprint.push(null); + lView.push(initialValue); + tView.blueprint.push(initialValue); tView.data.push(null); - lView.push(null); - } - - // We should only increment the expando start index if there aren't already directives - // and injectors saved in the "expando" section - if (!tView.expandoInstructions) { - tView.expandoStartIndex += numSlotsToAlloc; - } else { - // Since we're adding the dynamic nodes into the expando section, we need to let the host - // bindings know that they should skip x slots - // FIXME(misko): Refactor `expandoInstructions` so that it does not rely on relative binding - // offsets, but absolute values which Means we would not have to store it here. - tView.expandoInstructions.push(numSlotsToAlloc); } return allocIdx; } @@ -454,7 +414,7 @@ export function refreshView( } } - setHostBindingsByExecutingExpandoInstructions(tView, lView); + processHostBindingOpCodes(tView, lView); // Refresh child component views. const components = tView.components; @@ -653,7 +613,7 @@ export function createTView( const consts = typeof constsOrFactory === 'function' ? constsOrFactory() : constsOrFactory; const tView = blueprint[TVIEW as any] = ngDevMode ? new TViewConstructor( - type, + type, // type: TViewType, blueprint, // blueprint: LView, templateFn, // template: ComponentTemplate<{}>|null, null, // queries: TQueries|null @@ -662,24 +622,24 @@ export function createTView( cloneToTViewData(blueprint).fill(null, bindingStartIndex), // data: TData, bindingStartIndex, // bindingStartIndex: number, initialViewLength, // expandoStartIndex: number, - null, // expandoInstructions: ExpandoInstructions|null, - true, // firstCreatePass: boolean, - true, // firstUpdatePass: boolean, - false, // staticViewQueries: boolean, - false, // staticContentQueries: boolean, - null, // preOrderHooks: HookData|null, - null, // preOrderCheckHooks: HookData|null, - null, // contentHooks: HookData|null, - null, // contentCheckHooks: HookData|null, - null, // viewHooks: HookData|null, - null, // viewCheckHooks: HookData|null, - null, // destroyHooks: DestroyHookData|null, - null, // cleanup: any[]|null, - null, // contentQueries: number[]|null, - null, // components: number[]|null, - typeof directives === 'function' ? - directives() : - directives, // directiveRegistry: DirectiveDefList|null, + null, // hostBindingOpCodes: HostBindingOpCodes, + true, // firstCreatePass: boolean, + true, // firstUpdatePass: boolean, + false, // staticViewQueries: boolean, + false, // staticContentQueries: boolean, + null, // preOrderHooks: HookData|null, + null, // preOrderCheckHooks: HookData|null, + null, // contentHooks: HookData|null, + null, // contentCheckHooks: HookData|null, + null, // viewHooks: HookData|null, + null, // viewCheckHooks: HookData|null, + null, // destroyHooks: DestroyHookData|null, + null, // cleanup: any[]|null, + null, // contentQueries: number[]|null, + null, // components: number[]|null, + typeof directives === 'function' ? // + directives() : // + directives, // directiveRegistry: DirectiveDefList|null, typeof pipes === 'function' ? pipes() : pipes, // pipeRegistry: PipeDefList|null, null, // firstChild: TNode|null, schemas, // schemas: SchemaMetadata[]|null, @@ -698,7 +658,7 @@ export function createTView( data: blueprint.slice().fill(null, bindingStartIndex), bindingStartIndex: bindingStartIndex, expandoStartIndex: initialViewLength, - expandoInstructions: null, + hostBindingOpCodes: null, firstCreatePass: true, firstUpdatePass: true, staticViewQueries: false, @@ -945,14 +905,14 @@ function initializeInputAndOutputAliases(tView: TView, tNode: TNode): void { const start = tNode.directiveStart; const end = tNode.directiveEnd; - const defs = tView.data; + const tViewData = tView.data; const tNodeAttrs = tNode.attrs; const inputsFromAttrs: InitialInputData = ngDevMode ? new TNodeInitialInputs() : []; let inputsStore: PropertyAliases|null = null; let outputsStore: PropertyAliases|null = null; for (let i = start; i < end; i++) { - const directiveDef = defs[i] as DirectiveDef; + const directiveDef = tViewData[i] as DirectiveDef; const directiveInputs = directiveDef.inputs; // Do not use unbound attributes as inputs to structural directives, since structural // directive inputs can only be set using microsyntax (e.g. `
`). @@ -1146,10 +1106,15 @@ export function instantiateRootComponent(tView: TView, lView: LView, def: Com const rootTNode = getCurrentTNode()!; if (tView.firstCreatePass) { if (def.providersResolver) def.providersResolver(def); - generateExpandoInstructionBlock(tView, rootTNode, 1); - baseResolveDirective(tView, lView, def); + const directiveIndex = allocExpando(tView, lView, 1, null); + ngDevMode && + assertEqual( + directiveIndex, rootTNode.directiveStart, + 'Because this is a root component the allocated expando should match the TNode component.'); + configureViewWithDirective(tView, rootTNode, lView, directiveIndex, def); } - const directive = getNodeInjectable(lView, tView, lView.length - 1, rootTNode as TElementNode); + const directive = + getNodeInjectable(lView, tView, rootTNode.directiveStart, rootTNode as TElementNode); attachPatchData(directive, lView); const native = getNativeByTNode(rootTNode, lView); if (native) { @@ -1174,7 +1139,6 @@ export function resolveDirectives( const exportsMap: ({[key: string]: number}|null) = localRefs === null ? null : {'': -1}; if (directiveDefs !== null) { - let totalDirectiveHostVars = 0; hasDirectives = true; initTNodeFlags(tNode, tView.data.length, directiveDefs.length); // When the same token is provided by several directives on the same node, some rules apply in @@ -1187,18 +1151,22 @@ export function resolveDirectives( const def = directiveDefs[i]; if (def.providersResolver) def.providersResolver(def); } - generateExpandoInstructionBlock(tView, tNode, directiveDefs.length); let preOrderHooksFound = false; let preOrderCheckHooksFound = false; + let directiveIdx = allocExpando(tView, lView, directiveDefs.length, null); + ngDevMode && + assertSame( + directiveIdx, tNode.directiveStart, + 'TNode.directiveStart should point to just allocated space'); + for (let i = 0; i < directiveDefs.length; i++) { const def = directiveDefs[i]; // Merge the attrs in the order of matches. This assumes that the first directive is the // component itself, so that the component has the least priority. tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, def.hostAttrs); - baseResolveDirective(tView, lView, def); - - saveNameToExportMap(tView.data!.length - 1, def, exportsMap); + configureViewWithDirective(tView, tNode, lView, directiveIdx, def); + saveNameToExportMap(directiveIdx, def, exportsMap); if (def.contentQueries !== null) tNode.flags |= TNodeFlags.hasContentQuery; if (def.hostBindings !== null || def.hostAttrs !== null || def.hostVars !== 0) @@ -1221,12 +1189,10 @@ export function resolveDirectives( preOrderCheckHooksFound = true; } - addHostBindingsToExpandoInstructions(tView, def); - totalDirectiveHostVars += def.hostVars; + directiveIdx++; } initializeInputAndOutputAliases(tView, tNode); - growHostVarsSpace(tView, lView, totalDirectiveHostVars); } if (exportsMap) cacheMatchingLocalNames(tNode, localRefs, exportsMap); } @@ -1236,51 +1202,57 @@ export function resolveDirectives( } /** - * Add `hostBindings` to the `TView.expandoInstructions`. + * Add `hostBindings` to the `TView.hostBindingOpCodes`. * * @param tView `TView` to which the `hostBindings` should be added. + * @param tNode `TNode` the element which contains the directive + * @param lView `LView` current `LView` + * @param directiveIdx Directive index in view. + * @param directiveVarsIdx Where will the directive's vars be stored * @param def `ComponentDef`/`DirectiveDef`, which contains the `hostVars`/`hostBindings` to add. */ -export function addHostBindingsToExpandoInstructions( - tView: TView, def: ComponentDef|DirectiveDef): void { +export function registerHostBindingOpCodes( + tView: TView, tNode: TNode, lView: LView, directiveIdx: number, directiveVarsIdx: number, + def: ComponentDef|DirectiveDef): void { ngDevMode && assertFirstCreatePass(tView); - const expando = tView.expandoInstructions!; - // TODO(misko): PERF we are adding `hostBindings` even if there is nothing to add! This is - // suboptimal for performance. `def.hostBindings` may be null, - // but we still need to push null to the array as a placeholder - // to ensure the directive counter is incremented (so host - // binding functions always line up with the corrective directive). - // This is suboptimal for performance. See `currentDirectiveIndex` - // comment in `setHostBindingsByExecutingExpandoInstructions` for more - // details. expando.push(def.hostBindings); - expando.push(def.hostBindings); - const hostVars = def.hostVars; - if (hostVars !== 0) { - expando.push(def.hostVars); + + const hostBindings = def.hostBindings; + if (hostBindings) { + let hostBindingOpCodes = tView.hostBindingOpCodes; + if (hostBindingOpCodes === null) { + hostBindingOpCodes = tView.hostBindingOpCodes = [] as any as HostBindingOpCodes; + } + const elementIndx = ~tNode.index; + if (lastSelectedElementIdx(hostBindingOpCodes) != elementIndx) { + // Conditionally add select element so that we are more efficient in execution. + // NOTE: this is strictly not necessary and it trades code size for runtime perf. + // (We could just always add it.) + hostBindingOpCodes.push(elementIndx); + } + hostBindingOpCodes.push(directiveIdx, directiveVarsIdx, hostBindings); } } /** - * Grow the `LView`, blueprint and `TView.data` to accommodate the `hostBindings`. + * Returns the last selected element index in the `HostBindingOpCodes` * - * To support locality we don't know ahead of time how many `hostVars` of the containing directives - * we need to allocate. For this reason we allow growing these data structures as we discover more - * directives to accommodate them. + * For perf reasons we don't need to update the selected element index in `HostBindingOpCodes` only + * if it changes. This method returns the last index (or '0' if not found.) * - * @param tView `TView` which needs to be grown. - * @param lView `LView` which needs to be grown. - * @param count Size by which we need to grow the data structures. + * Selected element index are only the ones which are negative. */ -export function growHostVarsSpace(tView: TView, lView: LView, count: number) { - ngDevMode && assertFirstCreatePass(tView); - ngDevMode && assertSame(tView, lView[TVIEW], '`LView` must be associated with `TView`!'); - for (let i = 0; i < count; i++) { - lView.push(NO_CHANGE); - tView.blueprint.push(NO_CHANGE); - tView.data.push(null); +function lastSelectedElementIdx(hostBindingOpCodes: HostBindingOpCodes): number { + let i = hostBindingOpCodes.length; + while (i > 0) { + const value = hostBindingOpCodes[--i]; + if (typeof value === 'number' && value < 0) { + return value; + } } + return 0; } + /** * Instantiate all the directives that were previously resolved on the current node. */ @@ -1321,7 +1293,6 @@ function instantiateAllDirectives( function invokeDirectivesHostBindings(tView: TView, lView: LView, tNode: TNode) { const start = tNode.directiveStart; const end = tNode.directiveEnd; - const expando = tView.expandoInstructions!; const firstCreatePass = tView.firstCreatePass; const elementIndex = tNode.index; const currentDirectiveIndex = getCurrentDirectiveIndex(); @@ -1333,8 +1304,6 @@ function invokeDirectivesHostBindings(tView: TView, lView: LView, tNode: TNode) setCurrentDirectiveIndex(dirIndex); if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) { invokeHostBindingsInCreationMode(def, directive); - } else if (firstCreatePass) { - expando.push(null); } } } finally { @@ -1355,26 +1324,6 @@ export function invokeHostBindingsInCreationMode(def: DirectiveDef, directi } } -/** - * Generates a new block in TView.expandoInstructions for this node. - * - * Each expando block starts with the element index (turned negative so we can distinguish - * it from the hostVar count) and the directive count. See more in VIEW_DATA.md. - */ -export function generateExpandoInstructionBlock( - tView: TView, tNode: TNode, directiveCount: number): void { - ngDevMode && - assertEqual( - tView.firstCreatePass, true, - 'Expando block should only be generated on first create pass.'); - - const elementIndex = ~tNode.index; - const providerStartIndex = tNode.providerIndexes & TNodeProviderIndexes.ProvidersStartIndexMask; - const providerCount = tView.data.length - providerStartIndex; - (tView.expandoInstructions || (tView.expandoInstructions = [])) - .push(elementIndex, providerCount, directiveCount); -} - /** * Matches the current node against all available selectors. * If a component is matched (at most one), it is returned in first position in the array. @@ -1450,15 +1399,15 @@ function cacheMatchingLocalNames( * to their directive instances. */ function saveNameToExportMap( - index: number, def: DirectiveDef|ComponentDef, + directiveIdx: number, def: DirectiveDef|ComponentDef, exportsMap: {[key: string]: number}|null) { if (exportsMap) { if (def.exportAs) { for (let i = 0; i < def.exportAs.length; i++) { - exportsMap[def.exportAs[i]] = index; + exportsMap[def.exportAs[i]] = directiveIdx; } } - if (isComponentDef(def)) exportsMap[''] = index; + if (isComponentDef(def)) exportsMap[''] = directiveIdx; } } @@ -1479,13 +1428,32 @@ export function initTNodeFlags(tNode: TNode, index: number, numberOfDirectives: tNode.providerIndexes = index; } -function baseResolveDirective(tView: TView, viewData: LView, def: DirectiveDef) { - tView.data.push(def); +/** + * Setup directive for instantiation. + * + * We need to create a `NodeInjectorFactory` which is then inserted in both the `Blueprint` as well + * as `LView`. `TView` gets the `DirectiveDef`. + * + * @param tView `TView` + * @param tNode `TNode` + * @param lView `LView` + * @param directiveIndex Index where the directive will be stored in the Expando. + * @param def `DirectiveDef` + */ +function configureViewWithDirective( + tView: TView, tNode: TNode, lView: LView, directiveIndex: number, def: DirectiveDef): void { + ngDevMode && + assertGreaterThanOrEqual(directiveIndex, HEADER_OFFSET, 'Must be in Expando section'); + tView.data[directiveIndex] = def; const directiveFactory = def.factory || ((def as {factory: Function}).factory = getFactoryDef(def.type, true)); const nodeInjectorFactory = new NodeInjectorFactory(directiveFactory, isComponentDef(def), null); - tView.blueprint.push(nodeInjectorFactory); - viewData.push(nodeInjectorFactory); + tView.blueprint[directiveIndex] = nodeInjectorFactory; + lView[directiveIndex] = nodeInjectorFactory; + + registerHostBindingOpCodes( + tView, tNode, lView, directiveIndex, allocExpando(tView, lView, def.hostVars, NO_CHANGE), + def); } function addComponentLogic(lView: LView, hostTNode: TElementNode, def: ComponentDef): void { diff --git a/packages/core/src/render3/interfaces/node.ts b/packages/core/src/render3/interfaces/node.ts index f01f9d37a4..94e27e627f 100644 --- a/packages/core/src/render3/interfaces/node.ts +++ b/packages/core/src/render3/interfaces/node.ts @@ -409,11 +409,17 @@ export interface TNode { /** * Stores starting index of the directives. + * + * NOTE: The first directive is always component (if present). */ directiveStart: number; /** * Stores final exclusive index of the directives. + * + * The area right behind the `directiveStart-directiveEnd` range is used to allocate the + * `HostBindingFunction` `vars` (or null if no bindings.) Therefore `directiveEnd` is used to set + * `LFrame.bindingRootIndex` before `HostBindingFunction` is executed. */ directiveEnd: number; diff --git a/packages/core/src/render3/interfaces/view.ts b/packages/core/src/render3/interfaces/view.ts index 5d2d667a6f..331da6090a 100644 --- a/packages/core/src/render3/interfaces/view.ts +++ b/packages/core/src/render3/interfaces/view.ts @@ -427,11 +427,69 @@ export const enum PreOrderHookFlags { } /** - * Set of instructions used to process host bindings efficiently. + * Stores a set of OpCodes to process `HostBindingsFunction` associated with a current view. + * + * In order to invoke `HostBindingsFunction` we need: + * 1. 'elementIdx`: Index to the element associated with the `HostBindingsFunction`. + * 2. 'directiveIdx`: Index to the directive associated with the `HostBindingsFunction`. (This will + * become the context for the `HostBindingsFunction` invocation.) + * 3. `bindingRootIdx`: Location where the bindings for the `HostBindingsFunction` start. Internally + * `HostBindingsFunction` binding indexes start from `0` so we need to add `bindingRootIdx` to + * it. + * 4. `HostBindingsFunction`: A host binding function to execute. + * + * The above information needs to be encoded into the `HostBindingOpCodes` in an efficient manner. + * + * 1. `elementIdx` is encoded into the `HostBindingOpCodes` as `~elementIdx` (so a negative number); + * 2. `directiveIdx` + * 3. `bindingRootIdx` + * 4. `HostBindingsFunction` is passed in as is. + * + * The `HostBindingOpCodes` array contains: + * - negative number to select the element index. + * - followed by 1 or more of: + * - a number to select the directive index + * - a number to select the bindingRoot index + * - and a function to invoke. + * + * ## Example + * + * ``` + * const hostBindingOpCodes = [ + * ~30, // Select element 30 + * 40, 45, MyDir.ɵdir.hostBindings // Invoke host bindings on MyDir on element 30; + * // directiveIdx = 40; bindingRootIdx = 45; + * 50, 55, OtherDir.ɵdir.hostBindings // Invoke host bindings on OtherDire on element 30 + * // directiveIdx = 50; bindingRootIdx = 55; + * ] + * ``` + * + * ## Pseudocode + * ``` + * const hostBindingOpCodes = tView.hostBindingOpCodes; + * if (hostBindingOpCodes === null) return; + * for (let i = 0; i < hostBindingOpCodes.length; i++) { + * const opCode = hostBindingOpCodes[i] as number; + * if (opCode < 0) { + * // Negative numbers are element indexes. + * setSelectedIndex(~opCode); + * } else { + * // Positive numbers are NumberTuple which store bindingRootIndex and directiveIndex. + * const directiveIdx = opCode; + * const bindingRootIndx = hostBindingOpCodes[++i] as number; + * const hostBindingFn = hostBindingOpCodes[++i] as HostBindingsFunction; + * setBindingRootForHostBindings(bindingRootIndx, directiveIdx); + * const context = lView[directiveIdx]; + * hostBindingFn(RenderFlags.Update, context); + * } + * } + * ``` * - * See VIEW_DATA.md for more information. */ -export interface ExpandoInstructions extends Array|null> {} +export interface HostBindingOpCodes extends Array> { + __brand__: 'HostBindingOpCodes'; + debug?: string[]; +} /** * Explicitly marks `TView` as a specific type in `ngDevMode` @@ -572,13 +630,11 @@ export interface TView { firstChild: TNode|null; /** - * Set of instructions used to process host bindings efficiently. + * Stores the OpCodes to be replayed during change-detection to process the `HostBindings` * - * See VIEW_DATA.md for more information. + * See `HostBindingOpCodes` for encoding details. */ - // TODO(misko): `expandoInstructions` should be renamed to `hostBindingsInstructions` since they - // keep track of `hostBindings` which need to be executed. - expandoInstructions: ExpandoInstructions|null; + hostBindingOpCodes: HostBindingOpCodes|null; /** * Full registry of directives and components that may be found in this view. diff --git a/packages/core/src/render3/query.ts b/packages/core/src/render3/query.ts index 0252352018..14046b0673 100644 --- a/packages/core/src/render3/query.ts +++ b/packages/core/src/render3/query.ts @@ -570,7 +570,7 @@ function createTQuery(tView: TView, metadata: TQueryMetadata, nodeIndex: number) function saveContentQueryAndDirectiveIndex(tView: TView, directiveIndex: number) { const tViewContentQueries = tView.contentQueries || (tView.contentQueries = []); const lastSavedDirectiveIndex = - tView.contentQueries.length ? tViewContentQueries[tViewContentQueries.length - 1] : -1; + tViewContentQueries.length ? tViewContentQueries[tViewContentQueries.length - 1] : -1; if (directiveIndex !== lastSavedDirectiveIndex) { tViewContentQueries.push(tView.queries!.length - 1, directiveIndex); } diff --git a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json index 96d90bb28b..0d1b098faa 100644 --- a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json +++ b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json @@ -69,10 +69,10 @@ "name": "addComponentLogic" }, { - "name": "addHostBindingsToExpandoInstructions" + "name": "addToViewTree" }, { - "name": "addToViewTree" + "name": "allocExpando" }, { "name": "allocLFrame" @@ -86,9 +86,6 @@ { "name": "autoRegisterModuleById" }, - { - "name": "baseResolveDirective" - }, { "name": "callHook" }, @@ -104,6 +101,9 @@ { "name": "concatStringsWithSpace" }, + { + "name": "configureViewWithDirective" + }, { "name": "createLFrame" }, @@ -146,9 +146,6 @@ { "name": "findAttrIndexInNode" }, - { - "name": "generateExpandoInstructionBlock" - }, { "name": "generateInitialInputs" }, @@ -206,9 +203,6 @@ { "name": "getTView" }, - { - "name": "growHostVarsSpace" - }, { "name": "hasTagAndTypeMatch" }, @@ -284,9 +278,6 @@ { "name": "nativeAppendOrInsertBefore" }, - { - "name": "nativeInsertBefore" - }, { "name": "nextNgElementId" }, @@ -305,6 +296,9 @@ { "name": "refreshView" }, + { + "name": "registerHostBindingOpCodes" + }, { "name": "rememberChangeHistoryAndInvokeOnChangesHook" }, @@ -350,9 +344,6 @@ { "name": "setUpAttributes" }, - { - "name": "unwrapRNode" - }, { "name": "updateTransplantedViewCount" }, diff --git a/packages/core/test/bundling/forms/bundle.golden_symbols.json b/packages/core/test/bundling/forms/bundle.golden_symbols.json index 30129f0e8b..b19e08aa6c 100644 --- a/packages/core/test/bundling/forms/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms/bundle.golden_symbols.json @@ -698,15 +698,15 @@ { "name": "addComponentLogic" }, - { - "name": "addHostBindingsToExpandoInstructions" - }, { "name": "addToArray" }, { "name": "addToViewTree" }, + { + "name": "allocExpando" + }, { "name": "allocLFrame" }, @@ -734,9 +734,6 @@ { "name": "baseElement" }, - { - "name": "baseResolveDirective" - }, { "name": "bindingUpdated" }, @@ -785,6 +782,9 @@ { "name": "config" }, + { + "name": "configureViewWithDirective" + }, { "name": "connectableObservableDescriptor" }, @@ -941,9 +941,6 @@ { "name": "fromArray" }, - { - "name": "generateExpandoInstructionBlock" - }, { "name": "generateInitialInputs" }, @@ -1082,9 +1079,6 @@ { "name": "getTView" }, - { - "name": "growHostVarsSpace" - }, { "name": "handleError" }, @@ -1421,6 +1415,9 @@ { "name": "registerDestroyHooksIfSupported" }, + { + "name": "registerHostBindingOpCodes" + }, { "name": "registerPostOrderHooks" }, 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 d39dda1a43..86f1cbb727 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -56,6 +56,9 @@ { "name": "_renderCompCount" }, + { + "name": "allocExpando" + }, { "name": "allocLFrame" }, @@ -176,9 +179,6 @@ { "name": "nativeAppendOrInsertBefore" }, - { - "name": "nativeInsertBefore" - }, { "name": "nextNgElementId" }, @@ -194,6 +194,9 @@ { "name": "refreshView" }, + { + "name": "registerHostBindingOpCodes" + }, { "name": "rememberChangeHistoryAndInvokeOnChangesHook" }, @@ -224,16 +227,10 @@ { "name": "setSelectedIndex" }, - { - "name": "unwrapRNode" - }, { "name": "updateTransplantedViewCount" }, { "name": "viewAttachedToChangeDetector" - }, - { - "name": "ɵɵtext" } ] \ No newline at end of file diff --git a/packages/core/test/bundling/router/bundle.golden_symbols.json b/packages/core/test/bundling/router/bundle.golden_symbols.json index 01b94b278a..ac4e8100fe 100644 --- a/packages/core/test/bundling/router/bundle.golden_symbols.json +++ b/packages/core/test/bundling/router/bundle.golden_symbols.json @@ -920,9 +920,6 @@ { "name": "addComponentLogic" }, - { - "name": "addHostBindingsToExpandoInstructions" - }, { "name": "addToArray" }, @@ -935,6 +932,9 @@ { "name": "advanceActivatedRouteNodeAndItsChildren" }, + { + "name": "allocExpando" + }, { "name": "allocLFrame" }, @@ -965,9 +965,6 @@ { "name": "baseElement" }, - { - "name": "baseResolveDirective" - }, { "name": "bindingUpdated" }, @@ -1016,6 +1013,9 @@ { "name": "config" }, + { + "name": "configureViewWithDirective" + }, { "name": "connectableObservableDescriptor" }, @@ -1244,9 +1244,6 @@ { "name": "fromArray" }, - { - "name": "generateExpandoInstructionBlock" - }, { "name": "generateInitialInputs" }, @@ -1427,9 +1424,6 @@ { "name": "getToken" }, - { - "name": "growHostVarsSpace" - }, { "name": "handleError" }, @@ -1760,6 +1754,9 @@ { "name": "refreshView" }, + { + "name": "registerHostBindingOpCodes" + }, { "name": "registerPostOrderHooks" }, diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index a650b90fa8..ff13d11633 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -176,15 +176,15 @@ { "name": "addComponentLogic" }, - { - "name": "addHostBindingsToExpandoInstructions" - }, { "name": "addToArray" }, { "name": "addToViewTree" }, + { + "name": "allocExpando" + }, { "name": "allocLFrame" }, @@ -209,9 +209,6 @@ { "name": "attachPatchData" }, - { - "name": "baseResolveDirective" - }, { "name": "bindingUpdated" }, @@ -242,6 +239,9 @@ { "name": "concatStringsWithSpace" }, + { + "name": "configureViewWithDirective" + }, { "name": "createDirectivesInstances" }, @@ -323,9 +323,6 @@ { "name": "forwardRef" }, - { - "name": "generateExpandoInstructionBlock" - }, { "name": "generateInitialInputs" }, @@ -431,9 +428,6 @@ { "name": "getTView" }, - { - "name": "growHostVarsSpace" - }, { "name": "handleError" }, @@ -605,6 +599,9 @@ { "name": "refreshView" }, + { + "name": "registerHostBindingOpCodes" + }, { "name": "registerPostOrderHooks" }, diff --git a/packages/core/test/render3/is_shape_of.ts b/packages/core/test/render3/is_shape_of.ts index ac72703c7e..7248ccbd1f 100644 --- a/packages/core/test/render3/is_shape_of.ts +++ b/packages/core/test/render3/is_shape_of.ts @@ -119,7 +119,7 @@ const ShapeOfTView: ShapeOf = { staticViewQueries: true, staticContentQueries: true, firstChild: true, - expandoInstructions: true, + hostBindingOpCodes: true, directiveRegistry: true, pipeRegistry: true, preOrderHooks: true,