mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(core): do not store input/output public names (#60036)
Reworks the `TNode.inputs` and `TNode.outputs` to not store the public names of bindings. The only reason they were stored was for host directive re-aliasing which is handled through a different data structure now. PR Close #60036
This commit is contained in:
committed by
kirjs
parent
9f44b41053
commit
628ab4033b
@@ -10,7 +10,7 @@ import {setActiveConsumer} from '@angular/core/primitives/signals';
|
||||
|
||||
import {NotificationSource} from '../../change_detection/scheduling/zoneless_scheduling';
|
||||
import {assertIndexInRange} from '../../util/assert';
|
||||
import {NodeOutputBindings, TNode, TNodeType} from '../interfaces/node';
|
||||
import {TNode, TNodeType} from '../interfaces/node';
|
||||
import {GlobalTargetResolver, Renderer} from '../interfaces/renderer';
|
||||
import {RElement} from '../interfaces/renderer_dom';
|
||||
import {isComponentHost, isDirectiveHost} from '../interfaces/type_checks';
|
||||
@@ -238,22 +238,34 @@ export function listenerInternal(
|
||||
if (hostDirectiveOutputConfig && hostDirectiveOutputConfig.length) {
|
||||
for (let i = 0; i < hostDirectiveOutputConfig.length; i += 2) {
|
||||
const index = hostDirectiveOutputConfig[i] as number;
|
||||
ngDevMode && assertIndexInRange(lView, index);
|
||||
const instance = lView[index];
|
||||
const lookupName = hostDirectiveOutputConfig[i + 1] as string;
|
||||
const def = tView.data[index] as DirectiveDef<unknown>;
|
||||
const minifiedName = def.outputs[lookupName];
|
||||
listenToOutput(tNode, instance, eventName, minifiedName, listenerFn, lCleanup, tCleanup);
|
||||
listenToOutput(
|
||||
tNode,
|
||||
tView,
|
||||
lView,
|
||||
index,
|
||||
lookupName,
|
||||
eventName,
|
||||
listenerFn,
|
||||
lCleanup,
|
||||
tCleanup,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (outputConfig && outputConfig.length) {
|
||||
for (let i = 0; i < outputConfig.length; i += 2) {
|
||||
const index = outputConfig[i] as number;
|
||||
ngDevMode && assertIndexInRange(lView, index);
|
||||
const instance = lView[index];
|
||||
const minifiedName = outputConfig[i + 1] as string;
|
||||
listenToOutput(tNode, instance, eventName, minifiedName, listenerFn, lCleanup, tCleanup);
|
||||
for (const index of outputConfig) {
|
||||
listenToOutput(
|
||||
tNode,
|
||||
tView,
|
||||
lView,
|
||||
index,
|
||||
eventName,
|
||||
eventName,
|
||||
listenerFn,
|
||||
lCleanup,
|
||||
tCleanup,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,13 +273,19 @@ export function listenerInternal(
|
||||
|
||||
function listenToOutput(
|
||||
tNode: TNode,
|
||||
instance: any,
|
||||
tView: TView,
|
||||
lView: LView,
|
||||
index: number,
|
||||
lookupName: string,
|
||||
eventName: string,
|
||||
propertyName: string,
|
||||
listenerFn: (e?: any) => any,
|
||||
lCleanup: any[],
|
||||
tCleanup: any[] | null,
|
||||
) {
|
||||
ngDevMode && assertIndexInRange(lView, index);
|
||||
const instance = lView[index];
|
||||
const def = tView.data[index] as DirectiveDef<unknown>;
|
||||
const propertyName = def.outputs[lookupName];
|
||||
const output = instance[propertyName];
|
||||
|
||||
if (ngDevMode && !isOutputSubscribable(output)) {
|
||||
|
||||
@@ -324,8 +324,6 @@ function setNgReflectProperties(
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: this is identical to the block below, but will diverge in a future refactor.
|
||||
// Figure out if we still can't consolidate them somehow.
|
||||
const inputConfig = tNode.inputs?.[publicName];
|
||||
const hostInputConfig = tNode.hostDirectiveInputs?.[publicName];
|
||||
|
||||
@@ -340,11 +338,9 @@ function setNgReflectProperties(
|
||||
|
||||
// Note: we set the private name of the input as the reflected property, not the public one.
|
||||
if (inputConfig) {
|
||||
for (let i = 0; i < inputConfig.length; i += 2) {
|
||||
const index = inputConfig[i] as number;
|
||||
const lookupName = inputConfig[i + 1] as string;
|
||||
for (const index of inputConfig) {
|
||||
const def = tView.data[index] as DirectiveDef<unknown>;
|
||||
setNgReflectProperty(lView, tNode, def.inputs[lookupName][0], value);
|
||||
setNgReflectProperty(lView, tNode, def.inputs[publicName][0], value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -636,8 +632,6 @@ export function setInputsForProperty(
|
||||
const hostDirectiveInputs = tNode.hostDirectiveInputs?.[publicName];
|
||||
let hasMatch = false;
|
||||
|
||||
// TODO: this is identical to the block below, but will diverge in a future refactor.
|
||||
// Figure out if we still can't consolidate them somehow.
|
||||
if (hostDirectiveInputs) {
|
||||
for (let i = 0; i < hostDirectiveInputs.length; i += 2) {
|
||||
const index = hostDirectiveInputs[i] as number;
|
||||
@@ -650,13 +644,11 @@ export function setInputsForProperty(
|
||||
}
|
||||
|
||||
if (inputs) {
|
||||
for (let i = 0; i < inputs.length; i += 2) {
|
||||
const index = inputs[i] as number;
|
||||
for (const index of inputs) {
|
||||
ngDevMode && assertIndexInRange(lView, index);
|
||||
const privateName = inputs[i + 1] as string;
|
||||
const instance = lView[index];
|
||||
const def = tView.data[index] as DirectiveDef<any>;
|
||||
writeToDirectiveInput(def, instance, privateName, value);
|
||||
writeToDirectiveInput(def, instance, publicName, value);
|
||||
hasMatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -782,36 +782,28 @@ export interface TLetDeclarationNode extends TNode {
|
||||
export type TDirectiveHostNode = TElementNode | TContainerNode | TElementContainerNode;
|
||||
|
||||
/**
|
||||
* Store the runtime output names for all the directives.
|
||||
* Maps the public names of outputs available on a specific node to the index
|
||||
* of the directive instance that defines the output, for example:
|
||||
*
|
||||
* i+0: directive instance index
|
||||
* i+1: privateName
|
||||
*
|
||||
* e.g.
|
||||
* ```
|
||||
* {
|
||||
* "publicName": [0, 'change-minified']
|
||||
* "publicName": [0, 5]
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export type NodeOutputBindings = Record<string, (number | string)[]>;
|
||||
export type NodeOutputBindings = Record<string, number[]>;
|
||||
|
||||
/**
|
||||
* Store the runtime input for all directives applied to a node.
|
||||
* Maps the public names of inputs applied to a specific node to the index of the
|
||||
* directive instance to which the input value should be written, for example:
|
||||
*
|
||||
* This allows efficiently setting the same input on a directive that
|
||||
* might apply to multiple directives.
|
||||
*
|
||||
* i+0: directive instance index
|
||||
* i+1: privateName
|
||||
*
|
||||
* e.g.
|
||||
* ```
|
||||
* {
|
||||
* "publicName": [0, 'change-minified']
|
||||
* "publicName": [0, 5]
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export type NodeInputBindings = Record<string, (number | string)[]>;
|
||||
export type NodeInputBindings = Record<string, number[]>;
|
||||
|
||||
/**
|
||||
* This array contains information about input properties that
|
||||
|
||||
@@ -289,18 +289,14 @@ function setupSelectorMatchedInputsOrOutputs<T>(
|
||||
|
||||
for (const publicName in aliasMap) {
|
||||
if (aliasMap.hasOwnProperty(publicName)) {
|
||||
const value = aliasMap[publicName];
|
||||
let bindings: NodeInputBindings | NodeOutputBindings;
|
||||
let privateName: string;
|
||||
if (mode === BindingType.Inputs) {
|
||||
bindings = tNode.inputs ??= {};
|
||||
privateName = publicName;
|
||||
} else {
|
||||
bindings = tNode.outputs ??= {};
|
||||
privateName = value as string;
|
||||
}
|
||||
bindings[publicName] ??= [];
|
||||
bindings[publicName].push(directiveIndex, privateName);
|
||||
bindings[publicName].push(directiveIndex);
|
||||
setShadowStylingInputFlags(tNode, publicName);
|
||||
}
|
||||
}
|
||||
@@ -397,10 +393,11 @@ function setupInitialInputs(tNode: TNode, directiveIndex: number, isHostDirectiv
|
||||
// through the directive def, but we want to do it using the inputs store so that it can
|
||||
// account for host directive aliases.
|
||||
const inputConfig = inputs![attrName as string];
|
||||
for (let j = 0; j < inputConfig.length; j += 2) {
|
||||
if (inputConfig[j] === directiveIndex) {
|
||||
|
||||
for (const index of inputConfig) {
|
||||
if (index === directiveIndex) {
|
||||
inputsToStore ??= [];
|
||||
inputsToStore.push(inputConfig[j + 1] as string, attrs[i + 1] as string);
|
||||
inputsToStore.push(attrName as string, attrs[i + 1] as string);
|
||||
// A directive can't have multiple inputs with the same name so we can break here.
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user