refactor(ivy): split util functions into different files (#28382)
Google3 detected circular references here, so splitting up this rather hodge-podge list of functions into slightly better organizational units. PR Close #28382
This commit is contained in:
parent
7bae49b419
commit
c64b13e593
|
@ -262,7 +262,7 @@ export {getModuleFactory__POST_R3__ as ɵgetModuleFactory__POST_R3__} from './li
|
|||
export {
|
||||
publishGlobalUtil as ɵpublishGlobalUtil,
|
||||
publishDefaultGlobalUtils as ɵpublishDefaultGlobalUtils
|
||||
} from './render3/global_utils';
|
||||
} from './render3/util/global_utils';
|
||||
|
||||
export {createInjector as ɵcreateInjector} from './di/r3_injector';
|
||||
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
*/
|
||||
|
||||
import {Injector} from '../di';
|
||||
import {getComponent, getContext, getInjectionTokens, getInjector, getListeners, getLocalRefs, getViewComponent, isBrowserEvents, loadLContext, loadLContextFromNode} from '../render3/discovery_utils';
|
||||
import {getViewComponent} from '../render3/global_utils_api';
|
||||
import {TNode} from '../render3/interfaces/node';
|
||||
import {StylingIndex} from '../render3/interfaces/styling';
|
||||
import {LView, TData, TVIEW} from '../render3/interfaces/view';
|
||||
import {getProp, getValue, isClassBasedValue} from '../render3/styling/class_and_style_bindings';
|
||||
import {getStylingContext} from '../render3/styling/util';
|
||||
import {INTERPOLATION_DELIMITER, isPropMetadataString, renderStringify} from '../render3/util';
|
||||
import {getComponent, getContext, getInjectionTokens, getInjector, getListeners, getLocalRefs, isBrowserEvents, loadLContext, loadLContextFromNode} from '../render3/util/discovery_utils';
|
||||
import {INTERPOLATION_DELIMITER, isPropMetadataString, renderStringify} from '../render3/util/misc_utils';
|
||||
import {assertDomNode} from '../util/assert';
|
||||
import {DebugContext} from '../view/index';
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import {assertDefined, assertEqual, throwError} from '../util/assert';
|
|||
import {getComponentDef, getNgModuleDef} from './definition';
|
||||
import {TNode} from './interfaces/node';
|
||||
import {LView} from './interfaces/view';
|
||||
import {isLContainer, isLView} from './util';
|
||||
import {isLContainer, isLView} from './util/view_utils';
|
||||
|
||||
|
||||
export function assertComponentType(
|
||||
|
|
|
@ -12,7 +12,7 @@ import {throwErrorIfNoChangesMode} from './errors';
|
|||
import {LView} from './interfaces/view';
|
||||
import {getCheckNoChangesMode} from './state';
|
||||
import {NO_CHANGE} from './tokens';
|
||||
import {isDifferent} from './util';
|
||||
import {isDifferent} from './util/misc_utils';
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import {assertDefined} from '../util/assert';
|
|||
import {assertComponentType} from './assert';
|
||||
import {getComponentDef} from './definition';
|
||||
import {diPublicInInjector, getOrCreateNodeInjectorForNode} from './di';
|
||||
import {publishDefaultGlobalUtils} from './global_utils';
|
||||
import {registerPostOrderHooks, registerPreOrderHooks} from './hooks';
|
||||
import {CLEAN_PROMISE, addToViewTree, createLView, createNodeAtIndex, createTView, getOrCreateTView, initNodeFlags, instantiateRootComponent, invokeHostBindingsInCreationMode, locateHostElement, queueComponentIndexForCheck, refreshDescendantViews} from './instructions';
|
||||
import {ComponentDef, ComponentType, RenderFlags} from './interfaces/definition';
|
||||
|
@ -24,8 +23,12 @@ import {TElementNode, TNode, TNodeFlags, TNodeType} from './interfaces/node';
|
|||
import {PlayerHandler} from './interfaces/player';
|
||||
import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
|
||||
import {CONTEXT, FLAGS, HEADER_OFFSET, LView, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
|
||||
import {applyOnCreateInstructions} from './node_util';
|
||||
import {enterView, getPreviousOrParentTNode, leaveView, resetComponentState, setCurrentDirectiveDef} from './state';
|
||||
import {applyOnCreateInstructions, defaultScheduler, getRootView, readPatchedLView, renderStringify} from './util';
|
||||
import {publishDefaultGlobalUtils} from './util/global_utils';
|
||||
import {defaultScheduler, renderStringify} from './util/misc_utils';
|
||||
import {getRootContext, getRootView} from './util/view_traversal_utils';
|
||||
import {readPatchedLView} from './util/view_utils';
|
||||
|
||||
|
||||
|
||||
|
@ -245,19 +248,6 @@ export function LifecycleHooksFeature(component: any, def: ComponentDef<any>): v
|
|||
rootTView, { directiveStart: dirIndex, directiveEnd: dirIndex + 1 } as TNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the root context for any component by walking the parent `LView` until
|
||||
* reaching the root `LView`.
|
||||
*
|
||||
* @param component any component
|
||||
*/
|
||||
function getRootContext(component: any): RootContext {
|
||||
const rootContext = getRootView(component)[CONTEXT] as RootContext;
|
||||
ngDevMode && assertDefined(rootContext, 'rootContext');
|
||||
return rootContext;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wait on component until it is rendered.
|
||||
*
|
||||
|
|
|
@ -32,7 +32,8 @@ import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/
|
|||
import {RNode, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer';
|
||||
import {HEADER_OFFSET, LView, LViewFlags, RootContext, TVIEW} from './interfaces/view';
|
||||
import {enterView, leaveView} from './state';
|
||||
import {defaultScheduler, getTNode} from './util';
|
||||
import {defaultScheduler} from './util/misc_utils';
|
||||
import {getTNode} from './util/view_utils';
|
||||
import {createElementRef} from './view_engine_compatibility';
|
||||
import {RootViewRef, ViewRef} from './view_ref';
|
||||
|
||||
|
|
|
@ -6,13 +6,15 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import '../util/ng_dev_mode';
|
||||
|
||||
import {assertDomNode} from '../util/assert';
|
||||
|
||||
import {EMPTY_ARRAY} from './empty';
|
||||
import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context';
|
||||
import {TNode, TNodeFlags} from './interfaces/node';
|
||||
import {RElement} from './interfaces/renderer';
|
||||
import {CONTEXT, HEADER_OFFSET, HOST, LView, TVIEW} from './interfaces/view';
|
||||
import {getComponentViewByIndex, getNativeByTNode, readElementValue, readPatchedData} from './util';
|
||||
import {getComponentViewByIndex, getNativeByTNode, readElementValue, readPatchedData} from './util/view_utils';
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,10 @@ import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TN
|
|||
import {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view';
|
||||
import {assertNodeOfPossibleTypes} from './node_assert';
|
||||
import {getLView, getPreviousOrParentTNode, setTNodeAndViewData} from './state';
|
||||
import {findComponentView, getParentInjectorIndex, getParentInjectorView, hasParentInjector, isComponent, isComponentDef, renderStringify} from './util';
|
||||
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils';
|
||||
import {renderStringify} from './util/misc_utils';
|
||||
import {findComponentView} from './util/view_traversal_utils';
|
||||
import {isComponent, isComponentDef} from './util/view_utils';
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import {NodeInjectorFactory} from './interfaces/injector';
|
|||
import {TContainerNode, TElementContainerNode, TElementNode, TNodeFlags, TNodeProviderIndexes} from './interfaces/node';
|
||||
import {LView, TData, TVIEW, TView} from './interfaces/view';
|
||||
import {getLView, getPreviousOrParentTNode} from './state';
|
||||
import {isComponentDef} from './util';
|
||||
import {isComponentDef} from './util/view_utils';
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import {Type} from '../../interface/type';
|
|||
import {fillProperties} from '../../util/property';
|
||||
import {EMPTY_ARRAY, EMPTY_OBJ} from '../empty';
|
||||
import {ComponentDef, DirectiveDef, DirectiveDefFeature, RenderFlags} from '../interfaces/definition';
|
||||
import {isComponentDef} from '../util';
|
||||
import {isComponentDef} from '../util/view_utils';
|
||||
|
||||
import {NgOnChangesFeature} from './ng_onchanges_feature';
|
||||
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
* file in the public_api_guard test.
|
||||
*/
|
||||
|
||||
export {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent} from './discovery_utils';
|
||||
export {markDirty} from './instructions';
|
||||
export {getPlayers} from './players';
|
||||
export {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent} from './util/discovery_utils';
|
||||
|
|
|
@ -22,7 +22,9 @@ import {BINDING_INDEX, HEADER_OFFSET, LView, RENDERER, TVIEW, TView, T_HOST} fro
|
|||
import {appendChild, createTextNode, nativeRemoveNode} from './node_manipulation';
|
||||
import {getIsParent, getLView, getPreviousOrParentTNode, setIsParent, setPreviousOrParentTNode} from './state';
|
||||
import {NO_CHANGE} from './tokens';
|
||||
import {addAllToArray, getNativeByIndex, getNativeByTNode, getTNode, isLContainer, renderStringify} from './util';
|
||||
import {addAllToArray} from './util/array_utils';
|
||||
import {renderStringify} from './util/misc_utils';
|
||||
import {getNativeByIndex, getNativeByTNode, getTNode, isLContainer} from './util/view_utils';
|
||||
|
||||
const MARKER = `<EFBFBD>`;
|
||||
const ICU_BLOCK_REGEXP = /^\s*(<28>\d+:?\d*<2A>)\s*,\s*(select|plural)\s*,/;
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
*/
|
||||
import {LifecycleHooksFeature, renderComponent, whenRendered} from './component';
|
||||
import {defineBase, defineComponent, defineDirective, defineNgModule, definePipe, setComponentScope} from './definition';
|
||||
import {getComponent, getDirectives, getHostElement, getRenderedText} from './discovery_utils';
|
||||
import {InheritDefinitionFeature} from './features/inherit_definition_feature';
|
||||
import {NgOnChangesFeature} from './features/ng_onchanges_feature';
|
||||
import {ProvidersFeature} from './features/providers_feature';
|
||||
import {BaseDef, ComponentDef, ComponentDefWithMeta, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveDefWithMeta, DirectiveType, PipeDef, PipeDefWithMeta} from './interfaces/definition';
|
||||
import {getComponent, getDirectives, getHostElement, getRenderedText} from './util/discovery_utils';
|
||||
|
||||
export {ComponentFactory, ComponentFactoryResolver, ComponentRef, injectComponentFactoryResolver} from './component_ref';
|
||||
export {getFactoryOf, getInheritedFactory} from './di';
|
||||
|
@ -19,6 +19,7 @@ export {RenderFlags} from './interfaces/definition';
|
|||
export {CssSelectorList} from './interfaces/projection';
|
||||
|
||||
|
||||
|
||||
// clang-format off
|
||||
export {
|
||||
allocHostVars,
|
||||
|
@ -146,7 +147,7 @@ export {
|
|||
|
||||
export {templateRefExtractor} from './view_engine_compatibility_prebound';
|
||||
|
||||
export {resolveWindow, resolveDocument, resolveBody} from './util';
|
||||
export {resolveWindow, resolveDocument, resolveBody} from './util/misc_utils';
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -38,12 +38,15 @@ import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIE
|
|||
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
||||
import {appendChild, appendProjectedNode, createTextNode, insertView, removeView} from './node_manipulation';
|
||||
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
|
||||
import {decreaseElementDepthCount, enterView, getBindingsEnabled, getCheckNoChangesMode, getContextLView, getCurrentDirectiveDef, getElementDepthCount, getIsParent, getLView, getPreviousOrParentTNode, increaseElementDepthCount, isCreationMode, leaveView, nextContextImpl, resetComponentState, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setIsParent, setPreviousOrParentTNode,} from './state';
|
||||
import {applyOnCreateInstructions} from './node_util';
|
||||
import {decreaseElementDepthCount, enterView, getBindingsEnabled, getCheckNoChangesMode, getContextLView, getCurrentDirectiveDef, getElementDepthCount, getIsParent, getLView, getPreviousOrParentTNode, increaseElementDepthCount, isCreationMode, leaveView, nextContextImpl, resetComponentState, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setIsParent, setPreviousOrParentTNode} from './state';
|
||||
import {getInitialClassNameValue, getInitialStyleStringValue, initializeStaticContext as initializeStaticStylingContext, patchContextWithStaticAttrs, renderInitialClasses, renderInitialStyles, renderStyling, updateClassProp as updateElementClassProp, updateContextWithBindings, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling/class_and_style_bindings';
|
||||
import {BoundPlayerFactory} from './styling/player_factory';
|
||||
import {ANIMATION_PROP_PREFIX, allocateDirectiveIntoContext, createEmptyStylingContext, forceClassesAsString, forceStylesAsString, getStylingContext, hasClassInput, hasStyleInput, hasStyling, isAnimationProp} from './styling/util';
|
||||
import {NO_CHANGE} from './tokens';
|
||||
import {INTERPOLATION_DELIMITER, applyOnCreateInstructions, findComponentView, getComponentViewByIndex, getLViewParent, getNativeByIndex, getNativeByTNode, getRootContext, getRootView, getTNode, isComponent, isComponentDef, isContentQueryHost, isRootView, loadInternal, readElementValue, readPatchedLView, renderStringify} from './util';
|
||||
import {INTERPOLATION_DELIMITER, renderStringify} from './util/misc_utils';
|
||||
import {findComponentView, getLViewParent, getRootContext, getRootView} from './util/view_traversal_utils';
|
||||
import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getTNode, isComponent, isComponentDef, isContentQueryHost, isRootView, loadInternal, readElementValue, readPatchedLView} from './util/view_utils';
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import {componentNeedsResolution, maybeQueueResolutionOfComponentResources} from
|
|||
import {ViewEncapsulation} from '../../metadata/view';
|
||||
import {EMPTY_ARRAY, EMPTY_OBJ} from '../empty';
|
||||
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF} from '../fields';
|
||||
import {renderStringify} from '../util';
|
||||
import {renderStringify} from '../util/misc_utils';
|
||||
|
||||
import {angularCoreEnv} from './environment';
|
||||
import {flushModuleScopingQueueAsMuchAsPossible, patchComponentDefWithScope, transitiveScopesFor} from './module';
|
||||
|
|
|
@ -19,7 +19,7 @@ import {getComponentDef, getDirectiveDef, getNgModuleDef, getPipeDef} from '../d
|
|||
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from '../fields';
|
||||
import {ComponentDef} from '../interfaces/definition';
|
||||
import {NgModuleType} from '../ng_module_ref';
|
||||
import {renderStringify} from '../util';
|
||||
import {renderStringify} from '../util/misc_utils';
|
||||
|
||||
import {angularCoreEnv} from './environment';
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import {reflectDependencies} from '../../di/jit/util';
|
|||
import {Type} from '../../interface/type';
|
||||
import {Pipe} from '../../metadata/directives';
|
||||
import {NG_PIPE_DEF} from '../fields';
|
||||
import {renderStringify} from '../util';
|
||||
import {renderStringify} from '../util/misc_utils';
|
||||
|
||||
import {angularCoreEnv} from './environment';
|
||||
|
||||
|
|
|
@ -19,7 +19,9 @@ import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection'
|
|||
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
||||
import {CHILD_HEAD, CLEANUP, FLAGS, HEADER_OFFSET, HookData, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, T_HOST, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||
import {assertNodeType} from './node_assert';
|
||||
import {findComponentView, getLViewParent, getNativeByTNode, isComponent, isLContainer, isLView, isRootView, readElementValue, renderStringify} from './util';
|
||||
import {renderStringify} from './util/misc_utils';
|
||||
import {findComponentView, getLViewParent} from './util/view_traversal_utils';
|
||||
import {getNativeByTNode, isComponent, isLContainer, isLView, isRootView, readElementValue} from './util/view_utils';
|
||||
|
||||
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* @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 {RelativeInjectorLocation} from './interfaces/injector';
|
||||
import {TContainerNode, TElementNode, TNode} from './interfaces/node';
|
||||
import {DECLARATION_VIEW, LView, T_HOST} from './interfaces/view';
|
||||
import {getParentInjectorViewOffset} from './util/injector_utils';
|
||||
|
||||
export function applyOnCreateInstructions(tNode: TNode) {
|
||||
// there may be some instructions that need to run in a specific
|
||||
// order because the CREATE block in a directive runs before the
|
||||
// CREATE block in a template. To work around this instructions
|
||||
// can get access to the function array below and defer any code
|
||||
// to run after the element is created.
|
||||
let fns: Function[]|null;
|
||||
if (fns = tNode.onElementCreationFns) {
|
||||
for (let i = 0; i < fns.length; i++) {
|
||||
fns[i]();
|
||||
}
|
||||
tNode.onElementCreationFns = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a parent injector location number to find the view offset from the current injector,
|
||||
* then walks up the declaration view tree until the TNode of the parent injector is found.
|
||||
*
|
||||
* @param location The location of the parent injector, which contains the view offset
|
||||
* @param startView The LView instance from which to start walking up the view tree
|
||||
* @param startTNode The TNode instance of the starting element
|
||||
* @returns The TNode of the parent injector
|
||||
*/
|
||||
export function getParentInjectorTNode(
|
||||
location: RelativeInjectorLocation, startView: LView, startTNode: TNode): TElementNode|
|
||||
TContainerNode|null {
|
||||
if (startTNode.parent && startTNode.parent.injectorIndex !== -1) {
|
||||
// view offset is 0
|
||||
const injectorIndex = startTNode.parent.injectorIndex;
|
||||
let parentTNode = startTNode.parent;
|
||||
while (parentTNode.parent != null && injectorIndex == parentTNode.injectorIndex) {
|
||||
parentTNode = parentTNode.parent;
|
||||
}
|
||||
return parentTNode;
|
||||
}
|
||||
let viewOffset = getParentInjectorViewOffset(location);
|
||||
// view offset is 1
|
||||
let parentView = startView;
|
||||
let parentTNode = startView[T_HOST] as TElementNode;
|
||||
// view offset is superior to 1
|
||||
while (viewOffset > 1) {
|
||||
parentView = parentView[DECLARATION_VIEW] !;
|
||||
parentTNode = parentView[T_HOST] as TElementNode;
|
||||
viewOffset--;
|
||||
}
|
||||
return parentTNode;
|
||||
}
|
|
@ -12,7 +12,7 @@ import {scheduleTick} from './instructions';
|
|||
import {ComponentInstance, DirectiveInstance, Player} from './interfaces/player';
|
||||
import {RootContextFlags} from './interfaces/view';
|
||||
import {addPlayerInternal, getOrCreatePlayerContext, getPlayerContext, getPlayersInternal, getStylingContext, throwInvalidRefError} from './styling/util';
|
||||
import {getRootContext} from './util';
|
||||
import {getRootContext} from './util/view_traversal_utils';
|
||||
|
||||
/**
|
||||
* Adds a player to an element, directive or component instance that will later be
|
||||
|
|
|
@ -13,7 +13,7 @@ import {RElement, Renderer3, RendererStyleFlags3, isProceduralRenderer} from '..
|
|||
import {DirectiveOwnerAndPlayerBuilderIndex, DirectiveRegistryValues, DirectiveRegistryValuesIndex, InitialStylingValues, InitialStylingValuesIndex, MapBasedOffsetValues, MapBasedOffsetValuesIndex, SinglePropOffsetValues, SinglePropOffsetValuesIndex, StylingContext, StylingFlags, StylingIndex} from '../interfaces/styling';
|
||||
import {LView, RootContext} from '../interfaces/view';
|
||||
import {NO_CHANGE} from '../tokens';
|
||||
import {getRootContext} from '../util';
|
||||
import {getRootContext} from '../util/view_traversal_utils';
|
||||
|
||||
import {BoundPlayerFactory} from './player_factory';
|
||||
import {addPlayerInternal, allocPlayerContext, allocateDirectiveIntoContext, createEmptyStylingContext, getPlayerContext} from './util';
|
||||
|
|
|
@ -16,7 +16,7 @@ import {PlayState, Player, PlayerContext, PlayerIndex} from '../interfaces/playe
|
|||
import {RElement} from '../interfaces/renderer';
|
||||
import {InitialStylingValues, InitialStylingValuesIndex, StylingContext, StylingFlags, StylingIndex} from '../interfaces/styling';
|
||||
import {HEADER_OFFSET, HOST, LView, RootContext} from '../interfaces/view';
|
||||
import {getTNode} from '../util';
|
||||
import {getTNode} from '../util/view_utils';
|
||||
|
||||
import {CorePlayerHandler} from './core_player_handler';
|
||||
|
||||
|
|
|
@ -1,363 +0,0 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {assertDataInRange, assertDefined, assertGreaterThan, assertLessThan} from '../util/assert';
|
||||
import {global} from '../util/global';
|
||||
|
||||
import {assertLView} from './assert';
|
||||
import {LCONTAINER_LENGTH, LContainer} from './interfaces/container';
|
||||
import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context';
|
||||
import {ComponentDef, DirectiveDef} from './interfaces/definition';
|
||||
import {NO_PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags} from './interfaces/injector';
|
||||
import {TContainerNode, TElementNode, TNode, TNodeFlags, TNodeType} from './interfaces/node';
|
||||
import {RComment, RElement, RText} from './interfaces/renderer';
|
||||
import {CONTEXT, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, LView, LViewFlags, PARENT, RootContext, TData, TVIEW, T_HOST} from './interfaces/view';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of
|
||||
* that LContainer, which is an LView
|
||||
* @param lView the lView whose parent to get
|
||||
*/
|
||||
export function getLViewParent(lView: LView): LView|null {
|
||||
ngDevMode && assertLView(lView);
|
||||
const parent = lView[PARENT];
|
||||
return isLContainer(parent) ? parent[PARENT] ! : parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the value is an {@link LView}
|
||||
* @param value the value to check
|
||||
*/
|
||||
export function isLView(value: any): value is LView {
|
||||
return Array.isArray(value) && value.length >= HEADER_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the values are different from a change detection stand point.
|
||||
*
|
||||
* Constraints are relaxed in checkNoChanges mode. See `devModeEqual` for details.
|
||||
*/
|
||||
export function isDifferent(a: any, b: any): boolean {
|
||||
// NaN is the only value that is not equal to itself so the first
|
||||
// test checks if both a and b are not NaN
|
||||
return !(a !== a && b !== b) && a !== b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for stringify render output in Ivy.
|
||||
*/
|
||||
export function renderStringify(value: any): string {
|
||||
if (typeof value == 'function') return value.name || value;
|
||||
if (typeof value == 'string') return value;
|
||||
if (value == null) return '';
|
||||
if (typeof value == 'object' && typeof value.type == 'function')
|
||||
return value.type.name || value.type;
|
||||
return '' + value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens an array in non-recursive way. Input arrays are not modified.
|
||||
*/
|
||||
export function flatten(list: any[]): any[] {
|
||||
const result: any[] = [];
|
||||
let i = 0;
|
||||
|
||||
while (i < list.length) {
|
||||
const item = list[i];
|
||||
if (Array.isArray(item)) {
|
||||
if (item.length > 0) {
|
||||
list = item.concat(list.slice(i + 1));
|
||||
i = 0;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
result.push(item);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Retrieves a value from any `LView` or `TData`. */
|
||||
export function loadInternal<T>(view: LView | TData, index: number): T {
|
||||
ngDevMode && assertDataInRange(view, index + HEADER_OFFSET);
|
||||
return view[index + HEADER_OFFSET];
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the value of a slot in `LView` and returns the element node.
|
||||
*
|
||||
* Normally, element nodes are stored flat, but if the node has styles/classes on it,
|
||||
* it might be wrapped in a styling context. Or if that node has a directive that injects
|
||||
* ViewContainerRef, it may be wrapped in an LContainer. Or if that node is a component,
|
||||
* it will be wrapped in LView. It could even have all three, so we keep looping
|
||||
* until we find something that isn't an array.
|
||||
*
|
||||
* @param value The initial value in `LView`
|
||||
*/
|
||||
export function readElementValue(value: any): RElement {
|
||||
while (Array.isArray(value)) {
|
||||
value = value[HOST] as any;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an element value from the provided `viewData`, by unwrapping
|
||||
* from any containers, component views, or style contexts.
|
||||
*/
|
||||
export function getNativeByIndex(index: number, lView: LView): RElement {
|
||||
return readElementValue(lView[index + HEADER_OFFSET]);
|
||||
}
|
||||
|
||||
export function getNativeByTNode(tNode: TNode, hostView: LView): RElement|RText|RComment {
|
||||
return readElementValue(hostView[tNode.index]);
|
||||
}
|
||||
|
||||
export function getTNode(index: number, view: LView): TNode {
|
||||
ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
|
||||
ngDevMode && assertLessThan(index, view[TVIEW].data.length, 'wrong index for TNode');
|
||||
return view[TVIEW].data[index + HEADER_OFFSET] as TNode;
|
||||
}
|
||||
|
||||
export function getComponentViewByIndex(nodeIndex: number, hostView: LView): LView {
|
||||
// Could be an LView or an LContainer. If LContainer, unwrap to find LView.
|
||||
const slotValue = hostView[nodeIndex];
|
||||
const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
|
||||
ngDevMode && assertLView(lView);
|
||||
return lView;
|
||||
}
|
||||
|
||||
export function isContentQueryHost(tNode: TNode): boolean {
|
||||
return (tNode.flags & TNodeFlags.hasContentQuery) !== 0;
|
||||
}
|
||||
|
||||
export function isComponent(tNode: TNode): boolean {
|
||||
return (tNode.flags & TNodeFlags.isComponent) === TNodeFlags.isComponent;
|
||||
}
|
||||
|
||||
export function isComponentDef<T>(def: DirectiveDef<T>): def is ComponentDef<T> {
|
||||
return (def as ComponentDef<T>).template !== null;
|
||||
}
|
||||
|
||||
export function isLContainer(value: any): value is LContainer {
|
||||
// Styling contexts are also arrays, but their first index contains an element node
|
||||
return Array.isArray(value) && value.length === LCONTAINER_LENGTH;
|
||||
}
|
||||
|
||||
export function isRootView(target: LView): boolean {
|
||||
return (target[FLAGS] & LViewFlags.IsRoot) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the root view from any component or `LView` by walking the parent `LView` until
|
||||
* reaching the root `LView`.
|
||||
*
|
||||
* @param componentOrLView any component or `LView`
|
||||
*/
|
||||
export function getRootView(componentOrLView: LView | {}): LView {
|
||||
ngDevMode && assertDefined(componentOrLView, 'component');
|
||||
let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView) !;
|
||||
while (lView && !(lView[FLAGS] & LViewFlags.IsRoot)) {
|
||||
lView = getLViewParent(lView) !;
|
||||
}
|
||||
ngDevMode && assertLView(lView);
|
||||
return lView;
|
||||
}
|
||||
/**
|
||||
* Returns the `RootContext` instance that is associated with
|
||||
* the application where the target is situated. It does this by walking the parent views until it
|
||||
* gets to the root view, then getting the context off of that.
|
||||
*
|
||||
* @param viewOrComponent the `LView` or component to get the root context for.
|
||||
*/
|
||||
export function getRootContext(viewOrComponent: LView | {}): RootContext {
|
||||
const rootView = getRootView(viewOrComponent);
|
||||
ngDevMode &&
|
||||
assertDefined(rootView[CONTEXT], 'RootView has no context. Perhaps it is disconnected?');
|
||||
return rootView[CONTEXT] as RootContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the monkey-patch value data present on the target (which could be
|
||||
* a component, directive or a DOM node).
|
||||
*/
|
||||
export function readPatchedData(target: any): LView|LContext|null {
|
||||
ngDevMode && assertDefined(target, 'Target expected');
|
||||
return target[MONKEY_PATCH_KEY_NAME];
|
||||
}
|
||||
|
||||
export function readPatchedLView(target: any): LView|null {
|
||||
const value = readPatchedData(target);
|
||||
if (value) {
|
||||
return Array.isArray(value) ? value : (value as LContext).lView;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function hasParentInjector(parentLocation: RelativeInjectorLocation): boolean {
|
||||
return parentLocation !== NO_PARENT_INJECTOR;
|
||||
}
|
||||
|
||||
export function getParentInjectorIndex(parentLocation: RelativeInjectorLocation): number {
|
||||
return (parentLocation as any as number) & RelativeInjectorLocationFlags.InjectorIndexMask;
|
||||
}
|
||||
|
||||
export function getParentInjectorViewOffset(parentLocation: RelativeInjectorLocation): number {
|
||||
return (parentLocation as any as number) >> RelativeInjectorLocationFlags.ViewOffsetShift;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a parent injector location number to find the view offset from the current injector,
|
||||
* then walks up the declaration view tree until the view is found that contains the parent
|
||||
* injector.
|
||||
*
|
||||
* @param location The location of the parent injector, which contains the view offset
|
||||
* @param startView The LView instance from which to start walking up the view tree
|
||||
* @returns The LView instance that contains the parent injector
|
||||
*/
|
||||
export function getParentInjectorView(location: RelativeInjectorLocation, startView: LView): LView {
|
||||
let viewOffset = getParentInjectorViewOffset(location);
|
||||
let parentView = startView;
|
||||
// For most cases, the parent injector can be found on the host node (e.g. for component
|
||||
// or container), but we must keep the loop here to support the rarer case of deeply nested
|
||||
// <ng-template> tags or inline views, where the parent injector might live many views
|
||||
// above the child injector.
|
||||
while (viewOffset > 0) {
|
||||
parentView = parentView[DECLARATION_VIEW] !;
|
||||
viewOffset--;
|
||||
}
|
||||
return parentView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a parent injector location number to find the view offset from the current injector,
|
||||
* then walks up the declaration view tree until the TNode of the parent injector is found.
|
||||
*
|
||||
* @param location The location of the parent injector, which contains the view offset
|
||||
* @param startView The LView instance from which to start walking up the view tree
|
||||
* @param startTNode The TNode instance of the starting element
|
||||
* @returns The TNode of the parent injector
|
||||
*/
|
||||
export function getParentInjectorTNode(
|
||||
location: RelativeInjectorLocation, startView: LView, startTNode: TNode): TElementNode|
|
||||
TContainerNode|null {
|
||||
if (startTNode.parent && startTNode.parent.injectorIndex !== -1) {
|
||||
// view offset is 0
|
||||
const injectorIndex = startTNode.parent.injectorIndex;
|
||||
let parentTNode = startTNode.parent;
|
||||
while (parentTNode.parent != null && injectorIndex == parentTNode.injectorIndex) {
|
||||
parentTNode = parentTNode.parent;
|
||||
}
|
||||
return parentTNode;
|
||||
}
|
||||
|
||||
let viewOffset = getParentInjectorViewOffset(location);
|
||||
// view offset is 1
|
||||
let parentView = startView;
|
||||
let parentTNode = startView[T_HOST] as TElementNode;
|
||||
|
||||
// view offset is superior to 1
|
||||
while (viewOffset > 1) {
|
||||
parentView = parentView[DECLARATION_VIEW] !;
|
||||
parentTNode = parentView[T_HOST] as TElementNode;
|
||||
viewOffset--;
|
||||
}
|
||||
return parentTNode;
|
||||
}
|
||||
|
||||
export const defaultScheduler =
|
||||
(typeof requestAnimationFrame !== 'undefined' && requestAnimationFrame || // browser only
|
||||
setTimeout // everything else
|
||||
).bind(global);
|
||||
|
||||
/**
|
||||
* Equivalent to ES6 spread, add each item to an array.
|
||||
*
|
||||
* @param items The items to add
|
||||
* @param arr The array to which you want to add the items
|
||||
*/
|
||||
export function addAllToArray(items: any[], arr: any[]) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
arr.push(items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a current view, finds the nearest component's host (LElement).
|
||||
*
|
||||
* @param lView LView for which we want a host element node
|
||||
* @returns The host node
|
||||
*/
|
||||
export function findComponentView(lView: LView): LView {
|
||||
let rootTNode = lView[T_HOST];
|
||||
|
||||
while (rootTNode && rootTNode.type === TNodeType.View) {
|
||||
ngDevMode && assertDefined(lView[DECLARATION_VIEW], 'lView[DECLARATION_VIEW]');
|
||||
lView = lView[DECLARATION_VIEW] !;
|
||||
rootTNode = lView[T_HOST];
|
||||
}
|
||||
|
||||
ngDevMode && assertLView(lView);
|
||||
return lView;
|
||||
}
|
||||
|
||||
export function resolveWindow(element: RElement & {ownerDocument: Document}) {
|
||||
return {name: 'window', target: element.ownerDocument.defaultView};
|
||||
}
|
||||
|
||||
export function resolveDocument(element: RElement & {ownerDocument: Document}) {
|
||||
return {name: 'document', target: element.ownerDocument};
|
||||
}
|
||||
|
||||
export function resolveBody(element: RElement & {ownerDocument: Document}) {
|
||||
return {name: 'body', target: element.ownerDocument.body};
|
||||
}
|
||||
|
||||
/**
|
||||
* The special delimiter we use to separate property names, prefixes, and suffixes
|
||||
* in property binding metadata. See storeBindingMetadata().
|
||||
*
|
||||
* We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter
|
||||
* because it is a very uncommon character that is unlikely to be part of a user's
|
||||
* property names or interpolation strings. If it is in fact used in a property
|
||||
* binding, DebugElement.properties will not return the correct value for that
|
||||
* binding. However, there should be no runtime effect for real applications.
|
||||
*
|
||||
* This character is typically rendered as a question mark inside of a diamond.
|
||||
* See https://en.wikipedia.org/wiki/Specials_(Unicode_block)
|
||||
*
|
||||
*/
|
||||
export const INTERPOLATION_DELIMITER = `<EFBFBD>`;
|
||||
|
||||
/**
|
||||
* Determines whether or not the given string is a property metadata string.
|
||||
* See storeBindingMetadata().
|
||||
*/
|
||||
export function isPropMetadataString(str: string): boolean {
|
||||
return str.indexOf(INTERPOLATION_DELIMITER) >= 0;
|
||||
}
|
||||
|
||||
export function applyOnCreateInstructions(tNode: TNode) {
|
||||
// there may be some instructions that need to run in a specific
|
||||
// order because the CREATE block in a directive runs before the
|
||||
// CREATE block in a template. To work around this instructions
|
||||
// can get access to the function array below and defer any code
|
||||
// to run after the element is created.
|
||||
let fns: Function[]|null;
|
||||
if (fns = tNode.onElementCreationFns) {
|
||||
for (let i = 0; i < fns.length; i++) {
|
||||
fns[i]();
|
||||
}
|
||||
tNode.onElementCreationFns = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Equivalent to ES6 spread, add each item to an array.
|
||||
*
|
||||
* @param items The items to add
|
||||
* @param arr The array to which you want to add the items
|
||||
*/
|
||||
export function addAllToArray(items: any[], arr: any[]) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
arr.push(items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens an array in non-recursive way. Input arrays are not modified.
|
||||
*/
|
||||
export function flatten(list: any[]): any[] {
|
||||
const result: any[] = [];
|
||||
let i = 0;
|
||||
while (i < list.length) {
|
||||
const item = list[i];
|
||||
if (Array.isArray(item)) {
|
||||
if (item.length > 0) {
|
||||
list = item.concat(list.slice(i + 1));
|
||||
i = 0;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
result.push(item);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -6,16 +6,18 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Injector} from '../di/injector';
|
||||
import {Injector} from '../../di/injector';
|
||||
|
||||
import {assertLView} from './assert';
|
||||
import {discoverLocalRefs, getComponentAtNodeIndex, getDirectivesAtNodeIndex, getLContext} from './context_discovery';
|
||||
import {NodeInjector} from './di';
|
||||
import {LContext} from './interfaces/context';
|
||||
import {DirectiveDef} from './interfaces/definition';
|
||||
import {TElementNode, TNode, TNodeProviderIndexes} from './interfaces/node';
|
||||
import {CLEANUP, CONTEXT, FLAGS, HOST, LView, LViewFlags, TVIEW} from './interfaces/view';
|
||||
import {getLViewParent, getRootContext, readElementValue, renderStringify} from './util';
|
||||
import {assertLView} from '../assert';
|
||||
import {discoverLocalRefs, getComponentAtNodeIndex, getDirectivesAtNodeIndex, getLContext} from '../context_discovery';
|
||||
import {NodeInjector} from '../di';
|
||||
import {LContext} from '../interfaces/context';
|
||||
import {DirectiveDef} from '../interfaces/definition';
|
||||
import {TElementNode, TNode, TNodeProviderIndexes} from '../interfaces/node';
|
||||
import {CLEANUP, CONTEXT, FLAGS, HOST, LView, LViewFlags, TVIEW} from '../interfaces/view';
|
||||
import {renderStringify} from './misc_utils';
|
||||
import {getLViewParent, getRootContext} from './view_traversal_utils';
|
||||
import {readElementValue} from './view_utils';
|
||||
|
||||
|
||||
|
|
@ -5,10 +5,10 @@
|
|||
* 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 {assertDefined} from '../util/assert';
|
||||
import {global} from '../util/global';
|
||||
import {assertDefined} from '../../util/assert';
|
||||
import {global} from '../../util/global';
|
||||
|
||||
import {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getPlayers, getRootComponents, getViewComponent, markDirty} from './global_utils_api';
|
||||
import {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getPlayers, getRootComponents, getViewComponent, markDirty} from '../global_utils_api';
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* @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 {NO_PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags} from '../interfaces/injector';
|
||||
import {DECLARATION_VIEW, LView} from '../interfaces/view';
|
||||
/// Parent Injector Utils ///////////////////////////////////////////////////////////////
|
||||
export function hasParentInjector(parentLocation: RelativeInjectorLocation): boolean {
|
||||
return parentLocation !== NO_PARENT_INJECTOR;
|
||||
}
|
||||
|
||||
export function getParentInjectorIndex(parentLocation: RelativeInjectorLocation): number {
|
||||
return (parentLocation as any as number) & RelativeInjectorLocationFlags.InjectorIndexMask;
|
||||
}
|
||||
|
||||
export function getParentInjectorViewOffset(parentLocation: RelativeInjectorLocation): number {
|
||||
return (parentLocation as any as number) >> RelativeInjectorLocationFlags.ViewOffsetShift;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a parent injector location number to find the view offset from the current injector,
|
||||
* then walks up the declaration view tree until the view is found that contains the parent
|
||||
* injector.
|
||||
*
|
||||
* @param location The location of the parent injector, which contains the view offset
|
||||
* @param startView The LView instance from which to start walking up the view tree
|
||||
* @returns The LView instance that contains the parent injector
|
||||
*/
|
||||
export function getParentInjectorView(location: RelativeInjectorLocation, startView: LView): LView {
|
||||
let viewOffset = getParentInjectorViewOffset(location);
|
||||
let parentView = startView;
|
||||
// For most cases, the parent injector can be found on the host node (e.g. for component
|
||||
// or container), but we must keep the loop here to support the rarer case of deeply nested
|
||||
// <ng-template> tags or inline views, where the parent injector might live many views
|
||||
// above the child injector.
|
||||
while (viewOffset > 0) {
|
||||
parentView = parentView[DECLARATION_VIEW] !;
|
||||
viewOffset--;
|
||||
}
|
||||
return parentView;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* @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 {assertDefined} from '../../util/assert';
|
||||
import {global} from '../../util/global';
|
||||
import {RElement} from '../interfaces/renderer';
|
||||
import {CONTEXT, LView, RootContext} from '../interfaces/view';
|
||||
import {getRootView} from './view_traversal_utils';
|
||||
|
||||
/**
|
||||
* Returns whether the values are different from a change detection stand point.
|
||||
*
|
||||
* Constraints are relaxed in checkNoChanges mode. See `devModeEqual` for details.
|
||||
*/
|
||||
export function isDifferent(a: any, b: any): boolean {
|
||||
// NaN is the only value that is not equal to itself so the first
|
||||
// test checks if both a and b are not NaN
|
||||
return !(a !== a && b !== b) && a !== b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for stringify render output in Ivy.
|
||||
*/
|
||||
export function renderStringify(value: any): string {
|
||||
if (typeof value == 'function') return value.name || value;
|
||||
if (typeof value == 'string') return value;
|
||||
if (value == null) return '';
|
||||
if (typeof value == 'object' && typeof value.type == 'function')
|
||||
return value.type.name || value.type;
|
||||
return '' + value;
|
||||
}
|
||||
|
||||
|
||||
export const defaultScheduler =
|
||||
(typeof requestAnimationFrame !== 'undefined' && requestAnimationFrame || // browser only
|
||||
setTimeout // everything else
|
||||
).bind(global);
|
||||
|
||||
export function resolveWindow(element: RElement & {ownerDocument: Document}) {
|
||||
return {name: 'window', target: element.ownerDocument.defaultView};
|
||||
}
|
||||
|
||||
export function resolveDocument(element: RElement & {ownerDocument: Document}) {
|
||||
return {name: 'document', target: element.ownerDocument};
|
||||
}
|
||||
|
||||
export function resolveBody(element: RElement & {ownerDocument: Document}) {
|
||||
return {name: 'body', target: element.ownerDocument.body};
|
||||
}
|
||||
|
||||
/**
|
||||
* The special delimiter we use to separate property names, prefixes, and suffixes
|
||||
* in property binding metadata. See storeBindingMetadata().
|
||||
*
|
||||
* We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter
|
||||
* because it is a very uncommon character that is unlikely to be part of a user's
|
||||
* property names or interpolation strings. If it is in fact used in a property
|
||||
* binding, DebugElement.properties will not return the correct value for that
|
||||
* binding. However, there should be no runtime effect for real applications.
|
||||
*
|
||||
* This character is typically rendered as a question mark inside of a diamond.
|
||||
* See https://en.wikipedia.org/wiki/Specials_(Unicode_block)
|
||||
*
|
||||
*/
|
||||
export const INTERPOLATION_DELIMITER = `<EFBFBD>`;
|
||||
|
||||
/**
|
||||
* Determines whether or not the given string is a property metadata string.
|
||||
* See storeBindingMetadata().
|
||||
*/
|
||||
export function isPropMetadataString(str: string): boolean {
|
||||
return str.indexOf(INTERPOLATION_DELIMITER) >= 0;
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* @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 {assertDefined} from '../../util/assert';
|
||||
import {assertLView} from '../assert';
|
||||
import {TNodeType} from '../interfaces/node';
|
||||
import {CONTEXT, DECLARATION_VIEW, FLAGS, LView, LViewFlags, PARENT, RootContext, T_HOST} from '../interfaces/view';
|
||||
|
||||
import {isLContainer, isLView, readPatchedLView} from './view_utils';
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of
|
||||
* that LContainer, which is an LView
|
||||
* @param lView the lView whose parent to get
|
||||
*/
|
||||
export function getLViewParent(lView: LView): LView|null {
|
||||
ngDevMode && assertLView(lView);
|
||||
const parent = lView[PARENT];
|
||||
return isLContainer(parent) ? parent[PARENT] ! : parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the root view from any component or `LView` by walking the parent `LView` until
|
||||
* reaching the root `LView`.
|
||||
*
|
||||
* @param componentOrLView any component or `LView`
|
||||
*/
|
||||
export function getRootView(componentOrLView: LView | {}): LView {
|
||||
ngDevMode && assertDefined(componentOrLView, 'component');
|
||||
let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView) !;
|
||||
while (lView && !(lView[FLAGS] & LViewFlags.IsRoot)) {
|
||||
lView = getLViewParent(lView) !;
|
||||
}
|
||||
ngDevMode && assertLView(lView);
|
||||
return lView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a current view, finds the nearest component's host (LElement).
|
||||
*
|
||||
* @param lView LView for which we want a host element node
|
||||
* @returns The host node
|
||||
*/
|
||||
export function findComponentView(lView: LView): LView {
|
||||
let rootTNode = lView[T_HOST];
|
||||
while (rootTNode && rootTNode.type === TNodeType.View) {
|
||||
ngDevMode && assertDefined(lView[DECLARATION_VIEW], 'lView[DECLARATION_VIEW]');
|
||||
lView = lView[DECLARATION_VIEW] !;
|
||||
rootTNode = lView[T_HOST];
|
||||
}
|
||||
ngDevMode && assertLView(lView);
|
||||
return lView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the `RootContext` instance that is associated with
|
||||
* the application where the target is situated. It does this by walking the parent views until it
|
||||
* gets to the root view, then getting the context off of that.
|
||||
*
|
||||
* @param viewOrComponent the `LView` or component to get the root context for.
|
||||
*/
|
||||
export function getRootContext(viewOrComponent: LView | {}): RootContext {
|
||||
const rootView = getRootView(viewOrComponent);
|
||||
ngDevMode &&
|
||||
assertDefined(rootView[CONTEXT], 'RootView has no context. Perhaps it is disconnected?');
|
||||
return rootView[CONTEXT] as RootContext;
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
* @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 {assertDataInRange, assertDefined, assertGreaterThan, assertLessThan} from '../../util/assert';
|
||||
import {LCONTAINER_LENGTH, LContainer} from '../interfaces/container';
|
||||
import {LContext, MONKEY_PATCH_KEY_NAME} from '../interfaces/context';
|
||||
import {ComponentDef, DirectiveDef} from '../interfaces/definition';
|
||||
import {TNode, TNodeFlags} from '../interfaces/node';
|
||||
import {RComment, RElement, RText} from '../interfaces/renderer';
|
||||
import {FLAGS, HEADER_OFFSET, HOST, LView, LViewFlags, TData, TVIEW} from '../interfaces/view';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Takes the value of a slot in `LView` and returns the element node.
|
||||
*
|
||||
* Normally, element nodes are stored flat, but if the node has styles/classes on it,
|
||||
* it might be wrapped in a styling context. Or if that node has a directive that injects
|
||||
* ViewContainerRef, it may be wrapped in an LContainer. Or if that node is a component,
|
||||
* it will be wrapped in LView. It could even have all three, so we keep looping
|
||||
* until we find something that isn't an array.
|
||||
*
|
||||
* @param value The initial value in `LView`
|
||||
*/
|
||||
export function readElementValue(value: any): RElement {
|
||||
while (Array.isArray(value)) {
|
||||
value = value[HOST] as any;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an element value from the provided `viewData`, by unwrapping
|
||||
* from any containers, component views, or style contexts.
|
||||
*/
|
||||
export function getNativeByIndex(index: number, lView: LView): RElement {
|
||||
return readElementValue(lView[index + HEADER_OFFSET]);
|
||||
}
|
||||
|
||||
export function getNativeByTNode(tNode: TNode, hostView: LView): RElement|RText|RComment {
|
||||
return readElementValue(hostView[tNode.index]);
|
||||
}
|
||||
|
||||
export function getTNode(index: number, view: LView): TNode {
|
||||
ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
|
||||
ngDevMode && assertLessThan(index, view[TVIEW].data.length, 'wrong index for TNode');
|
||||
return view[TVIEW].data[index + HEADER_OFFSET] as TNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the value is an {@link LView}
|
||||
* @param value the value to check
|
||||
*/
|
||||
export function isLView(value: any): value is LView {
|
||||
return Array.isArray(value) && value.length >= HEADER_OFFSET;
|
||||
}
|
||||
|
||||
/** Retrieves a value from any `LView` or `TData`. */
|
||||
export function loadInternal<T>(view: LView | TData, index: number): T {
|
||||
ngDevMode && assertDataInRange(view, index + HEADER_OFFSET);
|
||||
return view[index + HEADER_OFFSET];
|
||||
}
|
||||
|
||||
export function getComponentViewByIndex(nodeIndex: number, hostView: LView): LView {
|
||||
// Could be an LView or an LContainer. If LContainer, unwrap to find LView.
|
||||
const slotValue = hostView[nodeIndex];
|
||||
const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
|
||||
return lView;
|
||||
}
|
||||
|
||||
export function isContentQueryHost(tNode: TNode): boolean {
|
||||
return (tNode.flags & TNodeFlags.hasContentQuery) !== 0;
|
||||
}
|
||||
|
||||
export function isComponent(tNode: TNode): boolean {
|
||||
return (tNode.flags & TNodeFlags.isComponent) === TNodeFlags.isComponent;
|
||||
}
|
||||
|
||||
export function isComponentDef<T>(def: DirectiveDef<T>): def is ComponentDef<T> {
|
||||
return (def as ComponentDef<T>).template !== null;
|
||||
}
|
||||
|
||||
export function isLContainer(value: any): value is LContainer {
|
||||
// Styling contexts are also arrays, but their first index contains an element node
|
||||
return Array.isArray(value) && value.length === LCONTAINER_LENGTH;
|
||||
}
|
||||
|
||||
export function isRootView(target: LView): boolean {
|
||||
return (target[FLAGS] & LViewFlags.IsRoot) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the monkey-patch value data present on the target (which could be
|
||||
* a component, directive or a DOM node).
|
||||
*/
|
||||
export function readPatchedData(target: any): LView|LContext|null {
|
||||
ngDevMode && assertDefined(target, 'Target expected');
|
||||
return target[MONKEY_PATCH_KEY_NAME];
|
||||
}
|
||||
|
||||
export function readPatchedLView(target: any): LView|null {
|
||||
const value = readPatchedData(target);
|
||||
if (value) {
|
||||
return Array.isArray(value) ? value : (value as LContext).lView;
|
||||
}
|
||||
return null;
|
||||
}
|
|
@ -25,8 +25,11 @@ import {RComment, RElement, isProceduralRenderer} from './interfaces/renderer';
|
|||
import {CONTEXT, LView, QUERIES, RENDERER, TView, T_HOST} from './interfaces/view';
|
||||
import {assertNodeOfPossibleTypes} from './node_assert';
|
||||
import {addRemoveViewFromContainer, appendChild, detachView, getBeforeNodeForView, insertView, nativeInsertBefore, nativeNextSibling, nativeParentNode, removeView} from './node_manipulation';
|
||||
import {getParentInjectorTNode} from './node_util';
|
||||
import {getLView, getPreviousOrParentTNode} from './state';
|
||||
import {findComponentView, getComponentViewByIndex, getNativeByTNode, getParentInjectorTNode, getParentInjectorView, hasParentInjector, isComponent, isLContainer, isRootView} from './util';
|
||||
import {getParentInjectorView, hasParentInjector} from './util/injector_utils';
|
||||
import {findComponentView} from './util/view_traversal_utils';
|
||||
import {getComponentViewByIndex, getNativeByTNode, isComponent, isLContainer, isRootView} from './util/view_utils';
|
||||
import {ViewRef} from './view_ref';
|
||||
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@ import {checkNoChangesInRootView, checkNoChangesInternal, detectChangesInRootVie
|
|||
import {TNode, TNodeType, TViewNode} from './interfaces/node';
|
||||
import {FLAGS, HOST, LView, LViewFlags, PARENT, T_HOST} from './interfaces/view';
|
||||
import {destroyLView} from './node_manipulation';
|
||||
import {getLViewParent, getNativeByTNode} from './util';
|
||||
import {getLViewParent} from './util/view_traversal_utils';
|
||||
import {getNativeByTNode} from './util/view_utils';
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import {SANITIZER} from '../render3/interfaces/view';
|
||||
import {getLView} from '../render3/state';
|
||||
import {renderStringify} from '../render3/util';
|
||||
import {renderStringify} from '../render3/util/misc_utils';
|
||||
|
||||
import {BypassType, allowSanitizationBypass} from './bypass';
|
||||
import {_sanitizeHtml as _sanitizeHtml} from './html_sanitizer';
|
||||
|
|
|
@ -16,7 +16,7 @@ import {ProvidersFeature, defineDirective, elementProperty, load, templateRefExt
|
|||
import {allocHostVars, bind, container, containerRefreshEnd, containerRefreshStart, createNodeAtIndex, createLView, createTView, directiveInject, element, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, injectAttribute, interpolation2, projection, projectionDef, reference, template, text, textBinding, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
|
||||
import {isProceduralRenderer, RElement} from '../../src/render3/interfaces/renderer';
|
||||
import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node';
|
||||
import {getNativeByIndex} from '../../src/render3/util';
|
||||
import {getNativeByIndex} from '../../src/render3/util/view_utils';
|
||||
import {LViewFlags} from '../../src/render3/interfaces/view';
|
||||
import {enterView, leaveView, getLView} from '../../src/render3/state';
|
||||
import {ViewRef} from '../../src/render3/view_ref';
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
*/
|
||||
import {StaticInjector} from '../../src/di/injector';
|
||||
import {createInjector} from '../../src/di/r3_injector';
|
||||
import {getComponent, getContext, getDirectives, getInjectionTokens, getInjector, getListeners, getLocalRefs, getRootComponents, getViewComponent, loadLContext} from '../../src/render3/discovery_utils';
|
||||
import {ProvidersFeature, RenderFlags, defineComponent, defineDirective, elementContainerEnd, elementContainerStart, getHostElement, i18n, i18nApply, i18nExp} from '../../src/render3/index';
|
||||
import {getComponent, getContext, getDirectives, getInjectionTokens, getInjector, getListeners, getLocalRefs, getRootComponents, getViewComponent, loadLContext} from '../../src/render3/util/discovery_utils';
|
||||
|
||||
import {element, elementEnd, elementStart, elementStyling, elementStylingApply, template, bind, elementProperty, text, textBinding, markDirty, listener} from '../../src/render3/instructions';
|
||||
import {ComponentFixture} from './render_util';
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
*/
|
||||
import {ɵmarkDirty as markDirty} from '@angular/core';
|
||||
|
||||
import {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent} from '../../src/render3/discovery_utils';
|
||||
import {GLOBAL_PUBLISH_EXPANDO_KEY, GlobalDevModeContainer, publishDefaultGlobalUtils, publishGlobalUtil} from '../../src/render3/global_utils';
|
||||
import {getPlayers} from '../../src/render3/players';
|
||||
import {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent} from '../../src/render3/util/discovery_utils';
|
||||
import {GLOBAL_PUBLISH_EXPANDO_KEY, GlobalDevModeContainer, publishDefaultGlobalUtils, publishGlobalUtil} from '../../src/render3/util/global_utils';
|
||||
import {global} from '../../src/util/global';
|
||||
|
||||
describe('global utils', () => {
|
||||
|
|
|
@ -12,7 +12,7 @@ import {defineComponent, defineDirective} from '../../src/render3/definition';
|
|||
import {getTranslationForTemplate, i18n, i18nApply, i18nAttributes, i18nEnd, i18nExp, i18nPostprocess, i18nStart} from '../../src/render3/i18n';
|
||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||
import {AttributeMarker} from '../../src/render3/interfaces/node';
|
||||
import {getNativeByIndex, getTNode} from '../../src/render3/util';
|
||||
import {getNativeByIndex, getTNode} from '../../src/render3/util/view_utils';
|
||||
import {NgIf} from './common_with_def';
|
||||
import {allocHostVars, element, elementEnd, elementStart, template, text, nextContext, bind, elementProperty, projectionDef, projection, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
|
||||
import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nUpdateOpCode, I18nUpdateOpCodes, TI18n} from '../../src/render3/interfaces/i18n';
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
import {Component as _Component, ComponentFactoryResolver, ElementRef, InjectFlags, Injectable as _Injectable, InjectionToken, InjectorType, Provider, RendererFactory2, ViewContainerRef, defineInjectable, defineInjector, inject, ɵNgModuleDef as NgModuleDef} from '../../src/core';
|
||||
import {forwardRef} from '../../src/di/forward_ref';
|
||||
import {createInjector} from '../../src/di/r3_injector';
|
||||
import {getInjector} from '../../src/render3/discovery_utils';
|
||||
import {ProvidersFeature, defineComponent, defineDirective, directiveInject, injectComponentFactoryResolver} from '../../src/render3/index';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, text, textBinding} from '../../src/render3/instructions';
|
||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||
import {NgModuleFactory} from '../../src/render3/ng_module_ref';
|
||||
import {getInjector} from '../../src/render3/util/discovery_utils';
|
||||
|
||||
import {getRendererFactory2} from './imported_renderer2';
|
||||
import {ComponentFixture} from './render_util';
|
||||
|
|
|
@ -11,7 +11,7 @@ import {ElementRef, QueryList, TemplateRef, ViewContainerRef} from '@angular/cor
|
|||
|
||||
import {EventEmitter} from '../..';
|
||||
import {AttributeMarker, ProvidersFeature, defineComponent, defineDirective, detectChanges} from '../../src/render3/index';
|
||||
import {getNativeByIndex} from '../../src/render3/util';
|
||||
import {getNativeByIndex} from '../../src/render3/util/view_utils';
|
||||
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, directiveInject, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, reference, template, text} from '../../src/render3/instructions';
|
||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||
|
|
|
@ -33,7 +33,7 @@ import {PlayerHandler} from '../../src/render3/interfaces/player';
|
|||
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, RendererStyleFlags3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
|
||||
import {HEADER_OFFSET, LView} from '../../src/render3/interfaces/view';
|
||||
import {destroyLView} from '../../src/render3/node_manipulation';
|
||||
import {getRootView} from '../../src/render3/util';
|
||||
import {getRootView} from '../../src/render3/util/view_traversal_utils';
|
||||
import {Sanitizer} from '../../src/sanitization/security';
|
||||
|
||||
import {getRendererFactory2} from './imported_renderer2';
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
import {devModeEqual} from '@angular/core/src/change_detection/change_detection_util';
|
||||
|
||||
import {flatten, isDifferent} from '../../src/render3/util';
|
||||
import {flatten} from '../../src/render3/util/array_utils';
|
||||
import {isDifferent} from '../../src/render3/util/misc_utils';
|
||||
|
||||
describe('util', () => {
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import {RElement} from '../../src/render3/interfaces/renderer';
|
|||
import {NgModuleFactory} from '../../src/render3/ng_module_ref';
|
||||
import {pipe, pipeBind1} from '../../src/render3/pipe';
|
||||
import {getLView} from '../../src/render3/state';
|
||||
import {getNativeByIndex} from '../../src/render3/util';
|
||||
import {getNativeByIndex} from '../../src/render3/util/view_utils';
|
||||
import {templateRefExtractor} from '../../src/render3/view_engine_compatibility_prebound';
|
||||
import {NgForOf} from '../../test/render3/common_with_def';
|
||||
|
||||
|
|
Loading…
Reference in New Issue