Skip to content

Commit e56c8bf

Browse files
committed
fix(ivy): align discovery methods for consistency (angular#27117)
PR Close angular#27117
1 parent ca40565 commit e56c8bf

21 files changed

+430
-214
lines changed

packages/core/src/change_detection/differs/keyvalue_differs.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Optional, SkipSelf, StaticProvider} from '../../di';
9+
import {Optional, SkipSelf, StaticProvider, defineInjectable} from '../../di';
10+
import {DefaultKeyValueDifferFactory} from './default_keyvalue_differ';
1011

1112

1213
/**
@@ -116,6 +117,12 @@ export interface KeyValueDifferFactory {
116117
* @publicApi
117118
*/
118119
export class KeyValueDiffers {
120+
/** @nocollapse */
121+
static ngInjectableDef = defineInjectable({
122+
providedIn: 'root',
123+
factory: () => new KeyValueDiffers([new DefaultKeyValueDifferFactory()])
124+
});
125+
119126
/**
120127
* @deprecated v4.0.0 - Should be private.
121128
*/

packages/core/src/di/r3_injector.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ export class R3Injector {
200200
defOrWrappedDef: InjectorType<any>|InjectorTypeWithProviders<any>,
201201
parents: InjectorType<any>[], dedupStack: InjectorType<any>[]) {
202202
defOrWrappedDef = resolveForwardRef(defOrWrappedDef);
203+
if (!defOrWrappedDef) return;
203204

204205
// Either the defOrWrappedDef is an InjectorType (with ngInjectorDef) or an
205206
// InjectorDefTypeWithProviders (aka ModuleWithProviders). Detecting either is a megamorphic

packages/core/src/render3/component.ts

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ import {Injector} from '../di/injector';
1313
import {Sanitizer} from '../sanitization/security';
1414

1515
import {assertComponentType, assertDefined} from './assert';
16-
import {getComponentViewByInstance} from './context_discovery';
16+
import {getContext} from './context_discovery';
1717
import {getComponentDef} from './definition';
1818
import {diPublicInInjector, getOrCreateNodeInjectorForNode} from './di';
19+
import {getHostElement} from './discovery_utils';
1920
import {publishDefaultGlobalUtils} from './global_utils';
2021
import {queueInitHooks, queueLifecycleHooks} from './hooks';
2122
import {CLEAN_PROMISE, createLViewData, createNodeAtIndex, createTView, getOrCreateTView, initNodeFlags, instantiateRootComponent, locateHostElement, prefillHostVars, queueComponentIndexForCheck, refreshDescendantViews} from './instructions';
@@ -28,6 +29,7 @@ import {enterView, leaveView, resetComponentState} from './state';
2829
import {defaultScheduler, getRootView, readElementValue, readPatchedLViewData, stringify} from './util';
2930

3031

32+
3133
/** Options that control how the component should be bootstrapped. */
3234
export interface CreateComponentOptions {
3335
/** Which renderer factory to use. */
@@ -121,8 +123,8 @@ export function renderComponent<T>(
121123

122124
const renderer = rendererFactory.createRenderer(hostRNode, componentDef);
123125
const rootView: LViewData = createLViewData(
124-
renderer, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags, undefined,
125-
opts.injector || null);
126+
null, renderer, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags,
127+
undefined, opts.injector || null);
126128

127129
const oldView = enterView(rootView, null);
128130
let component: T;
@@ -159,7 +161,7 @@ export function createRootComponentView(
159161
resetComponentState();
160162
const tView = rootView[TVIEW];
161163
const componentView = createLViewData(
162-
renderer,
164+
rootView, renderer,
163165
getOrCreateTView(
164166
def.template, def.consts, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery),
165167
null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, sanitizer);
@@ -243,32 +245,6 @@ function getRootContext(component: any): RootContext {
243245
return rootContext;
244246
}
245247

246-
/**
247-
* Retrieve the host element of the component.
248-
*
249-
* Use this function to retrieve the host element of the component. The host
250-
* element is the element which the component is associated with.
251-
*
252-
* @param component Component for which the host element should be retrieved.
253-
*/
254-
export function getHostElement<T>(component: T): HTMLElement {
255-
return readElementValue(getComponentViewByInstance(component)) as HTMLElement;
256-
}
257-
258-
/**
259-
* Retrieves the rendered text for a given component.
260-
*
261-
* This function retrieves the host element of a component and
262-
* and then returns the `textContent` for that element. This implies
263-
* that the text returned will include re-projected content of
264-
* the component as well.
265-
*
266-
* @param component The component to return the content text for.
267-
*/
268-
export function getRenderedText(component: any): string {
269-
const hostElement = getHostElement(component);
270-
return hostElement.textContent || '';
271-
}
272248

273249
/**
274250
* Wait on component until it is rendered.

packages/core/src/render3/component_ref.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
151151

152152
// Create the root view. Uses empty TView and ContentTemplate.
153153
const rootView: LViewData = createLViewData(
154-
renderer, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags, undefined,
155-
rootViewInjector);
154+
null, renderer, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags,
155+
undefined, rootViewInjector);
156156

157157
// rootView is the parent when bootstrapping
158158
const oldView = enterView(rootView, null);

packages/core/src/render3/context_discovery.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
import './ng_dev_mode';
99

1010
import {assertEqual} from './assert';
11+
import {EMPTY_ARRAY} from './definition';
1112
import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context';
1213
import {TNode, TNodeFlags} from './interfaces/node';
1314
import {RElement} from './interfaces/renderer';
1415
import {CONTEXT, HEADER_OFFSET, HOST, LViewData, TVIEW} from './interfaces/view';
1516
import {getComponentViewByIndex, getNativeByTNode, readElementValue, readPatchedData} from './util';
1617

1718

19+
1820
/** Returns the matching `LContext` data for a given DOM node, directive or component instance.
1921
*
2022
* This function will examine the provided DOM element, component, or directive instance\'s
@@ -31,6 +33,8 @@ import {getComponentViewByIndex, getNativeByTNode, readElementValue, readPatched
3133
* will be updated with a new context (which is then returned). If the monkey-patch value is not
3234
* detected for a component/directive instance then it will throw an error (all components and
3335
* directives should be automatically monkey-patched by ivy).
36+
*
37+
* @param target Component, Directive or DOM Node.
3438
*/
3539
export function getContext(target: any): LContext|null {
3640
let mpValue = readPatchedData(target);
@@ -54,7 +58,7 @@ export function getContext(target: any): LContext|null {
5458
if (nodeIndex == -1) {
5559
throw new Error('The provided directive was not found in the application');
5660
}
57-
directives = discoverDirectives(nodeIndex, lViewData, false);
61+
directives = getDirectivesAtNodeIndex(nodeIndex, lViewData, false);
5862
} else {
5963
nodeIndex = findViaNativeElement(lViewData, target as RElement);
6064
if (nodeIndex == -1) {
@@ -132,7 +136,8 @@ export function getContext(target: any): LContext|null {
132136
function createLContext(lViewData: LViewData, nodeIndex: number, native: RElement): LContext {
133137
return {
134138
lViewData,
135-
nodeIndex: nodeIndex, native,
139+
nodeIndex,
140+
native,
136141
component: undefined,
137142
directives: undefined,
138143
localRefs: undefined,
@@ -271,15 +276,22 @@ function assertDomElement(element: any) {
271276
* @param lViewData The target view data
272277
* @param includeComponents Whether or not to include components in returned directives
273278
*/
274-
export function discoverDirectives(
279+
export function getDirectivesAtNodeIndex(
275280
nodeIndex: number, lViewData: LViewData, includeComponents: boolean): any[]|null {
276281
const tNode = lViewData[TVIEW].data[nodeIndex] as TNode;
277282
let directiveStartIndex = getDirectiveStartIndex(tNode);
283+
if (directiveStartIndex == 0) return EMPTY_ARRAY;
278284
const directiveEndIndex = getDirectiveEndIndex(tNode, directiveStartIndex);
279285
if (!includeComponents && tNode.flags & TNodeFlags.isComponent) directiveStartIndex++;
280286
return lViewData.slice(directiveStartIndex, directiveEndIndex);
281287
}
282288

289+
export function getComponentAtNodeIndex(nodeIndex: number, lViewData: LViewData): {}|null {
290+
const tNode = lViewData[TVIEW].data[nodeIndex] as TNode;
291+
let directiveStartIndex = getDirectiveStartIndex(tNode);
292+
return tNode.flags & TNodeFlags.isComponent ? lViewData[directiveStartIndex] : null;
293+
}
294+
283295
/**
284296
* Returns a map of local references (local reference name => element or directive instance) that
285297
* exist on a given element.

packages/core/src/render3/debug.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ import {Renderer2, RendererType2} from '../render/api';
1111
import {DebugContext} from '../view';
1212
import {DebugRenderer2, DebugRendererFactory2} from '../view/services';
1313

14-
import {getHostComponent, getInjector, getLocalRefs, loadContext} from './discovery_utils';
14+
import {getComponent, getInjector, getLocalRefs, loadContext} from './discovery_utils';
1515
import {DirectiveDef} from './interfaces/definition';
1616
import {TNode, TNodeFlags} from './interfaces/node';
1717
import {TVIEW} from './interfaces/view';
1818

19+
1920
/**
2021
* Adapts the DebugRendererFactory2 to create a DebugRenderer2 specific for IVY.
2122
*
@@ -43,7 +44,7 @@ class Render3DebugContext implements DebugContext {
4344

4445
get injector(): Injector { return getInjector(this._nativeNode); }
4546

46-
get component(): any { return getHostComponent(this._nativeNode); }
47+
get component(): any { return getComponent(this._nativeNode); }
4748

4849
get providerTokens(): any[] {
4950
const lDebugCtx = loadContext(this._nativeNode);

0 commit comments

Comments
 (0)