This reverts commit 18b33e79d3
.
PR Close #41901
This commit is contained in:
parent
0dfd940a18
commit
2dd96e08ae
|
@ -3,7 +3,7 @@
|
||||||
"master": {
|
"master": {
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime-es2015": 1170,
|
"runtime-es2015": 1170,
|
||||||
"main-es2015": 138718,
|
"main-es2015": 138189,
|
||||||
"polyfills-es2015": 36964
|
"polyfills-es2015": 36964
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
"master": {
|
"master": {
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime-es2015": 1190,
|
"runtime-es2015": 1190,
|
||||||
"main-es2015": 137087,
|
"main-es2015": 136546,
|
||||||
"polyfills-es2015": 37641
|
"polyfills-es2015": 37641
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,10 +262,9 @@ class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugEleme
|
||||||
}
|
}
|
||||||
|
|
||||||
get name(): string {
|
get name(): string {
|
||||||
const context = getLContext(this.nativeNode)!;
|
const context = getLContext(this.nativeNode);
|
||||||
const lView = context ? context.lView : null;
|
if (context !== null) {
|
||||||
|
const lView = context.lView;
|
||||||
if (lView !== null) {
|
|
||||||
const tData = lView[TVIEW].data;
|
const tData = lView[TVIEW].data;
|
||||||
const tNode = tData[context.nodeIndex] as TNode;
|
const tNode = tData[context.nodeIndex] as TNode;
|
||||||
return tNode.value!;
|
return tNode.value!;
|
||||||
|
@ -287,13 +286,12 @@ class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugEleme
|
||||||
* - attribute bindings (e.g. `[attr.role]="menu"`)
|
* - attribute bindings (e.g. `[attr.role]="menu"`)
|
||||||
*/
|
*/
|
||||||
get properties(): {[key: string]: any;} {
|
get properties(): {[key: string]: any;} {
|
||||||
const context = getLContext(this.nativeNode)!;
|
const context = getLContext(this.nativeNode);
|
||||||
const lView = context ? context.lView : null;
|
if (context === null) {
|
||||||
|
|
||||||
if (lView === null) {
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lView = context.lView;
|
||||||
const tData = lView[TVIEW].data;
|
const tData = lView[TVIEW].data;
|
||||||
const tNode = tData[context.nodeIndex] as TNode;
|
const tNode = tData[context.nodeIndex] as TNode;
|
||||||
|
|
||||||
|
@ -314,13 +312,12 @@ class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugEleme
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = getLContext(element)!;
|
const context = getLContext(element);
|
||||||
const lView = context ? context.lView : null;
|
if (context === null) {
|
||||||
|
|
||||||
if (lView === null) {
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lView = context.lView;
|
||||||
const tNodeAttrs = (lView[TVIEW].data[context.nodeIndex] as TNode).attrs;
|
const tNodeAttrs = (lView[TVIEW].data[context.nodeIndex] as TNode).attrs;
|
||||||
const lowercaseTNodeAttrs: string[] = [];
|
const lowercaseTNodeAttrs: string[] = [];
|
||||||
|
|
||||||
|
@ -505,12 +502,11 @@ function _queryAllR3(
|
||||||
function _queryAllR3(
|
function _queryAllR3(
|
||||||
parentElement: DebugElement, predicate: Predicate<DebugElement>|Predicate<DebugNode>,
|
parentElement: DebugElement, predicate: Predicate<DebugElement>|Predicate<DebugNode>,
|
||||||
matches: DebugElement[]|DebugNode[], elementsOnly: boolean) {
|
matches: DebugElement[]|DebugNode[], elementsOnly: boolean) {
|
||||||
const context = getLContext(parentElement.nativeNode)!;
|
const context = getLContext(parentElement.nativeNode);
|
||||||
const lView = context ? context.lView : null;
|
if (context !== null) {
|
||||||
if (lView !== null) {
|
const parentTNode = context.lView[TVIEW].data[context.nodeIndex] as TNode;
|
||||||
const parentTNode = lView[TVIEW].data[context.nodeIndex] as TNode;
|
|
||||||
_queryNodeChildrenR3(
|
_queryNodeChildrenR3(
|
||||||
parentTNode, lView, predicate, matches, elementsOnly, parentElement.nativeNode);
|
parentTNode, context.lView, predicate, matches, elementsOnly, parentElement.nativeNode);
|
||||||
} else {
|
} else {
|
||||||
// If the context is null, then `parentElement` was either created with Renderer2 or native DOM
|
// If the context is null, then `parentElement` was either created with Renderer2 or native DOM
|
||||||
// APIs.
|
// APIs.
|
||||||
|
|
|
@ -8,15 +8,12 @@
|
||||||
import '../util/ng_dev_mode';
|
import '../util/ng_dev_mode';
|
||||||
|
|
||||||
import {assertDefined, assertDomNode} from '../util/assert';
|
import {assertDefined, assertDomNode} from '../util/assert';
|
||||||
import {EMPTY_ARRAY} from '../util/empty';
|
|
||||||
|
|
||||||
import {assertLView} from './assert';
|
import {EMPTY_ARRAY} from '../util/empty';
|
||||||
import {LContext} from './interfaces/context';
|
import {LContext} from './interfaces/context';
|
||||||
import {getLViewById} from './interfaces/lview_tracking';
|
|
||||||
import {TNode, TNodeFlags} from './interfaces/node';
|
import {TNode, TNodeFlags} from './interfaces/node';
|
||||||
import {RElement, RNode} from './interfaces/renderer_dom';
|
import {RElement, RNode} from './interfaces/renderer_dom';
|
||||||
import {isLView} from './interfaces/type_checks';
|
import {CONTEXT, HEADER_OFFSET, HOST, LView, TVIEW} from './interfaces/view';
|
||||||
import {CONTEXT, HEADER_OFFSET, HOST, ID, LView, TVIEW} from './interfaces/view';
|
|
||||||
import {getComponentLViewByIndex, unwrapRNode} from './util/view_utils';
|
import {getComponentLViewByIndex, unwrapRNode} from './util/view_utils';
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +43,7 @@ export function getLContext(target: any): LContext|null {
|
||||||
if (mpValue) {
|
if (mpValue) {
|
||||||
// only when it's an array is it considered an LView instance
|
// only when it's an array is it considered an LView instance
|
||||||
// ... otherwise it's an already constructed LContext instance
|
// ... otherwise it's an already constructed LContext instance
|
||||||
if (isLView(mpValue)) {
|
if (Array.isArray(mpValue)) {
|
||||||
const lView: LView = mpValue!;
|
const lView: LView = mpValue!;
|
||||||
let nodeIndex: number;
|
let nodeIndex: number;
|
||||||
let component: any = undefined;
|
let component: any = undefined;
|
||||||
|
@ -108,7 +105,12 @@ export function getLContext(target: any): LContext|null {
|
||||||
while (parent = parent.parentNode) {
|
while (parent = parent.parentNode) {
|
||||||
const parentContext = readPatchedData(parent);
|
const parentContext = readPatchedData(parent);
|
||||||
if (parentContext) {
|
if (parentContext) {
|
||||||
const lView = Array.isArray(parentContext) ? parentContext as LView : parentContext.lView;
|
let lView: LView|null;
|
||||||
|
if (Array.isArray(parentContext)) {
|
||||||
|
lView = parentContext as LView;
|
||||||
|
} else {
|
||||||
|
lView = parentContext.lView;
|
||||||
|
}
|
||||||
|
|
||||||
// the edge of the app was also reached here through another means
|
// the edge of the app was also reached here through another means
|
||||||
// (maybe because the DOM was changed manually).
|
// (maybe because the DOM was changed manually).
|
||||||
|
@ -134,7 +136,14 @@ export function getLContext(target: any): LContext|null {
|
||||||
* Creates an empty instance of a `LContext` context
|
* Creates an empty instance of a `LContext` context
|
||||||
*/
|
*/
|
||||||
function createLContext(lView: LView, nodeIndex: number, native: RNode): LContext {
|
function createLContext(lView: LView, nodeIndex: number, native: RNode): LContext {
|
||||||
return new LContext(lView[ID], nodeIndex, native);
|
return {
|
||||||
|
lView,
|
||||||
|
nodeIndex,
|
||||||
|
native,
|
||||||
|
component: undefined,
|
||||||
|
directives: undefined,
|
||||||
|
localRefs: undefined,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,24 +153,21 @@ function createLContext(lView: LView, nodeIndex: number, native: RNode): LContex
|
||||||
* @returns The component's view
|
* @returns The component's view
|
||||||
*/
|
*/
|
||||||
export function getComponentViewByInstance(componentInstance: {}): LView {
|
export function getComponentViewByInstance(componentInstance: {}): LView {
|
||||||
let patchedData = readPatchedData(componentInstance);
|
let lView = readPatchedData(componentInstance);
|
||||||
let lView: LView;
|
let view: LView;
|
||||||
|
|
||||||
if (isLView(patchedData)) {
|
if (Array.isArray(lView)) {
|
||||||
const contextLView: LView = patchedData;
|
const nodeIndex = findViaComponent(lView, componentInstance);
|
||||||
const nodeIndex = findViaComponent(contextLView, componentInstance);
|
view = getComponentLViewByIndex(nodeIndex, lView);
|
||||||
lView = getComponentLViewByIndex(nodeIndex, contextLView);
|
const context = createLContext(lView, nodeIndex, view[HOST] as RElement);
|
||||||
const context = createLContext(contextLView, nodeIndex, lView[HOST] as RElement);
|
|
||||||
context.component = componentInstance;
|
context.component = componentInstance;
|
||||||
attachPatchData(componentInstance, context);
|
attachPatchData(componentInstance, context);
|
||||||
attachPatchData(context.native, context);
|
attachPatchData(context.native, context);
|
||||||
} else {
|
} else {
|
||||||
const context = patchedData as unknown as LContext;
|
const context = lView as any as LContext;
|
||||||
const contextLView = context.lView!;
|
view = getComponentLViewByIndex(context.nodeIndex, context.lView);
|
||||||
ngDevMode && assertLView(contextLView);
|
|
||||||
lView = getComponentLViewByIndex(context.nodeIndex, contextLView);
|
|
||||||
}
|
}
|
||||||
return lView;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,10 +181,7 @@ const MONKEY_PATCH_KEY_NAME = '__ngContext__';
|
||||||
*/
|
*/
|
||||||
export function attachPatchData(target: any, data: LView|LContext) {
|
export function attachPatchData(target: any, data: LView|LContext) {
|
||||||
ngDevMode && assertDefined(target, 'Target expected');
|
ngDevMode && assertDefined(target, 'Target expected');
|
||||||
// Only attach the ID of the view in order to avoid memory leaks (see #41047). We only do this
|
target[MONKEY_PATCH_KEY_NAME] = data;
|
||||||
// for `LView`, because we have control over when an `LView` is created and destroyed, whereas
|
|
||||||
// we can't know when to remove an `LContext`.
|
|
||||||
target[MONKEY_PATCH_KEY_NAME] = isLView(data) ? data[ID] : data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -187,14 +190,13 @@ export function attachPatchData(target: any, data: LView|LContext) {
|
||||||
*/
|
*/
|
||||||
export function readPatchedData(target: any): LView|LContext|null {
|
export function readPatchedData(target: any): LView|LContext|null {
|
||||||
ngDevMode && assertDefined(target, 'Target expected');
|
ngDevMode && assertDefined(target, 'Target expected');
|
||||||
const data = target[MONKEY_PATCH_KEY_NAME];
|
return target[MONKEY_PATCH_KEY_NAME] || null;
|
||||||
return (typeof data === 'number') ? getLViewById(data) : data || null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readPatchedLView(target: any): LView|null {
|
export function readPatchedLView(target: any): LView|null {
|
||||||
const value = readPatchedData(target);
|
const value = readPatchedData(target);
|
||||||
if (value) {
|
if (value) {
|
||||||
return isLView(value) ? value : value.lView;
|
return Array.isArray(value) ? value : (value as LContext).lView;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {LQueries, TQueries} from '../interfaces/query';
|
||||||
import {Renderer3, RendererFactory3} from '../interfaces/renderer';
|
import {Renderer3, RendererFactory3} from '../interfaces/renderer';
|
||||||
import {RComment, RElement, RNode} from '../interfaces/renderer_dom';
|
import {RComment, RElement, RNode} from '../interfaces/renderer_dom';
|
||||||
import {getTStylingRangeNext, getTStylingRangeNextDuplicate, getTStylingRangePrev, getTStylingRangePrevDuplicate, TStylingKey, TStylingRange} from '../interfaces/styling';
|
import {getTStylingRangeNext, getTStylingRangeNextDuplicate, getTStylingRangePrev, getTStylingRangePrevDuplicate, TStylingKey, TStylingRange} from '../interfaces/styling';
|
||||||
import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DebugNode, DECLARATION_VIEW, DestroyHookData, FLAGS, HEADER_OFFSET, HookData, HOST, HostBindingOpCodes, ID, INJECTOR, LContainerDebug as ILContainerDebug, LView, LViewDebug as ILViewDebug, LViewDebugRange, LViewDebugRangeContent, LViewFlags, NEXT, NodeInjectorDebug, 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, NodeInjectorDebug, 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 {attachDebugObject} from '../util/debug_utils';
|
||||||
import {getParentInjectorIndex, getParentInjectorView} from '../util/injector_utils';
|
import {getParentInjectorIndex, getParentInjectorView} from '../util/injector_utils';
|
||||||
import {unwrapRNode} from '../util/view_utils';
|
import {unwrapRNode} from '../util/view_utils';
|
||||||
|
@ -513,9 +513,6 @@ export class LViewDebug implements ILViewDebug {
|
||||||
get tHost(): ITNode|null {
|
get tHost(): ITNode|null {
|
||||||
return this._raw_lView[T_HOST];
|
return this._raw_lView[T_HOST];
|
||||||
}
|
}
|
||||||
get id(): number {
|
|
||||||
return this._raw_lView[ID];
|
|
||||||
}
|
|
||||||
|
|
||||||
get decls(): LViewDebugRange {
|
get decls(): LViewDebugRange {
|
||||||
return toLViewRange(this.tView, this._raw_lView, HEADER_OFFSET, this.tView.bindingStartIndex);
|
return toLViewRange(this.tView, this._raw_lView, HEADER_OFFSET, this.tView.bindingStartIndex);
|
||||||
|
|
|
@ -28,13 +28,12 @@ import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags} fr
|
||||||
import {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS} from '../interfaces/container';
|
import {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS} from '../interfaces/container';
|
||||||
import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, HostBindingsFunction, PipeDefListOrFactory, RenderFlags, ViewQueriesFunction} from '../interfaces/definition';
|
import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, HostBindingsFunction, PipeDefListOrFactory, RenderFlags, ViewQueriesFunction} from '../interfaces/definition';
|
||||||
import {NodeInjectorFactory} from '../interfaces/injector';
|
import {NodeInjectorFactory} from '../interfaces/injector';
|
||||||
import {registerLView} from '../interfaces/lview_tracking';
|
|
||||||
import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliases, PropertyAliasValue, TAttributes, TConstantsOrFactory, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode} from '../interfaces/node';
|
import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliases, PropertyAliasValue, TAttributes, TConstantsOrFactory, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode} from '../interfaces/node';
|
||||||
import {isProceduralRenderer, Renderer3, RendererFactory3} from '../interfaces/renderer';
|
import {isProceduralRenderer, Renderer3, RendererFactory3} from '../interfaces/renderer';
|
||||||
import {RComment, RElement, RNode, RText} from '../interfaces/renderer_dom';
|
import {RComment, RElement, RNode, RText} from '../interfaces/renderer_dom';
|
||||||
import {SanitizerFn} from '../interfaces/sanitization';
|
import {SanitizerFn} from '../interfaces/sanitization';
|
||||||
import {isComponentDef, isComponentHost, isContentQueryHost, isRootView} from '../interfaces/type_checks';
|
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, HostBindingOpCodes, ID, 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 {assertPureTNodeType, assertTNodeType} from '../node_assert';
|
||||||
import {updateTextNode} from '../node_manipulation';
|
import {updateTextNode} from '../node_manipulation';
|
||||||
import {isInlineTemplate, isNodeMatchingSelectorList} from '../node_selector_matcher';
|
import {isInlineTemplate, isNodeMatchingSelectorList} from '../node_selector_matcher';
|
||||||
|
@ -144,7 +143,6 @@ export function createLView<T>(
|
||||||
lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null!;
|
lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null!;
|
||||||
lView[INJECTOR as any] = injector || parentLView && parentLView[INJECTOR] || null;
|
lView[INJECTOR as any] = injector || parentLView && parentLView[INJECTOR] || null;
|
||||||
lView[T_HOST] = tHostNode;
|
lView[T_HOST] = tHostNode;
|
||||||
lView[ID] = registerLView(lView);
|
|
||||||
ngDevMode &&
|
ngDevMode &&
|
||||||
assertEqual(
|
assertEqual(
|
||||||
tView.type == TViewType.Embedded ? parentLView !== null : true, true,
|
tView.type == TViewType.Embedded ? parentLView !== null : true, true,
|
||||||
|
@ -1908,12 +1906,9 @@ export function scheduleTick(rootContext: RootContext, flags: RootContextFlags)
|
||||||
export function tickRootContext(rootContext: RootContext) {
|
export function tickRootContext(rootContext: RootContext) {
|
||||||
for (let i = 0; i < rootContext.components.length; i++) {
|
for (let i = 0; i < rootContext.components.length; i++) {
|
||||||
const rootComponent = rootContext.components[i];
|
const rootComponent = rootContext.components[i];
|
||||||
const lView = readPatchedLView(rootComponent);
|
const lView = readPatchedLView(rootComponent)!;
|
||||||
// We might not have an `LView` if the component was destroyed.
|
const tView = lView[TVIEW];
|
||||||
if (lView !== null) {
|
renderComponentOrTemplate(tView, lView, tView.template, rootComponent);
|
||||||
const tView = lView[TVIEW];
|
|
||||||
renderComponentOrTemplate(tView, lView, tView.template, rootComponent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import {getLViewById} from './lview_tracking';
|
|
||||||
import {RNode} from './renderer_dom';
|
import {RNode} from './renderer_dom';
|
||||||
import {LView} from './view';
|
import {LView} from './view';
|
||||||
|
|
||||||
|
@ -22,41 +21,35 @@ import {LView} from './view';
|
||||||
* function. The component, element and each directive instance will share the same instance
|
* function. The component, element and each directive instance will share the same instance
|
||||||
* of the context.
|
* of the context.
|
||||||
*/
|
*/
|
||||||
export class LContext {
|
export interface LContext {
|
||||||
|
/**
|
||||||
|
* The component's parent view data.
|
||||||
|
*/
|
||||||
|
lView: LView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index instance of the node.
|
||||||
|
*/
|
||||||
|
nodeIndex: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instance of the DOM node that is attached to the lNode.
|
||||||
|
*/
|
||||||
|
native: RNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The instance of the Component node.
|
* The instance of the Component node.
|
||||||
*/
|
*/
|
||||||
public component: {}|null|undefined;
|
component: {}|null|undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of active directives that exist on this element.
|
* The list of active directives that exist on this element.
|
||||||
*/
|
*/
|
||||||
public directives: any[]|null|undefined;
|
directives: any[]|null|undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The map of local references (local reference name => element or directive instance) that
|
* The map of local references (local reference name => element or directive instance) that exist
|
||||||
* exist on this element.
|
* on this element.
|
||||||
*/
|
*/
|
||||||
public localRefs: {[key: string]: any}|null|undefined;
|
localRefs: {[key: string]: any}|null|undefined;
|
||||||
|
|
||||||
/** Component's parent view data. */
|
|
||||||
get lView(): LView|null {
|
|
||||||
return getLViewById(this.lViewId);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
/**
|
|
||||||
* ID of the component's parent view data.
|
|
||||||
*/
|
|
||||||
private lViewId: number,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The index instance of the node.
|
|
||||||
*/
|
|
||||||
public nodeIndex: number,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The instance of the DOM node that is attached to the lNode.
|
|
||||||
*/
|
|
||||||
public native: RNode) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC 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 {assertNumber} from '../../util/assert';
|
|
||||||
import {ID, LView} from './view';
|
|
||||||
|
|
||||||
// Keeps track of the currently-active LViews.
|
|
||||||
const TRACKED_LVIEWS = new Map<number, LView>();
|
|
||||||
|
|
||||||
// Used for generating unique IDs for LViews.
|
|
||||||
let uniqueIdCounter = 0;
|
|
||||||
|
|
||||||
/** Starts tracking an LView and returns a unique ID that can be used for future lookups. */
|
|
||||||
export function registerLView(lView: LView): number {
|
|
||||||
const id = uniqueIdCounter++;
|
|
||||||
TRACKED_LVIEWS.set(id, lView);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets an LView by its unique ID. */
|
|
||||||
export function getLViewById(id: number): LView|null {
|
|
||||||
ngDevMode && assertNumber(id, 'ID used for LView lookup must be a number');
|
|
||||||
return TRACKED_LVIEWS.get(id) || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Stops tracking an LView. */
|
|
||||||
export function unregisterLView(lView: LView): void {
|
|
||||||
ngDevMode && assertNumber(lView[ID], 'Cannot stop tracking an LView that does not have an ID');
|
|
||||||
TRACKED_LVIEWS.delete(lView[ID]);
|
|
||||||
}
|
|
|
@ -47,7 +47,6 @@ export const DECLARATION_COMPONENT_VIEW = 16;
|
||||||
export const DECLARATION_LCONTAINER = 17;
|
export const DECLARATION_LCONTAINER = 17;
|
||||||
export const PREORDER_HOOK_FLAGS = 18;
|
export const PREORDER_HOOK_FLAGS = 18;
|
||||||
export const QUERIES = 19;
|
export const QUERIES = 19;
|
||||||
export const ID = 20;
|
|
||||||
/**
|
/**
|
||||||
* Size of LView's header. Necessary to adjust for it when setting slots.
|
* Size of LView's header. Necessary to adjust for it when setting slots.
|
||||||
*
|
*
|
||||||
|
@ -55,7 +54,7 @@ export const ID = 20;
|
||||||
* instruction index into `LView` index. All other indexes should be in the `LView` index space and
|
* instruction index into `LView` index. All other indexes should be in the `LView` index space and
|
||||||
* there should be no need to refer to `HEADER_OFFSET` anywhere else.
|
* there should be no need to refer to `HEADER_OFFSET` anywhere else.
|
||||||
*/
|
*/
|
||||||
export const HEADER_OFFSET = 21;
|
export const HEADER_OFFSET = 20;
|
||||||
|
|
||||||
|
|
||||||
// This interface replaces the real LView interface if it is an arg or a
|
// This interface replaces the real LView interface if it is an arg or a
|
||||||
|
@ -327,9 +326,6 @@ export interface LView extends Array<any> {
|
||||||
* are not `Dirty`/`CheckAlways`.
|
* are not `Dirty`/`CheckAlways`.
|
||||||
*/
|
*/
|
||||||
[TRANSPLANTED_VIEWS_TO_REFRESH]: number;
|
[TRANSPLANTED_VIEWS_TO_REFRESH]: number;
|
||||||
|
|
||||||
/** Unique ID of the view. Used for `__ngContext__` lookups in the `LView` registry. */
|
|
||||||
[ID]: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Flags associated with an LView (saved in LView[FLAGS]) */
|
/** Flags associated with an LView (saved in LView[FLAGS]) */
|
||||||
|
|
|
@ -19,7 +19,6 @@ import {icuContainerIterate} from './i18n/i18n_tree_shaking';
|
||||||
import {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS, NATIVE, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
|
import {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS, NATIVE, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
|
||||||
import {ComponentDef} from './interfaces/definition';
|
import {ComponentDef} from './interfaces/definition';
|
||||||
import {NodeInjectorFactory} from './interfaces/injector';
|
import {NodeInjectorFactory} from './interfaces/injector';
|
||||||
import {unregisterLView} from './interfaces/lview_tracking';
|
|
||||||
import {TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
|
import {TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
|
||||||
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
|
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
|
||||||
import {isProceduralRenderer, ProceduralRenderer3, Renderer3, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
import {isProceduralRenderer, ProceduralRenderer3, Renderer3, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
||||||
|
@ -396,7 +395,6 @@ export function destroyLView(tView: TView, lView: LView) {
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyViewTree(lView);
|
destroyViewTree(lView);
|
||||||
unregisterLView(lView);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {Injector} from '../../di/injector';
|
||||||
import {ViewEncapsulation} from '../../metadata/view';
|
import {ViewEncapsulation} from '../../metadata/view';
|
||||||
import {assertEqual} from '../../util/assert';
|
import {assertEqual} from '../../util/assert';
|
||||||
import {assertLView} from '../assert';
|
import {assertLView} from '../assert';
|
||||||
import {discoverLocalRefs, getComponentAtNodeIndex, getDirectivesAtNodeIndex, getLContext, readPatchedLView} from '../context_discovery';
|
import {discoverLocalRefs, getComponentAtNodeIndex, getDirectivesAtNodeIndex, getLContext} from '../context_discovery';
|
||||||
import {getComponentDef, getDirectiveDef} from '../definition';
|
import {getComponentDef, getDirectiveDef} from '../definition';
|
||||||
import {NodeInjector} from '../di';
|
import {NodeInjector} from '../di';
|
||||||
import {buildDebugNode} from '../instructions/lview_debug';
|
import {buildDebugNode} from '../instructions/lview_debug';
|
||||||
|
@ -20,7 +20,6 @@ import {DirectiveDef} from '../interfaces/definition';
|
||||||
import {TElementNode, TNode, TNodeProviderIndexes} from '../interfaces/node';
|
import {TElementNode, TNode, TNodeProviderIndexes} from '../interfaces/node';
|
||||||
import {isLView} from '../interfaces/type_checks';
|
import {isLView} from '../interfaces/type_checks';
|
||||||
import {CLEANUP, CONTEXT, DebugNode, FLAGS, LView, LViewFlags, T_HOST, TVIEW, TViewType} from '../interfaces/view';
|
import {CLEANUP, CONTEXT, DebugNode, FLAGS, LView, LViewFlags, T_HOST, TVIEW, TViewType} from '../interfaces/view';
|
||||||
|
|
||||||
import {stringifyForError} from './stringify_utils';
|
import {stringifyForError} from './stringify_utils';
|
||||||
import {getLViewParent, getRootContext} from './view_traversal_utils';
|
import {getLViewParent, getRootContext} from './view_traversal_utils';
|
||||||
import {getTNode, unwrapRNode} from './view_utils';
|
import {getTNode, unwrapRNode} from './view_utils';
|
||||||
|
@ -53,16 +52,12 @@ import {getTNode, unwrapRNode} from './view_utils';
|
||||||
* @globalApi ng
|
* @globalApi ng
|
||||||
*/
|
*/
|
||||||
export function getComponent<T>(element: Element): T|null {
|
export function getComponent<T>(element: Element): T|null {
|
||||||
ngDevMode && assertDomElement(element);
|
assertDomElement(element);
|
||||||
const context = getLContext(element);
|
const context = getLContext(element);
|
||||||
if (context === null) return null;
|
if (context === null) return null;
|
||||||
|
|
||||||
if (context.component === undefined) {
|
if (context.component === undefined) {
|
||||||
const lView = context.lView;
|
context.component = getComponentAtNodeIndex(context.nodeIndex, context.lView);
|
||||||
if (lView === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
context.component = getComponentAtNodeIndex(context.nodeIndex, lView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.component as T;
|
return context.component as T;
|
||||||
|
@ -83,9 +78,8 @@ export function getComponent<T>(element: Element): T|null {
|
||||||
*/
|
*/
|
||||||
export function getContext<T>(element: Element): T|null {
|
export function getContext<T>(element: Element): T|null {
|
||||||
assertDomElement(element);
|
assertDomElement(element);
|
||||||
const context = getLContext(element)!;
|
const context = getLContext(element);
|
||||||
const lView = context ? context.lView : null;
|
return context === null ? null : context.lView[CONTEXT] as T;
|
||||||
return lView === null ? null : lView[CONTEXT] as T;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,11 +98,12 @@ export function getContext<T>(element: Element): T|null {
|
||||||
* @globalApi ng
|
* @globalApi ng
|
||||||
*/
|
*/
|
||||||
export function getOwningComponent<T>(elementOrDir: Element|{}): T|null {
|
export function getOwningComponent<T>(elementOrDir: Element|{}): T|null {
|
||||||
const context = getLContext(elementOrDir)!;
|
const context = getLContext(elementOrDir);
|
||||||
let lView = context ? context.lView : null;
|
if (context === null) return null;
|
||||||
if (lView === null) return null;
|
|
||||||
|
|
||||||
|
let lView = context.lView;
|
||||||
let parent: LView|null;
|
let parent: LView|null;
|
||||||
|
ngDevMode && assertLView(lView);
|
||||||
while (lView[TVIEW].type === TViewType.Embedded && (parent = getLViewParent(lView)!)) {
|
while (lView[TVIEW].type === TViewType.Embedded && (parent = getLViewParent(lView)!)) {
|
||||||
lView = parent;
|
lView = parent;
|
||||||
}
|
}
|
||||||
|
@ -127,8 +122,7 @@ export function getOwningComponent<T>(elementOrDir: Element|{}): T|null {
|
||||||
* @globalApi ng
|
* @globalApi ng
|
||||||
*/
|
*/
|
||||||
export function getRootComponents(elementOrDir: Element|{}): {}[] {
|
export function getRootComponents(elementOrDir: Element|{}): {}[] {
|
||||||
const lView = readPatchedLView(elementOrDir);
|
return [...getRootContext(elementOrDir).components];
|
||||||
return lView !== null ? [...getRootContext(lView).components] : [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -142,12 +136,11 @@ export function getRootComponents(elementOrDir: Element|{}): {}[] {
|
||||||
* @globalApi ng
|
* @globalApi ng
|
||||||
*/
|
*/
|
||||||
export function getInjector(elementOrDir: Element|{}): Injector {
|
export function getInjector(elementOrDir: Element|{}): Injector {
|
||||||
const context = getLContext(elementOrDir)!;
|
const context = getLContext(elementOrDir);
|
||||||
const lView = context ? context.lView : null;
|
if (context === null) return Injector.NULL;
|
||||||
if (lView === null) return Injector.NULL;
|
|
||||||
|
|
||||||
const tNode = lView[TVIEW].data[context.nodeIndex] as TElementNode;
|
const tNode = context.lView[TVIEW].data[context.nodeIndex] as TElementNode;
|
||||||
return new NodeInjector(tNode, lView);
|
return new NodeInjector(tNode, context.lView);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,9 +149,9 @@ export function getInjector(elementOrDir: Element|{}): Injector {
|
||||||
* @param element Element for which the injection tokens should be retrieved.
|
* @param element Element for which the injection tokens should be retrieved.
|
||||||
*/
|
*/
|
||||||
export function getInjectionTokens(element: Element): any[] {
|
export function getInjectionTokens(element: Element): any[] {
|
||||||
const context = getLContext(element)!;
|
const context = getLContext(element);
|
||||||
const lView = context ? context.lView : null;
|
if (context === null) return [];
|
||||||
if (lView === null) return [];
|
const lView = context.lView;
|
||||||
const tView = lView[TVIEW];
|
const tView = lView[TVIEW];
|
||||||
const tNode = tView.data[context.nodeIndex] as TNode;
|
const tNode = tView.data[context.nodeIndex] as TNode;
|
||||||
const providerTokens: any[] = [];
|
const providerTokens: any[] = [];
|
||||||
|
@ -207,12 +200,12 @@ export function getDirectives(node: Node): {}[] {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = getLContext(node)!;
|
const context = getLContext(node);
|
||||||
const lView = context ? context.lView : null;
|
if (context === null) {
|
||||||
if (lView === null) {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lView = context.lView;
|
||||||
const tView = lView[TVIEW];
|
const tView = lView[TVIEW];
|
||||||
const nodeIndex = context.nodeIndex;
|
const nodeIndex = context.nodeIndex;
|
||||||
if (!tView?.data[nodeIndex]) {
|
if (!tView?.data[nodeIndex]) {
|
||||||
|
@ -304,11 +297,7 @@ export function getLocalRefs(target: {}): {[key: string]: any} {
|
||||||
if (context === null) return {};
|
if (context === null) return {};
|
||||||
|
|
||||||
if (context.localRefs === undefined) {
|
if (context.localRefs === undefined) {
|
||||||
const lView = context.lView;
|
context.localRefs = discoverLocalRefs(context.lView, context.nodeIndex);
|
||||||
if (lView === null) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
context.localRefs = discoverLocalRefs(lView, context.nodeIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.localRefs || {};
|
return context.localRefs || {};
|
||||||
|
@ -394,11 +383,11 @@ export interface Listener {
|
||||||
* @globalApi ng
|
* @globalApi ng
|
||||||
*/
|
*/
|
||||||
export function getListeners(element: Element): Listener[] {
|
export function getListeners(element: Element): Listener[] {
|
||||||
ngDevMode && assertDomElement(element);
|
assertDomElement(element);
|
||||||
const lContext = getLContext(element);
|
const lContext = getLContext(element);
|
||||||
const lView = lContext === null ? null : lContext.lView;
|
if (lContext === null) return [];
|
||||||
if (lView === null) return [];
|
|
||||||
|
|
||||||
|
const lView = lContext.lView;
|
||||||
const tView = lView[TVIEW];
|
const tView = lView[TVIEW];
|
||||||
const lCleanup = lView[CLEANUP];
|
const lCleanup = lView[CLEANUP];
|
||||||
const tCleanup = tView.cleanup;
|
const tCleanup = tView.cleanup;
|
||||||
|
@ -452,13 +441,12 @@ export function getDebugNode(element: Element): DebugNode|null {
|
||||||
throw new Error('Expecting instance of DOM Element');
|
throw new Error('Expecting instance of DOM Element');
|
||||||
}
|
}
|
||||||
|
|
||||||
const lContext = getLContext(element)!;
|
const lContext = getLContext(element);
|
||||||
const lView = lContext ? lContext.lView : null;
|
if (lContext === null) {
|
||||||
|
|
||||||
if (lView === null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lView = lContext.lView;
|
||||||
const nodeIndex = lContext.nodeIndex;
|
const nodeIndex = lContext.nodeIndex;
|
||||||
if (nodeIndex !== -1) {
|
if (nodeIndex !== -1) {
|
||||||
const valueInLView = lView[nodeIndex];
|
const valueInLView = lView[nodeIndex];
|
||||||
|
@ -485,8 +473,7 @@ export function getDebugNode(element: Element): DebugNode|null {
|
||||||
export function getComponentLView(target: any): LView {
|
export function getComponentLView(target: any): LView {
|
||||||
const lContext = getLContext(target)!;
|
const lContext = getLContext(target)!;
|
||||||
const nodeIndx = lContext.nodeIndex;
|
const nodeIndx = lContext.nodeIndex;
|
||||||
const lView = lContext.lView!;
|
const lView = lContext.lView;
|
||||||
ngDevMode && assertLView(lView);
|
|
||||||
const componentLView = lView[nodeIndx];
|
const componentLView = lView[nodeIndx];
|
||||||
ngDevMode && assertLView(componentLView);
|
ngDevMode && assertLView(componentLView);
|
||||||
return componentLView;
|
return componentLView;
|
||||||
|
|
|
@ -141,47 +141,6 @@ describe('component', () => {
|
||||||
expect(fixture.nativeElement.textContent.trim()).toBe('hello');
|
expect(fixture.nativeElement.textContent.trim()).toBe('hello');
|
||||||
});
|
});
|
||||||
|
|
||||||
onlyInIvy('ViewEngine has a specific error for this while Ivy does not')
|
|
||||||
.it('should not throw when calling `detectChanges` on the ChangeDetectorRef of a destroyed view',
|
|
||||||
() => {
|
|
||||||
@Component({template: 'hello'})
|
|
||||||
class HelloComponent {
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This module is only used to declare the `entryComponets` since
|
|
||||||
// `configureTestingModule` doesn't support it. The module can be removed
|
|
||||||
// once ViewEngine is removed.
|
|
||||||
@NgModule({
|
|
||||||
declarations: [HelloComponent],
|
|
||||||
exports: [HelloComponent],
|
|
||||||
entryComponents: [HelloComponent]
|
|
||||||
})
|
|
||||||
class HelloModule {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({template: `<div #insertionPoint></div>`})
|
|
||||||
class App {
|
|
||||||
@ViewChild('insertionPoint', {read: ViewContainerRef})
|
|
||||||
viewContainerRef!: ViewContainerRef;
|
|
||||||
constructor(public componentFactoryResolver: ComponentFactoryResolver) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [App], imports: [HelloModule]});
|
|
||||||
const fixture = TestBed.createComponent(App);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const instance = fixture.componentInstance;
|
|
||||||
const factory =
|
|
||||||
instance.componentFactoryResolver.resolveComponentFactory(HelloComponent);
|
|
||||||
const componentRef = instance.viewContainerRef.createComponent(factory);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(() => {
|
|
||||||
componentRef.destroy();
|
|
||||||
componentRef.changeDetectorRef.detectChanges();
|
|
||||||
}).not.toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: add tests with Native once tests run in real browser (domino doesn't support shadow root)
|
// TODO: add tests with Native once tests run in real browser (domino doesn't support shadow root)
|
||||||
describe('encapsulation', () => {
|
describe('encapsulation', () => {
|
||||||
@Component({
|
@Component({
|
||||||
|
|
|
@ -27,7 +27,7 @@ onlyInIvy('Ivy specific').describe('Debug Representation', () => {
|
||||||
const fixture = TestBed.createComponent(MyComponent);
|
const fixture = TestBed.createComponent(MyComponent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const hostView = getLContext(fixture.componentInstance)!.lView!.debug!;
|
const hostView = getLContext(fixture.componentInstance)!.lView.debug!;
|
||||||
expect(hostView.hostHTML).toEqual(null);
|
expect(hostView.hostHTML).toEqual(null);
|
||||||
const myCompView = hostView.childViews[0] as LViewDebug;
|
const myCompView = hostView.childViews[0] as LViewDebug;
|
||||||
expect(myCompView.hostHTML).toContain('<div id="123">Hello World</div>');
|
expect(myCompView.hostHTML).toContain('<div id="123">Hello World</div>');
|
||||||
|
@ -47,7 +47,7 @@ onlyInIvy('Ivy specific').describe('Debug Representation', () => {
|
||||||
const fixture = TestBed.createComponent(MyComponent);
|
const fixture = TestBed.createComponent(MyComponent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const hostView = getLContext(fixture.componentInstance)!.lView!.debug!;
|
const hostView = getLContext(fixture.componentInstance)!.lView.debug!;
|
||||||
const myComponentView = hostView.childViews[0] as LViewDebug;
|
const myComponentView = hostView.childViews[0] as LViewDebug;
|
||||||
expect(myComponentView.decls).toEqual({
|
expect(myComponentView.decls).toEqual({
|
||||||
start: HEADER_OFFSET,
|
start: HEADER_OFFSET,
|
||||||
|
|
|
@ -69,19 +69,16 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-app',
|
selector: 'my-app',
|
||||||
template: `
|
template: `
|
||||||
<span (click)="log($event)" *ngIf="spanVisible">{{text}}</span>
|
<span (click)="log($event)">{{text}}</span>
|
||||||
<div dirA #div #foo="dirA"></div>
|
<div dirA #div #foo="dirA"></div>
|
||||||
<child></child>
|
<child></child>
|
||||||
<child dirA #child></child>
|
<child dirA #child></child>
|
||||||
<child dirA *ngIf="conditionalChildVisible"></child>
|
<child dirA *ngIf="true"></child>
|
||||||
<ng-container><p></p></ng-container>
|
<ng-container><p></p></ng-container>
|
||||||
<b *ngIf="visible">Bold</b>
|
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
class MyApp {
|
class MyApp {
|
||||||
text: string = 'INIT';
|
text: string = 'INIT';
|
||||||
spanVisible = true;
|
|
||||||
conditionalChildVisible = true;
|
|
||||||
@Input('a') b = 2;
|
@Input('a') b = 2;
|
||||||
@Output('c') d = new EventEmitter();
|
@Output('c') d = new EventEmitter();
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -108,15 +105,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
expect(getComponent<Child>(child[0])).toEqual(childComponent[0]);
|
expect(getComponent<Child>(child[0])).toEqual(childComponent[0]);
|
||||||
expect(getComponent<Child>(child[1])).toEqual(childComponent[1]);
|
expect(getComponent<Child>(child[1])).toEqual(childComponent[1]);
|
||||||
});
|
});
|
||||||
it('should not throw when called on a destroyed node', () => {
|
|
||||||
expect(getComponent(span[0])).toEqual(null);
|
|
||||||
expect(getComponent<Child>(child[2])).toEqual(childComponent[2]);
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.componentInstance.conditionalChildVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getComponent(span[0])).toEqual(null);
|
|
||||||
expect(getComponent<Child>(child[2])).toEqual(childComponent[2]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getComponentLView', () => {
|
describe('getComponentLView', () => {
|
||||||
|
@ -143,12 +131,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
expect(getContext<{$implicit: boolean}>(child[2])!.$implicit).toEqual(true);
|
expect(getContext<{$implicit: boolean}>(child[2])!.$implicit).toEqual(true);
|
||||||
expect(getContext<Child>(p[0])).toEqual(childComponent[0]);
|
expect(getContext<Child>(p[0])).toEqual(childComponent[0]);
|
||||||
});
|
});
|
||||||
it('should return null for destroyed node', () => {
|
|
||||||
expect(getContext(span[0])).toBeTruthy();
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getContext(span[0])).toBeNull();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getHostElement', () => {
|
describe('getHostElement', () => {
|
||||||
|
@ -164,12 +146,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
it('should throw on unknown target', () => {
|
it('should throw on unknown target', () => {
|
||||||
expect(() => getHostElement({})).toThrowError(); //
|
expect(() => getHostElement({})).toThrowError(); //
|
||||||
});
|
});
|
||||||
it('should return element for destroyed node', () => {
|
|
||||||
expect(getHostElement(span[0])).toEqual(span[0]);
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getHostElement(span[0])).toEqual(span[0]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getInjector', () => {
|
describe('getInjector', () => {
|
||||||
|
@ -187,12 +163,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
expect(getInjector(dirA[0]).get(String)).toEqual('Module');
|
expect(getInjector(dirA[0]).get(String)).toEqual('Module');
|
||||||
expect(getInjector(dirA[1]).get(String)).toEqual('Child');
|
expect(getInjector(dirA[1]).get(String)).toEqual('Child');
|
||||||
});
|
});
|
||||||
it('should retrieve injector from destroyed node', () => {
|
|
||||||
expect(getInjector(span[0])).toBeTruthy();
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getInjector(span[0])).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getDirectives', () => {
|
describe('getDirectives', () => {
|
||||||
|
@ -205,12 +175,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
expect(getDirectives(div[0])).toEqual([dirA[0]]);
|
expect(getDirectives(div[0])).toEqual([dirA[0]]);
|
||||||
expect(getDirectives(child[1])).toEqual([dirA[1]]);
|
expect(getDirectives(child[1])).toEqual([dirA[1]]);
|
||||||
});
|
});
|
||||||
it('should return empty array for destroyed node', () => {
|
|
||||||
expect(getDirectives(span[0])).toEqual([]);
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getDirectives(span[0])).toEqual([]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getOwningComponent', () => {
|
describe('getOwningComponent', () => {
|
||||||
|
@ -238,12 +202,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
expect(getOwningComponent<MyApp>(dirA[0])).toEqual(myApp);
|
expect(getOwningComponent<MyApp>(dirA[0])).toEqual(myApp);
|
||||||
expect(getOwningComponent<MyApp>(dirA[1])).toEqual(myApp);
|
expect(getOwningComponent<MyApp>(dirA[1])).toEqual(myApp);
|
||||||
});
|
});
|
||||||
it('should return null for destroyed node', () => {
|
|
||||||
expect(getOwningComponent<MyApp>(span[0])).toEqual(myApp);
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getOwningComponent<MyApp>(span[0])).toEqual(null);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getLocalRefs', () => {
|
describe('getLocalRefs', () => {
|
||||||
|
@ -261,13 +219,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
expect(getLocalRefs(child[1])).toEqual({child: childComponent[1]});
|
expect(getLocalRefs(child[1])).toEqual({child: childComponent[1]});
|
||||||
expect(getLocalRefs(dirA[1])).toEqual({child: childComponent[1]});
|
expect(getLocalRefs(dirA[1])).toEqual({child: childComponent[1]});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should retrieve from a destroyed node', () => {
|
|
||||||
expect(getLocalRefs(span[0])).toEqual({});
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getLocalRefs(span[0])).toEqual({});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getRootComponents', () => {
|
describe('getRootComponents', () => {
|
||||||
|
@ -283,12 +234,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
expect(getRootComponents(div[0])).toEqual(rootComponents);
|
expect(getRootComponents(div[0])).toEqual(rootComponents);
|
||||||
expect(getRootComponents(p[0])).toEqual(rootComponents);
|
expect(getRootComponents(p[0])).toEqual(rootComponents);
|
||||||
});
|
});
|
||||||
it('should return an empty array for a destroyed node', () => {
|
|
||||||
expect(getRootComponents(span[0])).toEqual([myApp]);
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getRootComponents(span[0])).toEqual([]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getListeners', () => {
|
describe('getListeners', () => {
|
||||||
|
@ -306,12 +251,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
listeners[0].callback('CLICKED');
|
listeners[0].callback('CLICKED');
|
||||||
expect(log).toEqual(['CLICKED']);
|
expect(log).toEqual(['CLICKED']);
|
||||||
});
|
});
|
||||||
it('should return no listeners for destroyed node', () => {
|
|
||||||
expect(getListeners(span[0]).length).toEqual(1);
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getListeners(span[0]).length).toEqual(0);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getInjectionTokens', () => {
|
describe('getInjectionTokens', () => {
|
||||||
|
@ -320,12 +259,6 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
expect(getInjectionTokens(child[0])).toEqual([String, Child]);
|
expect(getInjectionTokens(child[0])).toEqual([String, Child]);
|
||||||
expect(getInjectionTokens(child[1])).toEqual([String, Child, DirectiveA]);
|
expect(getInjectionTokens(child[1])).toEqual([String, Child, DirectiveA]);
|
||||||
});
|
});
|
||||||
it('should retrieve tokens from destroyed node', () => {
|
|
||||||
expect(getInjectionTokens(span[0])).toEqual([]);
|
|
||||||
fixture.componentInstance.spanVisible = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(getInjectionTokens(span[0])).toEqual([]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('markDirty', () => {
|
describe('markDirty', () => {
|
||||||
|
|
|
@ -32,7 +32,7 @@ onlyInIvy('Debug information exist in ivy only').describe('ngDevMode debug', ()
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [MyApp], imports: [CommonModule]});
|
TestBed.configureTestingModule({declarations: [MyApp], imports: [CommonModule]});
|
||||||
const fixture = TestBed.createComponent(MyApp);
|
const fixture = TestBed.createComponent(MyApp);
|
||||||
const rootLView = getLContext(fixture.nativeElement)!.lView!;
|
const rootLView = getLContext(fixture.nativeElement)!.lView;
|
||||||
expect(rootLView.constructor.name).toEqual('LRootView');
|
expect(rootLView.constructor.name).toEqual('LRootView');
|
||||||
|
|
||||||
const componentLView = getComponentLView(fixture.componentInstance);
|
const componentLView = getComponentLView(fixture.componentInstance);
|
||||||
|
@ -41,7 +41,7 @@ onlyInIvy('Debug information exist in ivy only').describe('ngDevMode debug', ()
|
||||||
const element: HTMLElement = fixture.nativeElement;
|
const element: HTMLElement = fixture.nativeElement;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const li = element.querySelector('li')!;
|
const li = element.querySelector('li')!;
|
||||||
const embeddedLView = getLContext(li)!.lView!;
|
const embeddedLView = getLContext(li)!.lView;
|
||||||
expect(embeddedLView.constructor.name).toEqual('LEmbeddedView_MyApp_li_1');
|
expect(embeddedLView.constructor.name).toEqual('LEmbeddedView_MyApp_li_1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -47,9 +47,6 @@
|
||||||
{
|
{
|
||||||
"name": "SimpleChange"
|
"name": "SimpleChange"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "TRACKED_LVIEWS"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TriggerComponent"
|
"name": "TriggerComponent"
|
||||||
},
|
},
|
||||||
|
@ -257,9 +254,6 @@
|
||||||
{
|
{
|
||||||
"name": "isInlineTemplate"
|
"name": "isInlineTemplate"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "isLView"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "isNodeMatchingSelector"
|
"name": "isNodeMatchingSelector"
|
||||||
},
|
},
|
||||||
|
@ -359,9 +353,6 @@
|
||||||
{
|
{
|
||||||
"name": "setUpAttributes"
|
"name": "setUpAttributes"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "uniqueIdCounter"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "updateTransplantedViewCount"
|
"name": "updateTransplantedViewCount"
|
||||||
},
|
},
|
||||||
|
|
|
@ -548,9 +548,6 @@
|
||||||
{
|
{
|
||||||
"name": "THROW_IF_NOT_FOUND"
|
"name": "THROW_IF_NOT_FOUND"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "TRACKED_LVIEWS"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TRANSITION_ID"
|
"name": "TRANSITION_ID"
|
||||||
},
|
},
|
||||||
|
@ -1571,9 +1568,6 @@
|
||||||
{
|
{
|
||||||
"name": "u"
|
"name": "u"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "uniqueIdCounter"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "unwrapRNode"
|
"name": "unwrapRNode"
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import '@angular/compiler';
|
import '@angular/compiler';
|
||||||
|
import {ɵwhenRendered as whenRendered} from '@angular/core';
|
||||||
import {withBody} from '@angular/private/testing';
|
import {withBody} from '@angular/private/testing';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
|
@ -17,8 +18,8 @@ describe('functional test for reactive forms', () => {
|
||||||
BUNDLES.forEach((bundle) => {
|
BUNDLES.forEach((bundle) => {
|
||||||
describe(`using ${bundle} bundle`, () => {
|
describe(`using ${bundle} bundle`, () => {
|
||||||
it('should render template form', withBody('<app-root></app-root>', async () => {
|
it('should render template form', withBody('<app-root></app-root>', async () => {
|
||||||
const {whenRendered, bootstrapApp} = require(path.join(PACKAGE, bundle));
|
require(path.join(PACKAGE, bundle));
|
||||||
await bootstrapApp();
|
await (window as any).waitForApp;
|
||||||
|
|
||||||
// Reactive forms
|
// Reactive forms
|
||||||
const reactiveFormsComponent = (window as any).reactiveFormsComponent;
|
const reactiveFormsComponent = (window as any).reactiveFormsComponent;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {Component, NgModule, ɵNgModuleFactory as NgModuleFactory, ɵwhenRendered as whenRendered} from '@angular/core';
|
import {Component, NgModule, ɵNgModuleFactory as NgModuleFactory} from '@angular/core';
|
||||||
import {FormArray, FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
import {FormArray, FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
||||||
import {BrowserModule, platformBrowser} from '@angular/platform-browser';
|
import {BrowserModule, platformBrowser} from '@angular/platform-browser';
|
||||||
|
|
||||||
|
@ -93,15 +93,5 @@ class FormsExampleModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bootstrapApp() {
|
(window as any).waitForApp = platformBrowser().bootstrapModuleFactory(
|
||||||
return platformBrowser().bootstrapModuleFactory(
|
new NgModuleFactory(FormsExampleModule), {ngZone: 'noop'});
|
||||||
new NgModuleFactory(FormsExampleModule), {ngZone: 'noop'});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This bundle includes `@angular/core` within it which means that the test asserting
|
|
||||||
// against it will load a different core bundle. These symbols are exposed so that they
|
|
||||||
// can interact with the correct `@angular/core` instance.
|
|
||||||
module.exports = {
|
|
||||||
whenRendered,
|
|
||||||
bootstrapApp
|
|
||||||
};
|
|
||||||
|
|
|
@ -536,9 +536,6 @@
|
||||||
{
|
{
|
||||||
"name": "THROW_IF_NOT_FOUND"
|
"name": "THROW_IF_NOT_FOUND"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "TRACKED_LVIEWS"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TRANSITION_ID"
|
"name": "TRANSITION_ID"
|
||||||
},
|
},
|
||||||
|
@ -1544,9 +1541,6 @@
|
||||||
{
|
{
|
||||||
"name": "u"
|
"name": "u"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "uniqueIdCounter"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "unwrapRNode"
|
"name": "unwrapRNode"
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import '@angular/compiler';
|
import '@angular/compiler';
|
||||||
|
import {ɵwhenRendered as whenRendered} from '@angular/core';
|
||||||
import {withBody} from '@angular/private/testing';
|
import {withBody} from '@angular/private/testing';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
|
@ -17,8 +18,8 @@ describe('functional test for forms', () => {
|
||||||
BUNDLES.forEach((bundle) => {
|
BUNDLES.forEach((bundle) => {
|
||||||
describe(`using ${bundle} bundle`, () => {
|
describe(`using ${bundle} bundle`, () => {
|
||||||
it('should render template form', withBody('<app-root></app-root>', async () => {
|
it('should render template form', withBody('<app-root></app-root>', async () => {
|
||||||
const {bootstrapApp, whenRendered} = require(path.join(PACKAGE, bundle));
|
require(path.join(PACKAGE, bundle));
|
||||||
await bootstrapApp();
|
await (window as any).waitForApp;
|
||||||
|
|
||||||
// Template forms
|
// Template forms
|
||||||
const templateFormsComponent = (window as any).templateFormsComponent;
|
const templateFormsComponent = (window as any).templateFormsComponent;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {Component, NgModule, ɵNgModuleFactory as NgModuleFactory, ɵwhenRendered as whenRendered} from '@angular/core';
|
import {Component, NgModule, ɵNgModuleFactory as NgModuleFactory} from '@angular/core';
|
||||||
import {FormsModule} from '@angular/forms';
|
import {FormsModule} from '@angular/forms';
|
||||||
import {BrowserModule, platformBrowser} from '@angular/platform-browser';
|
import {BrowserModule, platformBrowser} from '@angular/platform-browser';
|
||||||
|
|
||||||
|
@ -70,15 +70,5 @@ class FormsExampleModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bootstrapApp() {
|
(window as any).waitForApp = platformBrowser().bootstrapModuleFactory(
|
||||||
return platformBrowser().bootstrapModuleFactory(
|
new NgModuleFactory(FormsExampleModule), {ngZone: 'noop'});
|
||||||
new NgModuleFactory(FormsExampleModule), {ngZone: 'noop'});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This bundle includes `@angular/core` within it which means that the test asserting
|
|
||||||
// against it will load a different core bundle. These symbols are exposed so that they
|
|
||||||
// can interact with the correct `@angular/core` instance.
|
|
||||||
module.exports = {
|
|
||||||
whenRendered,
|
|
||||||
bootstrapApp
|
|
||||||
};
|
|
||||||
|
|
|
@ -41,9 +41,6 @@
|
||||||
{
|
{
|
||||||
"name": "SimpleChange"
|
"name": "SimpleChange"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "TRACKED_LVIEWS"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "ViewEncapsulation"
|
"name": "ViewEncapsulation"
|
||||||
},
|
},
|
||||||
|
@ -176,9 +173,6 @@
|
||||||
{
|
{
|
||||||
"name": "isInCheckNoChangesMode"
|
"name": "isInCheckNoChangesMode"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "isLView"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "isProceduralRenderer"
|
"name": "isProceduralRenderer"
|
||||||
},
|
},
|
||||||
|
@ -242,9 +236,6 @@
|
||||||
{
|
{
|
||||||
"name": "setSelectedIndex"
|
"name": "setSelectedIndex"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "uniqueIdCounter"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "updateTransplantedViewCount"
|
"name": "updateTransplantedViewCount"
|
||||||
},
|
},
|
||||||
|
|
|
@ -785,9 +785,6 @@
|
||||||
{
|
{
|
||||||
"name": "TQuery_"
|
"name": "TQuery_"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "TRACKED_LVIEWS"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TRANSITION_ID"
|
"name": "TRANSITION_ID"
|
||||||
},
|
},
|
||||||
|
@ -2018,9 +2015,6 @@
|
||||||
{
|
{
|
||||||
"name": "u"
|
"name": "u"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "uniqueIdCounter"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "unwrapElementRef"
|
"name": "unwrapElementRef"
|
||||||
},
|
},
|
||||||
|
|
|
@ -32,9 +32,6 @@
|
||||||
{
|
{
|
||||||
"name": "IterableDiffers"
|
"name": "IterableDiffers"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "LContext"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "NG_COMP_DEF"
|
"name": "NG_COMP_DEF"
|
||||||
},
|
},
|
||||||
|
@ -113,9 +110,6 @@
|
||||||
{
|
{
|
||||||
"name": "SkipSelf"
|
"name": "SkipSelf"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "TRACKED_LVIEWS"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TemplateRef"
|
"name": "TemplateRef"
|
||||||
},
|
},
|
||||||
|
@ -386,9 +380,6 @@
|
||||||
{
|
{
|
||||||
"name": "getLView"
|
"name": "getLView"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "getLViewById"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "getLViewParent"
|
"name": "getLViewParent"
|
||||||
},
|
},
|
||||||
|
@ -749,9 +740,6 @@
|
||||||
{
|
{
|
||||||
"name": "trackByIdentity"
|
"name": "trackByIdentity"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "uniqueIdCounter"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "unwrapRNode"
|
"name": "unwrapRNode"
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import '@angular/core/test/bundling/util/src/reflect_metadata';
|
import '@angular/core/test/bundling/util/src/reflect_metadata';
|
||||||
|
|
||||||
import {CommonModule} from '@angular/common';
|
import {CommonModule} from '@angular/common';
|
||||||
import {Component, Injectable, NgModule, ViewEncapsulation, ɵmarkDirty as markDirty, ɵrenderComponent as renderComponent, ɵwhenRendered as whenRendered} from '@angular/core';
|
import {Component, Injectable, NgModule, ViewEncapsulation, ɵmarkDirty as markDirty, ɵrenderComponent as renderComponent} from '@angular/core';
|
||||||
|
|
||||||
class Todo {
|
class Todo {
|
||||||
editing: boolean;
|
editing: boolean;
|
||||||
|
@ -133,9 +133,7 @@ class TodoStore {
|
||||||
class ToDoAppComponent {
|
class ToDoAppComponent {
|
||||||
newTodoText = '';
|
newTodoText = '';
|
||||||
|
|
||||||
constructor(public todoStore: TodoStore) {
|
constructor(public todoStore: TodoStore) {}
|
||||||
(window as any).todoAppComponent = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelEditingTodo(todo: Todo) {
|
cancelEditingTodo(todo: Todo) {
|
||||||
todo.editing = false;
|
todo.editing = false;
|
||||||
|
@ -202,8 +200,3 @@ class ToDoAppModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderComponent(ToDoAppComponent);
|
renderComponent(ToDoAppComponent);
|
||||||
|
|
||||||
// This bundle includes `@angular/core` within it which means that the test asserting
|
|
||||||
// against it will load a different core bundle. These symbols are exposed so that they
|
|
||||||
// can interact with the correct `@angular/core` instance.
|
|
||||||
module.exports = {whenRendered};
|
|
||||||
|
|
|
@ -7,9 +7,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import '@angular/compiler';
|
import '@angular/compiler';
|
||||||
|
import {ɵwhenRendered as whenRendered} from '@angular/core';
|
||||||
|
import {getComponent} from '@angular/core/src/render3';
|
||||||
import {withBody} from '@angular/private/testing';
|
import {withBody} from '@angular/private/testing';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
|
const UTF8 = {
|
||||||
|
encoding: 'utf-8'
|
||||||
|
};
|
||||||
const PACKAGE = 'angular/packages/core/test/bundling/todo';
|
const PACKAGE = 'angular/packages/core/test/bundling/todo';
|
||||||
const BUNDLES = ['bundle.js', 'bundle.min_debug.js', 'bundle.min.js'];
|
const BUNDLES = ['bundle.js', 'bundle.min_debug.js', 'bundle.min.js'];
|
||||||
|
|
||||||
|
@ -17,12 +22,13 @@ describe('functional test for todo', () => {
|
||||||
BUNDLES.forEach(bundle => {
|
BUNDLES.forEach(bundle => {
|
||||||
describe(bundle, () => {
|
describe(bundle, () => {
|
||||||
it('should render todo', withBody('<todo-app></todo-app>', async () => {
|
it('should render todo', withBody('<todo-app></todo-app>', async () => {
|
||||||
const {whenRendered} = require(path.join(PACKAGE, bundle));
|
require(path.join(PACKAGE, bundle));
|
||||||
|
const toDoAppComponent = getComponent(document.querySelector('todo-app')!);
|
||||||
expect(document.body.textContent).toContain('todos');
|
expect(document.body.textContent).toContain('todos');
|
||||||
expect(document.body.textContent).toContain('Demonstrate Components');
|
expect(document.body.textContent).toContain('Demonstrate Components');
|
||||||
expect(document.body.textContent).toContain('4 items left');
|
expect(document.body.textContent).toContain('4 items left');
|
||||||
document.querySelector('button')!.click();
|
document.querySelector('button')!.click();
|
||||||
await whenRendered((window as any).todoAppComponent);
|
await whenRendered(toDoAppComponent);
|
||||||
expect(document.body.textContent).toContain('3 items left');
|
expect(document.body.textContent).toContain('3 items left');
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import '@angular/core/test/bundling/util/src/reflect_metadata';
|
import '@angular/core/test/bundling/util/src/reflect_metadata';
|
||||||
import './translations';
|
import './translations';
|
||||||
import {CommonModule} from '@angular/common';
|
import {CommonModule} from '@angular/common';
|
||||||
import {Component, Injectable, NgModule, ViewEncapsulation, ɵmarkDirty as markDirty, ɵrenderComponent as renderComponent, ɵwhenRendered as whenRendered} from '@angular/core';
|
import {Component, Injectable, NgModule, ViewEncapsulation, ɵmarkDirty as markDirty, ɵrenderComponent as renderComponent} from '@angular/core';
|
||||||
|
|
||||||
class Todo {
|
class Todo {
|
||||||
editing: boolean;
|
editing: boolean;
|
||||||
|
@ -127,9 +127,7 @@ class TodoStore {
|
||||||
class ToDoAppComponent {
|
class ToDoAppComponent {
|
||||||
newTodoText = '';
|
newTodoText = '';
|
||||||
|
|
||||||
constructor(public todoStore: TodoStore) {
|
constructor(public todoStore: TodoStore) {}
|
||||||
(window as any).todoAppComponent = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelEditingTodo(todo: Todo) {
|
cancelEditingTodo(todo: Todo) {
|
||||||
todo.editing = false;
|
todo.editing = false;
|
||||||
|
@ -196,8 +194,3 @@ class ToDoAppModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderComponent(ToDoAppComponent);
|
renderComponent(ToDoAppComponent);
|
||||||
|
|
||||||
// This bundle includes `@angular/core` within it which means that the test asserting
|
|
||||||
// against it will load a different core bundle. These symbols are exposed so that they
|
|
||||||
// can interact with the correct `@angular/core` instance.
|
|
||||||
module.exports = {whenRendered};
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
import '@angular/localize/init';
|
import '@angular/localize/init';
|
||||||
import '@angular/compiler';
|
import '@angular/compiler';
|
||||||
|
|
||||||
|
import {ɵwhenRendered as whenRendered} from '@angular/core';
|
||||||
|
import {getComponent} from '@angular/core/src/render3';
|
||||||
import {clearTranslations} from '@angular/localize';
|
import {clearTranslations} from '@angular/localize';
|
||||||
import {withBody} from '@angular/private/testing';
|
import {withBody} from '@angular/private/testing';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
@ -20,7 +22,8 @@ describe('functional test for todo i18n', () => {
|
||||||
describe(bundle, () => {
|
describe(bundle, () => {
|
||||||
it('should render todo i18n', withBody('<todo-app></todo-app>', async () => {
|
it('should render todo i18n', withBody('<todo-app></todo-app>', async () => {
|
||||||
clearTranslations();
|
clearTranslations();
|
||||||
const {whenRendered} = require(path.join(PACKAGE, bundle));
|
require(path.join(PACKAGE, bundle));
|
||||||
|
const toDoAppComponent = getComponent(document.querySelector('todo-app')!);
|
||||||
expect(document.body.textContent).toContain('liste de tâches');
|
expect(document.body.textContent).toContain('liste de tâches');
|
||||||
expect(document.body.textContent).toContain('Démontrer les components');
|
expect(document.body.textContent).toContain('Démontrer les components');
|
||||||
expect(document.body.textContent).toContain('Démontrer NgModules');
|
expect(document.body.textContent).toContain('Démontrer NgModules');
|
||||||
|
@ -28,7 +31,7 @@ describe('functional test for todo i18n', () => {
|
||||||
expect(document.querySelector('.new-todo')!.getAttribute('placeholder'))
|
expect(document.querySelector('.new-todo')!.getAttribute('placeholder'))
|
||||||
.toEqual(`Qu'y a-t-il à faire ?`);
|
.toEqual(`Qu'y a-t-il à faire ?`);
|
||||||
document.querySelector('button')!.click();
|
document.querySelector('button')!.click();
|
||||||
await whenRendered((window as any).todoAppComponent);
|
await whenRendered(toDoAppComponent);
|
||||||
expect(document.body.textContent).toContain('3 tâches restantes');
|
expect(document.body.textContent).toContain('3 tâches restantes');
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import '@angular/core/test/bundling/util/src/reflect_metadata';
|
import '@angular/core/test/bundling/util/src/reflect_metadata';
|
||||||
|
|
||||||
import {CommonModule} from '@angular/common';
|
import {CommonModule} from '@angular/common';
|
||||||
import {Component, Injectable, NgModule, ɵNgModuleFactory as NgModuleFactory, ɵwhenRendered as whenRendered} from '@angular/core';
|
import {Component, Injectable, NgModule, ɵNgModuleFactory as NgModuleFactory} from '@angular/core';
|
||||||
import {BrowserModule, platformBrowser} from '@angular/platform-browser';
|
import {BrowserModule, platformBrowser} from '@angular/platform-browser';
|
||||||
|
|
||||||
class Todo {
|
class Todo {
|
||||||
|
@ -195,15 +195,5 @@ class ToDoAppModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bootstrapApp() {
|
(window as any).waitForApp =
|
||||||
return platformBrowser().bootstrapModuleFactory(
|
platformBrowser().bootstrapModuleFactory(new NgModuleFactory(ToDoAppModule), {ngZone: 'noop'});
|
||||||
new NgModuleFactory(ToDoAppModule), {ngZone: 'noop'});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This bundle includes `@angular/core` within it which means that the test asserting
|
|
||||||
// against it will load a different core bundle. These symbols are exposed so that they
|
|
||||||
// can interact with the correct `@angular/core` instance.
|
|
||||||
module.exports = {
|
|
||||||
whenRendered,
|
|
||||||
bootstrapApp
|
|
||||||
};
|
|
||||||
|
|
|
@ -7,9 +7,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import '@angular/compiler';
|
import '@angular/compiler';
|
||||||
|
import {ɵwhenRendered as whenRendered} from '@angular/core';
|
||||||
import {withBody} from '@angular/private/testing';
|
import {withBody} from '@angular/private/testing';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
|
const UTF8 = {
|
||||||
|
encoding: 'utf-8'
|
||||||
|
};
|
||||||
const PACKAGE = 'angular/packages/core/test/bundling/todo_r2';
|
const PACKAGE = 'angular/packages/core/test/bundling/todo_r2';
|
||||||
const BUNDLES = ['bundle.js', 'bundle.min_debug.js', 'bundle.min.js'];
|
const BUNDLES = ['bundle.js', 'bundle.min_debug.js', 'bundle.min.js'];
|
||||||
|
|
||||||
|
@ -18,8 +22,8 @@ describe('functional test for todo', () => {
|
||||||
describe(bundle, () => {
|
describe(bundle, () => {
|
||||||
it('should place styles on the elements within the component',
|
it('should place styles on the elements within the component',
|
||||||
withBody('<todo-app></todo-app>', async () => {
|
withBody('<todo-app></todo-app>', async () => {
|
||||||
const {bootstrapApp, whenRendered} = require(path.join(PACKAGE, bundle));
|
require(path.join(PACKAGE, bundle));
|
||||||
await bootstrapApp();
|
await (window as any).waitForApp;
|
||||||
const toDoAppComponent = (window as any).toDoAppComponent;
|
const toDoAppComponent = (window as any).toDoAppComponent;
|
||||||
await whenRendered(toDoAppComponent);
|
await whenRendered(toDoAppComponent);
|
||||||
|
|
||||||
|
|
|
@ -40,16 +40,16 @@ describe('i18n_parse', () => {
|
||||||
// TData | LView
|
// TData | LView
|
||||||
// ---------------------------+-------------------------------
|
// ---------------------------+-------------------------------
|
||||||
// ----- DECL -----
|
// ----- DECL -----
|
||||||
// 21: TI18n |
|
// 20: TI18n |
|
||||||
// ----- VARS -----
|
// ----- VARS -----
|
||||||
// 22: Binding for ICU |
|
// 21: Binding for ICU |
|
||||||
// ----- EXPANDO -----
|
// ----- EXPANDO -----
|
||||||
// 23: null | #text(before|)
|
// 22: null | #text(before|)
|
||||||
// 24: TIcu | <!-- ICU 20:0 -->
|
// 23: TIcu | <!-- ICU 20:0 -->
|
||||||
// 25: null | currently selected ICU case
|
// 24: null | currently selected ICU case
|
||||||
// 26: null | #text(caseA)
|
// 25: null | #text(caseA)
|
||||||
// 27: null | #text(otherCase)
|
// 26: null | #text(otherCase)
|
||||||
// 28: null | #text(|after)
|
// 27: null | #text(|after)
|
||||||
const tI18n = toT18n(`before|{
|
const tI18n = toT18n(`before|{
|
||||||
<EFBFBD>0<EFBFBD>, select,
|
<EFBFBD>0<EFBFBD>, select,
|
||||||
A {caseA}
|
A {caseA}
|
||||||
|
@ -153,21 +153,21 @@ describe('i18n_parse', () => {
|
||||||
// TData | LView
|
// TData | LView
|
||||||
// ---------------------------+-------------------------------
|
// ---------------------------+-------------------------------
|
||||||
// ----- DECL -----
|
// ----- DECL -----
|
||||||
// 21: TI18n |
|
// 20: TI18n |
|
||||||
// ----- VARS -----
|
// ----- VARS -----
|
||||||
// 22: Binding for parent ICU |
|
// 21: Binding for parent ICU |
|
||||||
|
// 22: Binding for child ICU |
|
||||||
// 23: Binding for child ICU |
|
// 23: Binding for child ICU |
|
||||||
// 24: Binding for child ICU |
|
|
||||||
// ----- EXPANDO -----
|
// ----- EXPANDO -----
|
||||||
// 25: TIcu (parent) | <!-- ICU 20:0 -->
|
// 24: TIcu (parent) | <!-- ICU 20:0 -->
|
||||||
// 26: null | currently selected ICU case
|
// 25: null | currently selected ICU case
|
||||||
// 27: null | #text( parentA )
|
// 26: null | #text( parentA )
|
||||||
// 28: TIcu (child) | <!-- nested ICU 0 -->
|
// 27: TIcu (child) | <!-- nested ICU 0 -->
|
||||||
// 29: null | currently selected ICU case
|
// 28: null | currently selected ICU case
|
||||||
// 30: null | #text(nested0)
|
// 29: null | #text(nested0)
|
||||||
// 31: null | #text({{<7B>2<EFBFBD>}})
|
// 30: null | #text({{<7B>2<EFBFBD>}})
|
||||||
// 32: null | #text( )
|
// 31: null | #text( )
|
||||||
// 33: null | #text( parentOther )
|
// 32: null | #text( parentOther )
|
||||||
const tI18n = toT18n(`{
|
const tI18n = toT18n(`{
|
||||||
<EFBFBD>0<EFBFBD>, select,
|
<EFBFBD>0<EFBFBD>, select,
|
||||||
A {parentA {<EFBFBD>1<EFBFBD>, select, 0 {nested0} other {<EFBFBD>2<EFBFBD>}}!}
|
A {parentA {<EFBFBD>1<EFBFBD>, select, 0 {nested0} other {<EFBFBD>2<EFBFBD>}}!}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {AttributeMarker, ɵɵadvance, ɵɵattribute, ɵɵdefineComponent, ɵɵde
|
||||||
import {ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵprojection, ɵɵprojectionDef, ɵɵtemplate, ɵɵtext} from '../../src/render3/instructions/all';
|
import {ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵprojection, ɵɵprojectionDef, ɵɵtemplate, ɵɵtext} from '../../src/render3/instructions/all';
|
||||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||||
import {domRendererFactory3, Renderer3, RendererFactory3} from '../../src/render3/interfaces/renderer';
|
import {domRendererFactory3, Renderer3, RendererFactory3} from '../../src/render3/interfaces/renderer';
|
||||||
import {CONTEXT, HEADER_OFFSET, ID, LView} from '../../src/render3/interfaces/view';
|
import {CONTEXT, HEADER_OFFSET} from '../../src/render3/interfaces/view';
|
||||||
import {ɵɵsanitizeUrl} from '../../src/sanitization/sanitization';
|
import {ɵɵsanitizeUrl} from '../../src/sanitization/sanitization';
|
||||||
import {Sanitizer} from '../../src/sanitization/sanitizer';
|
import {Sanitizer} from '../../src/sanitization/sanitizer';
|
||||||
import {SecurityContext} from '../../src/sanitization/security';
|
import {SecurityContext} from '../../src/sanitization/security';
|
||||||
|
@ -399,17 +399,19 @@ describe('element discovery', () => {
|
||||||
|
|
||||||
const section = fixture.hostElement.querySelector('section')!;
|
const section = fixture.hostElement.querySelector('section')!;
|
||||||
const sectionContext = getLContext(section)!;
|
const sectionContext = getLContext(section)!;
|
||||||
|
const sectionLView = sectionContext.lView!;
|
||||||
expect(sectionContext.nodeIndex).toEqual(HEADER_OFFSET);
|
expect(sectionContext.nodeIndex).toEqual(HEADER_OFFSET);
|
||||||
expect(sectionContext.lView!.length).toBeGreaterThan(HEADER_OFFSET);
|
expect(sectionLView.length).toBeGreaterThan(HEADER_OFFSET);
|
||||||
expect(sectionContext.native).toBe(section);
|
expect(sectionContext.native).toBe(section);
|
||||||
|
|
||||||
const div = fixture.hostElement.querySelector('div')!;
|
const div = fixture.hostElement.querySelector('div')!;
|
||||||
const divContext = getLContext(div)!;
|
const divContext = getLContext(div)!;
|
||||||
|
const divLView = divContext.lView!;
|
||||||
expect(divContext.nodeIndex).toEqual(HEADER_OFFSET + 1);
|
expect(divContext.nodeIndex).toEqual(HEADER_OFFSET + 1);
|
||||||
expect(divContext.lView!.length).toBeGreaterThan(HEADER_OFFSET);
|
expect(divLView.length).toBeGreaterThan(HEADER_OFFSET);
|
||||||
expect(divContext.native).toBe(div);
|
expect(divContext.native).toBe(div);
|
||||||
|
|
||||||
expect(divContext.lView).toBe(sectionContext.lView);
|
expect(divLView).toBe(sectionLView);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should cache the element context on a element was pre-emptively monkey-patched', () => {
|
it('should cache the element context on a element was pre-emptively monkey-patched', () => {
|
||||||
|
@ -736,7 +738,7 @@ describe('element discovery', () => {
|
||||||
const div1 = hostElm.querySelector('div:first-child')! as any;
|
const div1 = hostElm.querySelector('div:first-child')! as any;
|
||||||
const div2 = hostElm.querySelector('div:last-child')! as any;
|
const div2 = hostElm.querySelector('div:last-child')! as any;
|
||||||
const context = getLContext(hostElm)!;
|
const context = getLContext(hostElm)!;
|
||||||
const componentView = context.lView![context.nodeIndex];
|
const componentView = context.lView[context.nodeIndex];
|
||||||
|
|
||||||
expect(componentView).toContain(myDir1Instance);
|
expect(componentView).toContain(myDir1Instance);
|
||||||
expect(componentView).toContain(myDir2Instance);
|
expect(componentView).toContain(myDir2Instance);
|
||||||
|
@ -915,7 +917,7 @@ describe('element discovery', () => {
|
||||||
const context = getLContext(child)!;
|
const context = getLContext(child)!;
|
||||||
expect(readPatchedData(child)).toBeTruthy();
|
expect(readPatchedData(child)).toBeTruthy();
|
||||||
|
|
||||||
const componentData = context.lView![context.nodeIndex];
|
const componentData = context.lView[context.nodeIndex];
|
||||||
const component = componentData[CONTEXT];
|
const component = componentData[CONTEXT];
|
||||||
expect(component instanceof ChildComp).toBeTruthy();
|
expect(component instanceof ChildComp).toBeTruthy();
|
||||||
expect(readPatchedData(component)).toBe(context.lView);
|
expect(readPatchedData(component)).toBe(context.lView);
|
||||||
|
|
Loading…
Reference in New Issue