@angular/compiler 20.0.0-next.4 → 20.0.0-next.6

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 v20.0.0-next.4
2
+ * @license Angular v20.0.0-next.6
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -1320,14 +1320,13 @@ class TemplateLiteralElementExpr extends Expression {
1320
1320
  constructor(text, sourceSpan, rawText) {
1321
1321
  super(STRING_TYPE, sourceSpan);
1322
1322
  this.text = text;
1323
- // If `rawText` is not provided, try to extract the raw string from its
1324
- // associated `sourceSpan`. If that is also not available, "fake" the raw
1325
- // string instead by escaping the following control sequences:
1323
+ // If `rawText` is not provided, "fake" the raw string by escaping the following sequences:
1326
1324
  // - "\" would otherwise indicate that the next character is a control character.
1327
1325
  // - "`" and "${" are template string control sequences that would otherwise prematurely
1328
1326
  // indicate the end of the template literal element.
1329
- this.rawText =
1330
- rawText ?? sourceSpan?.toString() ?? escapeForTemplateLiteral(escapeSlashes(text));
1327
+ // Note that we can't rely on the `sourceSpan` here, because it may be incorrect (see
1328
+ // https://github.com/angular/angular/pull/60267#discussion_r1986402524).
1329
+ this.rawText = rawText ?? escapeForTemplateLiteral(escapeSlashes(text));
1331
1330
  }
1332
1331
  visitExpression(visitor, context) {
1333
1332
  return visitor.visitTemplateLiteralElementExpr(this, context);
@@ -2943,7 +2942,7 @@ class Identifiers {
2943
2942
  static pipeBind3 = { name: 'ɵɵpipeBind3', moduleName: CORE };
2944
2943
  static pipeBind4 = { name: 'ɵɵpipeBind4', moduleName: CORE };
2945
2944
  static pipeBindV = { name: 'ɵɵpipeBindV', moduleName: CORE };
2946
- static hostProperty = { name: 'ɵɵhostProperty', moduleName: CORE };
2945
+ static domProperty = { name: 'ɵɵdomProperty', moduleName: CORE };
2947
2946
  static property = { name: 'ɵɵproperty', moduleName: CORE };
2948
2947
  static propertyInterpolate = {
2949
2948
  name: 'ɵɵpropertyInterpolate',
@@ -5069,17 +5068,19 @@ let Element$1 = class Element {
5069
5068
  attributes;
5070
5069
  inputs;
5071
5070
  outputs;
5071
+ directives;
5072
5072
  children;
5073
5073
  references;
5074
5074
  sourceSpan;
5075
5075
  startSourceSpan;
5076
5076
  endSourceSpan;
5077
5077
  i18n;
5078
- constructor(name, attributes, inputs, outputs, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5078
+ constructor(name, attributes, inputs, outputs, directives, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5079
5079
  this.name = name;
5080
5080
  this.attributes = attributes;
5081
5081
  this.inputs = inputs;
5082
5082
  this.outputs = outputs;
5083
+ this.directives = directives;
5083
5084
  this.children = children;
5084
5085
  this.references = references;
5085
5086
  this.sourceSpan = sourceSpan;
@@ -5378,11 +5379,70 @@ let LetDeclaration$1 = class LetDeclaration {
5378
5379
  return visitor.visitLetDeclaration(this);
5379
5380
  }
5380
5381
  };
5382
+ let Component$1 = class Component {
5383
+ componentName;
5384
+ tagName;
5385
+ fullName;
5386
+ attributes;
5387
+ inputs;
5388
+ outputs;
5389
+ directives;
5390
+ children;
5391
+ references;
5392
+ sourceSpan;
5393
+ startSourceSpan;
5394
+ endSourceSpan;
5395
+ i18n;
5396
+ constructor(componentName, tagName, fullName, attributes, inputs, outputs, directives, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5397
+ this.componentName = componentName;
5398
+ this.tagName = tagName;
5399
+ this.fullName = fullName;
5400
+ this.attributes = attributes;
5401
+ this.inputs = inputs;
5402
+ this.outputs = outputs;
5403
+ this.directives = directives;
5404
+ this.children = children;
5405
+ this.references = references;
5406
+ this.sourceSpan = sourceSpan;
5407
+ this.startSourceSpan = startSourceSpan;
5408
+ this.endSourceSpan = endSourceSpan;
5409
+ this.i18n = i18n;
5410
+ }
5411
+ visit(visitor) {
5412
+ return visitor.visitComponent(this);
5413
+ }
5414
+ };
5415
+ let Directive$1 = class Directive {
5416
+ name;
5417
+ attributes;
5418
+ inputs;
5419
+ outputs;
5420
+ references;
5421
+ sourceSpan;
5422
+ startSourceSpan;
5423
+ endSourceSpan;
5424
+ i18n;
5425
+ constructor(name, attributes, inputs, outputs, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5426
+ this.name = name;
5427
+ this.attributes = attributes;
5428
+ this.inputs = inputs;
5429
+ this.outputs = outputs;
5430
+ this.references = references;
5431
+ this.sourceSpan = sourceSpan;
5432
+ this.startSourceSpan = startSourceSpan;
5433
+ this.endSourceSpan = endSourceSpan;
5434
+ this.i18n = i18n;
5435
+ }
5436
+ visit(visitor) {
5437
+ return visitor.visitDirective(this);
5438
+ }
5439
+ };
5381
5440
  class Template {
5382
5441
  tagName;
5383
5442
  attributes;
5384
5443
  inputs;
5385
5444
  outputs;
5445
+ directives;
5386
5446
  templateAttrs;
5387
5447
  children;
5388
5448
  references;
@@ -5396,11 +5456,12 @@ class Template {
5396
5456
  // `null` is a special case for when there is a structural directive on an `ng-template` so
5397
5457
  // the renderer can differentiate between the synthetic template and the one written in the
5398
5458
  // file.
5399
- tagName, attributes, inputs, outputs, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5459
+ tagName, attributes, inputs, outputs, directives, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5400
5460
  this.tagName = tagName;
5401
5461
  this.attributes = attributes;
5402
5462
  this.inputs = inputs;
5403
5463
  this.outputs = outputs;
5464
+ this.directives = directives;
5404
5465
  this.templateAttrs = templateAttrs;
5405
5466
  this.children = children;
5406
5467
  this.references = references;
@@ -5419,13 +5480,17 @@ class Content {
5419
5480
  attributes;
5420
5481
  children;
5421
5482
  sourceSpan;
5483
+ startSourceSpan;
5484
+ endSourceSpan;
5422
5485
  i18n;
5423
5486
  name = 'ng-content';
5424
- constructor(selector, attributes, children, sourceSpan, i18n) {
5487
+ constructor(selector, attributes, children, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5425
5488
  this.selector = selector;
5426
5489
  this.attributes = attributes;
5427
5490
  this.children = children;
5428
5491
  this.sourceSpan = sourceSpan;
5492
+ this.startSourceSpan = startSourceSpan;
5493
+ this.endSourceSpan = endSourceSpan;
5429
5494
  this.i18n = i18n;
5430
5495
  }
5431
5496
  visit(visitor) {
@@ -5508,6 +5573,7 @@ let RecursiveVisitor$1 = class RecursiveVisitor {
5508
5573
  visitAll$1(this, element.attributes);
5509
5574
  visitAll$1(this, element.inputs);
5510
5575
  visitAll$1(this, element.outputs);
5576
+ visitAll$1(this, element.directives);
5511
5577
  visitAll$1(this, element.children);
5512
5578
  visitAll$1(this, element.references);
5513
5579
  }
@@ -5515,6 +5581,7 @@ let RecursiveVisitor$1 = class RecursiveVisitor {
5515
5581
  visitAll$1(this, template.attributes);
5516
5582
  visitAll$1(this, template.inputs);
5517
5583
  visitAll$1(this, template.outputs);
5584
+ visitAll$1(this, template.directives);
5518
5585
  visitAll$1(this, template.children);
5519
5586
  visitAll$1(this, template.references);
5520
5587
  visitAll$1(this, template.variables);
@@ -5556,6 +5623,20 @@ let RecursiveVisitor$1 = class RecursiveVisitor {
5556
5623
  visitContent(content) {
5557
5624
  visitAll$1(this, content.children);
5558
5625
  }
5626
+ visitComponent(component) {
5627
+ visitAll$1(this, component.attributes);
5628
+ visitAll$1(this, component.inputs);
5629
+ visitAll$1(this, component.outputs);
5630
+ visitAll$1(this, component.directives);
5631
+ visitAll$1(this, component.children);
5632
+ visitAll$1(this, component.references);
5633
+ }
5634
+ visitDirective(directive) {
5635
+ visitAll$1(this, directive.attributes);
5636
+ visitAll$1(this, directive.inputs);
5637
+ visitAll$1(this, directive.outputs);
5638
+ visitAll$1(this, directive.references);
5639
+ }
5559
5640
  visitVariable(variable) { }
5560
5641
  visitReference(reference) { }
5561
5642
  visitTextAttribute(attribute) { }
@@ -6182,8 +6263,8 @@ const I18N_ICU_VAR_PREFIX = 'VAR_';
6182
6263
  function isI18nAttribute(name) {
6183
6264
  return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);
6184
6265
  }
6185
- function hasI18nAttrs(element) {
6186
- return element.attrs.some((attr) => isI18nAttribute(attr.name));
6266
+ function hasI18nAttrs(node) {
6267
+ return node.attrs.some((attr) => isI18nAttribute(attr.name));
6187
6268
  }
6188
6269
  function icuFromI18nMessage(message) {
6189
6270
  return message.nodes[0];
@@ -8820,9 +8901,9 @@ var OpKind;
8820
8901
  */
8821
8902
  OpKind[OpKind["I18nMessage"] = 31] = "I18nMessage";
8822
8903
  /**
8823
- * A host binding property.
8904
+ * A binding to a native DOM property.
8824
8905
  */
8825
- OpKind[OpKind["HostProperty"] = 32] = "HostProperty";
8906
+ OpKind[OpKind["DomProperty"] = 32] = "DomProperty";
8826
8907
  /**
8827
8908
  * A namespace change, which causes the subsequent elements to be processed as either HTML or SVG.
8828
8909
  */
@@ -10329,7 +10410,7 @@ function transformExpressionsInOp(op, transform, flags) {
10329
10410
  }
10330
10411
  break;
10331
10412
  case OpKind.Property:
10332
- case OpKind.HostProperty:
10413
+ case OpKind.DomProperty:
10333
10414
  case OpKind.Attribute:
10334
10415
  if (op.expression instanceof Interpolation) {
10335
10416
  transformExpressionsInInterpolation(op.expression, transform, flags);
@@ -11307,9 +11388,9 @@ function createSourceLocationOp(templatePath, locations) {
11307
11388
  };
11308
11389
  }
11309
11390
 
11310
- function createHostPropertyOp(name, expression, isAnimationTrigger, i18nContext, securityContext, sourceSpan) {
11391
+ function createDomPropertyOp(name, expression, isAnimationTrigger, i18nContext, securityContext, sourceSpan) {
11311
11392
  return {
11312
- kind: OpKind.HostProperty,
11393
+ kind: OpKind.DomProperty,
11313
11394
  name,
11314
11395
  expression,
11315
11396
  isAnimationTrigger,
@@ -11887,7 +11968,7 @@ function specializeBindings(job) {
11887
11968
  case BindingKind.Property:
11888
11969
  case BindingKind.Animation:
11889
11970
  if (job.kind === CompilationJobKind.Host) {
11890
- OpList.replace(op, createHostPropertyOp(op.name, op.expression, op.bindingKind === BindingKind.Animation, op.i18nContext, op.securityContext, op.sourceSpan));
11971
+ OpList.replace(op, createDomPropertyOp(op.name, op.expression, op.bindingKind === BindingKind.Animation, op.i18nContext, op.securityContext, op.sourceSpan));
11891
11972
  }
11892
11973
  else {
11893
11974
  OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind === BindingKind.Animation, op.securityContext, op.isStructuralTemplateAttribute, op.templateKind, op.i18nContext, op.i18nMessage, op.sourceSpan));
@@ -11920,7 +12001,7 @@ const CHAIN_COMPATIBILITY = new Map([
11920
12001
  [Identifiers.elementContainerStart, Identifiers.elementContainerStart],
11921
12002
  [Identifiers.elementEnd, Identifiers.elementEnd],
11922
12003
  [Identifiers.elementStart, Identifiers.elementStart],
11923
- [Identifiers.hostProperty, Identifiers.hostProperty],
12004
+ [Identifiers.domProperty, Identifiers.domProperty],
11924
12005
  [Identifiers.i18nExp, Identifiers.i18nExp],
11925
12006
  [Identifiers.listener, Identifiers.listener],
11926
12007
  [Identifiers.listener, Identifiers.listener],
@@ -13568,13 +13649,15 @@ class Attribute extends NodeWithI18n {
13568
13649
  class Element extends NodeWithI18n {
13569
13650
  name;
13570
13651
  attrs;
13652
+ directives;
13571
13653
  children;
13572
13654
  startSourceSpan;
13573
13655
  endSourceSpan;
13574
- constructor(name, attrs, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
13656
+ constructor(name, attrs, directives, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
13575
13657
  super(sourceSpan, i18n);
13576
13658
  this.name = name;
13577
13659
  this.attrs = attrs;
13660
+ this.directives = directives;
13578
13661
  this.children = children;
13579
13662
  this.startSourceSpan = startSourceSpan;
13580
13663
  this.endSourceSpan = endSourceSpan;
@@ -13614,6 +13697,47 @@ class Block extends NodeWithI18n {
13614
13697
  return visitor.visitBlock(this, context);
13615
13698
  }
13616
13699
  }
13700
+ class Component extends NodeWithI18n {
13701
+ componentName;
13702
+ tagName;
13703
+ fullName;
13704
+ attrs;
13705
+ directives;
13706
+ children;
13707
+ startSourceSpan;
13708
+ endSourceSpan;
13709
+ constructor(componentName, tagName, fullName, attrs, directives, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
13710
+ super(sourceSpan, i18n);
13711
+ this.componentName = componentName;
13712
+ this.tagName = tagName;
13713
+ this.fullName = fullName;
13714
+ this.attrs = attrs;
13715
+ this.directives = directives;
13716
+ this.children = children;
13717
+ this.startSourceSpan = startSourceSpan;
13718
+ this.endSourceSpan = endSourceSpan;
13719
+ }
13720
+ visit(visitor, context) {
13721
+ return visitor.visitComponent(this, context);
13722
+ }
13723
+ }
13724
+ class Directive {
13725
+ name;
13726
+ attrs;
13727
+ sourceSpan;
13728
+ startSourceSpan;
13729
+ endSourceSpan;
13730
+ constructor(name, attrs, sourceSpan, startSourceSpan, endSourceSpan = null) {
13731
+ this.name = name;
13732
+ this.attrs = attrs;
13733
+ this.sourceSpan = sourceSpan;
13734
+ this.startSourceSpan = startSourceSpan;
13735
+ this.endSourceSpan = endSourceSpan;
13736
+ }
13737
+ visit(visitor, context) {
13738
+ return visitor.visitDirective(this, context);
13739
+ }
13740
+ }
13617
13741
  class BlockParameter {
13618
13742
  expression;
13619
13743
  sourceSpan;
@@ -13660,6 +13784,7 @@ class RecursiveVisitor {
13660
13784
  visitElement(ast, context) {
13661
13785
  this.visitChildren(context, (visit) => {
13662
13786
  visit(ast.attrs);
13787
+ visit(ast.directives);
13663
13788
  visit(ast.children);
13664
13789
  });
13665
13790
  }
@@ -13680,6 +13805,17 @@ class RecursiveVisitor {
13680
13805
  }
13681
13806
  visitBlockParameter(ast, context) { }
13682
13807
  visitLetDeclaration(decl, context) { }
13808
+ visitComponent(component, context) {
13809
+ this.visitChildren(context, (visit) => {
13810
+ visit(component.attrs);
13811
+ visit(component.children);
13812
+ });
13813
+ }
13814
+ visitDirective(directive, context) {
13815
+ this.visitChildren(context, (visit) => {
13816
+ visit(directive.attrs);
13817
+ });
13818
+ }
13683
13819
  visitChildren(context, cb) {
13684
13820
  let results = [];
13685
13821
  let t = this;
@@ -15883,11 +16019,13 @@ class _Tokenizer {
15883
16019
  _currentTokenStart = null;
15884
16020
  _currentTokenType = null;
15885
16021
  _expansionCaseStack = [];
16022
+ _openDirectiveCount = 0;
15886
16023
  _inInterpolation = false;
15887
16024
  _preserveLineEndings;
15888
16025
  _i18nNormalizeLineEndingsInICUs;
15889
16026
  _tokenizeBlocks;
15890
16027
  _tokenizeLet;
16028
+ _selectorlessEnabled;
15891
16029
  tokens = [];
15892
16030
  errors = [];
15893
16031
  nonNormalizedIcuExpressions = [];
@@ -15915,6 +16053,7 @@ class _Tokenizer {
15915
16053
  this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false;
15916
16054
  this._tokenizeBlocks = options.tokenizeBlocks ?? true;
15917
16055
  this._tokenizeLet = options.tokenizeLet ?? true;
16056
+ this._selectorlessEnabled = options.selectorlessEnabled ?? false;
15918
16057
  try {
15919
16058
  this._cursor.init();
15920
16059
  }
@@ -15983,7 +16122,7 @@ class _Tokenizer {
15983
16122
  this.handleError(e);
15984
16123
  }
15985
16124
  }
15986
- this._beginToken(33 /* TokenType.EOF */);
16125
+ this._beginToken(41 /* TokenType.EOF */);
15987
16126
  this._endToken([]);
15988
16127
  }
15989
16128
  _getBlockName() {
@@ -16326,7 +16465,7 @@ class _Tokenizer {
16326
16465
  else {
16327
16466
  const name = this._cursor.getChars(nameStart);
16328
16467
  this._cursor.advance();
16329
- const char = NAMED_ENTITIES[name];
16468
+ const char = NAMED_ENTITIES.hasOwnProperty(name) && NAMED_ENTITIES[name];
16330
16469
  if (!char) {
16331
16470
  throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start));
16332
16471
  }
@@ -16382,7 +16521,7 @@ class _Tokenizer {
16382
16521
  this._cursor.advance();
16383
16522
  this._endToken([content]);
16384
16523
  }
16385
- _consumePrefixAndName() {
16524
+ _consumePrefixAndName(endPredicate) {
16386
16525
  const nameOrPrefixStart = this._cursor.clone();
16387
16526
  let prefix = '';
16388
16527
  while (this._cursor.peek() !== $COLON && !isPrefixEnd(this._cursor.peek())) {
@@ -16397,41 +16536,64 @@ class _Tokenizer {
16397
16536
  else {
16398
16537
  nameStart = nameOrPrefixStart;
16399
16538
  }
16400
- this._requireCharCodeUntilFn(isNameEnd, prefix === '' ? 0 : 1);
16539
+ this._requireCharCodeUntilFn(endPredicate, prefix === '' ? 0 : 1);
16401
16540
  const name = this._cursor.getChars(nameStart);
16402
16541
  return [prefix, name];
16403
16542
  }
16404
16543
  _consumeTagOpen(start) {
16405
16544
  let tagName;
16406
16545
  let prefix;
16407
- let openTagToken;
16546
+ let closingTagName;
16547
+ let openToken;
16408
16548
  try {
16409
- if (!isAsciiLetter(this._cursor.peek())) {
16410
- throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
16411
- }
16412
- openTagToken = this._consumeTagOpenStart(start);
16413
- prefix = openTagToken.parts[0];
16414
- tagName = openTagToken.parts[1];
16415
- this._attemptCharCodeUntilFn(isNotWhitespace);
16416
- while (this._cursor.peek() !== $SLASH &&
16417
- this._cursor.peek() !== $GT &&
16418
- this._cursor.peek() !== $LT &&
16419
- this._cursor.peek() !== $EOF) {
16420
- this._consumeAttributeName();
16549
+ if (this._selectorlessEnabled && isSelectorlessNameStart(this._cursor.peek())) {
16550
+ openToken = this._consumeComponentOpenStart(start);
16551
+ [closingTagName, prefix, tagName] = openToken.parts;
16552
+ if (prefix) {
16553
+ closingTagName += `:${prefix}`;
16554
+ }
16555
+ if (tagName) {
16556
+ closingTagName += `:${tagName}`;
16557
+ }
16421
16558
  this._attemptCharCodeUntilFn(isNotWhitespace);
16422
- if (this._attemptCharCode($EQ)) {
16423
- this._attemptCharCodeUntilFn(isNotWhitespace);
16424
- this._consumeAttributeValue();
16559
+ }
16560
+ else {
16561
+ if (!isAsciiLetter(this._cursor.peek())) {
16562
+ throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
16425
16563
  }
16564
+ openToken = this._consumeTagOpenStart(start);
16565
+ prefix = openToken.parts[0];
16566
+ tagName = closingTagName = openToken.parts[1];
16426
16567
  this._attemptCharCodeUntilFn(isNotWhitespace);
16427
16568
  }
16428
- this._consumeTagOpenEnd();
16569
+ while (!isAttributeTerminator(this._cursor.peek())) {
16570
+ if (this._selectorlessEnabled && this._cursor.peek() === $AT) {
16571
+ const start = this._cursor.clone();
16572
+ const nameStart = start.clone();
16573
+ nameStart.advance();
16574
+ if (isSelectorlessNameStart(nameStart.peek())) {
16575
+ this._consumeDirective(start, nameStart);
16576
+ }
16577
+ }
16578
+ else {
16579
+ this._consumeAttribute();
16580
+ }
16581
+ }
16582
+ if (openToken.type === 33 /* TokenType.COMPONENT_OPEN_START */) {
16583
+ this._consumeComponentOpenEnd();
16584
+ }
16585
+ else {
16586
+ this._consumeTagOpenEnd();
16587
+ }
16429
16588
  }
16430
16589
  catch (e) {
16431
16590
  if (e instanceof _ControlFlowError) {
16432
- if (openTagToken) {
16591
+ if (openToken) {
16433
16592
  // We errored before we could close the opening tag, so it is incomplete.
16434
- openTagToken.type = 4 /* TokenType.INCOMPLETE_TAG_OPEN */;
16593
+ openToken.type =
16594
+ openToken.type === 33 /* TokenType.COMPONENT_OPEN_START */
16595
+ ? 37 /* TokenType.INCOMPLETE_COMPONENT_OPEN */
16596
+ : 4 /* TokenType.INCOMPLETE_TAG_OPEN */;
16435
16597
  }
16436
16598
  else {
16437
16599
  // When the start tag is invalid, assume we want a "<" as text.
@@ -16445,13 +16607,13 @@ class _Tokenizer {
16445
16607
  }
16446
16608
  const contentTokenType = this._getTagDefinition(tagName).getContentType(prefix);
16447
16609
  if (contentTokenType === TagContentType.RAW_TEXT) {
16448
- this._consumeRawTextWithTagClose(prefix, tagName, false);
16610
+ this._consumeRawTextWithTagClose(openToken, closingTagName, false);
16449
16611
  }
16450
16612
  else if (contentTokenType === TagContentType.ESCAPABLE_RAW_TEXT) {
16451
- this._consumeRawTextWithTagClose(prefix, tagName, true);
16613
+ this._consumeRawTextWithTagClose(openToken, closingTagName, true);
16452
16614
  }
16453
16615
  }
16454
- _consumeRawTextWithTagClose(prefix, tagName, consumeEntities) {
16616
+ _consumeRawTextWithTagClose(openToken, tagName, consumeEntities) {
16455
16617
  this._consumeRawText(consumeEntities, () => {
16456
16618
  if (!this._attemptCharCode($LT))
16457
16619
  return false;
@@ -16463,23 +16625,79 @@ class _Tokenizer {
16463
16625
  this._attemptCharCodeUntilFn(isNotWhitespace);
16464
16626
  return this._attemptCharCode($GT);
16465
16627
  });
16466
- this._beginToken(3 /* TokenType.TAG_CLOSE */);
16628
+ this._beginToken(openToken.type === 33 /* TokenType.COMPONENT_OPEN_START */
16629
+ ? 36 /* TokenType.COMPONENT_CLOSE */
16630
+ : 3 /* TokenType.TAG_CLOSE */);
16467
16631
  this._requireCharCodeUntilFn((code) => code === $GT, 3);
16468
16632
  this._cursor.advance(); // Consume the `>`
16469
- this._endToken([prefix, tagName]);
16633
+ this._endToken(openToken.parts);
16470
16634
  }
16471
16635
  _consumeTagOpenStart(start) {
16472
16636
  this._beginToken(0 /* TokenType.TAG_OPEN_START */, start);
16473
- const parts = this._consumePrefixAndName();
16637
+ const parts = this._consumePrefixAndName(isNameEnd);
16474
16638
  return this._endToken(parts);
16475
16639
  }
16640
+ _consumeComponentOpenStart(start) {
16641
+ this._beginToken(33 /* TokenType.COMPONENT_OPEN_START */, start);
16642
+ const parts = this._consumeComponentName();
16643
+ return this._endToken(parts);
16644
+ }
16645
+ _consumeComponentName() {
16646
+ const nameStart = this._cursor.clone();
16647
+ while (isSelectorlessNameChar(this._cursor.peek())) {
16648
+ this._cursor.advance();
16649
+ }
16650
+ const name = this._cursor.getChars(nameStart);
16651
+ let prefix = '';
16652
+ let tagName = '';
16653
+ if (this._cursor.peek() === $COLON) {
16654
+ this._cursor.advance();
16655
+ [prefix, tagName] = this._consumePrefixAndName(isNameEnd);
16656
+ }
16657
+ return [name, prefix, tagName];
16658
+ }
16659
+ _consumeAttribute() {
16660
+ this._consumeAttributeName();
16661
+ this._attemptCharCodeUntilFn(isNotWhitespace);
16662
+ if (this._attemptCharCode($EQ)) {
16663
+ this._attemptCharCodeUntilFn(isNotWhitespace);
16664
+ this._consumeAttributeValue();
16665
+ }
16666
+ this._attemptCharCodeUntilFn(isNotWhitespace);
16667
+ }
16476
16668
  _consumeAttributeName() {
16477
16669
  const attrNameStart = this._cursor.peek();
16478
16670
  if (attrNameStart === $SQ || attrNameStart === $DQ) {
16479
16671
  throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan());
16480
16672
  }
16481
16673
  this._beginToken(14 /* TokenType.ATTR_NAME */);
16482
- const prefixAndName = this._consumePrefixAndName();
16674
+ let nameEndPredicate;
16675
+ if (this._openDirectiveCount > 0) {
16676
+ // If we're parsing attributes inside of directive syntax, we have to terminate the name
16677
+ // on the first non-matching closing paren. For example, if we have `@Dir(someAttr)`,
16678
+ // `@Dir` and `(` will have already been captured as `DIRECTIVE_NAME` and `DIRECTIVE_OPEN`
16679
+ // respectively, but the `)` will get captured as a part of the name for `someAttr`
16680
+ // because normally that would be an event binding.
16681
+ let openParens = 0;
16682
+ nameEndPredicate = (code) => {
16683
+ if (this._openDirectiveCount > 0) {
16684
+ if (code === $LPAREN) {
16685
+ openParens++;
16686
+ }
16687
+ else if (code === $RPAREN) {
16688
+ if (openParens === 0) {
16689
+ return true;
16690
+ }
16691
+ openParens--;
16692
+ }
16693
+ }
16694
+ return isNameEnd(code);
16695
+ };
16696
+ }
16697
+ else {
16698
+ nameEndPredicate = isNameEnd;
16699
+ }
16700
+ const prefixAndName = this._consumePrefixAndName(nameEndPredicate);
16483
16701
  this._endToken(prefixAndName);
16484
16702
  }
16485
16703
  _consumeAttributeValue() {
@@ -16510,10 +16728,32 @@ class _Tokenizer {
16510
16728
  this._requireCharCode($GT);
16511
16729
  this._endToken([]);
16512
16730
  }
16731
+ _consumeComponentOpenEnd() {
16732
+ const tokenType = this._attemptCharCode($SLASH)
16733
+ ? 35 /* TokenType.COMPONENT_OPEN_END_VOID */
16734
+ : 34 /* TokenType.COMPONENT_OPEN_END */;
16735
+ this._beginToken(tokenType);
16736
+ this._requireCharCode($GT);
16737
+ this._endToken([]);
16738
+ }
16513
16739
  _consumeTagClose(start) {
16740
+ if (this._selectorlessEnabled) {
16741
+ const clone = start.clone();
16742
+ while (clone.peek() !== $GT && !isSelectorlessNameStart(clone.peek())) {
16743
+ clone.advance();
16744
+ }
16745
+ if (isSelectorlessNameStart(clone.peek())) {
16746
+ this._beginToken(36 /* TokenType.COMPONENT_CLOSE */, start);
16747
+ const parts = this._consumeComponentName();
16748
+ this._attemptCharCodeUntilFn(isNotWhitespace);
16749
+ this._requireCharCode($GT);
16750
+ this._endToken(parts);
16751
+ return;
16752
+ }
16753
+ }
16514
16754
  this._beginToken(3 /* TokenType.TAG_CLOSE */, start);
16515
16755
  this._attemptCharCodeUntilFn(isNotWhitespace);
16516
- const prefixAndName = this._consumePrefixAndName();
16756
+ const prefixAndName = this._consumePrefixAndName(isNameEnd);
16517
16757
  this._attemptCharCodeUntilFn(isNotWhitespace);
16518
16758
  this._requireCharCode($GT);
16519
16759
  this._endToken(prefixAndName);
@@ -16669,6 +16909,50 @@ class _Tokenizer {
16669
16909
  parts.push(this._getProcessedChars(expressionStart, this._cursor));
16670
16910
  this._endToken(parts);
16671
16911
  }
16912
+ _consumeDirective(start, nameStart) {
16913
+ this._requireCharCode($AT);
16914
+ // Skip over the @ since it's not part of the name.
16915
+ this._cursor.advance();
16916
+ // Capture the rest of the name.
16917
+ while (isSelectorlessNameChar(this._cursor.peek())) {
16918
+ this._cursor.advance();
16919
+ }
16920
+ // Capture the opening token.
16921
+ this._beginToken(38 /* TokenType.DIRECTIVE_NAME */, start);
16922
+ const name = this._cursor.getChars(nameStart);
16923
+ this._endToken([name]);
16924
+ this._attemptCharCodeUntilFn(isNotWhitespace);
16925
+ // Optionally there might be attributes bound to the specific directive.
16926
+ // Stop parsing if there's no opening character for them.
16927
+ if (this._cursor.peek() !== $LPAREN) {
16928
+ return;
16929
+ }
16930
+ this._openDirectiveCount++;
16931
+ this._beginToken(39 /* TokenType.DIRECTIVE_OPEN */);
16932
+ this._cursor.advance();
16933
+ this._endToken([]);
16934
+ this._attemptCharCodeUntilFn(isNotWhitespace);
16935
+ // Capture all the attributes until we hit a closing paren.
16936
+ while (!isAttributeTerminator(this._cursor.peek()) && this._cursor.peek() !== $RPAREN) {
16937
+ this._consumeAttribute();
16938
+ }
16939
+ // Trim any trailing whitespace.
16940
+ this._attemptCharCodeUntilFn(isNotWhitespace);
16941
+ this._openDirectiveCount--;
16942
+ if (this._cursor.peek() !== $RPAREN) {
16943
+ // Stop parsing, instead of throwing, if we've hit the end of the tag.
16944
+ // This can be handled better later when turning the tokens into AST.
16945
+ if (this._cursor.peek() === $GT || this._cursor.peek() === $SLASH) {
16946
+ return;
16947
+ }
16948
+ throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
16949
+ }
16950
+ // Capture the closing token.
16951
+ this._beginToken(40 /* TokenType.DIRECTIVE_CLOSE */);
16952
+ this._cursor.advance();
16953
+ this._endToken([]);
16954
+ this._attemptCharCodeUntilFn(isNotWhitespace);
16955
+ }
16672
16956
  _getProcessedChars(start, end) {
16673
16957
  return this._processCarriageReturns(end.getChars(start));
16674
16958
  }
@@ -16784,6 +17068,15 @@ function isBlockNameChar(code) {
16784
17068
  function isBlockParameterChar(code) {
16785
17069
  return code !== $SEMICOLON && isNotWhitespace(code);
16786
17070
  }
17071
+ function isSelectorlessNameStart(code) {
17072
+ return code === $_ || (code >= $A && code <= $Z);
17073
+ }
17074
+ function isSelectorlessNameChar(code) {
17075
+ return isAsciiLetter(code) || isDigit(code) || code === $_;
17076
+ }
17077
+ function isAttributeTerminator(code) {
17078
+ return code === $SLASH || code === $GT || code === $LT || code === $EOF;
17079
+ }
16787
17080
  function mergeTextTokens(srcTokens) {
16788
17081
  const dstTokens = [];
16789
17082
  let lastDstToken = undefined;
@@ -17080,26 +17373,26 @@ let Parser$1 = class Parser {
17080
17373
  };
17081
17374
  class _TreeBuilder {
17082
17375
  tokens;
17083
- getTagDefinition;
17376
+ tagDefinitionResolver;
17084
17377
  _index = -1;
17085
17378
  // `_peek` will be initialized by the call to `_advance()` in the constructor.
17086
17379
  _peek;
17087
17380
  _containerStack = [];
17088
17381
  rootNodes = [];
17089
17382
  errors = [];
17090
- constructor(tokens, getTagDefinition) {
17383
+ constructor(tokens, tagDefinitionResolver) {
17091
17384
  this.tokens = tokens;
17092
- this.getTagDefinition = getTagDefinition;
17385
+ this.tagDefinitionResolver = tagDefinitionResolver;
17093
17386
  this._advance();
17094
17387
  }
17095
17388
  build() {
17096
- while (this._peek.type !== 33 /* TokenType.EOF */) {
17389
+ while (this._peek.type !== 41 /* TokenType.EOF */) {
17097
17390
  if (this._peek.type === 0 /* TokenType.TAG_OPEN_START */ ||
17098
17391
  this._peek.type === 4 /* TokenType.INCOMPLETE_TAG_OPEN */) {
17099
- this._consumeStartTag(this._advance());
17392
+ this._consumeElementStartTag(this._advance());
17100
17393
  }
17101
17394
  else if (this._peek.type === 3 /* TokenType.TAG_CLOSE */) {
17102
- this._consumeEndTag(this._advance());
17395
+ this._consumeElementEndTag(this._advance());
17103
17396
  }
17104
17397
  else if (this._peek.type === 12 /* TokenType.CDATA_START */) {
17105
17398
  this._closeVoidElement();
@@ -17138,6 +17431,13 @@ class _TreeBuilder {
17138
17431
  this._closeVoidElement();
17139
17432
  this._consumeIncompleteLet(this._advance());
17140
17433
  }
17434
+ else if (this._peek.type === 33 /* TokenType.COMPONENT_OPEN_START */ ||
17435
+ this._peek.type === 37 /* TokenType.INCOMPLETE_COMPONENT_OPEN */) {
17436
+ this._consumeComponentStartTag(this._advance());
17437
+ }
17438
+ else if (this._peek.type === 36 /* TokenType.COMPONENT_CLOSE */) {
17439
+ this._consumeComponentEndTag(this._advance());
17440
+ }
17141
17441
  else {
17142
17442
  // Skip all other tokens...
17143
17443
  this._advance();
@@ -17211,9 +17511,9 @@ class _TreeBuilder {
17211
17511
  if (!exp)
17212
17512
  return null;
17213
17513
  const end = this._advance();
17214
- exp.push({ type: 33 /* TokenType.EOF */, parts: [], sourceSpan: end.sourceSpan });
17514
+ exp.push({ type: 41 /* TokenType.EOF */, parts: [], sourceSpan: end.sourceSpan });
17215
17515
  // parse everything in between { and }
17216
- const expansionCaseParser = new _TreeBuilder(exp, this.getTagDefinition);
17516
+ const expansionCaseParser = new _TreeBuilder(exp, this.tagDefinitionResolver);
17217
17517
  expansionCaseParser.build();
17218
17518
  if (expansionCaseParser.errors.length > 0) {
17219
17519
  this.errors = this.errors.concat(expansionCaseParser.errors);
@@ -17251,7 +17551,7 @@ class _TreeBuilder {
17251
17551
  return null;
17252
17552
  }
17253
17553
  }
17254
- if (this._peek.type === 33 /* TokenType.EOF */) {
17554
+ if (this._peek.type === 41 /* TokenType.EOF */) {
17255
17555
  this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
17256
17556
  return null;
17257
17557
  }
@@ -17266,7 +17566,7 @@ class _TreeBuilder {
17266
17566
  const parent = this._getContainer();
17267
17567
  if (parent != null &&
17268
17568
  parent.children.length === 0 &&
17269
- this.getTagDefinition(parent.name).ignoreFirstLf) {
17569
+ this._getTagDefinition(parent)?.ignoreFirstLf) {
17270
17570
  text = text.substring(1);
17271
17571
  tokens[0] = { type: token.type, sourceSpan: token.sourceSpan, parts: [text] };
17272
17572
  }
@@ -17297,25 +17597,23 @@ class _TreeBuilder {
17297
17597
  }
17298
17598
  _closeVoidElement() {
17299
17599
  const el = this._getContainer();
17300
- if (el instanceof Element && this.getTagDefinition(el.name).isVoid) {
17600
+ if (el !== null && this._getTagDefinition(el)?.isVoid) {
17301
17601
  this._containerStack.pop();
17302
17602
  }
17303
17603
  }
17304
- _consumeStartTag(startTagToken) {
17305
- const [prefix, name] = startTagToken.parts;
17604
+ _consumeElementStartTag(startTagToken) {
17306
17605
  const attrs = [];
17307
- while (this._peek.type === 14 /* TokenType.ATTR_NAME */) {
17308
- attrs.push(this._consumeAttr(this._advance()));
17309
- }
17310
- const fullName = this._getElementFullName(prefix, name, this._getClosestParentElement());
17606
+ const directives = [];
17607
+ this._consumeAttributesAndDirectives(attrs, directives);
17608
+ const fullName = this._getElementFullName(startTagToken, this._getClosestElementLikeParent());
17311
17609
  let selfClosing = false;
17312
17610
  // Note: There could have been a tokenizer error
17313
17611
  // so that we don't get a token for the end tag...
17314
17612
  if (this._peek.type === 2 /* TokenType.TAG_OPEN_END_VOID */) {
17315
17613
  this._advance();
17316
17614
  selfClosing = true;
17317
- const tagDef = this.getTagDefinition(fullName);
17318
- if (!(tagDef.canSelfClose || getNsPrefix(fullName) !== null || tagDef.isVoid)) {
17615
+ const tagDef = this._getTagDefinition(fullName);
17616
+ if (!(tagDef?.canSelfClose || getNsPrefix(fullName) !== null || tagDef?.isVoid)) {
17319
17617
  this.errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void, custom and foreign elements can be self closed "${startTagToken.parts[1]}"`));
17320
17618
  }
17321
17619
  }
@@ -17327,10 +17625,10 @@ class _TreeBuilder {
17327
17625
  const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
17328
17626
  // Create a separate `startSpan` because `span` will be modified when there is an `end` span.
17329
17627
  const startSpan = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
17330
- const el = new Element(fullName, attrs, [], span, startSpan, undefined);
17331
- const parentEl = this._getContainer();
17332
- this._pushContainer(el, parentEl instanceof Element &&
17333
- this.getTagDefinition(parentEl.name).isClosedByChild(el.name));
17628
+ const el = new Element(fullName, attrs, directives, [], span, startSpan, undefined);
17629
+ const parent = this._getContainer();
17630
+ const isClosedByChild = parent !== null && !!this._getTagDefinition(parent)?.isClosedByChild(el.name);
17631
+ this._pushContainer(el, isClosedByChild);
17334
17632
  if (selfClosing) {
17335
17633
  // Elements that are self-closed have their `endSourceSpan` set to the full span, as the
17336
17634
  // element start tag also represents the end tag.
@@ -17343,6 +17641,73 @@ class _TreeBuilder {
17343
17641
  this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`));
17344
17642
  }
17345
17643
  }
17644
+ _consumeComponentStartTag(startToken) {
17645
+ const componentName = startToken.parts[0];
17646
+ const attrs = [];
17647
+ const directives = [];
17648
+ this._consumeAttributesAndDirectives(attrs, directives);
17649
+ const closestElement = this._getClosestElementLikeParent();
17650
+ const tagName = this._getComponentTagName(startToken, closestElement);
17651
+ const fullName = this._getComponentFullName(startToken, closestElement);
17652
+ const selfClosing = this._peek.type === 35 /* TokenType.COMPONENT_OPEN_END_VOID */;
17653
+ this._advance();
17654
+ const end = this._peek.sourceSpan.fullStart;
17655
+ const span = new ParseSourceSpan(startToken.sourceSpan.start, end, startToken.sourceSpan.fullStart);
17656
+ const startSpan = new ParseSourceSpan(startToken.sourceSpan.start, end, startToken.sourceSpan.fullStart);
17657
+ const node = new Component(componentName, tagName, fullName, attrs, directives, [], span, startSpan, undefined);
17658
+ const parent = this._getContainer();
17659
+ const isClosedByChild = parent !== null &&
17660
+ node.tagName !== null &&
17661
+ !!this._getTagDefinition(parent)?.isClosedByChild(node.tagName);
17662
+ this._pushContainer(node, isClosedByChild);
17663
+ if (selfClosing) {
17664
+ this._popContainer(fullName, Component, span);
17665
+ }
17666
+ else if (startToken.type === 37 /* TokenType.INCOMPLETE_COMPONENT_OPEN */) {
17667
+ this._popContainer(fullName, Component, null);
17668
+ this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`));
17669
+ }
17670
+ }
17671
+ _consumeAttributesAndDirectives(attributesResult, directivesResult) {
17672
+ while (this._peek.type === 14 /* TokenType.ATTR_NAME */ ||
17673
+ this._peek.type === 38 /* TokenType.DIRECTIVE_NAME */) {
17674
+ if (this._peek.type === 38 /* TokenType.DIRECTIVE_NAME */) {
17675
+ directivesResult.push(this._consumeDirective(this._peek));
17676
+ }
17677
+ else {
17678
+ attributesResult.push(this._consumeAttr(this._advance()));
17679
+ }
17680
+ }
17681
+ }
17682
+ _consumeComponentEndTag(endToken) {
17683
+ const fullName = this._getComponentFullName(endToken, this._getClosestElementLikeParent());
17684
+ if (!this._popContainer(fullName, Component, endToken.sourceSpan)) {
17685
+ const container = this._containerStack[this._containerStack.length - 1];
17686
+ let suffix;
17687
+ if (container instanceof Component && container.componentName === endToken.parts[0]) {
17688
+ suffix = `, did you mean "${container.fullName}"?`;
17689
+ }
17690
+ else {
17691
+ suffix = '. It may happen when the tag has already been closed by another tag.';
17692
+ }
17693
+ const errMsg = `Unexpected closing tag "${fullName}"${suffix}`;
17694
+ this.errors.push(TreeError.create(fullName, endToken.sourceSpan, errMsg));
17695
+ }
17696
+ }
17697
+ _getTagDefinition(nodeOrName) {
17698
+ if (typeof nodeOrName === 'string') {
17699
+ return this.tagDefinitionResolver(nodeOrName);
17700
+ }
17701
+ else if (nodeOrName instanceof Element) {
17702
+ return this.tagDefinitionResolver(nodeOrName.name);
17703
+ }
17704
+ else if (nodeOrName instanceof Component && nodeOrName.tagName !== null) {
17705
+ return this.tagDefinitionResolver(nodeOrName.tagName);
17706
+ }
17707
+ else {
17708
+ return null;
17709
+ }
17710
+ }
17346
17711
  _pushContainer(node, isClosedByChild) {
17347
17712
  if (isClosedByChild) {
17348
17713
  this._containerStack.pop();
@@ -17350,9 +17715,9 @@ class _TreeBuilder {
17350
17715
  this._addToParent(node);
17351
17716
  this._containerStack.push(node);
17352
17717
  }
17353
- _consumeEndTag(endTagToken) {
17354
- const fullName = this._getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this._getClosestParentElement());
17355
- if (this.getTagDefinition(fullName).isVoid) {
17718
+ _consumeElementEndTag(endTagToken) {
17719
+ const fullName = this._getElementFullName(endTagToken, this._getClosestElementLikeParent());
17720
+ if (this._getTagDefinition(fullName)?.isVoid) {
17356
17721
  this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, `Void elements do not have end tags "${endTagToken.parts[1]}"`));
17357
17722
  }
17358
17723
  else if (!this._popContainer(fullName, Element, endTagToken.sourceSpan)) {
@@ -17370,7 +17735,8 @@ class _TreeBuilder {
17370
17735
  let unexpectedCloseTagDetected = false;
17371
17736
  for (let stackIndex = this._containerStack.length - 1; stackIndex >= 0; stackIndex--) {
17372
17737
  const node = this._containerStack[stackIndex];
17373
- if ((node.name === expectedName || expectedName === null) && node instanceof expectedType) {
17738
+ const nodeName = node instanceof Component ? node.fullName : node.name;
17739
+ if ((nodeName === expectedName || expectedName === null) && node instanceof expectedType) {
17374
17740
  // Record the parse span with the element that is being closed. Any elements that are
17375
17741
  // removed from the element stack at this point are closed implicitly, so they won't get
17376
17742
  // an end source span (as there is no explicit closing element).
@@ -17380,8 +17746,7 @@ class _TreeBuilder {
17380
17746
  return !unexpectedCloseTagDetected;
17381
17747
  }
17382
17748
  // Blocks and most elements are not self closing.
17383
- if (node instanceof Block ||
17384
- (node instanceof Element && !this.getTagDefinition(node.name).closedByParent)) {
17749
+ if (node instanceof Block || !this._getTagDefinition(node)?.closedByParent) {
17385
17750
  // Note that we encountered an unexpected close tag but continue processing the element
17386
17751
  // stack so we can assign an `endSourceSpan` if there is a corresponding start tag for this
17387
17752
  // end tag in the stack.
@@ -17441,6 +17806,31 @@ class _TreeBuilder {
17441
17806
  new ParseSourceSpan(valueStartSpan.start, valueEnd, valueStartSpan.fullStart);
17442
17807
  return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart), attrName.sourceSpan, valueSpan, valueTokens.length > 0 ? valueTokens : undefined, undefined);
17443
17808
  }
17809
+ _consumeDirective(nameToken) {
17810
+ const attributes = [];
17811
+ let startSourceSpanEnd = nameToken.sourceSpan.end;
17812
+ let endSourceSpan = null;
17813
+ this._advance();
17814
+ if (this._peek.type === 39 /* TokenType.DIRECTIVE_OPEN */) {
17815
+ // Capture the opening token in the start span.
17816
+ startSourceSpanEnd = this._peek.sourceSpan.end;
17817
+ this._advance();
17818
+ // Cast here is necessary, because TS doesn't know that `_advance` changed `_peek`.
17819
+ while (this._peek.type === 14 /* TokenType.ATTR_NAME */) {
17820
+ attributes.push(this._consumeAttr(this._advance()));
17821
+ }
17822
+ if (this._peek.type === 40 /* TokenType.DIRECTIVE_CLOSE */) {
17823
+ endSourceSpan = this._peek.sourceSpan;
17824
+ this._advance();
17825
+ }
17826
+ else {
17827
+ this.errors.push(TreeError.create(null, nameToken.sourceSpan, 'Unterminated directive definition'));
17828
+ }
17829
+ }
17830
+ const startSourceSpan = new ParseSourceSpan(nameToken.sourceSpan.start, startSourceSpanEnd, nameToken.sourceSpan.fullStart);
17831
+ const sourceSpan = new ParseSourceSpan(startSourceSpan.start, endSourceSpan === null ? nameToken.sourceSpan.end : endSourceSpan.end, startSourceSpan.fullStart);
17832
+ return new Directive(nameToken.parts[0], attributes, sourceSpan, startSourceSpan, endSourceSpan);
17833
+ }
17444
17834
  _consumeBlockOpen(token) {
17445
17835
  const parameters = [];
17446
17836
  while (this._peek.type === 27 /* TokenType.BLOCK_PARAMETER */) {
@@ -17531,10 +17921,11 @@ class _TreeBuilder {
17531
17921
  ? this._containerStack[this._containerStack.length - 1]
17532
17922
  : null;
17533
17923
  }
17534
- _getClosestParentElement() {
17924
+ _getClosestElementLikeParent() {
17535
17925
  for (let i = this._containerStack.length - 1; i > -1; i--) {
17536
- if (this._containerStack[i] instanceof Element) {
17537
- return this._containerStack[i];
17926
+ const current = this._containerStack[i];
17927
+ if (current instanceof Element || current instanceof Component) {
17928
+ return current;
17538
17929
  }
17539
17930
  }
17540
17931
  return null;
@@ -17548,18 +17939,57 @@ class _TreeBuilder {
17548
17939
  parent.children.push(node);
17549
17940
  }
17550
17941
  }
17551
- _getElementFullName(prefix, localName, parentElement) {
17552
- if (prefix === '') {
17553
- prefix = this.getTagDefinition(localName).implicitNamespacePrefix || '';
17554
- if (prefix === '' && parentElement != null) {
17555
- const parentTagName = splitNsName(parentElement.name)[1];
17556
- const parentTagDefinition = this.getTagDefinition(parentTagName);
17557
- if (!parentTagDefinition.preventNamespaceInheritance) {
17558
- prefix = getNsPrefix(parentElement.name);
17942
+ _getElementFullName(token, parent) {
17943
+ const prefix = this._getPrefix(token, parent);
17944
+ return mergeNsAndName(prefix, token.parts[1]);
17945
+ }
17946
+ _getComponentFullName(token, parent) {
17947
+ const componentName = token.parts[0];
17948
+ const tagName = this._getComponentTagName(token, parent);
17949
+ if (tagName === null) {
17950
+ return componentName;
17951
+ }
17952
+ return tagName.startsWith(':') ? componentName + tagName : `${componentName}:${tagName}`;
17953
+ }
17954
+ _getComponentTagName(token, parent) {
17955
+ const prefix = this._getPrefix(token, parent);
17956
+ const tagName = token.parts[2];
17957
+ if (!prefix && !tagName) {
17958
+ return null;
17959
+ }
17960
+ else if (!prefix && tagName) {
17961
+ return tagName;
17962
+ }
17963
+ else {
17964
+ // TODO(crisbeto): re-evaluate this fallback. Maybe base it off the class name?
17965
+ return mergeNsAndName(prefix, tagName || 'ng-component');
17966
+ }
17967
+ }
17968
+ _getPrefix(token, parent) {
17969
+ let prefix;
17970
+ let tagName;
17971
+ if (token.type === 33 /* TokenType.COMPONENT_OPEN_START */ ||
17972
+ token.type === 37 /* TokenType.INCOMPLETE_COMPONENT_OPEN */ ||
17973
+ token.type === 36 /* TokenType.COMPONENT_CLOSE */) {
17974
+ prefix = token.parts[1];
17975
+ tagName = token.parts[2];
17976
+ }
17977
+ else {
17978
+ prefix = token.parts[0];
17979
+ tagName = token.parts[1];
17980
+ }
17981
+ prefix = prefix || this._getTagDefinition(tagName)?.implicitNamespacePrefix || '';
17982
+ if (!prefix && parent) {
17983
+ const parentName = parent instanceof Element ? parent.name : parent.tagName;
17984
+ if (parentName !== null) {
17985
+ const parentTagName = splitNsName(parentName)[1];
17986
+ const parentTagDefinition = this._getTagDefinition(parentTagName);
17987
+ if (parentTagDefinition !== null && !parentTagDefinition.preventNamespaceInheritance) {
17988
+ prefix = getNsPrefix(parentName);
17559
17989
  }
17560
17990
  }
17561
17991
  }
17562
- return mergeNsAndName(prefix, localName);
17992
+ return prefix;
17563
17993
  }
17564
17994
  }
17565
17995
  function lastOnStack(stack, element) {
@@ -17638,11 +18068,11 @@ class WhitespaceVisitor {
17638
18068
  if (SKIP_WS_TRIM_TAGS.has(element.name) || hasPreserveWhitespacesAttr(element.attrs)) {
17639
18069
  // don't descent into elements where we need to preserve whitespaces
17640
18070
  // but still visit all attributes to eliminate one used as a market to preserve WS
17641
- const newElement = new Element(element.name, visitAllWithSiblings(this, element.attrs), element.children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
18071
+ const newElement = new Element(element.name, visitAllWithSiblings(this, element.attrs), visitAllWithSiblings(this, element.directives), element.children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
17642
18072
  this.originalNodeMap?.set(newElement, element);
17643
18073
  return newElement;
17644
18074
  }
17645
- const newElement = new Element(element.name, element.attrs, visitAllWithSiblings(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
18075
+ const newElement = new Element(element.name, element.attrs, element.directives, visitAllWithSiblings(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
17646
18076
  this.originalNodeMap?.set(newElement, element);
17647
18077
  return newElement;
17648
18078
  }
@@ -17716,6 +18146,22 @@ class WhitespaceVisitor {
17716
18146
  visitLetDeclaration(decl, context) {
17717
18147
  return decl;
17718
18148
  }
18149
+ visitComponent(node, context) {
18150
+ if ((node.tagName && SKIP_WS_TRIM_TAGS.has(node.tagName)) ||
18151
+ hasPreserveWhitespacesAttr(node.attrs)) {
18152
+ // don't descent into elements where we need to preserve whitespaces
18153
+ // but still visit all attributes to eliminate one used as a market to preserve WS
18154
+ const newElement = new Component(node.componentName, node.tagName, node.fullName, visitAllWithSiblings(this, node.attrs), visitAllWithSiblings(this, node.directives), node.children, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.i18n);
18155
+ this.originalNodeMap?.set(newElement, node);
18156
+ return newElement;
18157
+ }
18158
+ const newElement = new Component(node.componentName, node.tagName, node.fullName, node.attrs, node.directives, visitAllWithSiblings(this, node.children), node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.i18n);
18159
+ this.originalNodeMap?.set(newElement, node);
18160
+ return newElement;
18161
+ }
18162
+ visitDirective(directive, context) {
18163
+ return directive;
18164
+ }
17719
18165
  visit(_node, context) {
17720
18166
  // `visitAllWithSiblings` provides context necessary for ICU messages to be handled correctly.
17721
18167
  // Prefer that over calling `html.visitAll` directly on this visitor.
@@ -19961,6 +20407,7 @@ const SCHEMA = [
19961
20407
  'q,blockquote,cite^[HTMLElement]|',
19962
20408
  'script^[HTMLElement]|!async,charset,%crossOrigin,!defer,event,htmlFor,integrity,!noModule,%referrerPolicy,src,text,type',
19963
20409
  'select^[HTMLElement]|autocomplete,!disabled,#length,!multiple,name,!required,#selectedIndex,#size,value',
20410
+ 'selectedcontent^[HTMLElement]|',
19964
20411
  'slot^[HTMLElement]|name',
19965
20412
  'source^[HTMLElement]|#height,media,sizes,src,srcset,type,#width',
19966
20413
  'span^[HTMLElement]|',
@@ -20615,28 +21062,13 @@ class _I18nVisitor {
20615
21062
  return new Message(i18nodes, context.placeholderToContent, context.placeholderToMessage, meaning, description, customId);
20616
21063
  }
20617
21064
  visitElement(el, context) {
20618
- const children = visitAll(this, el.children, context);
20619
- const attrs = {};
20620
- el.attrs.forEach((attr) => {
20621
- // Do not visit the attributes, translatable ones are top-level ASTs
20622
- attrs[attr.name] = attr.value;
20623
- });
20624
- const isVoid = getHtmlTagDefinition(el.name).isVoid;
20625
- const startPhName = context.placeholderRegistry.getStartTagPlaceholderName(el.name, attrs, isVoid);
20626
- context.placeholderToContent[startPhName] = {
20627
- text: el.startSourceSpan.toString(),
20628
- sourceSpan: el.startSourceSpan,
20629
- };
20630
- let closePhName = '';
20631
- if (!isVoid) {
20632
- closePhName = context.placeholderRegistry.getCloseTagPlaceholderName(el.name);
20633
- context.placeholderToContent[closePhName] = {
20634
- text: `</${el.name}>`,
20635
- sourceSpan: el.endSourceSpan ?? el.sourceSpan,
20636
- };
20637
- }
20638
- const node = new TagPlaceholder(el.name, attrs, startPhName, closePhName, children, isVoid, el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
20639
- return context.visitNodeFn(el, node);
21065
+ return this._visitElementLike(el, context);
21066
+ }
21067
+ visitComponent(component, context) {
21068
+ return this._visitElementLike(component, context);
21069
+ }
21070
+ visitDirective(directive, context) {
21071
+ throw new Error('Unreachable code');
20640
21072
  }
20641
21073
  visitAttribute(attribute, context) {
20642
21074
  const node = attribute.valueTokens === undefined || attribute.valueTokens.length === 1
@@ -20710,6 +21142,41 @@ class _I18nVisitor {
20710
21142
  visitLetDeclaration(decl, context) {
20711
21143
  return null;
20712
21144
  }
21145
+ _visitElementLike(node, context) {
21146
+ const children = visitAll(this, node.children, context);
21147
+ const attrs = {};
21148
+ const visitAttribute = (attr) => {
21149
+ // Do not visit the attributes, translatable ones are top-level ASTs
21150
+ attrs[attr.name] = attr.value;
21151
+ };
21152
+ let nodeName;
21153
+ let isVoid;
21154
+ if (node instanceof Element) {
21155
+ nodeName = node.name;
21156
+ isVoid = getHtmlTagDefinition(node.name).isVoid;
21157
+ }
21158
+ else {
21159
+ nodeName = node.fullName;
21160
+ isVoid = node.tagName ? getHtmlTagDefinition(node.tagName).isVoid : false;
21161
+ }
21162
+ node.attrs.forEach(visitAttribute);
21163
+ node.directives.forEach((dir) => dir.attrs.forEach(visitAttribute));
21164
+ const startPhName = context.placeholderRegistry.getStartTagPlaceholderName(nodeName, attrs, isVoid);
21165
+ context.placeholderToContent[startPhName] = {
21166
+ text: node.startSourceSpan.toString(),
21167
+ sourceSpan: node.startSourceSpan,
21168
+ };
21169
+ let closePhName = '';
21170
+ if (!isVoid) {
21171
+ closePhName = context.placeholderRegistry.getCloseTagPlaceholderName(nodeName);
21172
+ context.placeholderToContent[closePhName] = {
21173
+ text: `</${nodeName}>`,
21174
+ sourceSpan: node.endSourceSpan ?? node.sourceSpan,
21175
+ };
21176
+ }
21177
+ const i18nNode = new TagPlaceholder(nodeName, attrs, startPhName, closePhName, children, isVoid, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
21178
+ return context.visitNodeFn(node, i18nNode);
21179
+ }
20713
21180
  /**
20714
21181
  * Convert, text and interpolated tokens up into text and placeholder pieces.
20715
21182
  *
@@ -20972,15 +21439,74 @@ class I18nMetaVisitor {
20972
21439
  return new ParseTreeResult(result, this._errors);
20973
21440
  }
20974
21441
  visitElement(element) {
21442
+ this._visitElementLike(element);
21443
+ return element;
21444
+ }
21445
+ visitComponent(component, context) {
21446
+ this._visitElementLike(component);
21447
+ return component;
21448
+ }
21449
+ visitExpansion(expansion, currentMessage) {
21450
+ let message;
21451
+ const meta = expansion.i18n;
21452
+ this.hasI18nMeta = true;
21453
+ if (meta instanceof IcuPlaceholder) {
21454
+ // set ICU placeholder name (e.g. "ICU_1"),
21455
+ // generated while processing root element contents,
21456
+ // so we can reference it when we output translation
21457
+ const name = meta.name;
21458
+ message = this._generateI18nMessage([expansion], meta);
21459
+ const icu = icuFromI18nMessage(message);
21460
+ icu.name = name;
21461
+ if (currentMessage !== null) {
21462
+ // Also update the placeholderToMessage map with this new message
21463
+ currentMessage.placeholderToMessage[name] = message;
21464
+ }
21465
+ }
21466
+ else {
21467
+ // ICU is a top level message, try to use metadata from container element if provided via
21468
+ // `context` argument. Note: context may not be available for standalone ICUs (without
21469
+ // wrapping element), so fallback to ICU metadata in this case.
21470
+ message = this._generateI18nMessage([expansion], currentMessage || meta);
21471
+ }
21472
+ expansion.i18n = message;
21473
+ return expansion;
21474
+ }
21475
+ visitText(text) {
21476
+ return text;
21477
+ }
21478
+ visitAttribute(attribute) {
21479
+ return attribute;
21480
+ }
21481
+ visitComment(comment) {
21482
+ return comment;
21483
+ }
21484
+ visitExpansionCase(expansionCase) {
21485
+ return expansionCase;
21486
+ }
21487
+ visitBlock(block, context) {
21488
+ visitAll(this, block.children, context);
21489
+ return block;
21490
+ }
21491
+ visitBlockParameter(parameter, context) {
21492
+ return parameter;
21493
+ }
21494
+ visitLetDeclaration(decl, context) {
21495
+ return decl;
21496
+ }
21497
+ visitDirective(directive, context) {
21498
+ return directive;
21499
+ }
21500
+ _visitElementLike(node) {
20975
21501
  let message = undefined;
20976
- if (hasI18nAttrs(element)) {
21502
+ if (hasI18nAttrs(node)) {
20977
21503
  this.hasI18nMeta = true;
20978
21504
  const attrs = [];
20979
21505
  const attrsMeta = {};
20980
- for (const attr of element.attrs) {
21506
+ for (const attr of node.attrs) {
20981
21507
  if (attr.name === I18N_ATTR) {
20982
21508
  // root 'i18n' node attribute
20983
- const i18n = element.i18n || attr.value;
21509
+ const i18n = node.i18n || attr.value;
20984
21510
  // Generate a new AST with whitespace trimmed, but also generate a map
20985
21511
  // to correlate each new node to its original so we can apply i18n
20986
21512
  // information to the original node based on the trimmed content.
@@ -20994,20 +21520,27 @@ class I18nMetaVisitor {
20994
21520
  // backwards compatibility.
20995
21521
  const originalNodeMap = new Map();
20996
21522
  const trimmedNodes = this.preserveSignificantWhitespace
20997
- ? element.children
20998
- : visitAllWithSiblings(new WhitespaceVisitor(false /* preserveSignificantWhitespace */, originalNodeMap), element.children);
21523
+ ? node.children
21524
+ : visitAllWithSiblings(new WhitespaceVisitor(false /* preserveSignificantWhitespace */, originalNodeMap), node.children);
20999
21525
  message = this._generateI18nMessage(trimmedNodes, i18n, setI18nRefs(originalNodeMap));
21000
21526
  if (message.nodes.length === 0) {
21001
21527
  // Ignore the message if it is empty.
21002
21528
  message = undefined;
21003
21529
  }
21004
21530
  // Store the message on the element
21005
- element.i18n = message;
21531
+ node.i18n = message;
21006
21532
  }
21007
21533
  else if (attr.name.startsWith(I18N_ATTR_PREFIX)) {
21008
21534
  // 'i18n-*' attributes
21009
21535
  const name = attr.name.slice(I18N_ATTR_PREFIX.length);
21010
- if (isTrustedTypesSink(element.name, name)) {
21536
+ let isTrustedType;
21537
+ if (node instanceof Component) {
21538
+ isTrustedType = node.tagName === null ? false : isTrustedTypesSink(node.tagName, name);
21539
+ }
21540
+ else {
21541
+ isTrustedType = isTrustedTypesSink(node.name, name);
21542
+ }
21543
+ if (isTrustedType) {
21011
21544
  this._reportError(attr, `Translating attribute '${name}' is disallowed for security reasons.`);
21012
21545
  }
21013
21546
  else {
@@ -21032,59 +21565,10 @@ class I18nMetaVisitor {
21032
21565
  if (!this.keepI18nAttrs) {
21033
21566
  // update element's attributes,
21034
21567
  // keeping only non-i18n related ones
21035
- element.attrs = attrs;
21036
- }
21037
- }
21038
- visitAll(this, element.children, message);
21039
- return element;
21040
- }
21041
- visitExpansion(expansion, currentMessage) {
21042
- let message;
21043
- const meta = expansion.i18n;
21044
- this.hasI18nMeta = true;
21045
- if (meta instanceof IcuPlaceholder) {
21046
- // set ICU placeholder name (e.g. "ICU_1"),
21047
- // generated while processing root element contents,
21048
- // so we can reference it when we output translation
21049
- const name = meta.name;
21050
- message = this._generateI18nMessage([expansion], meta);
21051
- const icu = icuFromI18nMessage(message);
21052
- icu.name = name;
21053
- if (currentMessage !== null) {
21054
- // Also update the placeholderToMessage map with this new message
21055
- currentMessage.placeholderToMessage[name] = message;
21568
+ node.attrs = attrs;
21056
21569
  }
21057
21570
  }
21058
- else {
21059
- // ICU is a top level message, try to use metadata from container element if provided via
21060
- // `context` argument. Note: context may not be available for standalone ICUs (without
21061
- // wrapping element), so fallback to ICU metadata in this case.
21062
- message = this._generateI18nMessage([expansion], currentMessage || meta);
21063
- }
21064
- expansion.i18n = message;
21065
- return expansion;
21066
- }
21067
- visitText(text) {
21068
- return text;
21069
- }
21070
- visitAttribute(attribute) {
21071
- return attribute;
21072
- }
21073
- visitComment(comment) {
21074
- return comment;
21075
- }
21076
- visitExpansionCase(expansionCase) {
21077
- return expansionCase;
21078
- }
21079
- visitBlock(block, context) {
21080
- visitAll(this, block.children, context);
21081
- return block;
21082
- }
21083
- visitBlockParameter(parameter, context) {
21084
- return parameter;
21085
- }
21086
- visitLetDeclaration(decl, context) {
21087
- return decl;
21571
+ visitAll(this, node.children, message);
21088
21572
  }
21089
21573
  /**
21090
21574
  * Parse the general form `meta` passed into extract the explicit metadata needed to create a
@@ -22004,7 +22488,7 @@ function addNamesToView(unit, baseName, state, compatibility) {
22004
22488
  for (const op of unit.ops()) {
22005
22489
  switch (op.kind) {
22006
22490
  case OpKind.Property:
22007
- case OpKind.HostProperty:
22491
+ case OpKind.DomProperty:
22008
22492
  if (op.isAnimationTrigger) {
22009
22493
  op.name = '@' + op.name;
22010
22494
  }
@@ -22320,8 +22804,8 @@ const UPDATE_ORDERING = [
22320
22804
  * Host bindings have their own update ordering.
22321
22805
  */
22322
22806
  const UPDATE_HOST_ORDERING = [
22323
- { test: kindWithInterpolationTest(OpKind.HostProperty, true) },
22324
- { test: kindWithInterpolationTest(OpKind.HostProperty, false) },
22807
+ { test: kindWithInterpolationTest(OpKind.DomProperty, true) },
22808
+ { test: kindWithInterpolationTest(OpKind.DomProperty, false) },
22325
22809
  { test: kindTest(OpKind.Attribute) },
22326
22810
  { test: kindTest(OpKind.StyleMap), transform: keepLast },
22327
22811
  { test: kindTest(OpKind.ClassMap), transform: keepLast },
@@ -22340,7 +22824,7 @@ const handledOpKinds = new Set([
22340
22824
  OpKind.ClassProp,
22341
22825
  OpKind.Property,
22342
22826
  OpKind.TwoWayProperty,
22343
- OpKind.HostProperty,
22827
+ OpKind.DomProperty,
22344
22828
  OpKind.Attribute,
22345
22829
  ]);
22346
22830
  /**
@@ -23114,12 +23598,12 @@ function classMapInterpolate(strings, expressions, sourceSpan) {
23114
23598
  const interpolationArgs = collateInterpolationArgs(strings, expressions);
23115
23599
  return callVariadicInstruction(CLASS_MAP_INTERPOLATE_CONFIG, [], interpolationArgs, [], sourceSpan);
23116
23600
  }
23117
- function hostProperty(name, expression, sanitizer, sourceSpan) {
23601
+ function domProperty(name, expression, sanitizer, sourceSpan) {
23118
23602
  const args = [literal(name), expression];
23119
23603
  if (sanitizer !== null) {
23120
23604
  args.push(sanitizer);
23121
23605
  }
23122
- return call(Identifiers.hostProperty, args, sourceSpan);
23606
+ return call(Identifiers.domProperty, args, sourceSpan);
23123
23607
  }
23124
23608
  function syntheticHostProperty(name, expression, sourceSpan) {
23125
23609
  return call(Identifiers.syntheticHostProperty, [literal(name), expression], sourceSpan);
@@ -23658,7 +24142,7 @@ function reifyUpdateOperations(_unit, ops) {
23658
24142
  OpList.replace(op, attribute(op.name, op.expression, op.sanitizer, op.namespace));
23659
24143
  }
23660
24144
  break;
23661
- case OpKind.HostProperty:
24145
+ case OpKind.DomProperty:
23662
24146
  if (op.expression instanceof Interpolation) {
23663
24147
  throw new Error('not yet handled');
23664
24148
  }
@@ -23667,7 +24151,7 @@ function reifyUpdateOperations(_unit, ops) {
23667
24151
  OpList.replace(op, syntheticHostProperty(op.name, op.expression, op.sourceSpan));
23668
24152
  }
23669
24153
  else {
23670
- OpList.replace(op, hostProperty(op.name, op.expression, op.sanitizer, op.sourceSpan));
24154
+ OpList.replace(op, domProperty(op.name, op.expression, op.sanitizer, op.sourceSpan));
23671
24155
  }
23672
24156
  }
23673
24157
  break;
@@ -24501,7 +24985,7 @@ function resolveSanitizers(job) {
24501
24985
  switch (op.kind) {
24502
24986
  case OpKind.Property:
24503
24987
  case OpKind.Attribute:
24504
- case OpKind.HostProperty:
24988
+ case OpKind.DomProperty:
24505
24989
  let sanitizerFn = null;
24506
24990
  if (Array.isArray(op.securityContext) &&
24507
24991
  op.securityContext.length === 2 &&
@@ -24523,7 +25007,7 @@ function resolveSanitizers(job) {
24523
25007
  // <iframe>).
24524
25008
  if (op.sanitizer === null) {
24525
25009
  let isIframe = false;
24526
- if (job.kind === CompilationJobKind.Host || op.kind === OpKind.HostProperty) {
25010
+ if (job.kind === CompilationJobKind.Host || op.kind === OpKind.DomProperty) {
24527
25011
  // Note: for host bindings defined on a directive, we do not try to find all
24528
25012
  // possible places where it can be matched, so we can not determine whether
24529
25013
  // the host element is an <iframe>. In this case, we just assume it is and append a
@@ -25130,7 +25614,7 @@ function varsUsedByOp(op) {
25130
25614
  let slots;
25131
25615
  switch (op.kind) {
25132
25616
  case OpKind.Property:
25133
- case OpKind.HostProperty:
25617
+ case OpKind.DomProperty:
25134
25618
  case OpKind.Attribute:
25135
25619
  // All of these bindings use 1 variable slot, plus 1 slot for every interpolated expression,
25136
25620
  // if any.
@@ -25859,7 +26343,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
25859
26343
  const securityContexts = bindingParser
25860
26344
  .calcPossibleSecurityContexts(input.componentSelector, property.name, bindingKind === BindingKind.Attribute)
25861
26345
  .filter((context) => context !== SecurityContext.NONE);
25862
- ingestHostProperty(job, property, bindingKind, securityContexts);
26346
+ ingestDomProperty(job, property, bindingKind, securityContexts);
25863
26347
  }
25864
26348
  for (const [name, expr] of Object.entries(input.attributes) ?? []) {
25865
26349
  const securityContexts = bindingParser
@@ -25874,7 +26358,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
25874
26358
  }
25875
26359
  // TODO: We should refactor the parser to use the same types and structures for host bindings as
25876
26360
  // with ordinary components. This would allow us to share a lot more ingestion code.
25877
- function ingestHostProperty(job, property, bindingKind, securityContexts) {
26361
+ function ingestDomProperty(job, property, bindingKind, securityContexts) {
25878
26362
  let expression;
25879
26363
  const ast = property.expression.ast;
25880
26364
  if (ast instanceof Interpolation$1) {
@@ -27392,10 +27876,16 @@ class BindingParser {
27392
27876
  const prop = this._schemaRegistry.getMappedPropName(propName);
27393
27877
  return calcPossibleSecurityContexts(this._schemaRegistry, selector, prop, isAttribute);
27394
27878
  }
27879
+ parseEventListenerName(rawName) {
27880
+ const [target, eventName] = splitAtColon(rawName, [null, rawName]);
27881
+ return { eventName: eventName, target };
27882
+ }
27883
+ parseAnimationEventName(rawName) {
27884
+ const matches = splitAtPeriod(rawName, [rawName, null]);
27885
+ return { eventName: matches[0], phase: matches[1] === null ? null : matches[1].toLowerCase() };
27886
+ }
27395
27887
  _parseAnimationEvent(name, expression, sourceSpan, handlerSpan, targetEvents, keySpan) {
27396
- const matches = splitAtPeriod(name, [name, '']);
27397
- const eventName = matches[0];
27398
- const phase = matches[1].toLowerCase();
27888
+ const { eventName, phase } = this.parseAnimationEventName(name);
27399
27889
  const ast = this._parseAction(expression, handlerSpan);
27400
27890
  targetEvents.push(new ParsedEvent(eventName, phase, ParsedEventType.Animation, ast, sourceSpan, handlerSpan, keySpan));
27401
27891
  if (eventName.length === 0) {
@@ -27412,7 +27902,7 @@ class BindingParser {
27412
27902
  }
27413
27903
  _parseRegularEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) {
27414
27904
  // long format: 'target: eventName'
27415
- const [target, eventName] = splitAtColon(name, [null, name]);
27905
+ const { eventName, target } = this.parseEventListenerName(name);
27416
27906
  const prevErrorCount = this.errors.length;
27417
27907
  const ast = this._parseAction(expression, handlerSpan);
27418
27908
  const isValid = this.errors.length === prevErrorCount;
@@ -27495,15 +27985,22 @@ function isAnimationLabel(name) {
27495
27985
  return name[0] == '@';
27496
27986
  }
27497
27987
  function calcPossibleSecurityContexts(registry, selector, propName, isAttribute) {
27498
- const ctxs = [];
27499
- CssSelector.parse(selector).forEach((selector) => {
27500
- const elementNames = selector.element ? [selector.element] : registry.allKnownElementNames();
27501
- const notElementNames = new Set(selector.notSelectors
27502
- .filter((selector) => selector.isElementSelector())
27503
- .map((selector) => selector.element));
27504
- const possibleElementNames = elementNames.filter((elementName) => !notElementNames.has(elementName));
27505
- ctxs.push(...possibleElementNames.map((elementName) => registry.securityContext(elementName, propName, isAttribute)));
27506
- });
27988
+ let ctxs;
27989
+ const nameToContext = (elName) => registry.securityContext(elName, propName, isAttribute);
27990
+ if (selector === null) {
27991
+ ctxs = registry.allKnownElementNames().map(nameToContext);
27992
+ }
27993
+ else {
27994
+ ctxs = [];
27995
+ CssSelector.parse(selector).forEach((selector) => {
27996
+ const elementNames = selector.element ? [selector.element] : registry.allKnownElementNames();
27997
+ const notElementNames = new Set(selector.notSelectors
27998
+ .filter((selector) => selector.isElementSelector())
27999
+ .map((selector) => selector.element));
28000
+ const possibleElementNames = elementNames.filter((elName) => !notElementNames.has(elName));
28001
+ ctxs.push(...possibleElementNames.map(nameToContext));
28002
+ });
28003
+ }
27507
28004
  return ctxs.length === 0 ? [SecurityContext.NONE] : Array.from(new Set(ctxs)).sort();
27508
28005
  }
27509
28006
  /**
@@ -27616,11 +28113,13 @@ const FOR_LOOP_EXPRESSION_PATTERN = /^\s*([0-9A-Za-z_$]*)\s+of\s+([\S\s]*)/;
27616
28113
  /** Pattern for the tracking expression in a for loop block. */
27617
28114
  const FOR_LOOP_TRACK_PATTERN = /^track\s+([\S\s]*)/;
27618
28115
  /** Pattern for the `as` expression in a conditional block. */
27619
- const CONDITIONAL_ALIAS_PATTERN = /^(as\s)+(.*)/;
28116
+ const CONDITIONAL_ALIAS_PATTERN = /^(as\s+)(.*)/;
27620
28117
  /** Pattern used to identify an `else if` block. */
27621
28118
  const ELSE_IF_PATTERN = /^else[^\S\r\n]+if/;
27622
28119
  /** Pattern used to identify a `let` parameter. */
27623
28120
  const FOR_LOOP_LET_PATTERN = /^let\s+([\S\s]*)/;
28121
+ /** Pattern used to validate a JavaScript identifier. */
28122
+ const IDENTIFIER_PATTERN = /^[$A-Z_][0-9A-Z_$]*$/i;
27624
28123
  /**
27625
28124
  * Pattern to group a string into leading whitespace, non whitespace, and trailing whitespace.
27626
28125
  * Useful for getting the variable name span when a span can contain leading and trailing space.
@@ -27968,9 +28467,14 @@ function parseConditionalBlockParameters(block, errors, bindingParser) {
27968
28467
  }
27969
28468
  else {
27970
28469
  const name = aliasMatch[2].trim();
27971
- const variableStart = param.sourceSpan.start.moveBy(aliasMatch[1].length);
27972
- const variableSpan = new ParseSourceSpan(variableStart, variableStart.moveBy(name.length));
27973
- expressionAlias = new Variable(name, name, variableSpan, variableSpan);
28470
+ if (IDENTIFIER_PATTERN.test(name)) {
28471
+ const variableStart = param.sourceSpan.start.moveBy(aliasMatch[1].length);
28472
+ const variableSpan = new ParseSourceSpan(variableStart, variableStart.moveBy(name.length));
28473
+ expressionAlias = new Variable(name, name, variableSpan, variableSpan);
28474
+ }
28475
+ else {
28476
+ errors.push(new ParseError(param.sourceSpan, '"as" expression must be a valid JavaScript identifier'));
28477
+ }
27974
28478
  }
27975
28479
  }
27976
28480
  return { expression, expressionAlias };
@@ -28581,6 +29085,17 @@ const BINDING_DELIMS = {
28581
29085
  EVENT: { start: '(', end: ')' },
28582
29086
  };
28583
29087
  const TEMPLATE_ATTR_PREFIX = '*';
29088
+ // TODO(crisbeto): any other tag names that shouldn't be allowed here?
29089
+ const UNSUPPORTED_SELECTORLESS_TAGS = new Set([
29090
+ 'link',
29091
+ 'style',
29092
+ 'script',
29093
+ 'ng-template',
29094
+ 'ng-container',
29095
+ 'ng-content',
29096
+ ]);
29097
+ // TODO(crisbeto): any other attributes that should not be allowed here?
29098
+ const UNSUPPORTED_SELECTORLESS_DIRECTIVE_ATTRS = new Set(['ngProjectAs', 'ngNonBindable']);
28584
29099
  function htmlAstToRender3Ast(htmlNodes, bindingParser, options) {
28585
29100
  const transformer = new HtmlAstToIvyAst(bindingParser, options);
28586
29101
  const ivyNodes = visitAll(transformer, htmlNodes, htmlNodes);
@@ -28644,52 +29159,8 @@ class HtmlAstToIvyAst {
28644
29159
  }
28645
29160
  // Whether the element is a `<ng-template>`
28646
29161
  const isTemplateElement = isNgTemplate(element.name);
28647
- const parsedProperties = [];
28648
- const boundEvents = [];
28649
- const variables = [];
28650
- const references = [];
28651
- const attributes = [];
28652
- const i18nAttrsMeta = {};
28653
- const templateParsedProperties = [];
28654
- const templateVariables = [];
28655
- // Whether the element has any *-attribute
28656
- let elementHasInlineTemplate = false;
28657
- for (const attribute of element.attrs) {
28658
- let hasBinding = false;
28659
- const normalizedName = normalizeAttributeName(attribute.name);
28660
- // `*attr` defines template bindings
28661
- let isTemplateBinding = false;
28662
- if (attribute.i18n) {
28663
- i18nAttrsMeta[attribute.name] = attribute.i18n;
28664
- }
28665
- if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) {
28666
- // *-attributes
28667
- if (elementHasInlineTemplate) {
28668
- this.reportError(`Can't have multiple template bindings on one element. Use only one attribute prefixed with *`, attribute.sourceSpan);
28669
- }
28670
- isTemplateBinding = true;
28671
- elementHasInlineTemplate = true;
28672
- const templateValue = attribute.value;
28673
- const templateKey = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length);
28674
- const parsedVariables = [];
28675
- const absoluteValueOffset = attribute.valueSpan
28676
- ? attribute.valueSpan.start.offset
28677
- : // If there is no value span the attribute does not have a value, like `attr` in
28678
- //`<div attr></div>`. In this case, point to one character beyond the last character of
28679
- // the attribute name.
28680
- attribute.sourceSpan.start.offset + attribute.name.length;
28681
- this.bindingParser.parseInlineTemplateBinding(templateKey, templateValue, attribute.sourceSpan, absoluteValueOffset, [], templateParsedProperties, parsedVariables, true /* isIvyAst */);
28682
- templateVariables.push(...parsedVariables.map((v) => new Variable(v.name, v.value, v.sourceSpan, v.keySpan, v.valueSpan)));
28683
- }
28684
- else {
28685
- // Check for variables, events, property bindings, interpolation
28686
- hasBinding = this.parseAttribute(isTemplateElement, attribute, [], parsedProperties, boundEvents, variables, references);
28687
- }
28688
- if (!hasBinding && !isTemplateBinding) {
28689
- // don't include the bindings as attributes as well in the AST
28690
- attributes.push(this.visitAttribute(attribute));
28691
- }
28692
- }
29162
+ const { attributes, boundEvents, references, variables, templateVariables, elementHasInlineTemplate, parsedProperties, templateParsedProperties, i18nAttrsMeta, } = this.prepareAttributes(element.attrs, isTemplateElement);
29163
+ const directives = this.extractDirectives(element);
28693
29164
  let children;
28694
29165
  if (preparsedElement.nonBindable) {
28695
29166
  // The `NonBindableVisitor` may need to return an array of nodes for blocks so we need
@@ -28704,44 +29175,24 @@ class HtmlAstToIvyAst {
28704
29175
  if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
28705
29176
  const selector = preparsedElement.selectAttr;
28706
29177
  const attrs = element.attrs.map((attr) => this.visitAttribute(attr));
28707
- parsedElement = new Content(selector, attrs, children, element.sourceSpan, element.i18n);
29178
+ parsedElement = new Content(selector, attrs, children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
28708
29179
  this.ngContentSelectors.push(selector);
28709
29180
  }
28710
29181
  else if (isTemplateElement) {
28711
29182
  // `<ng-template>`
28712
- const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta);
28713
- parsedElement = new Template(element.name, attributes, attrs.bound, boundEvents, [
29183
+ const attrs = this.categorizePropertyAttributes(element.name, parsedProperties, i18nAttrsMeta);
29184
+ parsedElement = new Template(element.name, attributes, attrs.bound, boundEvents, directives, [
28714
29185
  /* no template attributes */
28715
29186
  ], children, references, variables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
28716
29187
  }
28717
29188
  else {
28718
- const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta);
28719
- parsedElement = new Element$1(element.name, attributes, attrs.bound, boundEvents, children, references, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
29189
+ const attrs = this.categorizePropertyAttributes(element.name, parsedProperties, i18nAttrsMeta);
29190
+ parsedElement = new Element$1(element.name, attributes, attrs.bound, boundEvents, directives, children, references, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
28720
29191
  }
28721
29192
  if (elementHasInlineTemplate) {
28722
29193
  // If this node is an inline-template (e.g. has *ngFor) then we need to create a template
28723
29194
  // node that contains this node.
28724
- // Moreover, if the node is an element, then we need to hoist its attributes to the template
28725
- // node for matching against content projection selectors.
28726
- const attrs = this.extractAttributes('ng-template', templateParsedProperties, i18nAttrsMeta);
28727
- const templateAttrs = [];
28728
- attrs.literal.forEach((attr) => templateAttrs.push(attr));
28729
- attrs.bound.forEach((attr) => templateAttrs.push(attr));
28730
- const hoistedAttrs = parsedElement instanceof Element$1
28731
- ? {
28732
- attributes: parsedElement.attributes,
28733
- inputs: parsedElement.inputs,
28734
- outputs: parsedElement.outputs,
28735
- }
28736
- : { attributes: [], inputs: [], outputs: [] };
28737
- // For <ng-template>s with structural directives on them, avoid passing i18n information to
28738
- // the wrapping template to prevent unnecessary i18n instructions from being generated. The
28739
- // necessary i18n meta information will be extracted from child elements.
28740
- const i18n = isTemplateElement && isI18nRootElement ? undefined : element.i18n;
28741
- const name = parsedElement instanceof Template ? null : parsedElement.name;
28742
- parsedElement = new Template(name, hoistedAttrs.attributes, hoistedAttrs.inputs, hoistedAttrs.outputs, templateAttrs, [parsedElement], [
28743
- /* no references */
28744
- ], templateVariables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, i18n);
29195
+ parsedElement = this.wrapInTemplate(parsedElement, templateParsedProperties, templateVariables, i18nAttrsMeta, isTemplateElement, isI18nRootElement);
28745
29196
  }
28746
29197
  if (isI18nRootElement) {
28747
29198
  this.inI18nBlock = false;
@@ -28805,6 +29256,43 @@ class HtmlAstToIvyAst {
28805
29256
  }
28806
29257
  return new LetDeclaration$1(decl.name, value, decl.sourceSpan, decl.nameSpan, decl.valueSpan);
28807
29258
  }
29259
+ visitComponent(component) {
29260
+ const isI18nRootElement = isI18nRootNode(component.i18n);
29261
+ if (isI18nRootElement) {
29262
+ if (this.inI18nBlock) {
29263
+ this.reportError('Cannot mark a component as translatable inside of a translatable section. Please remove the nested i18n marker.', component.sourceSpan);
29264
+ }
29265
+ this.inI18nBlock = true;
29266
+ }
29267
+ if (component.tagName !== null && UNSUPPORTED_SELECTORLESS_TAGS.has(component.tagName)) {
29268
+ this.reportError(`Tag name "${component.tagName}" cannot be used as a component tag`, component.startSourceSpan);
29269
+ return null;
29270
+ }
29271
+ const { attributes, boundEvents, references, templateVariables, elementHasInlineTemplate, parsedProperties, templateParsedProperties, i18nAttrsMeta, } = this.prepareAttributes(component.attrs, false);
29272
+ const directives = this.extractDirectives(component);
29273
+ let children;
29274
+ if (component.attrs.find((attr) => attr.name === 'ngNonBindable')) {
29275
+ // The `NonBindableVisitor` may need to return an array of nodes for blocks so we need
29276
+ // to flatten the array here. Avoid doing this for the `HtmlAstToIvyAst` since `flat` creates
29277
+ // a new array.
29278
+ children = visitAll(NON_BINDABLE_VISITOR, component.children).flat(Infinity);
29279
+ }
29280
+ else {
29281
+ children = visitAll(this, component.children, component.children);
29282
+ }
29283
+ const attrs = this.categorizePropertyAttributes(component.tagName, parsedProperties, i18nAttrsMeta);
29284
+ let node = new Component$1(component.componentName, component.tagName, component.fullName, attributes, attrs.bound, boundEvents, directives, children, references, component.sourceSpan, component.startSourceSpan, component.endSourceSpan, component.i18n);
29285
+ if (elementHasInlineTemplate) {
29286
+ node = this.wrapInTemplate(node, templateParsedProperties, templateVariables, i18nAttrsMeta, false, isI18nRootElement);
29287
+ }
29288
+ if (isI18nRootElement) {
29289
+ this.inI18nBlock = false;
29290
+ }
29291
+ return node;
29292
+ }
29293
+ visitDirective() {
29294
+ return null;
29295
+ }
28808
29296
  visitBlockParameter() {
28809
29297
  return null;
28810
29298
  }
@@ -28881,8 +29369,8 @@ class HtmlAstToIvyAst {
28881
29369
  }
28882
29370
  return relatedBlocks;
28883
29371
  }
28884
- // convert view engine `ParsedProperty` to a format suitable for IVY
28885
- extractAttributes(elementName, properties, i18nPropsMeta) {
29372
+ /** Splits up the property attributes depending on whether they're static or bound. */
29373
+ categorizePropertyAttributes(elementName, properties, i18nPropsMeta) {
28886
29374
  const bound = [];
28887
29375
  const literal = [];
28888
29376
  properties.forEach((prop) => {
@@ -28902,6 +29390,65 @@ class HtmlAstToIvyAst {
28902
29390
  });
28903
29391
  return { bound, literal };
28904
29392
  }
29393
+ prepareAttributes(attrs, isTemplateElement) {
29394
+ const parsedProperties = [];
29395
+ const boundEvents = [];
29396
+ const variables = [];
29397
+ const references = [];
29398
+ const attributes = [];
29399
+ const i18nAttrsMeta = {};
29400
+ const templateParsedProperties = [];
29401
+ const templateVariables = [];
29402
+ // Whether the element has any *-attribute
29403
+ let elementHasInlineTemplate = false;
29404
+ for (const attribute of attrs) {
29405
+ let hasBinding = false;
29406
+ const normalizedName = normalizeAttributeName(attribute.name);
29407
+ // `*attr` defines template bindings
29408
+ let isTemplateBinding = false;
29409
+ if (attribute.i18n) {
29410
+ i18nAttrsMeta[attribute.name] = attribute.i18n;
29411
+ }
29412
+ if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) {
29413
+ // *-attributes
29414
+ if (elementHasInlineTemplate) {
29415
+ this.reportError(`Can't have multiple template bindings on one element. Use only one attribute prefixed with *`, attribute.sourceSpan);
29416
+ }
29417
+ isTemplateBinding = true;
29418
+ elementHasInlineTemplate = true;
29419
+ const templateValue = attribute.value;
29420
+ const templateKey = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length);
29421
+ const parsedVariables = [];
29422
+ const absoluteValueOffset = attribute.valueSpan
29423
+ ? attribute.valueSpan.start.offset
29424
+ : // If there is no value span the attribute does not have a value, like `attr` in
29425
+ //`<div attr></div>`. In this case, point to one character beyond the last character of
29426
+ // the attribute name.
29427
+ attribute.sourceSpan.start.offset + attribute.name.length;
29428
+ this.bindingParser.parseInlineTemplateBinding(templateKey, templateValue, attribute.sourceSpan, absoluteValueOffset, [], templateParsedProperties, parsedVariables, true /* isIvyAst */);
29429
+ templateVariables.push(...parsedVariables.map((v) => new Variable(v.name, v.value, v.sourceSpan, v.keySpan, v.valueSpan)));
29430
+ }
29431
+ else {
29432
+ // Check for variables, events, property bindings, interpolation
29433
+ hasBinding = this.parseAttribute(isTemplateElement, attribute, [], parsedProperties, boundEvents, variables, references);
29434
+ }
29435
+ if (!hasBinding && !isTemplateBinding) {
29436
+ // don't include the bindings as attributes as well in the AST
29437
+ attributes.push(this.visitAttribute(attribute));
29438
+ }
29439
+ }
29440
+ return {
29441
+ attributes,
29442
+ boundEvents,
29443
+ references,
29444
+ variables,
29445
+ templateVariables,
29446
+ elementHasInlineTemplate,
29447
+ parsedProperties,
29448
+ templateParsedProperties,
29449
+ i18nAttrsMeta,
29450
+ };
29451
+ }
28905
29452
  parseAttribute(isTemplateElement, attribute, matchableAttributes, parsedProperties, boundEvents, variables, references) {
28906
29453
  const name = normalizeAttributeName(attribute.name);
28907
29454
  const value = attribute.value;
@@ -29000,6 +29547,81 @@ class HtmlAstToIvyAst {
29000
29547
  const hasBinding = this.bindingParser.parsePropertyInterpolation(name, value, srcSpan, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan, attribute.valueTokens ?? null);
29001
29548
  return hasBinding;
29002
29549
  }
29550
+ extractDirectives(node) {
29551
+ const elementName = node instanceof Component ? node.tagName : node.name;
29552
+ const directives = [];
29553
+ const seenDirectives = new Set();
29554
+ for (const directive of node.directives) {
29555
+ let invalid = false;
29556
+ for (const attr of directive.attrs) {
29557
+ if (attr.name.startsWith(TEMPLATE_ATTR_PREFIX)) {
29558
+ invalid = true;
29559
+ this.reportError(`Shorthand template syntax "${attr.name}" is not supported inside a directive context`, attr.sourceSpan);
29560
+ }
29561
+ else if (UNSUPPORTED_SELECTORLESS_DIRECTIVE_ATTRS.has(attr.name)) {
29562
+ invalid = true;
29563
+ this.reportError(`Attribute "${attr.name}" is not supported in a directive context`, attr.sourceSpan);
29564
+ }
29565
+ }
29566
+ if (!invalid && seenDirectives.has(directive.name)) {
29567
+ invalid = true;
29568
+ this.reportError(`Cannot apply directive "${directive.name}" multiple times on the same element`, directive.sourceSpan);
29569
+ }
29570
+ if (invalid) {
29571
+ continue;
29572
+ }
29573
+ const { attributes, parsedProperties, boundEvents, references, i18nAttrsMeta } = this.prepareAttributes(directive.attrs, false);
29574
+ const { bound: inputs } = this.categorizePropertyAttributes(elementName, parsedProperties, i18nAttrsMeta);
29575
+ for (const input of inputs) {
29576
+ if (input.type !== BindingType.Property && input.type !== BindingType.TwoWay) {
29577
+ invalid = true;
29578
+ this.reportError('Binding is not supported in a directive context', input.sourceSpan);
29579
+ }
29580
+ }
29581
+ if (invalid) {
29582
+ continue;
29583
+ }
29584
+ seenDirectives.add(directive.name);
29585
+ directives.push(new Directive$1(directive.name, attributes, inputs, boundEvents, references, directive.sourceSpan, directive.startSourceSpan, directive.endSourceSpan, undefined));
29586
+ }
29587
+ return directives;
29588
+ }
29589
+ wrapInTemplate(node, templateProperties, templateVariables, i18nAttrsMeta, isTemplateElement, isI18nRootElement) {
29590
+ // We need to hoist the attributes of the node to the template for content projection purposes.
29591
+ const attrs = this.categorizePropertyAttributes('ng-template', templateProperties, i18nAttrsMeta);
29592
+ const templateAttrs = [];
29593
+ attrs.literal.forEach((attr) => templateAttrs.push(attr));
29594
+ attrs.bound.forEach((attr) => templateAttrs.push(attr));
29595
+ const hoistedAttrs = {
29596
+ attributes: [],
29597
+ inputs: [],
29598
+ outputs: [],
29599
+ };
29600
+ if (node instanceof Element$1 || node instanceof Component$1) {
29601
+ hoistedAttrs.attributes.push(...node.attributes);
29602
+ hoistedAttrs.inputs.push(...node.inputs);
29603
+ hoistedAttrs.outputs.push(...node.outputs);
29604
+ }
29605
+ // For <ng-template>s with structural directives on them, avoid passing i18n information to
29606
+ // the wrapping template to prevent unnecessary i18n instructions from being generated. The
29607
+ // necessary i18n meta information will be extracted from child elements.
29608
+ const i18n = isTemplateElement && isI18nRootElement ? undefined : node.i18n;
29609
+ let name;
29610
+ if (node instanceof Component$1) {
29611
+ name = node.tagName;
29612
+ }
29613
+ else if (node instanceof Template) {
29614
+ name = null;
29615
+ }
29616
+ else {
29617
+ name = node.name;
29618
+ }
29619
+ return new Template(name, hoistedAttrs.attributes, hoistedAttrs.inputs, hoistedAttrs.outputs, [
29620
+ // Do not copy over the directives.
29621
+ ], templateAttrs, [node], [
29622
+ // Do not copy over the references.
29623
+ ], templateVariables, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, i18n);
29624
+ }
29003
29625
  _visitTextWithInterpolation(value, sourceSpan, interpolatedTokens, i18n) {
29004
29626
  const valueNoNgsp = replaceNgsp(value);
29005
29627
  const expr = this.bindingParser.parseInterpolation(valueNoNgsp, sourceSpan, interpolatedTokens);
@@ -29050,7 +29672,8 @@ class NonBindableVisitor {
29050
29672
  const children = visitAll(this, ast.children, null);
29051
29673
  return new Element$1(ast.name, visitAll(this, ast.attrs),
29052
29674
  /* inputs */ [],
29053
- /* outputs */ [], children,
29675
+ /* outputs */ [],
29676
+ /* directives */ [], children,
29054
29677
  /* references */ [], ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
29055
29678
  }
29056
29679
  visitComment(comment) {
@@ -29086,6 +29709,17 @@ class NonBindableVisitor {
29086
29709
  visitLetDeclaration(decl, context) {
29087
29710
  return new Text$3(`@let ${decl.name} = ${decl.value};`, decl.sourceSpan);
29088
29711
  }
29712
+ visitComponent(ast, context) {
29713
+ const children = visitAll(this, ast.children, null);
29714
+ return new Element$1(ast.fullName, visitAll(this, ast.attrs),
29715
+ /* inputs */ [],
29716
+ /* outputs */ [],
29717
+ /* directives */ [], children,
29718
+ /* references */ [], ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
29719
+ }
29720
+ visitDirective(directive, context) {
29721
+ return null;
29722
+ }
29089
29723
  }
29090
29724
  const NON_BINDABLE_VISITOR = new NonBindableVisitor();
29091
29725
  function normalizeAttributeName(attrName) {
@@ -29942,6 +30576,7 @@ class Scope {
29942
30576
  }
29943
30577
  }
29944
30578
  visitElement(element) {
30579
+ element.directives.forEach((node) => node.visit(this));
29945
30580
  // `Element`s in the template may have `Reference`s which are captured in the scope.
29946
30581
  element.references.forEach((node) => this.visitReference(node));
29947
30582
  // Recurse into the `Element`'s children.
@@ -29949,6 +30584,7 @@ class Scope {
29949
30584
  this.elementsInScope.add(element);
29950
30585
  }
29951
30586
  visitTemplate(template) {
30587
+ template.directives.forEach((node) => node.visit(this));
29952
30588
  // References on a <ng-template> are defined in the outer scope, so capture them before
29953
30589
  // processing the template's child scope.
29954
30590
  template.references.forEach((node) => this.visitReference(node));
@@ -30003,6 +30639,12 @@ class Scope {
30003
30639
  visitLetDeclaration(decl) {
30004
30640
  this.maybeDeclare(decl);
30005
30641
  }
30642
+ visitComponent(component) {
30643
+ throw new Error('TODO');
30644
+ }
30645
+ visitDirective(directive) {
30646
+ throw new Error('TODO');
30647
+ }
30006
30648
  // Unused visitors.
30007
30649
  visitBoundAttribute(attr) { }
30008
30650
  visitBoundEvent(event) { }
@@ -30104,6 +30746,10 @@ class DirectiveBinder {
30104
30746
  // First, determine the HTML shape of the node for the purpose of directive matching.
30105
30747
  // Do this by building up a `CssSelector` for the node.
30106
30748
  const cssSelector = createCssSelectorFromNode(node);
30749
+ // TODO(crisbeto): account for selectorless directives here.
30750
+ if (node.directives.length > 0) {
30751
+ throw new Error('TODO');
30752
+ }
30107
30753
  // Next, use the `SelectorMatcher` to get the list of directives on the node.
30108
30754
  const directives = [];
30109
30755
  this.matcher.match(cssSelector, (_selector, results) => directives.push(...results));
@@ -30203,6 +30849,12 @@ class DirectiveBinder {
30203
30849
  visitContent(content) {
30204
30850
  content.children.forEach((child) => child.visit(this));
30205
30851
  }
30852
+ visitComponent(component) {
30853
+ throw new Error('TODO');
30854
+ }
30855
+ visitDirective(directive) {
30856
+ throw new Error('TODO');
30857
+ }
30206
30858
  // Unused visitors.
30207
30859
  visitVariable(variable) { }
30208
30860
  visitReference(reference) { }
@@ -30333,6 +30985,7 @@ class TemplateBinder extends RecursiveAstVisitor {
30333
30985
  // Visit the inputs, outputs, and children of the element.
30334
30986
  element.inputs.forEach(this.visitNode);
30335
30987
  element.outputs.forEach(this.visitNode);
30988
+ element.directives.forEach(this.visitNode);
30336
30989
  element.children.forEach(this.visitNode);
30337
30990
  element.references.forEach(this.visitNode);
30338
30991
  }
@@ -30340,6 +30993,7 @@ class TemplateBinder extends RecursiveAstVisitor {
30340
30993
  // First, visit inputs, outputs and template attributes of the template node.
30341
30994
  template.inputs.forEach(this.visitNode);
30342
30995
  template.outputs.forEach(this.visitNode);
30996
+ template.directives.forEach(this.visitNode);
30343
30997
  template.templateAttrs.forEach(this.visitNode);
30344
30998
  template.references.forEach(this.visitNode);
30345
30999
  // Next, recurse into the template.
@@ -30357,6 +31011,12 @@ class TemplateBinder extends RecursiveAstVisitor {
30357
31011
  this.symbols.set(reference, this.rootNode);
30358
31012
  }
30359
31013
  }
31014
+ visitComponent(component) {
31015
+ throw new Error('TODO');
31016
+ }
31017
+ visitDirective(directive) {
31018
+ throw new Error('TODO');
31019
+ }
30360
31020
  // Unused template visitors
30361
31021
  visitText(text) { }
30362
31022
  visitTextAttribute(attribute) { }
@@ -31425,7 +32085,7 @@ class _Visitor {
31425
32085
  this._init(_VisitorMode.Merge, interpolationConfig);
31426
32086
  this._translations = translations;
31427
32087
  // Construct a single fake root element
31428
- const wrapper = new Element('wrapper', [], nodes, undefined, undefined, undefined);
32088
+ const wrapper = new Element('wrapper', [], [], nodes, undefined, undefined, undefined);
31429
32089
  const translatedNode = wrapper.visit(this, null);
31430
32090
  if (this._inI18nBlock) {
31431
32091
  this._reportError(nodes[nodes.length - 1], 'Unclosed block');
@@ -31511,7 +32171,41 @@ class _Visitor {
31511
32171
  return text;
31512
32172
  }
31513
32173
  visitElement(el, context) {
31514
- this._mayBeAddBlockChildren(el);
32174
+ return this._visitElementLike(el, context);
32175
+ }
32176
+ visitAttribute(attribute, context) {
32177
+ throw new Error('unreachable code');
32178
+ }
32179
+ visitBlock(block, context) {
32180
+ visitAll(this, block.children, context);
32181
+ }
32182
+ visitBlockParameter(parameter, context) { }
32183
+ visitLetDeclaration(decl, context) { }
32184
+ visitComponent(component, context) {
32185
+ return this._visitElementLike(component, context);
32186
+ }
32187
+ visitDirective(directive, context) {
32188
+ throw new Error('unreachable code');
32189
+ }
32190
+ _init(mode, interpolationConfig) {
32191
+ this._mode = mode;
32192
+ this._inI18nBlock = false;
32193
+ this._inI18nNode = false;
32194
+ this._depth = 0;
32195
+ this._inIcu = false;
32196
+ this._msgCountAtSectionStart = undefined;
32197
+ this._errors = [];
32198
+ this._messages = [];
32199
+ this._inImplicitNode = false;
32200
+ this._createI18nMessage = createI18nMessageFactory(interpolationConfig, DEFAULT_CONTAINER_BLOCKS,
32201
+ // When dropping significant whitespace we need to retain whitespace tokens or
32202
+ // else we won't be able to reuse source spans because empty tokens would be
32203
+ // removed and cause a mismatch.
32204
+ /* retainEmptyTokens */ !this._preserveSignificantWhitespace,
32205
+ /* preserveExpressionWhitespace */ this._preserveSignificantWhitespace);
32206
+ }
32207
+ _visitElementLike(node, context) {
32208
+ this._mayBeAddBlockChildren(node);
31515
32209
  this._depth++;
31516
32210
  const wasInI18nNode = this._inI18nNode;
31517
32211
  const wasInImplicitNode = this._inImplicitNode;
@@ -31520,9 +32214,10 @@ class _Visitor {
31520
32214
  // Extract:
31521
32215
  // - top level nodes with the (implicit) "i18n" attribute if not already in a section
31522
32216
  // - ICU messages
31523
- const i18nAttr = _getI18nAttr(el);
32217
+ const nodeName = node instanceof Component ? node.tagName : node.name;
32218
+ const i18nAttr = _getI18nAttr(node);
31524
32219
  const i18nMeta = i18nAttr ? i18nAttr.value : '';
31525
- const isImplicit = this._implicitTags.some((tag) => el.name === tag) &&
32220
+ const isImplicit = this._implicitTags.some((tag) => nodeName === tag) &&
31526
32221
  !this._inIcu &&
31527
32222
  !this._isInTranslatableSection;
31528
32223
  const isTopLevelImplicit = !wasInImplicitNode && isImplicit;
@@ -31530,29 +32225,29 @@ class _Visitor {
31530
32225
  if (!this._isInTranslatableSection && !this._inIcu) {
31531
32226
  if (i18nAttr || isTopLevelImplicit) {
31532
32227
  this._inI18nNode = true;
31533
- const message = this._addMessage(el.children, i18nMeta);
31534
- translatedChildNodes = this._translateMessage(el, message);
32228
+ const message = this._addMessage(node.children, i18nMeta);
32229
+ translatedChildNodes = this._translateMessage(node, message);
31535
32230
  }
31536
32231
  if (this._mode == _VisitorMode.Extract) {
31537
32232
  const isTranslatable = i18nAttr || isTopLevelImplicit;
31538
32233
  if (isTranslatable)
31539
- this._openTranslatableSection(el);
31540
- visitAll(this, el.children);
32234
+ this._openTranslatableSection(node);
32235
+ visitAll(this, node.children);
31541
32236
  if (isTranslatable)
31542
- this._closeTranslatableSection(el, el.children);
32237
+ this._closeTranslatableSection(node, node.children);
31543
32238
  }
31544
32239
  }
31545
32240
  else {
31546
32241
  if (i18nAttr || isTopLevelImplicit) {
31547
- this._reportError(el, 'Could not mark an element as translatable inside a translatable section');
32242
+ this._reportError(node, 'Could not mark an element as translatable inside a translatable section');
31548
32243
  }
31549
32244
  if (this._mode == _VisitorMode.Extract) {
31550
32245
  // Descend into child nodes for extraction
31551
- visitAll(this, el.children);
32246
+ visitAll(this, node.children);
31552
32247
  }
31553
32248
  }
31554
32249
  if (this._mode === _VisitorMode.Merge) {
31555
- const visitNodes = translatedChildNodes || el.children;
32250
+ const visitNodes = translatedChildNodes || node.children;
31556
32251
  visitNodes.forEach((child) => {
31557
32252
  const visited = child.visit(this, context);
31558
32253
  if (visited && !this._isInTranslatableSection) {
@@ -31562,48 +32257,29 @@ class _Visitor {
31562
32257
  }
31563
32258
  });
31564
32259
  }
31565
- this._visitAttributesOf(el);
32260
+ this._visitAttributesOf(node);
31566
32261
  this._depth--;
31567
32262
  this._inI18nNode = wasInI18nNode;
31568
32263
  this._inImplicitNode = wasInImplicitNode;
31569
32264
  if (this._mode === _VisitorMode.Merge) {
31570
- const translatedAttrs = this._translateAttributes(el);
31571
- return new Element(el.name, translatedAttrs, childNodes, el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
32265
+ if (node instanceof Element) {
32266
+ return new Element(node.name, this._translateAttributes(node), this._translateDirectives(node), childNodes, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
32267
+ }
32268
+ else {
32269
+ return new Component(node.componentName, node.tagName, node.fullName, this._translateAttributes(node), this._translateDirectives(node), childNodes, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
32270
+ }
31572
32271
  }
31573
32272
  return null;
31574
32273
  }
31575
- visitAttribute(attribute, context) {
31576
- throw new Error('unreachable code');
31577
- }
31578
- visitBlock(block, context) {
31579
- visitAll(this, block.children, context);
31580
- }
31581
- visitBlockParameter(parameter, context) { }
31582
- visitLetDeclaration(decl, context) { }
31583
- _init(mode, interpolationConfig) {
31584
- this._mode = mode;
31585
- this._inI18nBlock = false;
31586
- this._inI18nNode = false;
31587
- this._depth = 0;
31588
- this._inIcu = false;
31589
- this._msgCountAtSectionStart = undefined;
31590
- this._errors = [];
31591
- this._messages = [];
31592
- this._inImplicitNode = false;
31593
- this._createI18nMessage = createI18nMessageFactory(interpolationConfig, DEFAULT_CONTAINER_BLOCKS,
31594
- // When dropping significant whitespace we need to retain whitespace tokens or
31595
- // else we won't be able to reuse source spans because empty tokens would be
31596
- // removed and cause a mismatch.
31597
- /* retainEmptyTokens */ !this._preserveSignificantWhitespace,
31598
- /* preserveExpressionWhitespace */ this._preserveSignificantWhitespace);
31599
- }
31600
32274
  // looks for translatable attributes
31601
32275
  _visitAttributesOf(el) {
31602
32276
  const explicitAttrNameToValue = {};
31603
- const implicitAttrNames = this._implicitAttrs[el.name] || [];
32277
+ const implicitAttrNames = this._implicitAttrs[el instanceof Component ? el.tagName || '' : el.name] || [];
31604
32278
  el.attrs
31605
- .filter((attr) => attr.name.startsWith(_I18N_ATTR_PREFIX))
31606
- .forEach((attr) => (explicitAttrNameToValue[attr.name.slice(_I18N_ATTR_PREFIX.length)] = attr.value));
32279
+ .filter((attr) => attr instanceof Attribute && attr.name.startsWith(_I18N_ATTR_PREFIX))
32280
+ .forEach((attr) => {
32281
+ explicitAttrNameToValue[attr.name.slice(_I18N_ATTR_PREFIX.length)] = attr.value;
32282
+ });
31607
32283
  el.attrs.forEach((attr) => {
31608
32284
  if (attr.name in explicitAttrNameToValue) {
31609
32285
  this._addMessage([attr], explicitAttrNameToValue[attr.name]);
@@ -31676,16 +32352,15 @@ class _Visitor {
31676
32352
  return [];
31677
32353
  }
31678
32354
  // translate the attributes of an element and remove i18n specific attributes
31679
- _translateAttributes(el) {
31680
- const attributes = el.attrs;
32355
+ _translateAttributes(node) {
31681
32356
  const i18nParsedMessageMeta = {};
31682
- attributes.forEach((attr) => {
32357
+ const translatedAttributes = [];
32358
+ node.attrs.forEach((attr) => {
31683
32359
  if (attr.name.startsWith(_I18N_ATTR_PREFIX)) {
31684
32360
  i18nParsedMessageMeta[attr.name.slice(_I18N_ATTR_PREFIX.length)] = _parseMessageMeta(attr.value);
31685
32361
  }
31686
32362
  });
31687
- const translatedAttributes = [];
31688
- attributes.forEach((attr) => {
32363
+ node.attrs.forEach((attr) => {
31689
32364
  if (attr.name === _I18N_ATTR || attr.name.startsWith(_I18N_ATTR_PREFIX)) {
31690
32365
  // strip i18n specific attributes
31691
32366
  return;
@@ -31703,11 +32378,11 @@ class _Visitor {
31703
32378
  translatedAttributes.push(new Attribute(attr.name, value, attr.sourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */));
31704
32379
  }
31705
32380
  else {
31706
- this._reportError(el, `Unexpected translation for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
32381
+ this._reportError(node, `Unexpected translation for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
31707
32382
  }
31708
32383
  }
31709
32384
  else {
31710
- this._reportError(el, `Translation unavailable for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
32385
+ this._reportError(node, `Translation unavailable for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
31711
32386
  }
31712
32387
  }
31713
32388
  else {
@@ -31716,6 +32391,9 @@ class _Visitor {
31716
32391
  });
31717
32392
  return translatedAttributes;
31718
32393
  }
32394
+ _translateDirectives(node) {
32395
+ return node.directives.map((dir) => new Directive(dir.name, this._translateAttributes(dir), dir.sourceSpan, dir.startSourceSpan, dir.endSourceSpan));
32396
+ }
31719
32397
  /**
31720
32398
  * Add the node as a child of the block when:
31721
32399
  * - we are in a block,
@@ -31791,7 +32469,7 @@ function _isClosingComment(n) {
31791
32469
  return !!(n instanceof Comment && n.value && n.value === '/i18n');
31792
32470
  }
31793
32471
  function _getI18nAttr(p) {
31794
- return p.attrs.find((attr) => attr.name === _I18N_ATTR) || null;
32472
+ return (p.attrs.find((attr) => attr instanceof Attribute && attr.name === _I18N_ATTR) || null);
31795
32473
  }
31796
32474
  function _parseMessageMeta(i18n) {
31797
32475
  if (!i18n)
@@ -31839,7 +32517,12 @@ class XmlParser extends Parser$1 {
31839
32517
  }
31840
32518
  parse(source, url, options = {}) {
31841
32519
  // Blocks and let declarations aren't supported in an XML context.
31842
- return super.parse(source, url, { ...options, tokenizeBlocks: false, tokenizeLet: false });
32520
+ return super.parse(source, url, {
32521
+ ...options,
32522
+ tokenizeBlocks: false,
32523
+ tokenizeLet: false,
32524
+ selectorlessEnabled: false,
32525
+ });
31843
32526
  }
31844
32527
  }
31845
32528
 
@@ -32063,6 +32746,8 @@ class XliffParser {
32063
32746
  visitBlock(block, context) { }
32064
32747
  visitBlockParameter(parameter, context) { }
32065
32748
  visitLetDeclaration(decl, context) { }
32749
+ visitComponent(component, context) { }
32750
+ visitDirective(directive, context) { }
32066
32751
  _addError(node, message) {
32067
32752
  this._errors.push(new I18nError(node.sourceSpan, message));
32068
32753
  }
@@ -32118,6 +32803,12 @@ let XmlToI18n$2 = class XmlToI18n {
32118
32803
  visitBlock(block, context) { }
32119
32804
  visitBlockParameter(parameter, context) { }
32120
32805
  visitLetDeclaration(decl, context) { }
32806
+ visitComponent(component, context) {
32807
+ this._addError(component, 'Unexpected node');
32808
+ }
32809
+ visitDirective(directive, context) {
32810
+ this._addError(directive, 'Unexpected node');
32811
+ }
32121
32812
  _addError(node, message) {
32122
32813
  this._errors.push(new I18nError(node.sourceSpan, message));
32123
32814
  }
@@ -32378,6 +33069,8 @@ class Xliff2Parser {
32378
33069
  visitBlock(block, context) { }
32379
33070
  visitBlockParameter(parameter, context) { }
32380
33071
  visitLetDeclaration(decl, context) { }
33072
+ visitComponent(component, context) { }
33073
+ visitDirective(directive, context) { }
32381
33074
  _addError(node, message) {
32382
33075
  this._errors.push(new I18nError(node.sourceSpan, message));
32383
33076
  }
@@ -32450,6 +33143,12 @@ let XmlToI18n$1 = class XmlToI18n {
32450
33143
  visitBlock(block, context) { }
32451
33144
  visitBlockParameter(parameter, context) { }
32452
33145
  visitLetDeclaration(decl, context) { }
33146
+ visitComponent(component, context) {
33147
+ this._addError(component, 'Unexpected node');
33148
+ }
33149
+ visitDirective(directive, context) {
33150
+ this._addError(directive, 'Unexpected node');
33151
+ }
32453
33152
  _addError(node, message) {
32454
33153
  this._errors.push(new I18nError(node.sourceSpan, message));
32455
33154
  }
@@ -32589,6 +33288,12 @@ class XtbParser {
32589
33288
  visitBlock(block, context) { }
32590
33289
  visitBlockParameter(block, context) { }
32591
33290
  visitLetDeclaration(decl, context) { }
33291
+ visitComponent(component, context) {
33292
+ this._addError(component, 'Unexpected node');
33293
+ }
33294
+ visitDirective(directive, context) {
33295
+ this._addError(directive, 'Unexpected node');
33296
+ }
32592
33297
  _addError(node, message) {
32593
33298
  this._errors.push(new I18nError(node.sourceSpan, message));
32594
33299
  }
@@ -32642,6 +33347,12 @@ class XmlToI18n {
32642
33347
  visitBlock(block, context) { }
32643
33348
  visitBlockParameter(block, context) { }
32644
33349
  visitLetDeclaration(decl, context) { }
33350
+ visitComponent(component, context) {
33351
+ this._addError(component, 'Unexpected node');
33352
+ }
33353
+ visitDirective(directive, context) {
33354
+ this._addError(directive, 'Unexpected node');
33355
+ }
32645
33356
  _addError(node, message) {
32646
33357
  this._errors.push(new I18nError(node.sourceSpan, message));
32647
33358
  }
@@ -33055,7 +33766,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
33055
33766
  function compileDeclareClassMetadata(metadata) {
33056
33767
  const definitionMap = new DefinitionMap();
33057
33768
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
33058
- definitionMap.set('version', literal('20.0.0-next.4'));
33769
+ definitionMap.set('version', literal('20.0.0-next.6'));
33059
33770
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33060
33771
  definitionMap.set('type', metadata.type);
33061
33772
  definitionMap.set('decorators', metadata.decorators);
@@ -33073,7 +33784,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
33073
33784
  callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
33074
33785
  callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
33075
33786
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
33076
- definitionMap.set('version', literal('20.0.0-next.4'));
33787
+ definitionMap.set('version', literal('20.0.0-next.6'));
33077
33788
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33078
33789
  definitionMap.set('type', metadata.type);
33079
33790
  definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
@@ -33168,7 +33879,7 @@ function createDirectiveDefinitionMap(meta) {
33168
33879
  const definitionMap = new DefinitionMap();
33169
33880
  const minVersion = getMinimumVersionForPartialOutput(meta);
33170
33881
  definitionMap.set('minVersion', literal(minVersion));
33171
- definitionMap.set('version', literal('20.0.0-next.4'));
33882
+ definitionMap.set('version', literal('20.0.0-next.6'));
33172
33883
  // e.g. `type: MyDirective`
33173
33884
  definitionMap.set('type', meta.type.value);
33174
33885
  if (meta.isStandalone !== undefined) {
@@ -33584,7 +34295,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
33584
34295
  function compileDeclareFactoryFunction(meta) {
33585
34296
  const definitionMap = new DefinitionMap();
33586
34297
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
33587
- definitionMap.set('version', literal('20.0.0-next.4'));
34298
+ definitionMap.set('version', literal('20.0.0-next.6'));
33588
34299
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33589
34300
  definitionMap.set('type', meta.type.value);
33590
34301
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -33619,7 +34330,7 @@ function compileDeclareInjectableFromMetadata(meta) {
33619
34330
  function createInjectableDefinitionMap(meta) {
33620
34331
  const definitionMap = new DefinitionMap();
33621
34332
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
33622
- definitionMap.set('version', literal('20.0.0-next.4'));
34333
+ definitionMap.set('version', literal('20.0.0-next.6'));
33623
34334
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33624
34335
  definitionMap.set('type', meta.type.value);
33625
34336
  // Only generate providedIn property if it has a non-null value
@@ -33670,7 +34381,7 @@ function compileDeclareInjectorFromMetadata(meta) {
33670
34381
  function createInjectorDefinitionMap(meta) {
33671
34382
  const definitionMap = new DefinitionMap();
33672
34383
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
33673
- definitionMap.set('version', literal('20.0.0-next.4'));
34384
+ definitionMap.set('version', literal('20.0.0-next.6'));
33674
34385
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33675
34386
  definitionMap.set('type', meta.type.value);
33676
34387
  definitionMap.set('providers', meta.providers);
@@ -33703,7 +34414,7 @@ function createNgModuleDefinitionMap(meta) {
33703
34414
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
33704
34415
  }
33705
34416
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
33706
- definitionMap.set('version', literal('20.0.0-next.4'));
34417
+ definitionMap.set('version', literal('20.0.0-next.6'));
33707
34418
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33708
34419
  definitionMap.set('type', meta.type.value);
33709
34420
  // We only generate the keys in the metadata if the arrays contain values.
@@ -33754,7 +34465,7 @@ function compileDeclarePipeFromMetadata(meta) {
33754
34465
  function createPipeDefinitionMap(meta) {
33755
34466
  const definitionMap = new DefinitionMap();
33756
34467
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
33757
- definitionMap.set('version', literal('20.0.0-next.4'));
34468
+ definitionMap.set('version', literal('20.0.0-next.6'));
33758
34469
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33759
34470
  // e.g. `type: MyPipe`
33760
34471
  definitionMap.set('type', meta.type.value);
@@ -33912,7 +34623,7 @@ function compileHmrUpdateCallback(definitions, constantStatements, meta) {
33912
34623
  * @description
33913
34624
  * Entry point for all public APIs of the compiler package.
33914
34625
  */
33915
- const VERSION = new Version('20.0.0-next.4');
34626
+ const VERSION = new Version('20.0.0-next.6');
33916
34627
 
33917
34628
  //////////////////////////////////////
33918
34629
  // THIS FILE HAS GLOBAL SIDE EFFECT //
@@ -33938,5 +34649,5 @@ const VERSION = new Version('20.0.0-next.4');
33938
34649
  // the late binding of the Compiler to the @angular/core for jit compilation.
33939
34650
  publishFacade(_global);
33940
34651
 
33941
- export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, ArrowFunctionExpr, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, BindingType, Block, BlockParameter, BoundElementProperty, BuiltinType, BuiltinTypeName, CUSTOM_ELEMENTS_SCHEMA, Call, Chain, ChangeDetectionStrategy, CommaExpr, Comment, CompilerConfig, Conditional, ConditionalExpr, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, DomElementSchemaRegistry, DynamicImportExpr, EOF, Element, ElementSchemaRegistry, EmitterVisitorContext, EmptyExpr$1 as EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, FactoryTarget$1 as FactoryTarget, FunctionExpr, HtmlParser, HtmlTagDefinition, I18NHtmlParser, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation$1 as Interpolation, InterpolationConfig, InvokeFunctionExpr, JSDocComment, JitEvaluator, KeyedRead, KeyedWrite, LeadingComment, LetDeclaration, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralPrimitive, LocalizedString, MapType, MessageBundle, NONE_TYPE, NO_ERRORS_SCHEMA, NodeWithI18n, NonNullAssert, NotExpr, ParenthesizedExpr, ParenthesizedExpression, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedEventType, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser, ParserError, PrefixNot, PropertyRead, PropertyWrite, Identifiers as R3Identifiers, R3NgModuleMetadataKind, R3SelectorScopeMode, R3TargetBinder, R3TemplateDependencyKind, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveVisitor, ResourceLoader, ReturnStatement, STRING_TYPE, SafeCall, SafeKeyedRead, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, Serializer, SplitInterpolation, Statement, StmtModifier, StringToken, StringTokenKind, TagContentType, TaggedTemplateLiteral, TaggedTemplateLiteralExpr, TemplateBindingParseResult, TemplateLiteral, TemplateLiteralElement, TemplateLiteralElementExpr, TemplateLiteralExpr, Text, ThisReceiver, BlockNode as TmplAstBlockNode, BoundAttribute as TmplAstBoundAttribute, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, DeferredBlock as TmplAstDeferredBlock, DeferredBlockError as TmplAstDeferredBlockError, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredTrigger as TmplAstDeferredTrigger, Element$1 as TmplAstElement, ForLoopBlock as TmplAstForLoopBlock, ForLoopBlockEmpty as TmplAstForLoopBlockEmpty, HostElement as TmplAstHostElement, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, IfBlock as TmplAstIfBlock, IfBlockBranch as TmplAstIfBlockBranch, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, LetDeclaration$1 as TmplAstLetDeclaration, NeverDeferredTrigger as TmplAstNeverDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, SwitchBlock as TmplAstSwitchBlock, SwitchBlockCase as TmplAstSwitchBlockCase, Template as TmplAstTemplate, Text$3 as TmplAstText, TextAttribute as TmplAstTextAttribute, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, UnknownBlock as TmplAstUnknownBlock, Variable as TmplAstVariable, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger, Token, TokenType, TransplantedType, TreeError, Type, TypeModifier, TypeofExpr, TypeofExpression, Unary, UnaryOperator, UnaryOperatorExpr, VERSION, VariableBinding, Version, ViewEncapsulation, VoidExpr, VoidExpression, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, compileClassDebugInfo, compileClassMetadata, compileComponentClassMetadata, compileComponentDeclareClassMetadata, compileComponentFromMetadata, compileDeclareClassMetadata, compileDeclareComponentFromMetadata, compileDeclareDirectiveFromMetadata, compileDeclareFactoryFunction, compileDeclareInjectableFromMetadata, compileDeclareInjectorFromMetadata, compileDeclareNgModuleFromMetadata, compileDeclarePipeFromMetadata, compileDeferResolverFunction, compileDirectiveFromMetadata, compileFactoryFunction, compileHmrInitializer, compileHmrUpdateCallback, compileInjectable, compileInjector, compileNgModule, compileOpaqueAsyncClassMetadata, compilePipeFromMetadata, computeMsgId, core, createCssSelectorFromNode, createInjectableType, createMayBeForwardRefExpression, devOnlyGuardedExpression, emitDistinctChangesOnlyDefaultValue, encapsulateStyle, findMatchingDirectivesAndPipes, getHtmlTagDefinition, getNsPrefix, getSafePropertyAccessString, identifierName, isNgContainer, isNgContent, isNgTemplate, jsDocComment, leadingComment, literal, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, splitNsName, visitAll$1 as tmplAstVisitAll, verifyHostBindings, visitAll };
34652
+ export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, ArrowFunctionExpr, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, BindingType, Block, BlockParameter, BoundElementProperty, BuiltinType, BuiltinTypeName, CUSTOM_ELEMENTS_SCHEMA, Call, Chain, ChangeDetectionStrategy, CommaExpr, Comment, CompilerConfig, Component, Conditional, ConditionalExpr, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, Directive, DomElementSchemaRegistry, DynamicImportExpr, EOF, Element, ElementSchemaRegistry, EmitterVisitorContext, EmptyExpr$1 as EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, FactoryTarget$1 as FactoryTarget, FunctionExpr, HtmlParser, HtmlTagDefinition, I18NHtmlParser, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation$1 as Interpolation, InterpolationConfig, InvokeFunctionExpr, JSDocComment, JitEvaluator, KeyedRead, KeyedWrite, LeadingComment, LetDeclaration, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralPrimitive, LocalizedString, MapType, MessageBundle, NONE_TYPE, NO_ERRORS_SCHEMA, NodeWithI18n, NonNullAssert, NotExpr, ParenthesizedExpr, ParenthesizedExpression, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedEventType, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser, ParserError, PrefixNot, PropertyRead, PropertyWrite, Identifiers as R3Identifiers, R3NgModuleMetadataKind, R3SelectorScopeMode, R3TargetBinder, R3TemplateDependencyKind, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveVisitor, ResourceLoader, ReturnStatement, STRING_TYPE, SafeCall, SafeKeyedRead, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, Serializer, SplitInterpolation, Statement, StmtModifier, StringToken, StringTokenKind, TagContentType, TaggedTemplateLiteral, TaggedTemplateLiteralExpr, TemplateBindingParseResult, TemplateLiteral, TemplateLiteralElement, TemplateLiteralElementExpr, TemplateLiteralExpr, Text, ThisReceiver, BlockNode as TmplAstBlockNode, BoundAttribute as TmplAstBoundAttribute, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Component$1 as TmplAstComponent, Content as TmplAstContent, DeferredBlock as TmplAstDeferredBlock, DeferredBlockError as TmplAstDeferredBlockError, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredTrigger as TmplAstDeferredTrigger, Directive$1 as TmplAstDirective, Element$1 as TmplAstElement, ForLoopBlock as TmplAstForLoopBlock, ForLoopBlockEmpty as TmplAstForLoopBlockEmpty, HostElement as TmplAstHostElement, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, IfBlock as TmplAstIfBlock, IfBlockBranch as TmplAstIfBlockBranch, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, LetDeclaration$1 as TmplAstLetDeclaration, NeverDeferredTrigger as TmplAstNeverDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, SwitchBlock as TmplAstSwitchBlock, SwitchBlockCase as TmplAstSwitchBlockCase, Template as TmplAstTemplate, Text$3 as TmplAstText, TextAttribute as TmplAstTextAttribute, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, UnknownBlock as TmplAstUnknownBlock, Variable as TmplAstVariable, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger, Token, TokenType, TransplantedType, TreeError, Type, TypeModifier, TypeofExpr, TypeofExpression, Unary, UnaryOperator, UnaryOperatorExpr, VERSION, VariableBinding, Version, ViewEncapsulation, VoidExpr, VoidExpression, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, compileClassDebugInfo, compileClassMetadata, compileComponentClassMetadata, compileComponentDeclareClassMetadata, compileComponentFromMetadata, compileDeclareClassMetadata, compileDeclareComponentFromMetadata, compileDeclareDirectiveFromMetadata, compileDeclareFactoryFunction, compileDeclareInjectableFromMetadata, compileDeclareInjectorFromMetadata, compileDeclareNgModuleFromMetadata, compileDeclarePipeFromMetadata, compileDeferResolverFunction, compileDirectiveFromMetadata, compileFactoryFunction, compileHmrInitializer, compileHmrUpdateCallback, compileInjectable, compileInjector, compileNgModule, compileOpaqueAsyncClassMetadata, compilePipeFromMetadata, computeMsgId, core, createCssSelectorFromNode, createInjectableType, createMayBeForwardRefExpression, devOnlyGuardedExpression, emitDistinctChangesOnlyDefaultValue, encapsulateStyle, findMatchingDirectivesAndPipes, getHtmlTagDefinition, getNsPrefix, getSafePropertyAccessString, identifierName, isNgContainer, isNgContent, isNgTemplate, jsDocComment, leadingComment, literal, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, splitNsName, visitAll$1 as tmplAstVisitAll, verifyHostBindings, visitAll };
33942
34653
  //# sourceMappingURL=compiler.mjs.map