@angular/compiler 17.0.7 → 17.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/esm2022/src/constant_pool.mjs +5 -3
  2. package/esm2022/src/ml_parser/tags.mjs +8 -3
  3. package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
  4. package/esm2022/src/render3/partial/directive.mjs +1 -1
  5. package/esm2022/src/render3/partial/factory.mjs +1 -1
  6. package/esm2022/src/render3/partial/injectable.mjs +1 -1
  7. package/esm2022/src/render3/partial/injector.mjs +1 -1
  8. package/esm2022/src/render3/partial/ng_module.mjs +1 -1
  9. package/esm2022/src/render3/partial/pipe.mjs +1 -1
  10. package/esm2022/src/render3/view/template.mjs +7 -7
  11. package/esm2022/src/template/pipeline/ir/src/enums.mjs +7 -3
  12. package/esm2022/src/template/pipeline/ir/src/expression.mjs +5 -1
  13. package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +27 -9
  14. package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +4 -2
  15. package/esm2022/src/template/pipeline/src/emit.mjs +3 -3
  16. package/esm2022/src/template/pipeline/src/ingest.mjs +37 -34
  17. package/esm2022/src/template/pipeline/src/phases/attribute_extraction.mjs +5 -15
  18. package/esm2022/src/template/pipeline/src/phases/const_collection.mjs +25 -10
  19. package/esm2022/src/template/pipeline/src/phases/convert_i18n_bindings.mjs +2 -2
  20. package/esm2022/src/template/pipeline/src/phases/create_defer_deps_fns.mjs +3 -2
  21. package/esm2022/src/template/pipeline/src/phases/create_i18n_contexts.mjs +63 -51
  22. package/esm2022/src/template/pipeline/src/phases/deduplicate_text_bindings.mjs +40 -0
  23. package/esm2022/src/template/pipeline/src/phases/extract_i18n_messages.mjs +52 -49
  24. package/esm2022/src/template/pipeline/src/phases/host_style_property_parsing.mjs +2 -2
  25. package/esm2022/src/template/pipeline/src/phases/i18n_const_collection.mjs +2 -3
  26. package/esm2022/src/template/pipeline/src/phases/i18n_text_extraction.mjs +22 -3
  27. package/esm2022/src/template/pipeline/src/phases/parse_extracted_styles.mjs +19 -1
  28. package/esm2022/src/template/pipeline/src/phases/reify.mjs +8 -8
  29. package/esm2022/src/template/pipeline/src/phases/resolve_i18n_expression_placeholders.mjs +23 -10
  30. package/esm2022/src/template/pipeline/src/phases/var_counting.mjs +8 -1
  31. package/esm2022/src/version.mjs +1 -1
  32. package/fesm2022/compiler.mjs +347 -253
  33. package/fesm2022/compiler.mjs.map +1 -1
  34. package/index.d.ts +3 -3
  35. package/package.json +2 -2
  36. package/esm2022/src/template/pipeline/src/phases/resolve_i18n_icu_placeholders.mjs +0 -62
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v17.0.7
2
+ * @license Angular v17.0.8
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -2308,7 +2308,9 @@ class ConstantPool {
2308
2308
  }))));
2309
2309
  }
2310
2310
  }
2311
- getSharedFunctionReference(fn, prefix) {
2311
+ // TODO: useUniqueName(false) is necessary for naming compatibility with
2312
+ // TemplateDefinitionBuilder, but should be removed once Template Pipeline is the default.
2313
+ getSharedFunctionReference(fn, prefix, useUniqueName = true) {
2312
2314
  const isArrow = fn instanceof ArrowFunctionExpr;
2313
2315
  for (const current of this.statements) {
2314
2316
  // Arrow functions are saved as variables so we check if the
@@ -2323,7 +2325,7 @@ class ConstantPool {
2323
2325
  }
2324
2326
  }
2325
2327
  // Otherwise declare the function.
2326
- const name = this.uniqueName(prefix);
2328
+ const name = useUniqueName ? this.uniqueName(prefix) : prefix;
2327
2329
  this.statements.push(fn.toDeclStmt(name, StmtModifier.Final));
2328
2330
  return variable(name);
2329
2331
  }
@@ -3685,13 +3687,18 @@ var TagContentType;
3685
3687
  TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
3686
3688
  TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
3687
3689
  })(TagContentType || (TagContentType = {}));
3688
- function splitNsName(elementName) {
3690
+ function splitNsName(elementName, fatal = true) {
3689
3691
  if (elementName[0] != ':') {
3690
3692
  return [null, elementName];
3691
3693
  }
3692
3694
  const colonIndex = elementName.indexOf(':', 1);
3693
3695
  if (colonIndex === -1) {
3694
- throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
3696
+ if (fatal) {
3697
+ throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
3698
+ }
3699
+ else {
3700
+ return [null, elementName];
3701
+ }
3695
3702
  }
3696
3703
  return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
3697
3704
  }
@@ -8966,14 +8973,18 @@ var OpKind;
8966
8973
  * An instruction to update an ICU expression.
8967
8974
  */
8968
8975
  OpKind[OpKind["IcuEnd"] = 42] = "IcuEnd";
8976
+ /**
8977
+ * An instruction representing a placeholder in an ICU expression.
8978
+ */
8979
+ OpKind[OpKind["IcuPlaceholder"] = 43] = "IcuPlaceholder";
8969
8980
  /**
8970
8981
  * An i18n context containing information needed to generate an i18n message.
8971
8982
  */
8972
- OpKind[OpKind["I18nContext"] = 43] = "I18nContext";
8983
+ OpKind[OpKind["I18nContext"] = 44] = "I18nContext";
8973
8984
  /**
8974
8985
  * A creation op that corresponds to i18n attributes on an element.
8975
8986
  */
8976
- OpKind[OpKind["I18nAttributes"] = 44] = "I18nAttributes";
8987
+ OpKind[OpKind["I18nAttributes"] = 45] = "I18nAttributes";
8977
8988
  })(OpKind || (OpKind = {}));
8978
8989
  /**
8979
8990
  * Distinguishes different kinds of IR expressions.
@@ -9572,12 +9583,13 @@ function createDeferWhenOp(target, expr, prefetch, sourceSpan) {
9572
9583
  sourceSpan,
9573
9584
  ...NEW_OP,
9574
9585
  ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
9586
+ ...TRAIT_CONSUMES_VARS,
9575
9587
  };
9576
9588
  }
9577
9589
  /**
9578
9590
  * Create an i18n expression op.
9579
9591
  */
