diff --git a/packages/core/src/render3/instructions/change_detection.ts b/packages/core/src/render3/instructions/change_detection.ts index 01b9eef0b30..4ac9d2cae3c 100644 --- a/packages/core/src/render3/instructions/change_detection.ts +++ b/packages/core/src/render3/instructions/change_detection.ts @@ -13,7 +13,7 @@ import {assertDefined, assertEqual} from '../../util/assert'; import {assertLContainer} from '../assert'; import {getComponentViewByInstance} from '../context_discovery'; import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags} from '../hooks'; -import {CONTAINER_HEADER_OFFSET, HAS_CHILD_VIEWS_TO_REFRESH, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS} from '../interfaces/container'; +import {CONTAINER_HEADER_OFFSET, LContainer, LContainerFlags, MOVED_VIEWS} from '../interfaces/container'; import {ComponentTemplate, RenderFlags} from '../interfaces/definition'; import {CONTEXT, EFFECTS_TO_SCHEDULE, ENVIRONMENT, FLAGS, InitPhaseState, LView, LViewFlags, PARENT, REACTIVE_TEMPLATE_CONSUMER, TVIEW, TView, TViewType} from '../interfaces/view'; import {getOrBorrowReactiveLViewConsumer, maybeReturnReactiveLViewConsumer, ReactiveLViewConsumer} from '../reactive_lview_consumer'; @@ -324,7 +324,7 @@ function viewShouldHaveReactiveConsumer(tView: TView) { function detectChangesInEmbeddedViews(lView: LView, mode: ChangeDetectionMode) { for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) { - lContainer[HAS_CHILD_VIEWS_TO_REFRESH] = false; + lContainer[FLAGS] &= ~LContainerFlags.HasChildViewsToRefresh; for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) { const embeddedLView = lContainer[i]; detectChangesInViewIfAttached(embeddedLView, mode); @@ -340,7 +340,7 @@ function detectChangesInEmbeddedViews(lView: LView, mode: ChangeDetectionMode) { function markTransplantedViewsForRefresh(lView: LView) { for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) { - if (!lContainer[HAS_TRANSPLANTED_VIEWS]) continue; + if (!(lContainer[FLAGS] & LContainerFlags.HasTransplantedViews)) continue; const movedViews = lContainer[MOVED_VIEWS]!; ngDevMode && assertDefined(movedViews, 'Transplanted View flags set but missing MOVED_VIEWS'); diff --git a/packages/core/src/render3/instructions/shared.ts b/packages/core/src/render3/instructions/shared.ts index bf72fb51414..0ad5d165713 100644 --- a/packages/core/src/render3/instructions/shared.ts +++ b/packages/core/src/render3/instructions/shared.ts @@ -1387,15 +1387,14 @@ export function createLContainer( const lContainer: LContainer = [ hostNative, // host native true, // Boolean `true` in this position signifies that this is an `LContainer` - false, // has transplanted views + 0, // flags currentView, // parent null, // next tNode, // t_host - false, // has child views to refresh + null, // dehydrated views native, // native, null, // view refs null, // moved views - null, // dehydrated views ]; ngDevMode && assertEqual( diff --git a/packages/core/src/render3/interfaces/container.ts b/packages/core/src/render3/interfaces/container.ts index 3d5cc7dcc61..841e6dab8f8 100644 --- a/packages/core/src/render3/interfaces/container.ts +++ b/packages/core/src/render3/interfaces/container.ts @@ -10,8 +10,7 @@ import {DehydratedContainerView} from '../../hydration/interfaces'; import {TNode} from './node'; import {RComment, RElement} from './renderer_dom'; -import {HOST, LView, NEXT, PARENT, T_HOST} from './view'; - +import {FLAGS, HOST, LView, NEXT, PARENT, T_HOST} from './view'; /** @@ -27,27 +26,13 @@ export const TYPE = 1; * Uglify will inline these when minifying so there shouldn't be a cost. */ -/** - * Flag to signify that this `LContainer` may have transplanted views which need to be change - * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`. - * - * This flag, once set, is never unset for the `LContainer`. This means that when unset we can skip - * a lot of work in `refreshEmbeddedViews`. But when set we still need to verify - * that the `MOVED_VIEWS` are transplanted and on-push. - */ -export const HAS_TRANSPLANTED_VIEWS = 2; - -// PARENT and NEXT are indices 3 and 4 +// FLAGS, PARENT, NEXT, and T_HOST are indices 2, 3, 4, and 5 // As we already have these constants in LView, we don't need to re-create them. -// T_HOST is index 5 -// We already have this constants in LView, we don't need to re-create it. - -export const HAS_CHILD_VIEWS_TO_REFRESH = 6; +export const DEHYDRATED_VIEWS = 6; export const NATIVE = 7; export const VIEW_REFS = 8; export const MOVED_VIEWS = 9; -export const DEHYDRATED_VIEWS = 10; /** * Size of LContainer's header. Represents the index after which all views in the @@ -55,7 +40,7 @@ export const DEHYDRATED_VIEWS = 10; * which views are already in the DOM (and don't need to be re-added) and so we can * remove views from the DOM when they are no longer required. */ -export const CONTAINER_HEADER_OFFSET = 11; +export const CONTAINER_HEADER_OFFSET = 10; /** * The state associated with a container. @@ -80,13 +65,8 @@ export interface LContainer extends Array { */ [TYPE]: true; - /** - * Flag to signify that this `LContainer` may have transplanted views which need to be change - * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`. - * - * This flag, once set, is never unset for the `LContainer`. - */ - [HAS_TRANSPLANTED_VIEWS]: boolean; + /** Flags for this container. See LContainerFlags for more info. */ + [FLAGS]: LContainerFlags; /** * Access to the parent view is necessary so we can propagate back @@ -100,12 +80,6 @@ export interface LContainer extends Array { */ [NEXT]: LView|LContainer|null; - /** - * Indicates that this LContainer has a view underneath it that needs to be refreshed during - * change detection. - */ - [HAS_CHILD_VIEWS_TO_REFRESH]: boolean; - /** * A collection of views created based on the underlying `` element but inserted into * a different `LContainer`. We need to track views created from a given declaration point since @@ -143,3 +117,20 @@ export interface LContainer extends Array { */ [DEHYDRATED_VIEWS]: DehydratedContainerView[]|null; } + +/** Flags associated with an LContainer (saved in LContainer[FLAGS]) */ +export enum LContainerFlags { + None = 0, + /** + * Flag to signify that this `LContainer` may have transplanted views which need to be change + * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`. + * + * This flag, once set, is never unset for the `LContainer`. + */ + HasTransplantedViews = 1 << 1, + /** + * Indicates that this LContainer has a view underneath it that needs to be refreshed during + * change detection. + */ + HasChildViewsToRefresh = 1 << 2, +} diff --git a/packages/core/src/render3/interfaces/view.ts b/packages/core/src/render3/interfaces/view.ts index 31fcdfc9b2e..afdc38edfa2 100644 --- a/packages/core/src/render3/interfaces/view.ts +++ b/packages/core/src/render3/interfaces/view.ts @@ -32,9 +32,9 @@ import {TDeferBlockDetails} from '../../defer/interfaces'; // Uglify will inline these when minifying so there shouldn't be a cost. export const HOST = 0; export const TVIEW = 1; -export const FLAGS = 2; // Shared with LContainer +export const FLAGS = 2; export const PARENT = 3; export const NEXT = 4; export const T_HOST = 5; diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts index 2acc93d6f63..0b94493d6fa 100644 --- a/packages/core/src/render3/node_manipulation.ts +++ b/packages/core/src/render3/node_manipulation.ts @@ -18,7 +18,7 @@ import {escapeCommentText} from '../util/dom'; import {assertLContainer, assertLView, assertParentView, assertProjectionSlots, assertTNodeForLView} from './assert'; import {attachPatchData} from './context_discovery'; import {icuContainerIterate} from './i18n/i18n_tree_shaking'; -import {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS, NATIVE} from './interfaces/container'; +import {CONTAINER_HEADER_OFFSET, LContainer, LContainerFlags, MOVED_VIEWS, NATIVE} from './interfaces/container'; import {ComponentDef} from './interfaces/definition'; import {NodeInjectorFactory} from './interfaces/injector'; import {unregisterLView} from './interfaces/lview_tracking'; @@ -298,7 +298,7 @@ function trackMovedView(declarationContainer: LContainer, lView: LView) { // At this point the declaration-component is not same as insertion-component; this means that // this is a transplanted view. Mark the declared lView as having transplanted views so that // those views can participate in CD. - declarationContainer[HAS_TRANSPLANTED_VIEWS] = true; + declarationContainer[FLAGS] |= LContainerFlags.HasTransplantedViews; } if (movedViews === null) { declarationContainer[MOVED_VIEWS] = [lView]; diff --git a/packages/core/src/render3/util/view_utils.ts b/packages/core/src/render3/util/view_utils.ts index 8e792824f4b..7520b2a82ef 100644 --- a/packages/core/src/render3/util/view_utils.ts +++ b/packages/core/src/render3/util/view_utils.ts @@ -9,7 +9,7 @@ import {RuntimeError, RuntimeErrorCode} from '../../errors'; import {assertDefined, assertGreaterThan, assertGreaterThanOrEqual, assertIndexInRange, assertLessThan} from '../../util/assert'; import {assertTNode, assertTNodeForLView} from '../assert'; -import {HAS_CHILD_VIEWS_TO_REFRESH, LContainer, TYPE} from '../interfaces/container'; +import {LContainer, LContainerFlags, TYPE} from '../interfaces/container'; import {TConstants, TNode} from '../interfaces/node'; import {RNode} from '../interfaces/renderer_dom'; import {isLContainer, isLView} from '../interfaces/type_checks'; @@ -224,13 +224,13 @@ export function markAncestorsForTraversal(lView: LView) { while (parent !== null) { // We stop adding markers to the ancestors once we reach one that already has the marker. This // is to avoid needlessly traversing all the way to the root when the marker already exists. - if ((isLContainer(parent) && parent[HAS_CHILD_VIEWS_TO_REFRESH] || + if ((isLContainer(parent) && (parent[FLAGS] & LContainerFlags.HasChildViewsToRefresh) || (isLView(parent) && parent[FLAGS] & LViewFlags.HasChildViewsToRefresh))) { break; } if (isLContainer(parent)) { - parent[HAS_CHILD_VIEWS_TO_REFRESH] = true; + parent[FLAGS] |= LContainerFlags.HasChildViewsToRefresh; } else { parent[FLAGS] |= LViewFlags.HasChildViewsToRefresh; if (!viewAttachedToChangeDetector(parent)) { diff --git a/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json b/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json index b647704f5c2..2e7cb1d94c1 100644 --- a/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json @@ -233,12 +233,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "INJECTOR2" }, @@ -266,6 +260,9 @@ { "name": "Injector" }, + { + "name": "LContainerFlags" + }, { "name": "LEAVE_TOKEN_REGEX" }, diff --git a/packages/core/test/bundling/animations/bundle.golden_symbols.json b/packages/core/test/bundling/animations/bundle.golden_symbols.json index 72e2c5d6243..43094abeb5d 100644 --- a/packages/core/test/bundling/animations/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animations/bundle.golden_symbols.json @@ -257,12 +257,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "INJECTOR2" }, @@ -290,6 +284,9 @@ { "name": "KeyEventsPlugin" }, + { + "name": "LContainerFlags" + }, { "name": "LEAVE_TOKEN_REGEX" }, 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 a4c46fa0a2e..db31761dc1b 100644 --- a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json +++ b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json @@ -164,12 +164,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "INJECTOR2" }, @@ -197,6 +191,9 @@ { "name": "KeyEventsPlugin" }, + { + "name": "LContainerFlags" + }, { "name": "LOCALE_ID2" }, diff --git a/packages/core/test/bundling/defer/bundle.golden_symbols.json b/packages/core/test/bundling/defer/bundle.golden_symbols.json index 2caad4a19a0..f4e3b0a5e79 100644 --- a/packages/core/test/bundling/defer/bundle.golden_symbols.json +++ b/packages/core/test/bundling/defer/bundle.golden_symbols.json @@ -194,12 +194,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "INJECTOR2" }, @@ -230,6 +224,9 @@ { "name": "KeyEventsPlugin" }, + { + "name": "LContainerFlags" + }, { "name": "LOADING_AFTER_SLOT" }, diff --git a/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json b/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json index 5a6cba9c057..e4313b3e406 100644 --- a/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json @@ -242,12 +242,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "INJECTOR2" }, @@ -281,6 +275,9 @@ { "name": "KeyEventsPlugin" }, + { + "name": "LContainerFlags" + }, { "name": "LOCALE_ID2" }, diff --git a/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json b/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json index e99ef7be74e..195dff896bb 100644 --- a/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json @@ -227,12 +227,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "INJECTOR2" }, @@ -266,6 +260,9 @@ { "name": "KeyEventsPlugin" }, + { + "name": "LContainerFlags" + }, { "name": "LOCALE_ID2" }, 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 08a2573d7b6..25d0847c0e3 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -104,12 +104,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "HelloWorldModule" }, @@ -137,6 +131,9 @@ { "name": "Injector" }, + { + "name": "LContainerFlags" + }, { "name": "LOCALE_ID2" }, diff --git a/packages/core/test/bundling/hydration/bundle.golden_symbols.json b/packages/core/test/bundling/hydration/bundle.golden_symbols.json index ba9e490964c..ddaa32ae55b 100644 --- a/packages/core/test/bundling/hydration/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hydration/bundle.golden_symbols.json @@ -185,12 +185,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "HEADERS" }, @@ -239,6 +233,9 @@ { "name": "Injector" }, + { + "name": "LContainerFlags" + }, { "name": "LOCALE_ID2" }, diff --git a/packages/core/test/bundling/router/bundle.golden_symbols.json b/packages/core/test/bundling/router/bundle.golden_symbols.json index 4b5113f9373..63994aba112 100644 --- a/packages/core/test/bundling/router/bundle.golden_symbols.json +++ b/packages/core/test/bundling/router/bundle.golden_symbols.json @@ -272,12 +272,6 @@ { "name": "GuardsCheckStart" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "HistoryStateManager" }, @@ -323,6 +317,9 @@ { "name": "ItemComponent" }, + { + "name": "LContainerFlags" + }, { "name": "LOCALE_ID2" }, diff --git a/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json b/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json index 08acc73fd23..4f00f629567 100644 --- a/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json +++ b/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json @@ -146,12 +146,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "INJECTOR2" }, @@ -179,6 +173,9 @@ { "name": "Injector" }, + { + "name": "LContainerFlags" + }, { "name": "LOCALE_ID2" }, diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index 4d7b68f4aba..17dfc360fa3 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -167,12 +167,6 @@ { "name": "GenericBrowserDomAdapter" }, - { - "name": "HAS_CHILD_VIEWS_TO_REFRESH" - }, - { - "name": "HAS_TRANSPLANTED_VIEWS" - }, { "name": "INJECTOR2" }, @@ -206,6 +200,9 @@ { "name": "KeyEventsPlugin" }, + { + "name": "LContainerFlags" + }, { "name": "LOCALE_ID2" },