@angular/compiler 17.1.0 → 17.1.2

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v17.1.0
2
+ * @license Angular v17.1.2
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -5157,7 +5157,7 @@ function getAttrsForDirectiveMatching(elOrTpl) {
5157
5157
  }
5158
5158
  });
5159
5159
  elOrTpl.inputs.forEach(i => {
5160
- if (i.type === 0 /* BindingType.Property */) {
5160
+ if (i.type === 0 /* BindingType.Property */ || i.type === 5 /* BindingType.TwoWay */) {
5161
5161
  attributesMap[i.name] = '';
5162
5162
  }
5163
5163
  });
@@ -6949,6 +6949,7 @@ var ParsedPropertyType;
6949
6949
  ParsedPropertyType[ParsedPropertyType["DEFAULT"] = 0] = "DEFAULT";
6950
6950
  ParsedPropertyType[ParsedPropertyType["LITERAL_ATTR"] = 1] = "LITERAL_ATTR";
6951
6951
  ParsedPropertyType[ParsedPropertyType["ANIMATION"] = 2] = "ANIMATION";
6952
+ ParsedPropertyType[ParsedPropertyType["TWO_WAY"] = 3] = "TWO_WAY";
6952
6953
  })(ParsedPropertyType || (ParsedPropertyType = {}));
6953
6954
  class ParsedEvent {
6954
6955
  // Regular events have a target
@@ -11041,7 +11042,7 @@ function createExtractedAttributeOp(target, bindingKind, namespace, name, expres
11041
11042
  ...NEW_OP,
11042
11043
  };
11043
11044
  }