9580
- function createI18nExpressionOp(context, target, i18nOwner, handle, expression, i18nPlaceholder, resolutionTime, usage, name, sourceSpan) {
9592
+ function createI18nExpressionOp(context, target, i18nOwner, handle, expression, icuPlaceholder, i18nPlaceholder, resolutionTime, usage, name, sourceSpan) {
9581
9593
  return {
9582
9594
  kind: OpKind.I18nExpression,
9583
9595
  context,
@@ -9585,6 +9597,7 @@ function createI18nExpressionOp(context, target, i18nOwner, handle, expression,
9585
9597
  i18nOwner,
9586
9598
  handle,
9587
9599
  expression,
9600
+ icuPlaceholder,
9588
9601
  i18nPlaceholder,
9589
9602
  resolutionTime,
9590
9603
  usage,
@@ -10354,6 +10367,9 @@ function transformExpressionsInOp(op, transform, flags) {
10354
10367
  op.placeholderConfig =
10355
10368
  transformExpressionsInExpression(op.placeholderConfig, transform, flags);
10356
10369
  }
10370
+ if (op.resolverFn !== null) {
10371
+ op.resolverFn = transformExpressionsInExpression(op.resolverFn, transform, flags);
10372
+ }
10357
10373
  break;
10358
10374
  case OpKind.I18nMessage:
10359
10375
  for (const [placeholder, expr] of op.params) {
@@ -10390,6 +10406,7 @@ function transformExpressionsInOp(op, transform, flags) {
10390
10406
  case OpKind.Template:
10391
10407
  case OpKind.Text:
10392
10408
  case OpKind.I18nAttributes:
10409
+ case OpKind.IcuPlaceholder:
10393
10410
  // These operations contain no expressions.
10394
10411
  break;
10395
10412
  default:
@@ -10797,7 +10814,7 @@ function isElementOrContainerOp(op) {
10797
10814
  /**
10798
10815
  * Create an `ElementStartOp`.
10799
10816
  */
10800
- function createElementStartOp(tag, xref, namespace, i18nPlaceholder, sourceSpan) {
10817
+ function createElementStartOp(tag, xref, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
10801
10818
  return {
10802
10819
  kind: OpKind.ElementStart,
10803
10820
  xref,
@@ -10808,7 +10825,8 @@ function createElementStartOp(tag, xref, namespace, i18nPlaceholder, sourceSpan)
10808
10825
  nonBindable: false,
10809
10826
  namespace,
10810
10827
  i18nPlaceholder,
10811
- sourceSpan,
10828
+ startSourceSpan,
10829
+ wholeSourceSpan,
10812
10830
  ...TRAIT_CONSUMES_SLOT,
10813
10831
  ...NEW_OP,
10814
10832
  };
@@ -10816,7 +10834,7 @@ function createElementStartOp(tag, xref, namespace, i18nPlaceholder, sourceSpan)
10816
10834
  /**
10817
10835
  * Create a `TemplateOp`.
10818
10836
  */
10819
- function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, sourceSpan) {
10837
+ function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
10820
10838
  return {
10821
10839
  kind: OpKind.Template,
10822
10840
  xref,
@@ -10831,12 +10849,13 @@ function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace
10831
10849
  nonBindable: false,
10832
10850
  namespace,
10833
10851
  i18nPlaceholder,
10834
- sourceSpan,
10852
+ startSourceSpan,
10853
+ wholeSourceSpan,
10835
10854
  ...TRAIT_CONSUMES_SLOT,
10836
10855
  ...NEW_OP,
10837
10856
  };
10838
10857
  }
10839
- function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, sourceSpan) {
10858
+ function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, startSourceSpan, wholeSourceSpan) {
10840
10859
  return {
10841
10860
  kind: OpKind.RepeaterCreate,
10842
10861
  attributes: null,
@@ -10856,9 +10875,11 @@ function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i1
10856
10875
  usesComponentInstance: false,
10857
10876
  i18nPlaceholder,
10858
10877
  emptyI18nPlaceholder,
10859
- sourceSpan,
10878
+ startSourceSpan,
10879
+ wholeSourceSpan,
10860
10880
  ...TRAIT_CONSUMES_SLOT,
10861
10881
  ...NEW_OP,
10882
+ ...TRAIT_CONSUMES_VARS,
10862
10883
  numSlotsUsed: emptyView === null ? 2 : 3,
10863
10884
  };
10864
10885
  }
@@ -10890,12 +10911,13 @@ function createEnableBindingsOp(xref) {
10890
10911
  /**
10891
10912
  * Create a `TextOp`.
10892
10913
  */
10893
- function createTextOp(xref, initialValue, sourceSpan) {
10914
+ function createTextOp(xref, initialValue, icuPlaceholder, sourceSpan) {
10894
10915
  return {
10895
10916
  kind: OpKind.Text,
10896
10917
  xref,
10897
10918
  handle: new SlotHandle(),
10898
10919
  initialValue,
10920
+ icuPlaceholder,
10899
10921
  sourceSpan,
10900
10922
  ...TRAIT_CONSUMES_SLOT,
10901
10923
  ...NEW_OP,
@@ -11085,6 +11107,19 @@ function createIcuEndOp(xref) {
11085
11107
  ...NEW_OP,
11086
11108
  };
11087
11109
  }
11110
+ /**
11111
+ * Creates an ICU placeholder op.
11112
+ */
11113
+ function createIcuPlaceholderOp(xref, name, strings) {
11114
+ return {
11115
+ kind: OpKind.IcuPlaceholder,
11116
+ xref,
11117
+ name,
11118
+ strings,
11119
+ expressionPlaceholders: [],
11120
+ ...NEW_OP,
11121
+ };
11122
+ }
11088
11123
  function createI18nContextOp(contextKind, xref, i18nBlock, message, sourceSpan) {
11089
11124
  if (i18nBlock === null && contextKind !== I18nContextKind.Attr) {
11090
11125
  throw new Error('AssertionError: i18nBlock must be provided for non-attribute contexts.');
@@ -11551,21 +11586,11 @@ function extractAttributeOp(unit, op, elements) {
11551
11586
  if (op.expression instanceof Interpolation) {
11552
11587
  return;
11553
11588
  }
11554
- let extractable = op.expression.isConstant();
11589
+ let extractable = op.isTextAttribute || op.expression.isConstant();
11555
11590
  if (unit.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
11556
- // TemplateDefinitionBuilder only extracted attributes that were string literals.
11557
- extractable = isStringLiteral(op.expression);
11558
- if (op.name === 'style' || op.name === 'class') {
11559
- // For style and class attributes, TemplateDefinitionBuilder only extracted them if they were
11560
- // text attributes. For example, `[attr.class]="'my-class'"` was not extracted despite being a
11561
- // string literal, because it is not a text attribute.
11562
- extractable &&= op.isTextAttribute;
11563
- }
11564
- if (unit.job.kind === CompilationJobKind.Host) {
11565
- // TemplateDefinitionBuilder also does not seem to extract string literals if they are part of
11566
- // a host attribute.
11567
- extractable &&= op.isTextAttribute;
11568
- }
11591
+ // TemplateDefinitionBuilder only extracts text attributes. It does not extract attriibute
11592
+ // bindings, even if they are constants.
11593
+ extractable &&= op.isTextAttribute;
11569
11594
  }
11570
11595
  if (extractable) {
11571
11596
  const extractedAttributeOp = createExtractedAttributeOp(op.target, op.isStructuralTemplateAttribute ? BindingKind.Template : BindingKind.Attribute, op.name, op.expression, op.i18nContext, op.i18nMessage, op.securityContext);
@@ -11859,7 +11884,7 @@ function collectElementConsts(job) {
11859
11884
  for (const unit of job.units) {
11860
11885
  for (const op of unit.create) {
11861
11886
  if (op.kind === OpKind.ExtractedAttribute) {
11862
- const attributes = allElementAttributes.get(op.target) || new ElementAttributes();
11887
+ const attributes = allElementAttributes.get(op.target) || new ElementAttributes(job.compatibility);
11863
11888
  allElementAttributes.set(op.target, attributes);
11864
11889
  attributes.add(op.bindingKind, op.name, op.expression, op.trustedValueFn);
11865
11890
  OpList.remove(op);
@@ -11904,11 +11929,6 @@ const FLYWEIGHT_ARRAY = Object.freeze([]);
11904
11929
  * Container for all of the various kinds of attributes which are applied on an element.
11905
11930
  */
11906
11931
  class ElementAttributes {
11907
- constructor() {
11908
- this.known = new Set();
11909
- this.byKind = new Map;
11910
- this.projectAs = null;
11911
- }
11912
11932
  get attributes() {
11913
11933
  return this.byKind.get(BindingKind.Attribute) ?? FLYWEIGHT_ARRAY;
11914
11934
  }
@@ -11927,11 +11947,31 @@ class ElementAttributes {
11927
11947
  get i18n() {
11928
11948
  return this.byKind.get(BindingKind.I18n) ?? FLYWEIGHT_ARRAY;
11929
11949
  }
11950
+ constructor(compatibility) {
11951
+ this.compatibility = compatibility;
11952
+ this.known = new Map();
11953
+ this.byKind = new Map;
11954
+ this.projectAs = null;
11955
+ }
11956
+ isKnown(kind, name, value) {
11957
+ const nameToValue = this.known.get(kind) ?? new Set();
11958
+ this.known.set(kind, nameToValue);
11959
+ if (nameToValue.has(name)) {
11960
+ return true;
11961
+ }
11962
+ nameToValue.add(name);
11963
+ return false;
11964
+ }
11930
11965
  add(kind, name, value, trustedValueFn) {
11931
- if (this.known.has(name)) {
11966
+ // TemplateDefinitionBuilder puts duplicate attribute, class, and style values into the consts
11967
+ // array. This seems inefficient, we can probably keep just the first one or the last value
11968
+ // (whichever actually gets applied when multiple values are listed for the same attribute).
11969
+ const allowDuplicates = this.compatibility === CompatibilityMode.TemplateDefinitionBuilder &&
11970
+ (kind === BindingKind.Attribute || kind === BindingKind.ClassName ||
11971
+ kind === BindingKind.StyleProperty);
11972
+ if (!allowDuplicates && this.isKnown(kind, name, value)) {
11932
11973
  return;
11933
11974
  }
11934
- this.known.add(name);
11935
11975
  // TODO: Can this be its own phase
11936
11976
  if (name === 'ngProjectAs') {
11937
11977
  if (value === null || !(value instanceof LiteralExpr) || (value.value == null) ||
@@ -11970,7 +12010,7 @@ class ElementAttributes {
11970
12010
  * Gets an array of literal expressions representing the attribute's namespaced name.
11971
12011
  */
11972
12012
  function getAttributeNameLiterals$1(name) {
11973
- const [attributeNamespace, attributeName] = splitNsName(name);
12013
+ const [attributeNamespace, attributeName] = splitNsName(name, false);
11974
12014
  const nameLiteral = literal(attributeName);
11975
12015
  if (attributeNamespace) {
11976
12016
  return [
@@ -12043,7 +12083,7 @@ function convertI18nBindings(job) {
12043
12083
  if (op.expression.i18nPlaceholders.length !== op.expression.expressions.length) {
12044
12084
  throw new Error(`AssertionError: An i18n attribute binding instruction requires the same number of expressions and placeholders, but found ${op.expression.i18nPlaceholders.length} placeholders and ${op.expression.expressions.length} expressions`);
12045
12085
  }
12046
- ops.push(createI18nExpressionOp(op.i18nContext, i18nAttributesForElem.target, i18nAttributesForElem.xref, i18nAttributesForElem.handle, expr, op.expression.i18nPlaceholders[i], I18nParamResolutionTime.Creation, I18nExpressionFor.I18nAttribute, op.name, op.sourceSpan));
12086
+ ops.push(createI18nExpressionOp(op.i18nContext, i18nAttributesForElem.target, i18nAttributesForElem.xref, i18nAttributesForElem.handle, expr, null, op.expression.i18nPlaceholders[i], I18nParamResolutionTime.Creation, I18nExpressionFor.I18nAttribute, op.name, op.sourceSpan));
12047
12087
  }
12048
12088
  OpList.replaceWithMany(op, ops);
12049
12089
  break;
@@ -12080,7 +12120,8 @@ function createDeferDepsFns(job) {
12080
12120
  if (op.handle.slot === null) {
12081
12121
  throw new Error('AssertionError: slot must be assigned bfore extracting defer deps functions');
12082
12122
  }
12083
- op.resolverFn = job.pool.getSharedFunctionReference(depsFnExpr, `${job.componentName}_Defer_${op.handle.slot}_DepsFn`);
12123
+ op.resolverFn = job.pool.getSharedFunctionReference(depsFnExpr, `${job.componentName}_Defer_${op.handle.slot}_DepsFn`,
12124
+ /* Don't use unique names for TDB compatibility */ false);
12084
12125
  }
12085
12126
  }
12086
12127
  }
@@ -12097,75 +12138,119 @@ function createDeferDepsFns(job) {
12097
12138
  * message.)
12098
12139
  */
12099
12140
  function createI18nContexts(job) {
12100
- const rootContexts = new Map();
12101
- let currentI18nOp = null;
12102
- let xref;
12103
- // We use the message instead of the message ID, because placeholder values might differ even
12104
- // when IDs are the same.
12105
- const messageToContext = new Map();
12141
+ // Create i18n context ops for i18n attrs.
12142
+ const attrContextByMessage = new Map();
12143
+ for (const unit of job.units) {
12144
+ for (const op of unit.ops()) {
12145
+ switch (op.kind) {
12146
+ case OpKind.Binding:
12147
+ case OpKind.Property:
12148
+ case OpKind.Attribute:
12149
+ case OpKind.ExtractedAttribute:
12150
+ if (op.i18nMessage === null) {
12151
+ continue;
12152
+ }
12153
+ if (!attrContextByMessage.has(op.i18nMessage)) {
12154
+ const i18nContext = createI18nContextOp(I18nContextKind.Attr, job.allocateXrefId(), null, op.i18nMessage, null);
12155
+ unit.create.push(i18nContext);
12156
+ attrContextByMessage.set(op.i18nMessage, i18nContext.xref);
12157
+ }
12158
+ op.i18nContext = attrContextByMessage.get(op.i18nMessage);
12159
+ break;
12160
+ }
12161
+ }
12162
+ }
12163
+ // Create i18n context ops for root i18n blocks.
12164
+ const blockContextByI18nBlock = new Map();
12106
12165
  for (const unit of job.units) {
12107
12166
  for (const op of unit.create) {
12108
12167
  switch (op.kind) {
12109
12168
  case OpKind.I18nStart:
12110
- currentI18nOp = op;
12111
- // Each root i18n block gets its own context, child ones refer to the context for their
12112
- // root block.
12113
12169
  if (op.xref === op.root) {
12114
- xref = job.allocateXrefId();
12115
- unit.create.push(createI18nContextOp(I18nContextKind.RootI18n, xref, op.xref, op.message, null));
12116
- op.context = xref;
12117
- rootContexts.set(op.xref, xref);
12170
+ const contextOp = createI18nContextOp(I18nContextKind.RootI18n, job.allocateXrefId(), op.xref, op.message, null);
12171
+ unit.create.push(contextOp);
12172
+ op.context = contextOp.xref;
12173
+ blockContextByI18nBlock.set(op.xref, contextOp);
12118
12174
  }
12119
12175
  break;
12176
+ }
12177
+ }
12178
+ }
12179
+ // Assign i18n contexts for child i18n blocks. These don't need their own conext, instead they
12180
+ // should inherit from their root i18n block.
12181
+ for (const unit of job.units) {
12182
+ for (const op of unit.create) {
12183
+ if (op.kind === OpKind.I18nStart && op.xref !== op.root) {
12184
+ const rootContext = blockContextByI18nBlock.get(op.root);
12185
+ if (rootContext === undefined) {
12186
+ throw Error('AssertionError: Root i18n block i18n context should have been created.');
12187
+ }
12188
+ op.context = rootContext.xref;
12189
+ blockContextByI18nBlock.set(op.xref, rootContext);
12190
+ }
12191
+ }
12192
+ }
12193
+ // Create or assign i18n contexts for ICUs.
12194
+ let currentI18nOp = null;
12195
+ for (const unit of job.units) {
12196
+ for (const op of unit.create) {
12197
+ switch (op.kind) {
12198
+ case OpKind.I18nStart:
12199
+ currentI18nOp = op;
12200
+ break;
12120
12201
  case OpKind.I18nEnd:
12121
12202
  currentI18nOp = null;
12122
12203
  break;
12123
12204
  case OpKind.IcuStart:
12124
- // If an ICU represents a different message than its containing block, we give it its own
12125
- // i18n context.
12126
12205
  if (currentI18nOp === null) {
12127
- throw Error('Unexpected ICU outside of an i18n block.');
12206
+ throw Error('AssertionError: Unexpected ICU outside of an i18n block.');
12128
12207
  }
12129
12208
  if (op.message.id !== currentI18nOp.message.id) {
12130
- // There was an enclosing i18n block around this ICU somewhere.
12131
- xref = job.allocateXrefId();
12132
- unit.create.push(createI18nContextOp(I18nContextKind.Icu, xref, currentI18nOp.xref, op.message, null));
12133
- op.context = xref;
12209
+ // This ICU is a sub-message inside its parent i18n block message. We need to give it
12210
+ // its own context.
12211
+ const contextOp = createI18nContextOp(I18nContextKind.Icu, job.allocateXrefId(), currentI18nOp.xref, op.message, null);
12212
+ unit.create.push(contextOp);
12213
+ op.context = contextOp.xref;
12134
12214
  }
12135
12215
  else {
12136
- // The i18n block was generated because of this ICU, OR it was explicit, but the ICU is
12137
- // the only localizable content inside of it.
12216
+ // This ICU is the only translatable content in its parent i18n block. We need to
12217
+ // convert the parent's context into an ICU context.
12138
12218
  op.context = currentI18nOp.context;
12219
+ blockContextByI18nBlock.get(currentI18nOp.xref).contextKind = I18nContextKind.Icu;
12139
12220
  }
12140
12221
  break;
12141
12222
  }
12142
12223
  }
12143
- for (const op of unit.ops()) {
12144
- switch (op.kind) {
12145
- case OpKind.Binding:
12146
- case OpKind.Property:
12147
- case OpKind.Attribute:
12148
- case OpKind.ExtractedAttribute:
12149
- if (!op.i18nMessage) {
12150
- continue;
12151
- }
12152
- if (!messageToContext.has(op.i18nMessage)) {
12153
- // create the context
12154
- const i18nContext = job.allocateXrefId();
12155
- unit.create.push(createI18nContextOp(I18nContextKind.Attr, i18nContext, null, op.i18nMessage, null));
12156
- messageToContext.set(op.i18nMessage, i18nContext);
12157
- }
12158
- op.i18nContext = messageToContext.get(op.i18nMessage);
12159
- break;
12160
- }
12161
- }
12162
12224
  }
12163
- // Assign contexts to child i18n blocks, now that all root i18n blocks have their context
12164
- // assigned.
12225
+ }
12226
+
12227
+ /**
12228
+ * Deduplicate text bindings, e.g. <div class="cls1" class="cls2">
12229
+ */
12230
+ function deduplicateTextBindings(job) {
12231
+ const seen = new Map();
12165
12232
  for (const unit of job.units) {
12166
- for (const op of unit.create) {
12167
- if (op.kind === OpKind.I18nStart && op.xref !== op.root) {
12168
- op.context = rootContexts.get(op.root);
12233
+ for (const op of unit.update.reversed()) {
12234
+ if (op.kind === OpKind.Binding && op.isTextAttribute) {
12235
+ const seenForElement = seen.get(op.target) || new Set();
12236
+ if (seenForElement.has(op.name)) {
12237
+ if (job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
12238
+ // For most duplicated attributes, TemplateDefinitionBuilder lists all of the values in
12239
+ // the consts array. However, for style and class attributes it only keeps the last one.
12240
+ // We replicate that behavior here since it has actual consequences for apps with
12241
+ // duplicate class or style attrs.
12242
+ if (op.name === 'style' || op.name === 'class') {
12243
+ OpList.remove(op);
12244
+ }
12245
+ }
12246
+ else {
12247
+ // TODO: Determine the correct behavior. It would probably make sense to merge multiple
12248
+ // style and class attributes. Alternatively we could just throw an error, as HTML
12249
+ // doesn't permit duplicate attributes.
12250
+ }
12251
+ }
12252
+ seenForElement.add(op.name);
12253
+ seen.set(op.target, seenForElement);
12169
12254
  }
12170
12255
  }
12171
12256
  }
@@ -12551,13 +12636,18 @@ const LIST_DELIMITER = '|';
12551
12636
  * used in the final output.
12552
12637
  */
12553
12638
  function extractI18nMessages(job) {
12554
- // Save the i18n start and i18n context ops for later use.
12555
- const i18nContexts = new Map();
12639
+ // Create an i18n message for each context.
12640
+ // TODO: Merge the context op with the message op since they're 1:1 anyways.
12641
+ const i18nMessagesByContext = new Map();
12556
12642
  const i18nBlocks = new Map();
12643
+ const i18nContexts = new Map();
12557
12644
  for (const unit of job.units) {
12558
12645
  for (const op of unit.create) {
12559
12646
  switch (op.kind) {
12560
12647
  case OpKind.I18nContext:
12648
+ const i18nMessageOp = createI18nMessage(job, op);
12649
+ unit.create.push(i18nMessageOp);
12650
+ i18nMessagesByContext.set(op.xref, i18nMessageOp);
12561
12651
  i18nContexts.set(op.xref, op);
12562
12652
  break;
12563
12653
  case OpKind.I18nStart:
@@ -12566,54 +12656,47 @@ function extractI18nMessages(job) {
12566
12656
  }
12567
12657
  }
12568
12658
  }
12569
- // TODO: Miles and I think that contexts have a 1-to-1 correspondence with extracted messages, so
12570
- // this phase can probably be simplified.
12571
- // Extract messages from contexts of i18n attributes.
12572
- for (const unit of job.units) {
12573
- for (const op of unit.create) {
12574
- if (op.kind !== OpKind.I18nContext || op.contextKind !== I18nContextKind.Attr) {
12575
- continue;
12576
- }
12577
- const i18nMessageOp = createI18nMessage(job, op);
12578
- unit.create.push(i18nMessageOp);
12579
- }
12580
- }
12581
- // Extract messages from root i18n blocks.
12582
- const i18nBlockMessages = new Map();
12583
- for (const unit of job.units) {
12584
- for (const op of unit.create) {
12585
- if (op.kind === OpKind.I18nStart && op.xref === op.root) {
12586
- if (!op.context) {
12587
- throw Error('I18n start op should have its context set.');
12588
- }
12589
- const i18nMessageOp = createI18nMessage(job, i18nContexts.get(op.context));
12590
- i18nBlockMessages.set(op.xref, i18nMessageOp);
12591
- unit.create.push(i18nMessageOp);
12592
- }
12593
- }
12594
- }
12595
- // Extract messages from ICUs with their own sub-context.
12659
+ // Associate sub-messages for ICUs with their root message. At this point we can also remove the
12660
+ // ICU start/end ops, as they are no longer needed.
12661
+ let currentIcu = null;
12596
12662
  for (const unit of job.units) {
12597
12663
  for (const op of unit.create) {
12598
12664
  switch (op.kind) {
12599
12665
  case OpKind.IcuStart:
12600
- if (!op.context) {
12601
- throw Error('ICU op should have its context set.');
12666
+ currentIcu = op;
12667
+ OpList.remove(op);
12668
+ // Skip any contexts not associated with an ICU.
12669
+ const icuContext = i18nContexts.get(op.context);
12670
+ if (icuContext.contextKind !== I18nContextKind.Icu) {
12671
+ continue;
12602
12672
  }
12603
- const i18nContext = i18nContexts.get(op.context);
12604
- if (i18nContext.contextKind === I18nContextKind.Icu) {
12605
- if (i18nContext.i18nBlock === null) {
12606
- throw Error('ICU context should have its i18n block set.');
12607
- }
12608
- const subMessage = createI18nMessage(job, i18nContext, op.messagePlaceholder);
12609
- unit.create.push(subMessage);
12610
- const rootI18nId = i18nBlocks.get(i18nContext.i18nBlock).root;
12611
- const parentMessage = i18nBlockMessages.get(rootI18nId);
12612
- parentMessage?.subMessages.push(subMessage.xref);
12673
+ // Skip ICUs that share a context with their i18n message. These represent root-level
12674
+ // ICUs, not sub-messages.
12675
+ const i18nBlock = i18nBlocks.get(icuContext.i18nBlock);
12676
+ if (i18nBlock.context === icuContext.xref) {
12677
+ continue;
12613
12678
  }
12614
- OpList.remove(op);
12679
+ // Find the root message and push this ICUs message as a sub-message.
12680
+ const rootI18nBlock = i18nBlocks.get(i18nBlock.root);
12681
+ const rootMessage = i18nMessagesByContext.get(rootI18nBlock.context);
12682
+ if (rootMessage === undefined) {
12683
+ throw Error('AssertionError: ICU sub-message should belong to a root message.');
12684
+ }
12685
+ const subMessage = i18nMessagesByContext.get(icuContext.xref);
12686
+ subMessage.messagePlaceholder = op.messagePlaceholder;
12687
+ rootMessage.subMessages.push(subMessage.xref);
12615
12688
  break;
12616
12689
  case OpKind.IcuEnd:
12690
+ currentIcu = null;
12691
+ OpList.remove(op);
12692
+ break;
12693
+ case OpKind.IcuPlaceholder:
12694
+ // Add ICU placeholders to the message, then remove the ICU placeholder ops.
12695
+ if (currentIcu === null || currentIcu.context == null) {
12696
+ throw Error('AssertionError: Unexpected ICU placeholder outside of i18n context');
12697
+ }
12698
+ const msg = i18nMessagesByContext.get(currentIcu.context);
12699
+ msg.postprocessingParams.set(op.name, literal(formatIcuPlaceholder(op)));
12617
12700
  OpList.remove(op);
12618
12701
  break;
12619
12702
  }
@@ -12626,14 +12709,19 @@ function extractI18nMessages(job) {
12626
12709
  function createI18nMessage(job, context, messagePlaceholder) {
12627
12710
  let formattedParams = formatParams(context.params);
12628
12711
  const formattedPostprocessingParams = formatParams(context.postprocessingParams);
12629
- let needsPostprocessing = formattedPostprocessingParams.size > 0;
12630
- for (const values of context.params.values()) {
12631
- if (values.length > 1) {
12632
- needsPostprocessing = true;
12633
- }
12634
- }
12712
+ let needsPostprocessing = [...context.params.values()].some(v => v.length > 1);
12635
12713
  return createI18nMessageOp(job.allocateXrefId(), context.xref, context.i18nBlock, context.message, messagePlaceholder ?? null, formattedParams, formattedPostprocessingParams, needsPostprocessing);
12636
12714
  }
12715
+ /**
12716
+ * Formats an ICU placeholder into a single string with expression placeholders.
12717
+ */
12718
+ function formatIcuPlaceholder(op) {
12719
+ if (op.strings.length !== op.expressionPlaceholders.length + 1) {
12720
+ throw Error(`AsserionError: Invalid ICU placeholder with ${op.strings.length} strings and ${op.expressionPlaceholders.length} expressions`);
12721
+ }
12722
+ const values = op.expressionPlaceholders.map(formatValue);
12723
+ return op.strings.flatMap((str, i) => [str, values[i] || '']).join('');
12724
+ }
12637
12725
  /**
12638
12726
  * Formats a map of `I18nParamValue[]` values into a map of `Expression` values.
12639
12727
  */
@@ -12972,7 +13060,7 @@ const BANG_IMPORTANT = '!important';
12972
13060
  */
12973
13061
  function parseHostStyleProperties(job) {
12974
13062
  for (const op of job.root.update) {
12975
- if (op.kind !== OpKind.Binding) {
13063
+ if (!(op.kind === OpKind.Binding && op.bindingKind === BindingKind.Property)) {
12976
13064
  continue;
12977
13065
  }
12978
13066
  if (op.name.endsWith(BANG_IMPORTANT)) {
@@ -20130,7 +20218,7 @@ function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
20130
20218
  let transformFn = undefined;
20131
20219
  // If nescessary, add a post-processing step and resolve any placeholder params that are
20132
20220
  // set in post-processing.
20133
- if (messageOp.needsPostprocessing) {
20221
+ if (messageOp.needsPostprocessing || messageOp.postprocessingParams.size > 0) {
20134
20222
  // Sort the post-processing params for consistency with TemaplateDefinitionBuilder output.
20135
20223
  const postprocessingParams = Object.fromEntries([...messageOp.postprocessingParams.entries()].sort());
20136
20224
  const formattedPostprocessingParams = formatI18nPlaceholderNamesInMap(postprocessingParams, /* useCamelCase */ false);
@@ -20160,7 +20248,6 @@ function addSubMessageParams(messageOp, subMessagePlaceholders) {
20160
20248
  else {
20161
20249
  messageOp.params.set(placeholder, literal(`${ESCAPE}${I18N_ICU_MAPPING_PREFIX}${placeholder}${ESCAPE}`));
20162
20250
  messageOp.postprocessingParams.set(placeholder, literalArr(subMessages));
20163
- messageOp.needsPostprocessing = true;
20164
20251
  }
20165
20252
  }
20166
20253
  }
@@ -20246,6 +20333,7 @@ function convertI18nText(job) {
20246
20333
  let currentIcu = null;
20247
20334
  const textNodeI18nBlocks = new Map();
20248
20335
  const textNodeIcus = new Map();
20336
+ const icuPlaceholderByText = new Map();
20249
20337
  for (const op of unit.create) {
20250
20338
  switch (op.kind) {
20251
20339
  case OpKind.I18nStart:
@@ -20270,7 +20358,19 @@ function convertI18nText(job) {
20270
20358
  if (currentI18n !== null) {
20271
20359
  textNodeI18nBlocks.set(op.xref, currentI18n);
20272
20360
  textNodeIcus.set(op.xref, currentIcu);
20273
- OpList.remove(op);
20361
+ if (op.icuPlaceholder !== null) {
20362
+ // Create an op to represent the ICU placeholder. Initially set its static text to the
20363
+ // value of the text op, though this may be overwritten later if this text op is a
20364
+ // placeholder for an interpolation.
20365
+ const icuPlaceholderOp = createIcuPlaceholderOp(job.allocateXrefId(), op.icuPlaceholder, [op.initialValue]);
20366
+ OpList.replace(op, icuPlaceholderOp);
20367
+ icuPlaceholderByText.set(op.xref, icuPlaceholderOp);
20368
+ }
20369
+ else {
20370
+ // Otherwise just remove the text op, since its value is already accounted for in the
20371
+ // translated message.
20372
+ OpList.remove(op);
20373
+ }
20274
20374
  }
20275
20375
  break;
20276
20376
  }
@@ -20285,6 +20385,7 @@ function convertI18nText(job) {
20285
20385
  }
20286
20386
  const i18nOp = textNodeI18nBlocks.get(op.target);
20287
20387
  const icuOp = textNodeIcus.get(op.target);
20388
+ const icuPlaceholder = icuPlaceholderByText.get(op.target);
20288
20389
  const contextId = icuOp ? icuOp.context : i18nOp.context;
20289
20390
  const resolutionTime = icuOp ? I18nParamResolutionTime.Postproccessing :
20290
20391
  I18nParamResolutionTime.Creation;
@@ -20293,9 +20394,14 @@ function convertI18nText(job) {
20293
20394
  const expr = op.interpolation.expressions[i];
20294
20395
  // For now, this i18nExpression depends on the slot context of the enclosing i18n block.
20295
20396
  // Later, we will modify this, and advance to a different point.
20296
- ops.push(createI18nExpressionOp(contextId, i18nOp.xref, i18nOp.xref, i18nOp.handle, expr, op.interpolation.i18nPlaceholders[i], resolutionTime, I18nExpressionFor.I18nText, '', expr.sourceSpan ?? op.sourceSpan));
20397
+ ops.push(createI18nExpressionOp(contextId, i18nOp.xref, i18nOp.xref, i18nOp.handle, expr, icuPlaceholder?.xref ?? null, op.interpolation.i18nPlaceholders[i] ?? null, resolutionTime, I18nExpressionFor.I18nText, '', expr.sourceSpan ?? op.sourceSpan));
20297
20398
  }
20298
20399
  OpList.replaceWithMany(op, ops);
20400
+ // If this interpolation is part of an ICU placeholder, add the strings and expressions to
20401
+ // the placeholder.
20402
+ if (icuPlaceholder !== undefined) {
20403
+ icuPlaceholder.strings = op.interpolation.strings;
20404
+ }
20299
20405
  break;
20300
20406
  }
20301
20407
  }
@@ -20824,10 +20930,28 @@ function keepLast(ops) {
20824
20930
  * class property.
20825
20931
  */
20826
20932
  function parseExtractedStyles(job) {
20933
+ const elements = new Map();
20934
+ for (const unit of job.units) {
20935
+ for (const op of unit.create) {
20936
+ if (isElementOrContainerOp(op)) {
20937
+ elements.set(op.xref, op);
20938
+ }
20939
+ }
20940
+ }
20827
20941
  for (const unit of job.units) {
20828
20942
  for (const op of unit.create) {
20829
20943
  if (op.kind === OpKind.ExtractedAttribute && op.bindingKind === BindingKind.Attribute &&
20830
20944
  isStringLiteral(op.expression)) {
20945
+ const target = elements.get(op.target);
20946
+ if (target !== undefined && target.kind === OpKind.Template &&
20947
+ target.templateKind === TemplateKind.Structural) {
20948
+ // TemplateDefinitionBuilder will not apply class and style bindings to structural
20949
+ // directives; instead, it will leave them as attributes.
20950
+ // (It's not clear what that would mean, anyway -- classes and styles on a structural
20951
+ // element should probably be a parse error.)
20952
+ // TODO: We may be able to remove this once Template Pipeline is the default.
20953
+ continue;
20954
+ }
20831
20955
  if (op.name === 'style') {
20832
20956
  const parsedStyles = parse(op.expression.value);
20833
20957
  for (let i = 0; i < parsedStyles.length - 1; i += 2) {
@@ -21719,19 +21843,19 @@ function reifyCreateOperations(unit, ops) {
21719
21843
  OpList.replace(op, text(op.handle.slot, op.initialValue, op.sourceSpan));
21720
21844
  break;
21721
21845
  case OpKind.ElementStart:
21722
- OpList.replace(op, elementStart(op.handle.slot, op.tag, op.attributes, op.localRefs, op.sourceSpan));
21846
+ OpList.replace(op, elementStart(op.handle.slot, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
21723
21847
  break;
21724
21848
  case OpKind.Element:
21725
- OpList.replace(op, element(op.handle.slot, op.tag, op.attributes, op.localRefs, op.sourceSpan));
21849
+ OpList.replace(op, element(op.handle.slot, op.tag, op.attributes, op.localRefs, op.wholeSourceSpan));
21726
21850
  break;
21727
21851
  case OpKind.ElementEnd:
21728
21852
  OpList.replace(op, elementEnd(op.sourceSpan));
21729
21853
  break;
21730
21854
  case OpKind.ContainerStart:
21731
- OpList.replace(op, elementContainerStart(op.handle.slot, op.attributes, op.localRefs, op.sourceSpan));
21855
+ OpList.replace(op, elementContainerStart(op.handle.slot, op.attributes, op.localRefs, op.startSourceSpan));
21732
21856
  break;
21733
21857
  case OpKind.Container:
21734
- OpList.replace(op, elementContainer(op.handle.slot, op.attributes, op.localRefs, op.sourceSpan));
21858
+ OpList.replace(op, elementContainer(op.handle.slot, op.attributes, op.localRefs, op.wholeSourceSpan));
21735
21859
  break;
21736
21860
  case OpKind.ContainerEnd:
21737
21861
  OpList.replace(op, elementContainerEnd());
@@ -21759,7 +21883,7 @@ function reifyCreateOperations(unit, ops) {
21759
21883
  throw new Error(`AssertionError: local refs array should have been extracted into a constant`);
21760
21884
  }
21761
21885
  const childView = unit.job.views.get(op.xref);
21762
- OpList.replace(op, template(op.handle.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes, op.localRefs, op.sourceSpan));
21886
+ OpList.replace(op, template(op.handle.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
21763
21887
  break;
21764
21888
  case OpKind.DisableBindings:
21765
21889
  OpList.replace(op, disableBindings());
@@ -21774,7 +21898,7 @@ function reifyCreateOperations(unit, ops) {
21774
21898
  const listenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
21775
21899
  const eventTargetResolver = op.eventTarget ? GLOBAL_TARGET_RESOLVERS$1.get(op.eventTarget) : null;
21776
21900
  if (eventTargetResolver === undefined) {
21777
- throw new Error(`AssertionError: unknown event target ${op.eventTarget}`);
21901
+ throw new Error(`Unexpected global target '${op.eventTarget}' defined for '${op.name}' event. Supported list of global targets: window,document,body.`);
21778
21902
  }
21779
21903
  OpList.replace(op, listener(op.name, listenerFn, eventTargetResolver, op.hostListener && op.isAnimationListener, op.sourceSpan));
21780
21904
  break;
@@ -21861,7 +21985,7 @@ function reifyCreateOperations(unit, ops) {
21861
21985
  emptyDecls = emptyView.decls;
21862
21986
  emptyVars = emptyView.vars;
21863
21987
  }
21864
- OpList.replace(op, repeaterCreate(op.handle.slot, repeaterView.fnName, op.decls, op.vars, op.tag, op.attributes, op.trackByFn, op.usesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, op.sourceSpan));
21988
+ OpList.replace(op, repeaterCreate(op.handle.slot, repeaterView.fnName, op.decls, op.vars, op.tag, op.attributes, op.trackByFn, op.usesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, op.wholeSourceSpan));
21865
21989
  break;
21866
21990
  case OpKind.Statement:
21867
21991
  // Pass statement operations directly through.
@@ -22491,6 +22615,7 @@ function resolveI18nExpressionPlaceholders(job) {
22491
22615
  // Record all of the i18n context ops, and the sub-template index for each i18n op.
22492
22616
  const subTemplateIndicies = new Map();
22493
22617
  const i18nContexts = new Map();
22618
+ const icuPlaceholders = new Map();
22494
22619
  for (const unit of job.units) {
22495
22620
  for (const op of unit.create) {
22496
22621
  switch (op.kind) {
@@ -22500,6 +22625,9 @@ function resolveI18nExpressionPlaceholders(job) {
22500
22625
  case OpKind.I18nContext:
22501
22626
  i18nContexts.set(op.xref, op);
22502
22627
  break;
22628
+ case OpKind.IcuPlaceholder:
22629
+ icuPlaceholders.set(op.xref, op);
22630
+ break;
22503
22631
  }
22504
22632
  }
22505
22633
  }
@@ -22513,76 +22641,32 @@ function resolveI18nExpressionPlaceholders(job) {
22513
22641
  for (const unit of job.units) {
22514
22642
  for (const op of unit.update) {
22515
22643
  if (op.kind === OpKind.I18nExpression) {
22516
- const i18nContext = i18nContexts.get(op.context);
22517
22644
  const index = expressionIndices.get(referenceIndex(op)) || 0;
22518
22645
  const subTemplateIndex = subTemplateIndicies.get(op.i18nOwner) ?? null;
22519
- // Add the expression index in the appropriate params map.
22520
- const params = op.resolutionTime === I18nParamResolutionTime.Creation ?
22521
- i18nContext.params :
22522
- i18nContext.postprocessingParams;
22523
- const values = params.get(op.i18nPlaceholder) || [];
22524
- values.push({
22646
+ const value = {
22525
22647
  value: index,
22526
22648
  subTemplateIndex: subTemplateIndex,
22527
22649
  flags: I18nParamValueFlags.ExpressionIndex
22528
- });
22529
- params.set(op.i18nPlaceholder, values);
22650
+ };
22651
+ updatePlaceholder(op, value, i18nContexts, icuPlaceholders);
22530
22652
  expressionIndices.set(referenceIndex(op), index + 1);
22531
22653
  }
22532
22654
  }
22533
22655
  }
22534
22656
  }
22535
-
22536
- /**
22537
- * Resolves placeholders for element tags inside of an ICU.
22538
- */
22539
- function resolveI18nIcuPlaceholders(job) {
22540
- for (const unit of job.units) {
22541
- for (const op of unit.create) {
22542
- if (op.kind === OpKind.I18nContext && op.contextKind === I18nContextKind.Icu) {
22543
- for (const node of op.message.nodes) {
22544
- node.visit(new ResolveIcuPlaceholdersVisitor(op.postprocessingParams));
22545
- }
22546
- }
22547
- }
22548
- }
22549
- }
22550
- /**
22551
- * Visitor for i18n AST that resolves ICU params into the given map.
22552
- */
22553
- class ResolveIcuPlaceholdersVisitor extends RecurseVisitor {
22554
- constructor(params) {
22555
- super();
22556
- this.params = params;
22557
- }
22558
- visitContainerPlaceholder(placeholder) {
22559
- // Add the start and end source span for container placeholders. These need to be recorded for
22560
- // elements inside ICUs. The slots for the nodes were recorded separately under the i18n
22561
- // block's context as part of the `resolveI18nElementPlaceholders` phase.
22562
- if (placeholder.startName && placeholder.startSourceSpan &&
22563
- !this.params.has(placeholder.startName)) {
22564
- this.params.set(placeholder.startName, [{
22565
- value: placeholder.startSourceSpan?.toString(),
22566
- subTemplateIndex: null,
22567
- flags: I18nParamValueFlags.None
22568
- }]);
22569
- }
22570
- if (placeholder.closeName && placeholder.endSourceSpan &&
22571
- !this.params.has(placeholder.closeName)) {
22572
- this.params.set(placeholder.closeName, [{
22573
- value: placeholder.endSourceSpan?.toString(),
22574
- subTemplateIndex: null,
22575
- flags: I18nParamValueFlags.None
22576
- }]);
22577
- }
22578
- }
22579
- visitTagPlaceholder(placeholder) {
22580
- super.visitTagPlaceholder(placeholder);
22581
- this.visitContainerPlaceholder(placeholder);
22657
+ function updatePlaceholder(op, value, i18nContexts, icuPlaceholders) {
22658
+ if (op.i18nPlaceholder !== null) {
22659
+ const i18nContext = i18nContexts.get(op.context);
22660
+ const params = op.resolutionTime === I18nParamResolutionTime.Creation ?
22661
+ i18nContext.params :
22662
+ i18nContext.postprocessingParams;
22663
+ const values = params.get(op.i18nPlaceholder) || [];
22664
+ values.push(value);
22665
+ params.set(op.i18nPlaceholder, values);
22582
22666
  }
22583
- visitBlockPlaceholder(placeholder) {
22584
- super.visitBlockPlaceholder(placeholder);
22585
- this.visitContainerPlaceholder(placeholder);
22667
+ if (op.icuPlaceholder !== null) {
22668
+ const icuPlaceholderOp = icuPlaceholders.get(op.icuPlaceholder);
22669
+ icuPlaceholderOp?.expressionPlaceholders.push(value);
22586
22670
  }
22587
22671
  }
22588
22672
 
@@ -23257,7 +23341,14 @@ function varsUsedByOp(op) {
23257
23341
  return op.interpolation.expressions.length;
23258
23342
  case OpKind.I18nExpression:
23259
23343
  case OpKind.Conditional:
23344
+ case OpKind.DeferWhen:
23260
23345
  return 1;
23346
+ case OpKind.RepeaterCreate:
23347
+ // Repeaters may require an extra variable binding slot, if they have an empty view, for the
23348
+ // empty block tracking.
23349
+ // TODO: It's a bit odd to have a create mode instruction consume variable slots. Maybe we can
23350
+ // find a way to use the Repeater update op instead.
23351
+ return op.emptyView ? 1 : 0;
23261
23352
  default:
23262
23353
  throw new Error(`Unhandled op: ${OpKind[op.kind]}`);
23263
23354
  }
@@ -23741,6 +23832,7 @@ const phases = [
23741
23832
  { kind: CompilationJobKind.Tmpl, fn: emitNamespaceChanges },
23742
23833
  { kind: CompilationJobKind.Tmpl, fn: propagateI18nBlocks },
23743
23834
  { kind: CompilationJobKind.Tmpl, fn: wrapI18nIcus },
23835
+ { kind: CompilationJobKind.Both, fn: deduplicateTextBindings },
23744
23836
  { kind: CompilationJobKind.Both, fn: specializeStyleBindings },
23745
23837
  { kind: CompilationJobKind.Both, fn: specializeBindings },
23746
23838
  { kind: CompilationJobKind.Both, fn: extractAttributes },
@@ -23779,7 +23871,6 @@ const phases = [
23779
23871
  { kind: CompilationJobKind.Tmpl, fn: createDeferDepsFns },
23780
23872
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nElementPlaceholders },
23781
23873
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nExpressionPlaceholders },
23782
- { kind: CompilationJobKind.Tmpl, fn: resolveI18nIcuPlaceholders },
23783
23874
  { kind: CompilationJobKind.Tmpl, fn: extractI18nMessages },
23784
23875
  { kind: CompilationJobKind.Tmpl, fn: generateTrackFns },
23785
23876
  { kind: CompilationJobKind.Tmpl, fn: collectI18nConsts },
@@ -23939,7 +24030,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
23939
24030
  const securityContexts = bindingParser
23940
24031
  .calcPossibleSecurityContexts(input.componentSelector, property.name, bindingKind === BindingKind.Attribute)
23941
24032
  .filter(context => context !== SecurityContext.NONE);
23942
- ingestHostProperty(job, property, bindingKind, false, securityContexts);
24033
+ ingestHostProperty(job, property, bindingKind, securityContexts);
23943
24034
  }
23944
24035
  for (const [name, expr] of Object.entries(input.attributes) ?? []) {
23945
24036
  const securityContexts = bindingParser.calcPossibleSecurityContexts(input.componentSelector, name, true)
@@ -23953,7 +24044,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
23953
24044
  }
23954
24045
  // TODO: We should refactor the parser to use the same types and structures for host bindings as
23955
24046
  // with ordinary components. This would allow us to share a lot more ingestion code.
23956
- function ingestHostProperty(job, property, bindingKind, isTextAttribute, securityContexts) {
24047
+ function ingestHostProperty(job, property, bindingKind, securityContexts) {
23957
24048
  let expression;
23958
24049
  const ast = property.expression.ast;
23959
24050
  if (ast instanceof Interpolation$1) {
@@ -23962,20 +24053,21 @@ function ingestHostProperty(job, property, bindingKind, isTextAttribute, securit
23962
24053
  else {
23963
24054
  expression = convertAst(ast, job, property.sourceSpan);
23964
24055
  }
23965
- job.root.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, securityContexts, isTextAttribute, false, null, /* TODO: How do Host bindings handle i18n attrs? */ null, property.sourceSpan));
24056
+ job.root.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, securityContexts, false, false, null, /* TODO: How do Host bindings handle i18n attrs? */ null, property.sourceSpan));
23966
24057
  }
23967
24058
  function ingestHostAttribute(job, name, value, securityContexts) {
23968
- const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null, securityContexts, true, false, null,
24059
+ const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null, securityContexts,
24060
+ /* Host attributes should always be extracted to const hostAttrs, even if they are not
24061
+ *strictly* text literals */
24062
+ true, false, null,
23969
24063
  /* TODO */ null,
23970
- /* TODO: host attribute source spans */ null);
24064
+ /** TODO: May be null? */ value.sourceSpan);
23971
24065
  job.root.update.push(attrBinding);
23972
24066
  }
23973
24067
  function ingestHostEvent(job, event) {
23974
24068
  const [phase, target] = event.type === 0 /* e.ParsedEventType.Regular */ ? [null, event.targetOrPhase] :
23975
24069
  [event.targetOrPhase, null];
23976
- const eventBinding = createListenerOp(job.root.xref, new SlotHandle(), event.name, null, [], phase, target, true, event.sourceSpan);
23977
- // TODO: Can this be a chain?
23978
- eventBinding.handlerOps.push(createStatementOp(new ReturnStatement(convertAst(event.handler.ast, job, event.sourceSpan), event.handlerSpan)));
24070
+ const eventBinding = createListenerOp(job.root.xref, new SlotHandle(), event.name, null, makeListenerHandlerOps(job.root, event.handler, event.handlerSpan), phase, target, true, event.sourceSpan);
23979
24071
  job.root.create.push(eventBinding);
23980
24072
  }
23981
24073
  /**
@@ -23993,10 +24085,10 @@ function ingestNodes(unit, template) {
23993
24085
  ingestContent(unit, node);
23994
24086
  }
23995
24087
  else if (node instanceof Text$3) {
23996
- ingestText(unit, node);
24088
+ ingestText(unit, node, null);
23997
24089
  }
23998
24090
  else if (node instanceof BoundText) {
23999
- ingestBoundText(unit, node);
24091
+ ingestBoundText(unit, node, null);
24000
24092
  }
24001
24093
  else if (node instanceof IfBlock) {
24002
24094
  ingestIfBlock(unit, node);
@@ -24028,7 +24120,7 @@ function ingestElement(unit, element) {
24028
24120
  }
24029
24121
  const id = unit.job.allocateXrefId();
24030
24122
  const [namespaceKey, elementName] = splitNsName(element.name);
24031
- const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n instanceof TagPlaceholder ? element.i18n : undefined, element.startSourceSpan);
24123
+ const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n instanceof TagPlaceholder ? element.i18n : undefined, element.startSourceSpan, element.sourceSpan);
24032
24124
  unit.create.push(startOp);
24033
24125
  ingestElementBindings(unit, startOp, element);
24034
24126
  ingestReferences(startOp, element);
@@ -24071,7 +24163,7 @@ function ingestTemplate(unit, tmpl) {
24071
24163
  '' :
24072
24164
  prefixWithNamespace(tagNameWithoutNamespace, namespace);
24073
24165
  const templateKind = isPlainTemplate(tmpl) ? TemplateKind.NgTemplate : TemplateKind.Structural;
24074
- const templateOp = createTemplateOp(childView.xref, templateKind, tagNameWithoutNamespace, functionNameSuffix, namespace, i18nPlaceholder, tmpl.startSourceSpan);
24166
+ const templateOp = createTemplateOp(childView.xref, templateKind, tagNameWithoutNamespace, functionNameSuffix, namespace, i18nPlaceholder, tmpl.startSourceSpan, tmpl.sourceSpan);
24075
24167
  unit.create.push(templateOp);
24076
24168
  ingestTemplateBindings(unit, templateOp, tmpl, templateKind);
24077
24169
  ingestReferences(templateOp, tmpl);
@@ -24106,13 +24198,13 @@ function ingestContent(unit, content) {
24106
24198
  /**
24107
24199
  * Ingest a literal text node from the AST into the given `ViewCompilation`.
24108
24200
  */
24109
- function ingestText(unit, text) {
24110
- unit.create.push(createTextOp(unit.job.allocateXrefId(), text.value, text.sourceSpan));
24201
+ function ingestText(unit, text, icuPlaceholder) {
24202
+ unit.create.push(createTextOp(unit.job.allocateXrefId(), text.value, icuPlaceholder, text.sourceSpan));
24111
24203
  }
24112
24204
  /**
24113
24205
  * Ingest an interpolated text node from the AST into the given `ViewCompilation`.
24114
24206
  */
24115
- function ingestBoundText(unit, text, i18nPlaceholders) {
24207
+ function ingestBoundText(unit, text, icuPlaceholder) {
24116
24208
  let value = text.value;
24117
24209
  if (value instanceof ASTWithSource) {
24118
24210
  value = value.ast;
@@ -24123,19 +24215,16 @@ function ingestBoundText(unit, text, i18nPlaceholders) {
24123
24215
  if (text.i18n !== undefined && !(text.i18n instanceof Container)) {
24124
24216
  throw Error(`Unhandled i18n metadata type for text interpolation: ${text.i18n?.constructor.name}`);
24125
24217
  }
24126
- if (i18nPlaceholders === undefined) {
24127
- // TODO: We probably can just use the placeholders field, instead of walking the AST.
24128
- i18nPlaceholders = text.i18n instanceof Container ?
24129
- text.i18n.children
24130
- .filter((node) => node instanceof Placeholder)
24131
- .map(placeholder => placeholder.name) :
24132
- [];
24133
- }
24218
+ const i18nPlaceholders = text.i18n instanceof Container ?
24219
+ text.i18n.children
24220
+ .filter((node) => node instanceof Placeholder)
24221
+ .map(placeholder => placeholder.name) :
24222
+ [];
24134
24223
  if (i18nPlaceholders.length > 0 && i18nPlaceholders.length !== value.expressions.length) {
24135
24224
  throw Error(`Unexpected number of i18n placeholders (${value.expressions.length}) for BoundText with ${value.expressions.length} expressions`);
24136
24225
  }
24137
24226
  const textXref = unit.job.allocateXrefId();
24138
- unit.create.push(createTextOp(textXref, '', text.sourceSpan));
24227
+ unit.create.push(createTextOp(textXref, '', icuPlaceholder, text.sourceSpan));
24139
24228
  // TemplateDefinitionBuilder does not generate source maps for sub-expressions inside an
24140
24229
  // interpolation. We copy that behavior in compatibility mode.
24141
24230
  // TODO: is it actually correct to generate these extra maps in modern mode?
@@ -24168,7 +24257,7 @@ function ingestIfBlock(unit, ifBlock) {
24168
24257
  }
24169
24258
  ifCaseI18nMeta = ifCase.i18n;
24170
24259
  }
24171
- const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, tagName, 'Conditional', Namespace.HTML, ifCaseI18nMeta, ifCase.sourceSpan);
24260
+ const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, tagName, 'Conditional', Namespace.HTML, ifCaseI18nMeta, ifCase.startSourceSpan, ifCase.sourceSpan);
24172
24261
  unit.create.push(templateOp);
24173
24262
  if (firstXref === null) {
24174
24263
  firstXref = cView.xref;
@@ -24198,7 +24287,7 @@ function ingestSwitchBlock(unit, switchBlock) {
24198
24287
  }
24199
24288
  switchCaseI18nMeta = switchCase.i18n;
24200
24289
  }
24201
- const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, null, 'Case', Namespace.HTML, switchCaseI18nMeta, switchCase.sourceSpan);
24290
+ const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, null, 'Case', Namespace.HTML, switchCaseI18nMeta, switchCase.startSourceSpan, switchCase.sourceSpan);
24202
24291
  unit.create.push(templateOp);
24203
24292
  if (firstXref === null) {
24204
24293
  firstXref = cView.xref;
@@ -24223,7 +24312,7 @@ function ingestDeferView(unit, suffix, i18nMeta, children, sourceSpan) {
24223
24312
  }
24224
24313
  const secondaryView = unit.job.allocateView(unit.xref);
24225
24314
  ingestNodes(secondaryView, children);
24226
- const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML, i18nMeta, sourceSpan);
24315
+ const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML, i18nMeta, sourceSpan, sourceSpan);
24227
24316
  unit.create.push(templateOp);
24228
24317
  return templateOp;
24229
24318
  }
@@ -24301,6 +24390,11 @@ function ingestDeferBlock(unit, deferBlock) {
24301
24390
  deferOnOps.push(deferOnOp);
24302
24391
  }
24303
24392
  if (triggers.when !== undefined) {
24393
+ if (triggers.when.value instanceof Interpolation$1) {
24394
+ // TemplateDefinitionBuilder supports this case, but it's very strange to me. What would it
24395
+ // even mean?
24396
+ throw new Error(`Unexpected interpolation in defer block when trigger`);
24397
+ }
24304
24398
  const deferOnOp = createDeferWhenOp(deferXref, convertAst(triggers.when.value, unit.job, triggers.when.sourceSpan), prefetch, triggers.when.sourceSpan);
24305
24399
  deferWhenOps.push(deferOnOp);
24306
24400
  }
@@ -24320,10 +24414,10 @@ function ingestIcu(unit, icu) {
24320
24414
  unit.create.push(createIcuStartOp(xref, icu.i18n, icuFromI18nMessage(icu.i18n).name, null));
24321
24415
  for (const [placeholder, text] of Object.entries({ ...icu.vars, ...icu.placeholders })) {
24322
24416
  if (text instanceof BoundText) {
24323
- ingestBoundText(unit, text, [placeholder]);
24417
+ ingestBoundText(unit, text, placeholder);
24324
24418
  }
24325
24419
  else {
24326
- ingestText(unit, text);
24420
+ ingestText(unit, text, placeholder);
24327
24421
  }
24328
24422
  }
24329
24423
  unit.create.push(createIcuEndOp(xref));
@@ -24380,7 +24474,7 @@ function ingestForBlock(unit, forBlock) {
24380
24474
  const i18nPlaceholder = forBlock.i18n;
24381
24475
  const emptyI18nPlaceholder = forBlock.empty?.i18n;
24382
24476
  const tagName = ingestControlFlowInsertionPoint(unit, repeaterView.xref, forBlock);
24383
- const repeaterCreate = createRepeaterCreateOp(repeaterView.xref, emptyView?.xref ?? null, tagName, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, forBlock.sourceSpan);
24477
+ const repeaterCreate = createRepeaterCreateOp(repeaterView.xref, emptyView?.xref ?? null, tagName, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, forBlock.startSourceSpan, forBlock.sourceSpan);
24384
24478
  unit.create.push(repeaterCreate);
24385
24479
  const expression = convertAst(forBlock.expression, unit.job, convertSourceSpan(forBlock.expression.span, forBlock.sourceSpan));
24386
24480
  const repeater = createRepeaterOp(repeaterCreate.xref, repeaterCreate.handle, expression, forBlock.sourceSpan);
@@ -24498,13 +24592,13 @@ function convertAst(ast, job, baseSourceSpan) {
24498
24592
  throw new Error(`Unhandled expression type "${ast.constructor.name}" in file "${baseSourceSpan?.start.file.url}"`);
24499
24593
  }
24500
24594
  }
24501
- function convertAstWithInterpolation(job, value, i18nMeta) {
24595
+ function convertAstWithInterpolation(job, value, i18nMeta, sourceSpan) {
24502
24596
  let expression;
24503
24597
  if (value instanceof Interpolation$1) {
24504
- expression = new Interpolation(value.strings, value.expressions.map(e => convertAst(e, job, null)), Object.keys(asMessage(i18nMeta)?.placeholders ?? {}));
24598
+ expression = new Interpolation(value.strings, value.expressions.map(e => convertAst(e, job, sourceSpan ?? null)), Object.keys(asMessage(i18nMeta)?.placeholders ?? {}));
24505
24599
  }
24506
24600
  else if (value instanceof AST) {
24507
- expression = convertAst(value, job, null);
24601
+ expression = convertAst(value, job, sourceSpan ?? null);
24508
24602
  }
24509
24603
  else {
24510
24604
  expression = literal(value);
@@ -29479,12 +29573,16 @@ class BindingScope {
29479
29573
  }
29480
29574
  /** Binding scope of a `track` function inside a `for` loop block. */
29481
29575
  class TrackByBindingScope extends BindingScope {
29482
- constructor(parentScope, globalAliases) {
29576
+ constructor(parentScope, globalOverrides) {
29483
29577
  super(parentScope.bindingLevel + 1, parentScope);
29484
- this.globalAliases = globalAliases;
29578
+ this.globalOverrides = globalOverrides;
29485
29579
  this.componentAccessCount = 0;
29486
29580
  }
29487
29581
  get(name) {
29582
+ // Intercept any overridden globals.
29583
+ if (this.globalOverrides.hasOwnProperty(name)) {
29584
+ return variable(this.globalOverrides[name]);
29585
+ }
29488
29586
  let current = this.parent;
29489
29587
  // Prevent accesses of template variables outside the `for` loop.
29490
29588
  while (current) {
@@ -29493,10 +29591,6 @@ class TrackByBindingScope extends BindingScope {
29493
29591
  }
29494
29592
  current = current.parent;
29495
29593
  }
29496
- // Intercept any aliased globals.
29497
- if (this.globalAliases[name]) {
29498
- return variable(this.globalAliases[name]);
29499
- }
29500
29594
  // When the component scope is accessed, we redirect it through `this`.
29501
29595
  this.componentAccessCount++;
29502
29596
  return variable('this').prop(name);
@@ -31994,7 +32088,7 @@ function publishFacade(global) {
31994
32088
  * @description
31995
32089
  * Entry point for all public APIs of the compiler package.
31996
32090
  */
31997
- const VERSION = new Version('17.0.7');
32091
+ const VERSION = new Version('17.0.8');
31998
32092
 
31999
32093
  class CompilerConfig {
32000
32094
  constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
@@ -33560,7 +33654,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
33560
33654
  function compileDeclareClassMetadata(metadata) {
33561
33655
  const definitionMap = new DefinitionMap();
33562
33656
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
33563
- definitionMap.set('version', literal('17.0.7'));
33657
+ definitionMap.set('version', literal('17.0.8'));
33564
33658
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33565
33659
  definitionMap.set('type', metadata.type);
33566
33660
  definitionMap.set('decorators', metadata.decorators);
@@ -33668,7 +33762,7 @@ function createDirectiveDefinitionMap(meta) {
33668
33762
  // in 16.1 is actually used.
33669
33763
  const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
33670
33764
  definitionMap.set('minVersion', literal(minVersion));
33671
- definitionMap.set('version', literal('17.0.7'));
33765
+ definitionMap.set('version', literal('17.0.8'));
33672
33766
  // e.g. `type: MyDirective`
33673
33767
  definitionMap.set('type', meta.type.value);
33674
33768
  if (meta.isStandalone) {
@@ -33945,7 +34039,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
33945
34039
  function compileDeclareFactoryFunction(meta) {
33946
34040
  const definitionMap = new DefinitionMap();
33947
34041
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
33948
- definitionMap.set('version', literal('17.0.7'));
34042
+ definitionMap.set('version', literal('17.0.8'));
33949
34043
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33950
34044
  definitionMap.set('type', meta.type.value);
33951
34045
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -33980,7 +34074,7 @@ function compileDeclareInjectableFromMetadata(meta) {
33980
34074
  function createInjectableDefinitionMap(meta) {
33981
34075
  const definitionMap = new DefinitionMap();
33982
34076
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
33983
- definitionMap.set('version', literal('17.0.7'));
34077
+ definitionMap.set('version', literal('17.0.8'));
33984
34078
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33985
34079
  definitionMap.set('type', meta.type.value);
33986
34080
  // Only generate providedIn property if it has a non-null value
@@ -34031,7 +34125,7 @@ function compileDeclareInjectorFromMetadata(meta) {
34031
34125
  function createInjectorDefinitionMap(meta) {
34032
34126
  const definitionMap = new DefinitionMap();
34033
34127
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
34034
- definitionMap.set('version', literal('17.0.7'));
34128
+ definitionMap.set('version', literal('17.0.8'));
34035
34129
  definitionMap.set('ngImport', importExpr(Identifiers.core));
34036
34130
  definitionMap.set('type', meta.type.value);
34037
34131
  definitionMap.set('providers', meta.providers);
@@ -34064,7 +34158,7 @@ function createNgModuleDefinitionMap(meta) {
34064
34158
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
34065
34159
  }
34066
34160
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
34067
- definitionMap.set('version', literal('17.0.7'));
34161
+ definitionMap.set('version', literal('17.0.8'));
34068
34162
  definitionMap.set('ngImport', importExpr(Identifiers.core));
34069
34163
  definitionMap.set('type', meta.type.value);
34070
34164
  // We only generate the keys in the metadata if the arrays contain values.
@@ -34115,7 +34209,7 @@ function compileDeclarePipeFromMetadata(meta) {
34115
34209
  function createPipeDefinitionMap(meta) {
34116
34210
  const definitionMap = new DefinitionMap();
34117
34211
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
34118
- definitionMap.set('version', literal('17.0.7'));
34212
+ definitionMap.set('version', literal('17.0.8'));
34119
34213
  definitionMap.set('ngImport', importExpr(Identifiers.core));
34120
34214
  // e.g. `type: MyPipe`
34121
34215
  definitionMap.set('type', meta.type.value);