diff --git a/packages/core/src/render3/i18n.ts b/packages/core/src/render3/i18n.ts
index a24d51b4c3..ae19790c0b 100644
--- a/packages/core/src/render3/i18n.ts
+++ b/packages/core/src/render3/i18n.ts
@@ -471,7 +471,9 @@ function i18nStartFirstPass(
}
}
- allocExpando(viewData, i18nVarsCount);
+ if (i18nVarsCount > 0) {
+ allocExpando(viewData, i18nVarsCount);
+ }
ngDevMode &&
attachI18nOpCodesDebug(
diff --git a/packages/core/src/render3/instructions/shared.ts b/packages/core/src/render3/instructions/shared.ts
index 3d215c4ad2..c25a81cae5 100644
--- a/packages/core/src/render3/instructions/shared.ts
+++ b/packages/core/src/render3/instructions/shared.ts
@@ -11,7 +11,7 @@ import {Type} from '../../interface/type';
import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../../metadata/schema';
import {validateAgainstEventAttributes, validateAgainstEventProperties} from '../../sanitization/sanitization';
import {Sanitizer} from '../../sanitization/security';
-import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertLessThan, assertNotEqual, assertNotSame} from '../../util/assert';
+import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertLessThan, assertNotEqual, assertNotSame} from '../../util/assert';
import {createNamedArrayType} from '../../util/named_array_type';
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
import {assertLView, assertPreviousIsParent} from '../assert';
@@ -316,24 +316,31 @@ export function assignTViewNodeToLView(
* When elements are created dynamically after a view blueprint is created (e.g. through
* i18nApply() or ComponentFactory.create), we need to adjust the blueprint for future
* template passes.
+ *
+ * @param view The LView containing the blueprint to adjust
+ * @param numSlotsToAlloc The number of slots to alloc in the LView, should be >0
*/
export function allocExpando(view: LView, numSlotsToAlloc: number) {
- const tView = view[TVIEW];
- if (tView.firstTemplatePass) {
- for (let i = 0; i < numSlotsToAlloc; i++) {
- tView.blueprint.push(null);
- tView.data.push(null);
- view.push(null);
- }
+ ngDevMode && assertGreaterThan(
+ numSlotsToAlloc, 0, 'The number of slots to alloc should be greater than 0');
+ if (numSlotsToAlloc > 0) {
+ const tView = view[TVIEW];
+ if (tView.firstTemplatePass) {
+ for (let i = 0; i < numSlotsToAlloc; i++) {
+ tView.blueprint.push(null);
+ tView.data.push(null);
+ view.push(null);
+ }
- // We should only increment the expando start index if there aren't already directives
- // and injectors saved in the "expando" section
- if (!tView.expandoInstructions) {
- tView.expandoStartIndex += numSlotsToAlloc;
- } else {
- // Since we're adding the dynamic nodes into the expando section, we need to let the host
- // bindings know that they should skip x slots
- tView.expandoInstructions.push(numSlotsToAlloc);
+ // We should only increment the expando start index if there aren't already directives
+ // and injectors saved in the "expando" section
+ if (!tView.expandoInstructions) {
+ tView.expandoStartIndex += numSlotsToAlloc;
+ } else {
+ // Since we're adding the dynamic nodes into the expando section, we need to let the host
+ // bindings know that they should skip x slots
+ tView.expandoInstructions.push(numSlotsToAlloc);
+ }
}
}
}
diff --git a/packages/core/test/acceptance/i18n_spec.ts b/packages/core/test/acceptance/i18n_spec.ts
index 2ba68ebafd..b4677823b4 100644
--- a/packages/core/test/acceptance/i18n_spec.ts
+++ b/packages/core/test/acceptance/i18n_spec.ts
@@ -1463,6 +1463,30 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
.toEqual(`