11044
- function createDeferOp(xref, main, mainSlot, metadata, sourceSpan) {
11045
+ function createDeferOp(xref, main, mainSlot, metadata, resolverFn, sourceSpan) {
11045
11046
  return {
11046
11047
  kind: OpKind.Defer,
11047
11048
  xref,
@@ -11060,7 +11061,7 @@ function createDeferOp(xref, main, mainSlot, metadata, sourceSpan) {
11060
11061
  errorView: null,
11061
11062
  errorSlot: null,
11062
11063
  metadata,
11063
- resolverFn: null,
11064
+ resolverFn,
11064
11065
  sourceSpan,
11065
11066
  ...NEW_OP,
11066
11067
  ...TRAIT_CONSUMES_SLOT,
@@ -11249,11 +11250,12 @@ class CompilationJob {
11249
11250
  * embedded views or host bindings.
11250
11251
  */
11251
11252
  class ComponentCompilationJob extends CompilationJob {
11252
- constructor(componentName, pool, compatibility, relativeContextFilePath, i18nUseExternalIds, deferBlocksMeta) {
11253
+ constructor(componentName, pool, compatibility, relativeContextFilePath, i18nUseExternalIds, deferBlocksMeta, allDeferrableDepsFn) {
11253
11254
  super(componentName, pool, compatibility);
11254
11255
  this.relativeContextFilePath = relativeContextFilePath;
11255
11256
  this.i18nUseExternalIds = i18nUseExternalIds;
11256
11257
  this.deferBlocksMeta = deferBlocksMeta;
11258
+ this.allDeferrableDepsFn = allDeferrableDepsFn;
11257
11259
  this.kind = CompilationJobKind.Tmpl;
11258
11260
  this.fnSuffix = 'Template';
11259
11261
  this.views = new Map();
@@ -12176,6 +12178,9 @@ function createDeferDepsFns(job) {
12176
12178
  if (op.metadata.deps.length === 0) {
12177
12179
  continue;
12178
12180
  }
12181
+ if (op.resolverFn !== null) {
12182
+ continue;
12183
+ }
12179
12184
  const dependencies = [];
12180
12185
  for (const dep of op.metadata.deps) {
12181
12186
  if (dep.isDeferrable) {
@@ -12194,7 +12199,8 @@ function createDeferDepsFns(job) {
12194
12199
  if (op.handle.slot === null) {
12195
12200
  throw new Error('AssertionError: slot must be assigned bfore extracting defer deps functions');
12196
12201
  }
12197
- op.resolverFn = job.pool.getSharedFunctionReference(depsFnExpr, `${job.componentName}_Defer_${op.handle.slot}_DepsFn`,
12202
+ const fullPathName = unit.fnName?.replace(`_Template`, ``);
12203
+ op.resolverFn = job.pool.getSharedFunctionReference(depsFnExpr, `${fullPathName}_Defer_${op.handle.slot}_DepsFn`,
12198
12204
  /* Don't use unique names for TDB compatibility */ false);
12199
12205
  }
12200
12206
  }
@@ -12282,7 +12288,7 @@ function createI18nContexts(job) {
12282
12288
  if (op.message.id !== currentI18nOp.message.id) {
12283
12289
  // This ICU is a sub-message inside its parent i18n block message. We need to give it
12284
12290
  // its own context.
12285
- const contextOp = createI18nContextOp(I18nContextKind.Icu, job.allocateXrefId(), currentI18nOp.xref, op.message, null);
12291
+ const contextOp = createI18nContextOp(I18nContextKind.Icu, job.allocateXrefId(), currentI18nOp.root, op.message, null);
12286
12292
  unit.create.push(contextOp);
12287
12293
  op.context = contextOp.xref;
12288
12294
  }
@@ -23954,7 +23960,6 @@ const phases = [
23954
23960
  { kind: CompilationJobKind.Both, fn: expandSafeReads },
23955
23961
  { kind: CompilationJobKind.Both, fn: generateTemporaryVariables },
23956
23962
  { kind: CompilationJobKind.Tmpl, fn: allocateSlots },
23957
- { kind: CompilationJobKind.Tmpl, fn: createDeferDepsFns },
23958
23963
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nElementPlaceholders },
23959
23964
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nExpressionPlaceholders },
23960
23965
  { kind: CompilationJobKind.Tmpl, fn: extractI18nMessages },
@@ -23967,6 +23972,7 @@ const phases = [
23967
23972
  { kind: CompilationJobKind.Tmpl, fn: generateAdvance },
23968
23973
  { kind: CompilationJobKind.Both, fn: optimizeVariables },
23969
23974
  { kind: CompilationJobKind.Both, fn: nameFunctionsAndVariables },
23975
+ { kind: CompilationJobKind.Tmpl, fn: createDeferDepsFns },
23970
23976
  { kind: CompilationJobKind.Tmpl, fn: mergeNextContextExpressions },
23971
23977
  { kind: CompilationJobKind.Tmpl, fn: generateNgContainerOps },
23972
23978
  { kind: CompilationJobKind.Tmpl, fn: collapseEmptyInstructions },
@@ -24092,8 +24098,8 @@ const NG_TEMPLATE_TAG_NAME$1 = 'ng-template';
24092
24098
  * representation.
24093
24099
  * TODO: Refactor more of the ingestion code into phases.
24094
24100
  */
24095
- function ingestComponent(componentName, template, constantPool, relativeContextFilePath, i18nUseExternalIds, deferBlocksMeta) {
24096
- const job = new ComponentCompilationJob(componentName, constantPool, compatibilityMode, relativeContextFilePath, i18nUseExternalIds, deferBlocksMeta);
24101
+ function ingestComponent(componentName, template, constantPool, relativeContextFilePath, i18nUseExternalIds, deferBlocksMeta, allDeferrableDepsFn) {
24102
+ const job = new ComponentCompilationJob(componentName, constantPool, compatibilityMode, relativeContextFilePath, i18nUseExternalIds, deferBlocksMeta, allDeferrableDepsFn);
24097
24103
  ingestNodes(job.root, template);
24098
24104
  return job;
24099
24105
  }
@@ -24151,7 +24157,7 @@ function ingestHostAttribute(job, name, value, securityContexts) {
24151
24157
  job.root.update.push(attrBinding);
24152
24158
  }
24153
24159
  function ingestHostEvent(job, event) {
24154
- const [phase, target] = event.type === 0 /* e.ParsedEventType.Regular */ ? [null, event.targetOrPhase] :
24160
+ const [phase, target] = event.type !== 1 /* e.ParsedEventType.Animation */ ? [null, event.targetOrPhase] :
24155
24161
  [event.targetOrPhase, null];
24156
24162
  const eventBinding = createListenerOp(job.root.xref, new SlotHandle(), event.name, null, makeListenerHandlerOps(job.root, event.handler, event.handlerSpan), phase, target, true, event.sourceSpan);
24157
24163
  job.root.create.push(eventBinding);
@@ -24417,7 +24423,7 @@ function ingestDeferBlock(unit, deferBlock) {
24417
24423
  const error = ingestDeferView(unit, 'Error', deferBlock.error?.i18n, deferBlock.error?.children, deferBlock.error?.sourceSpan);
24418
24424
  // Create the main defer op, and ops for all secondary views.
24419
24425
  const deferXref = unit.job.allocateXrefId();
24420
- const deferOp = createDeferOp(deferXref, main.xref, main.handle, blockMeta, deferBlock.sourceSpan);
24426
+ const deferOp = createDeferOp(deferXref, main.xref, main.handle, blockMeta, unit.job.allDeferrableDepsFn, deferBlock.sourceSpan);
24421
24427
  deferOp.placeholderView = placeholder?.xref ?? null;
24422
24428
  deferOp.placeholderSlot = placeholder?.handle ?? null;
24423
24429
  deferOp.loadingSlot = loading?.handle ?? null;
@@ -24742,6 +24748,8 @@ function convertAstWithInterpolation(job, value, i18nMeta, sourceSpan) {
24742
24748
  // TODO: Can we populate Template binding kinds in ingest?
24743
24749
  const BINDING_KINDS = new Map([
24744
24750
  [0 /* e.BindingType.Property */, BindingKind.Property],
24751
+ // TODO(crisbeto): we'll need a different BindingKind for two-way bindings.
24752
+ [5 /* e.BindingType.TwoWay */, BindingKind.Property],
24745
24753
  [1 /* e.BindingType.Attribute */, BindingKind.Attribute],
24746
24754
  [2 /* e.BindingType.Class */, BindingKind.ClassName],
24747
24755
  [3 /* e.BindingType.Style */, BindingKind.StyleProperty],
@@ -24887,8 +24895,8 @@ function createTemplateBinding(view, xref, type, name, value, unit, securityCont
24887
24895
  // update instruction.
24888
24896
  if (templateKind === TemplateKind.Structural) {
24889
24897
  if (!isStructuralTemplateAttribute &&
24890
- (type === 0 /* e.BindingType.Property */ || type === 2 /* e.BindingType.Class */ ||
24891
- type === 3 /* e.BindingType.Style */)) {
24898
+ (type === 0 /* e.BindingType.Property */ || type === 5 /* e.BindingType.TwoWay */ ||
24899
+ type === 2 /* e.BindingType.Class */ || type === 3 /* e.BindingType.Style */)) {
24892
24900
  // Because this binding doesn't really target the ng-template, it must be a binding on an
24893
24901
  // inner node of a structural template. We can't skip it entirely, because we still need it on
24894
24902
  // the ng-template's consts (e.g. for the purposes of directive matching). However, we should
@@ -25699,7 +25707,7 @@ class BindingParser {
25699
25707
  for (const propName of Object.keys(properties)) {
25700
25708
  const expression = properties[propName];
25701
25709
  if (typeof expression === 'string') {
25702
- this.parsePropertyBinding(propName, expression, true, sourceSpan, sourceSpan.start.offset, undefined, [],
25710
+ this.parsePropertyBinding(propName, expression, true, false, sourceSpan, sourceSpan.start.offset, undefined, [],
25703
25711
  // Use the `sourceSpan` for `keySpan`. This isn't really accurate, but neither is the
25704
25712
  // sourceSpan, as it represents the sourceSpan of the host itself rather than the
25705
25713
  // source of the host binding (which doesn't exist in the template). Regardless,
@@ -25795,7 +25803,7 @@ class BindingParser {
25795
25803
  else if (binding.value) {
25796
25804
  const srcSpan = isIvyAst ? bindingSpan : sourceSpan;
25797
25805
  const valueSpan = moveParseSourceSpan(sourceSpan, binding.value.ast.sourceSpan);
25798
- this._parsePropertyAst(key, binding.value, srcSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
25806
+ this._parsePropertyAst(key, binding.value, false, srcSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
25799
25807
  }
25800
25808
  else {
25801
25809
  targetMatchableAttrs.push([key, '' /* value */]);
@@ -25848,7 +25856,7 @@ class BindingParser {
25848
25856
  targetProps.push(new ParsedProperty(name, this._exprParser.wrapLiteralPrimitive(value, '', absoluteOffset), ParsedPropertyType.LITERAL_ATTR, sourceSpan, keySpan, valueSpan));
25849
25857
  }
25850
25858
  }
25851
- parsePropertyBinding(name, expression, isHost, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps, keySpan) {
25859
+ parsePropertyBinding(name, expression, isHost, isPartOfAssignmentBinding, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps, keySpan) {
25852
25860
  if (name.length === 0) {
25853
25861
  this._reportError(`Property name is missing in binding`, sourceSpan);
25854
25862
  }
@@ -25871,20 +25879,20 @@ class BindingParser {
25871
25879
  this._parseAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps);
25872
25880
  }
25873
25881
  else {
25874
- this._parsePropertyAst(name, this.parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
25882
+ this._parsePropertyAst(name, this.parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), isPartOfAssignmentBinding, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
25875
25883
  }
25876
25884
  }
25877
25885
  parsePropertyInterpolation(name, value, sourceSpan, valueSpan, targetMatchableAttrs, targetProps, keySpan, interpolatedTokens) {
25878
25886
  const expr = this.parseInterpolation(value, valueSpan || sourceSpan, interpolatedTokens);
25879
25887
  if (expr) {
25880
- this._parsePropertyAst(name, expr, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
25888
+ this._parsePropertyAst(name, expr, false, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
25881
25889
  return true;
25882
25890
  }
25883
25891
  return false;
25884
25892
  }
25885
- _parsePropertyAst(name, ast, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
25893
+ _parsePropertyAst(name, ast, isPartOfAssignmentBinding, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
25886
25894
  targetMatchableAttrs.push([name, ast.source]);
25887
- targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.DEFAULT, sourceSpan, keySpan, valueSpan));
25895
+ targetProps.push(new ParsedProperty(name, ast, isPartOfAssignmentBinding ? ParsedPropertyType.TWO_WAY : ParsedPropertyType.DEFAULT, sourceSpan, keySpan, valueSpan));
25888
25896
  }
25889
25897
  _parseAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
25890
25898
  if (name.length === 0) {
@@ -25954,7 +25962,8 @@ class BindingParser {
25954
25962
  const mappedPropName = this._schemaRegistry.getMappedPropName(boundProp.name);
25955
25963
  boundPropertyName = mapPropertyName ? mappedPropName : boundProp.name;
25956
25964
  securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, mappedPropName, false);
25957
- bindingType = 0 /* BindingType.Property */;
25965
+ bindingType =
25966
+ boundProp.type === ParsedPropertyType.TWO_WAY ? 5 /* BindingType.TwoWay */ : 0 /* BindingType.Property */;
25958
25967
  if (!skipValidation) {
25959
25968
  this._validatePropertyOrAttributeName(mappedPropName, boundProp.sourceSpan, false);
25960
25969
  }
@@ -26004,7 +26013,7 @@ class BindingParser {
26004
26013
  const [target, eventName] = splitAtColon(name, [null, name]);
26005
26014
  const ast = this._parseAction(expression, isAssignmentEvent, handlerSpan);
26006
26015
  targetMatchableAttrs.push([name, ast.source]);
26007
- targetEvents.push(new ParsedEvent(eventName, target, 0 /* ParsedEventType.Regular */, ast, sourceSpan, handlerSpan, keySpan));
26016
+ targetEvents.push(new ParsedEvent(eventName, target, isAssignmentEvent ? 2 /* ParsedEventType.TwoWay */ : 0 /* ParsedEventType.Regular */, ast, sourceSpan, handlerSpan, keySpan));
26008
26017
  // Don't detect directives for event names for now,
26009
26018
  // so don't add the event name to the matchableAttrs
26010
26019
  }
@@ -26179,11 +26188,16 @@ const FOR_LOOP_EXPRESSION_PATTERN = /^\s*([0-9A-Za-z_$]*)\s+of\s+([\S\s]*)/;
26179
26188
  /** Pattern for the tracking expression in a for loop block. */
26180
26189
  const FOR_LOOP_TRACK_PATTERN = /^track\s+([\S\s]*)/;
26181
26190
  /** Pattern for the `as` expression in a conditional block. */
26182
- const CONDITIONAL_ALIAS_PATTERN = /^as\s+(.*)/;
26191
+ const CONDITIONAL_ALIAS_PATTERN = /^(as\s)+(.*)/;
26183
26192
  /** Pattern used to identify an `else if` block. */
26184
26193
  const ELSE_IF_PATTERN = /^else[^\S\r\n]+if/;
26185
26194
  /** Pattern used to identify a `let` parameter. */
26186
26195
  const FOR_LOOP_LET_PATTERN = /^let\s+([\S\s]*)/;
26196
+ /**
26197
+ * Pattern to group a string into leading whitespace, non whitespace, and trailing whitespace.
26198
+ * Useful for getting the variable name span when a span can contain leading and trailing space.
26199
+ */
26200
+ const CHARACTERS_IN_SURROUNDING_WHITESPACE_PATTERN = /(\s*)(\S+)(\s*)/;
26187
26201
  /** Names of variables that are allowed to be used in the `let` expression of a `for` loop. */
26188
26202
  const ALLOWED_FOR_LOOP_LET_VARIABLES = new Set(['$index', '$first', '$last', '$even', '$odd', '$count']);
26189
26203
  /**
@@ -26323,8 +26337,13 @@ function parseForLoopParameters(block, errors, bindingParser) {
26323
26337
  return null;
26324
26338
  }
26325
26339
  const [, itemName, rawExpression] = match;
26340
+ // `expressionParam.expression` contains the variable declaration and the expression of the
26341
+ // for...of statement, i.e. 'user of users' The variable of a ForOfStatement is _only_ the "const
26342
+ // user" part and does not include "of x".
26343
+ const variableName = expressionParam.expression.split(' ')[0];
26344
+ const variableSpan = new ParseSourceSpan(expressionParam.sourceSpan.start, expressionParam.sourceSpan.start.moveBy(variableName.length));
26326
26345
  const result = {
26327
- itemName: new Variable(itemName, '$implicit', expressionParam.sourceSpan, expressionParam.sourceSpan),
26346
+ itemName: new Variable(itemName, '$implicit', variableSpan, variableSpan),
26328
26347
  trackBy: null,
26329
26348
  expression: parseBlockParameterToBinding(expressionParam, bindingParser, rawExpression),
26330
26349
  context: {},
@@ -26332,7 +26351,8 @@ function parseForLoopParameters(block, errors, bindingParser) {
26332
26351
  for (const param of secondaryParams) {
26333
26352
  const letMatch = param.expression.match(FOR_LOOP_LET_PATTERN);
26334
26353
  if (letMatch !== null) {
26335
- parseLetParameter(param.sourceSpan, letMatch[1], param.sourceSpan, result.context, errors);
26354
+ const variablesSpan = new ParseSourceSpan(param.sourceSpan.start.moveBy(letMatch[0].length - letMatch[1].length), param.sourceSpan.end);
26355
+ parseLetParameter(param.sourceSpan, letMatch[1], variablesSpan, result.context, errors);
26336
26356
  continue;
26337
26357
  }
26338
26358
  const trackMatch = param.expression.match(FOR_LOOP_TRACK_PATTERN);
@@ -26363,6 +26383,7 @@ function parseForLoopParameters(block, errors, bindingParser) {
26363
26383
  /** Parses the `let` parameter of a `for` loop block. */
26364
26384
  function parseLetParameter(sourceSpan, expression, span, context, errors) {
26365
26385
  const parts = expression.split(',');
26386
+ let startSpan = span.start;
26366
26387
  for (const part of parts) {
26367
26388
  const expressionParts = part.split('=');
26368
26389
  const name = expressionParts.length === 2 ? expressionParts[0].trim() : '';
@@ -26377,8 +26398,26 @@ function parseLetParameter(sourceSpan, expression, span, context, errors) {
26377
26398
  errors.push(new ParseError(sourceSpan, `Duplicate "let" parameter variable "${variableName}"`));
26378
26399
  }
26379
26400
  else {
26380
- context[variableName] = new Variable(name, variableName, span, span);
26401
+ const [, keyLeadingWhitespace, keyName] = expressionParts[0].match(CHARACTERS_IN_SURROUNDING_WHITESPACE_PATTERN) ?? [];
26402
+ const keySpan = keyLeadingWhitespace !== undefined && expressionParts.length === 2 ?
26403
+ new ParseSourceSpan(
26404
+ /* strip leading spaces */
26405
+ startSpan.moveBy(keyLeadingWhitespace.length),
26406
+ /* advance to end of the variable name */
26407
+ startSpan.moveBy(keyLeadingWhitespace.length + keyName.length)) :
26408
+ span;
26409
+ let valueSpan = undefined;
26410
+ if (expressionParts.length === 2) {
26411
+ const [, valueLeadingWhitespace, implicit] = expressionParts[1].match(CHARACTERS_IN_SURROUNDING_WHITESPACE_PATTERN) ?? [];
26412
+ valueSpan = valueLeadingWhitespace !== undefined ?
26413
+ new ParseSourceSpan(startSpan.moveBy(expressionParts[0].length + 1 + valueLeadingWhitespace.length), startSpan.moveBy(expressionParts[0].length + 1 + valueLeadingWhitespace.length +
26414
+ implicit.length)) :
26415
+ undefined;
26416
+ }
26417
+ const sourceSpan = new ParseSourceSpan(keySpan.start, valueSpan?.end ?? keySpan.end);
26418
+ context[variableName] = new Variable(name, variableName, sourceSpan, keySpan, valueSpan);
26381
26419
  }
26420
+ startSpan = startSpan.moveBy(part.length + 1 /* add 1 to move past the comma */);
26382
26421
  }
26383
26422
  }
26384
26423
  /**
@@ -26490,8 +26529,10 @@ function parseConditionalBlockParameters(block, errors, bindingParser) {
26490
26529
  errors.push(new ParseError(param.sourceSpan, 'Conditional can only have one "as" expression'));
26491
26530
  }
26492
26531
  else {
26493
- const name = aliasMatch[1].trim();
26494
- expressionAlias = new Variable(name, name, param.sourceSpan, param.sourceSpan);
26532
+ const name = aliasMatch[2].trim();
26533
+ const variableStart = param.sourceSpan.start.moveBy(aliasMatch[1].length);
26534
+ const variableSpan = new ParseSourceSpan(variableStart, variableStart.moveBy(name.length));
26535
+ expressionAlias = new Variable(name, name, variableSpan, variableSpan);
26495
26536
  }
26496
26537
  }
26497
26538
  return { expression, expressionAlias };
@@ -27352,7 +27393,7 @@ class HtmlAstToIvyAst {
27352
27393
  if (bindParts[KW_BIND_IDX] != null) {
27353
27394
  const identifier = bindParts[IDENT_KW_IDX];
27354
27395
  const keySpan = createKeySpan(srcSpan, bindParts[KW_BIND_IDX], identifier);
27355
- this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
27396
+ this.bindingParser.parsePropertyBinding(identifier, value, false, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
27356
27397
  }
27357
27398
  else if (bindParts[KW_LET_IDX]) {
27358
27399
  if (isTemplateElement) {
@@ -27379,7 +27420,7 @@ class HtmlAstToIvyAst {
27379
27420
  else if (bindParts[KW_BINDON_IDX]) {
27380
27421
  const identifier = bindParts[IDENT_KW_IDX];
27381
27422
  const keySpan = createKeySpan(srcSpan, bindParts[KW_BINDON_IDX], identifier);
27382
- this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
27423
+ this.bindingParser.parsePropertyBinding(identifier, value, false, true, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
27383
27424
  this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan);
27384
27425
  }
27385
27426
  else if (bindParts[KW_AT_IDX]) {
@@ -27409,11 +27450,11 @@ class HtmlAstToIvyAst {
27409
27450
  const identifier = name.substring(delims.start.length, name.length - delims.end.length);
27410
27451
  const keySpan = createKeySpan(srcSpan, delims.start, identifier);
27411
27452
  if (delims.start === BINDING_DELIMS.BANANA_BOX.start) {
27412
- this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
27453
+ this.bindingParser.parsePropertyBinding(identifier, value, false, true, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
27413
27454
  this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan);
27414
27455
  }
27415
27456
  else if (delims.start === BINDING_DELIMS.PROPERTY.start) {
27416
- this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
27457
+ this.bindingParser.parsePropertyBinding(identifier, value, false, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
27417
27458
  }
27418
27459
  else {
27419
27460
  const events = [];
@@ -28282,7 +28323,8 @@ class TemplateDefinitionBuilder {
28282
28323
  element.inputs.forEach(input => {
28283
28324
  const stylingInputWasSet = stylingBuilder.registerBoundInput(input);
28284
28325
  if (!stylingInputWasSet) {
28285
- if (input.type === 0 /* BindingType.Property */ && input.i18n) {
28326
+ if ((input.type === 0 /* BindingType.Property */ || input.type === 5 /* BindingType.TwoWay */) &&
28327
+ input.i18n) {
28286
28328
  boundI18nAttrs.push(input);
28287
28329
  }
28288
28330
  else {
@@ -28408,7 +28450,7 @@ class TemplateDefinitionBuilder {
28408
28450
  }
28409
28451
  }
28410
28452
  this.allocateBindingSlots(value);
28411
- if (inputType === 0 /* BindingType.Property */) {
28453
+ if (inputType === 0 /* BindingType.Property */ || inputType === 5 /* BindingType.TwoWay */) {
28412
28454
  if (value instanceof Interpolation$1) {
28413
28455
  // prop="{{value}}" and friends
28414
28456
  this.interpolatedUpdateInstruction(getPropertyInterpolationExpression(value), elementIndex, attrName, input, value, params);
@@ -30173,16 +30215,16 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
30173
30215
  // e.g. `template: function MyComponent_Template(_ctx, _cm) {...}`
30174
30216
  const templateTypeName = meta.name;
30175
30217
  const templateName = templateTypeName ? `${templateTypeName}_Template` : null;
30218
+ let allDeferrableDepsFn = null;
30219
+ if (meta.deferBlocks.size > 0 && meta.deferrableTypes.size > 0 &&
30220
+ meta.deferBlockDepsEmitMode === 1 /* DeferBlockDepsEmitMode.PerComponent */) {
30221
+ const fnName = `${templateTypeName}_DeferFn`;
30222
+ allDeferrableDepsFn = createDeferredDepsFunction(constantPool, fnName, meta.deferrableTypes);
30223
+ }
30176
30224
  // Template compilation is currently conditional as we're in the process of rewriting it.
30177
30225
  if (!USE_TEMPLATE_PIPELINE) {
30178
30226
  // This is the main path currently used in compilation, which compiles the template with the
30179
30227
  // legacy `TemplateDefinitionBuilder`.
30180
- let allDeferrableDepsFn = null;
30181
- if (meta.deferBlocks.size > 0 && meta.deferrableTypes.size > 0 &&
30182
- meta.deferBlockDepsEmitMode === 1 /* DeferBlockDepsEmitMode.PerComponent */) {
30183
- const fnName = `${templateTypeName}_DeferFn`;
30184
- allDeferrableDepsFn = createDeferredDepsFunction(constantPool, fnName, meta.deferrableTypes);
30185
- }
30186
30228
  const template = meta.template;
30187
30229
  const templateBuilder = new TemplateDefinitionBuilder(constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, Identifiers.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds, meta.deferBlocks, new Map(), allDeferrableDepsFn);
30188
30230
  const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []);
@@ -30219,7 +30261,7 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
30219
30261
  else {
30220
30262
  // This path compiles the template using the prototype template pipeline. First the template is
30221
30263
  // ingested into IR:
30222
- const tpl = ingestComponent(meta.name, meta.template.nodes, constantPool, meta.relativeContextFilePath, meta.i18nUseExternalIds, meta.deferBlocks);
30264
+ const tpl = ingestComponent(meta.name, meta.template.nodes, constantPool, meta.relativeContextFilePath, meta.i18nUseExternalIds, meta.deferBlocks, allDeferrableDepsFn);
30223
30265
  // Then the IR is transformed to prepare it for cod egeneration.
30224
30266
  transform(tpl, CompilationJobKind.Tmpl);
30225
30267
  // Finally we emit the template function:
@@ -32315,7 +32357,7 @@ function publishFacade(global) {
32315
32357
  * @description
32316
32358
  * Entry point for all public APIs of the compiler package.
32317
32359
  */
32318
- const VERSION = new Version('17.1.0');
32360
+ const VERSION = new Version('17.1.2');
32319
32361
 
32320
32362
  class CompilerConfig {
32321
32363
  constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
@@ -33881,7 +33923,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$5 = '12.0.0';
33881
33923
  function compileDeclareClassMetadata(metadata) {
33882
33924
  const definitionMap = new DefinitionMap();
33883
33925
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
33884
- definitionMap.set('version', literal('17.1.0'));
33926
+ definitionMap.set('version', literal('17.1.2'));
33885
33927
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33886
33928
  definitionMap.set('type', metadata.type);
33887
33929
  definitionMap.set('decorators', metadata.decorators);
@@ -33977,7 +34019,7 @@ function createDirectiveDefinitionMap(meta) {
33977
34019
  const definitionMap = new DefinitionMap();
33978
34020
  const minVersion = getMinimumVersionForPartialOutput(meta);
33979
34021
  definitionMap.set('minVersion', literal(minVersion));
33980
- definitionMap.set('version', literal('17.1.0'));
34022
+ definitionMap.set('version', literal('17.1.2'));
33981
34023
  // e.g. `type: MyDirective`
33982
34024
  definitionMap.set('type', meta.type.value);
33983
34025
  if (meta.isStandalone) {
@@ -34361,7 +34403,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
34361
34403
  function compileDeclareFactoryFunction(meta) {
34362
34404
  const definitionMap = new DefinitionMap();
34363
34405
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
34364
- definitionMap.set('version', literal('17.1.0'));
34406
+ definitionMap.set('version', literal('17.1.2'));
34365
34407
  definitionMap.set('ngImport', importExpr(Identifiers.core));
34366
34408
  definitionMap.set('type', meta.type.value);
34367
34409
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -34396,7 +34438,7 @@ function compileDeclareInjectableFromMetadata(meta) {
34396
34438
  function createInjectableDefinitionMap(meta) {
34397
34439
  const definitionMap = new DefinitionMap();
34398
34440
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
34399
- definitionMap.set('version', literal('17.1.0'));
34441
+ definitionMap.set('version', literal('17.1.2'));
34400
34442
  definitionMap.set('ngImport', importExpr(Identifiers.core));
34401
34443
  definitionMap.set('type', meta.type.value);
34402
34444
  // Only generate providedIn property if it has a non-null value
@@ -34447,7 +34489,7 @@ function compileDeclareInjectorFromMetadata(meta) {
34447
34489
  function createInjectorDefinitionMap(meta) {
34448
34490
  const definitionMap = new DefinitionMap();
34449
34491
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
34450
- definitionMap.set('version', literal('17.1.0'));
34492
+ definitionMap.set('version', literal('17.1.2'));
34451
34493
  definitionMap.set('ngImport', importExpr(Identifiers.core));
34452
34494
  definitionMap.set('type', meta.type.value);
34453
34495
  definitionMap.set('providers', meta.providers);
@@ -34480,7 +34522,7 @@ function createNgModuleDefinitionMap(meta) {
34480
34522
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
34481
34523
  }
34482
34524
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
34483
- definitionMap.set('version', literal('17.1.0'));
34525
+ definitionMap.set('version', literal('17.1.2'));
34484
34526
  definitionMap.set('ngImport', importExpr(Identifiers.core));
34485
34527
  definitionMap.set('type', meta.type.value);
34486
34528
  // We only generate the keys in the metadata if the arrays contain values.
@@ -34531,7 +34573,7 @@ function compileDeclarePipeFromMetadata(meta) {
34531
34573
  function createPipeDefinitionMap(meta) {
34532
34574
  const definitionMap = new DefinitionMap();
34533
34575
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
34534
- definitionMap.set('version', literal('17.1.0'));
34576
+ definitionMap.set('version', literal('17.1.2'));
34535
34577
  definitionMap.set('ngImport', importExpr(Identifiers.core));
34536
34578
  // e.g. `type: MyPipe`
34537
34579
  definitionMap.set('type', meta.type.value);