Skip to content

Commit fa260a9

Browse files
crisbetothePunderWoman
authored andcommitted
refactor(core): add assertion to avoid writes to directive factories (#59980)
Attempting to write to directive inputs before the directive is created can lead to subtle issues that won't necessarily trigger errors. These changes add an assertion to catch such issues earlier. PR Close #59980
1 parent a1b4579 commit fa260a9

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

packages/core/src/render3/instructions/write_to_directive_input.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {InputSignalNode} from '../../authoring/input/input_signal_node';
1313
import {applyValueToInputField} from '../apply_value_input_field';
1414
import {DirectiveDef} from '../interfaces/definition';
1515
import {InputFlags} from '../interfaces/input_flags';
16+
import {isFactory} from '../interfaces/injector';
1617

1718
export function writeToDirectiveInput<T>(
1819
def: DirectiveDef<T>,
@@ -22,10 +23,21 @@ export function writeToDirectiveInput<T>(
2223
) {
2324
const prevConsumer = setActiveConsumer(null);
2425
try {
25-
if (ngDevMode && !def.inputs.hasOwnProperty(publicName)) {
26-
throw new Error(
27-
`ASSERTION ERROR: Directive ${def.type.name} does not have an input with a public name of "${publicName}"`,
28-
);
26+
if (ngDevMode) {
27+
if (!def.inputs.hasOwnProperty(publicName)) {
28+
throw new Error(
29+
`ASSERTION ERROR: Directive ${def.type.name} does not have an input with a public name of "${publicName}"`,
30+
);
31+
}
32+
33+
// Usually we resolve the directive instance using `LView[someIndex]` before writing to an
34+
// input, however if the read happens to early, the `LView[someIndex]` might actually be a
35+
// `NodeInjectorFactory`. Check for this specific case here since it can break in subtle ways.
36+
if (isFactory(instance)) {
37+
throw new Error(
38+
`ASSERTION ERROR: Cannot write input to factory for type ${def.type.name}. Directive has not been created yet.`,
39+
);
40+
}
2941
}
3042

3143
const [privateName, flags, transform] = def.inputs[publicName];

0 commit comments

Comments
 (0)