@angular/compiler-cli 21.0.6 → 21.0.7

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.
@@ -87,7 +87,7 @@ import {
87
87
  toUnredirectedSourceFile,
88
88
  tryParseInitializerApi,
89
89
  untagAllTsFiles
90
- } from "./chunk-PUEBQK4X.js";
90
+ } from "./chunk-ULL25HYK.js";
91
91
  import {
92
92
  LogicalFileSystem,
93
93
  absoluteFromSourceFile,
@@ -622,12 +622,15 @@ var DirectiveExtractor = class extends ClassExtractor {
622
622
  }
623
623
  /** Extract docs info for directives and components (including underlying class info). */
624
624
  extract() {
625
+ const selector = this.metadata.selector ?? "";
626
+ const aliases = extractAliasesFromSelector(selector);
625
627
  return {
626
628
  ...super.extract(),
627
629
  isStandalone: this.metadata.isStandalone,
628
- selector: this.metadata.selector ?? "",
630
+ selector,
629
631
  exportAs: this.metadata.exportAs ?? [],
630
- entryType: this.metadata.isComponent ? EntryType.Component : EntryType.Directive
632
+ entryType: this.metadata.isComponent ? EntryType.Component : EntryType.Directive,
633
+ ...aliases.length > 0 && { aliases }
631
634
  };
632
635
  }
633
636
  /** Extracts docs info for a directive property, including input/output metadata. */
@@ -717,6 +720,21 @@ function extractPipeSyntax(metadata, classDeclaration) {
717
720
  });
718
721
  return `{{ value_expression | ${metadata.name}${paramNames.length ? ":" + paramNames.join(":") : ""} }}`;
719
722
  }
723
+ function extractAliasesFromSelector(selector) {
724
+ if (!selector) {
725
+ return [];
726
+ }
727
+ const aliases = [];
728
+ const attributeRegex = /\[([^\]=]+)(?:=[^\]]+)?\]/g;
729
+ let match;
730
+ while ((match = attributeRegex.exec(selector)) !== null) {
731
+ const attributeName = match[1].trim();
732
+ if (attributeName) {
733
+ aliases.push(attributeName);
734
+ }
735
+ }
736
+ return aliases;
737
+ }
720
738
 
721
739
  // packages/compiler-cli/src/ngtsc/docs/src/constant_extractor.js
722
740
  import ts7 from "typescript";
@@ -1204,7 +1222,7 @@ var DocsExtractor = class {
1204
1222
  if (isAngularPrivateName(exportName)) {
1205
1223
  continue;
1206
1224
  }
1207
- const entry = this.extractDeclarations(exportName, declarations);
1225
+ const entry = this.extractDeclarations(declarations);
1208
1226
  if (entry && !isIgnoredDocEntry(entry)) {
1209
1227
  const realSourceFile = declarations[0].getSourceFile();
1210
1228
  const importedSymbols = getImportedSymbols(realSourceFile);
@@ -1233,7 +1251,7 @@ var DocsExtractor = class {
1233
1251
  * the same name. This is used to combine entries, e.g. for a type and a namespace that are
1234
1252
  * exported under the same name.
1235
1253
  */
1236
- extractDeclarations(exportName, nodes) {
1254
+ extractDeclarations(nodes) {
1237
1255
  const entries = nodes.map((node) => this.extractDeclaration(node));
1238
1256
  const decorator = entries.find((e) => e?.entryType === EntryType.Decorator);
1239
1257
  if (decorator) {
@@ -2138,7 +2156,7 @@ var IndexingContext = class {
2138
2156
  import { ParseSourceFile } from "@angular/compiler";
2139
2157
 
2140
2158
  // packages/compiler-cli/src/ngtsc/indexer/src/template.js
2141
- import { ASTWithSource, CombinedRecursiveAstVisitor, ImplicitReceiver, PropertyRead, TmplAstComponent, TmplAstDirective, TmplAstElement, TmplAstReference, TmplAstTemplate, TmplAstVariable, tmplAstVisitAll } from "@angular/compiler";
2159
+ import { ASTWithSource, CombinedRecursiveAstVisitor, ImplicitReceiver, PropertyRead, ThisReceiver, TmplAstComponent, TmplAstDirective, TmplAstElement, TmplAstReference, TmplAstTemplate, TmplAstVariable, tmplAstVisitAll } from "@angular/compiler";
2142
2160
  var TemplateVisitor = class extends CombinedRecursiveAstVisitor {
2143
2161
  boundTemplate;
2144
2162
  // Identifiers of interest found in the template.
@@ -2368,7 +2386,7 @@ var TemplateVisitor = class extends CombinedRecursiveAstVisitor {
2368
2386
  if (this.currentAstWithSource === null || this.currentAstWithSource.source === null) {
2369
2387
  return;
2370
2388
  }
2371
- if (!(ast.receiver instanceof ImplicitReceiver)) {
2389
+ if (!(ast.receiver instanceof ImplicitReceiver) && !(ast.receiver instanceof ThisReceiver)) {
2372
2390
  return;
2373
2391
  }
2374
2392
  const { absoluteOffset, source: expressionStr } = this.currentAstWithSource;
@@ -3664,7 +3682,7 @@ var SUPPORTED_DIAGNOSTIC_NAMES = /* @__PURE__ */ new Set([
3664
3682
  ]);
3665
3683
 
3666
3684
  // packages/compiler-cli/src/ngtsc/typecheck/template_semantics/src/template_semantics_checker.js
3667
- import { ASTWithSource as ASTWithSource5, ImplicitReceiver as ImplicitReceiver2, ParsedEventType as ParsedEventType2, PropertyRead as PropertyRead6, Binary as Binary3, RecursiveAstVisitor, TmplAstBoundEvent as TmplAstBoundEvent3, TmplAstLetDeclaration as TmplAstLetDeclaration2, TmplAstRecursiveVisitor, TmplAstVariable as TmplAstVariable2 } from "@angular/compiler";
3685
+ import { ASTWithSource as ASTWithSource5, ImplicitReceiver as ImplicitReceiver2, ParsedEventType as ParsedEventType2, PropertyRead as PropertyRead6, Binary as Binary3, RecursiveAstVisitor, TmplAstBoundEvent as TmplAstBoundEvent3, TmplAstLetDeclaration as TmplAstLetDeclaration2, TmplAstRecursiveVisitor, TmplAstVariable as TmplAstVariable2, ThisReceiver as ThisReceiver2 } from "@angular/compiler";
3668
3686
  import ts23 from "typescript";
3669
3687
  var TemplateSemanticsCheckerImpl = class {
3670
3688
  templateTypeChecker;
@@ -3716,7 +3734,7 @@ var ExpressionsSemanticsVisitor = class extends RecursiveAstVisitor {
3716
3734
  this.checkForIllegalWriteInTwoWayBinding(ast, context);
3717
3735
  }
3718
3736
  checkForIllegalWriteInEventBinding(ast, context) {
3719
- if (!(context instanceof TmplAstBoundEvent3) || !(ast.receiver instanceof ImplicitReceiver2)) {
3737
+ if (!this.shouldCheckForIllegalWrites(ast, context)) {
3720
3738
  return;
3721
3739
  }
3722
3740
  const target = this.templateTypeChecker.getExpressionTarget(ast, this.component);
@@ -3726,7 +3744,7 @@ var ExpressionsSemanticsVisitor = class extends RecursiveAstVisitor {
3726
3744
  }
3727
3745
  }
3728
3746
  checkForIllegalWriteInTwoWayBinding(ast, context) {
3729
- if (!(context instanceof TmplAstBoundEvent3) || context.type !== ParsedEventType2.TwoWay || !(ast.receiver instanceof ImplicitReceiver2) || ast !== unwrapAstWithSource(context.handler)) {
3747
+ if (!this.shouldCheckForIllegalWrites(ast, context) || context.type !== ParsedEventType2.TwoWay || ast !== unwrapAstWithSource(context.handler)) {
3730
3748
  return;
3731
3749
  }
3732
3750
  const target = this.templateTypeChecker.getExpressionTarget(ast, this.component);
@@ -3757,6 +3775,9 @@ var ExpressionsSemanticsVisitor = class extends RecursiveAstVisitor {
3757
3775
  }
3758
3776
  ]);
3759
3777
  }
3778
+ shouldCheckForIllegalWrites(ast, context) {
3779
+ return context instanceof TmplAstBoundEvent3 && (ast.receiver instanceof ImplicitReceiver2 || ast.receiver instanceof ThisReceiver2);
3780
+ }
3760
3781
  };
3761
3782
  function unwrapAstWithSource(ast) {
3762
3783
  return ast instanceof ASTWithSource5 ? ast.ast : ast;
@@ -12,7 +12,7 @@ import {
12
12
  formatDiagnostics,
13
13
  performCompilation,
14
14
  readConfiguration
15
- } from "./chunk-ML6J2RBK.js";
15
+ } from "./chunk-SGVDYEOA.js";
16
16
 
17
17
  // packages/compiler-cli/src/main.js
18
18
  import ts2 from "typescript";
@@ -8,7 +8,7 @@ import {
8
8
  TrackedIncrementalBuildStrategy,
9
9
  freshCompilationTicket,
10
10
  incrementalFromCompilerTicket
11
- } from "./chunk-6VDGFZBQ.js";
11
+ } from "./chunk-IVLAY5II.js";
12
12
  import {
13
13
  ActivePerfRecorder,
14
14
  OptimizeFor,
@@ -18,7 +18,7 @@ import {
18
18
  TsCreateProgramDriver,
19
19
  replaceTsWithNgInErrors,
20
20
  retagAllTsFiles
21
- } from "./chunk-PUEBQK4X.js";
21
+ } from "./chunk-ULL25HYK.js";
22
22
  import {
23
23
  absoluteFrom,
24
24
  createFileSystemTsReadDirectoryFn,
@@ -4434,12 +4434,13 @@ var StaticInterpreter = class {
4434
4434
  return res;
4435
4435
  }
4436
4436
  visitTypeQuery(node, context) {
4437
- if (!ts16.isIdentifier(node.exprName)) {
4437
+ const exprName = ts16.isQualifiedName(node.exprName) ? node.exprName.right : node.exprName;
4438
+ if (!ts16.isIdentifier(exprName)) {
4438
4439
  return DynamicValue.fromUnknown(node);
4439
4440
  }
4440
- const decl = this.host.getDeclarationOfIdentifier(node.exprName);
4441
+ const decl = this.host.getDeclarationOfIdentifier(exprName);
4441
4442
  if (decl === null) {
4442
- return DynamicValue.fromUnknownIdentifier(node.exprName);
4443
+ return DynamicValue.fromUnknownIdentifier(exprName);
4443
4444
  }
4444
4445
  const declContext = { ...context, ...joinModuleContext(context, node, decl) };
4445
4446
  return this.visitDeclaration(decl.node, declContext);
@@ -9595,7 +9596,7 @@ function parseTemplateDeclaration(node, decorator, component, containingFile, ev
9595
9596
  resolvedTemplateUrl: containingFile
9596
9597
  };
9597
9598
  } else {
9598
- throw new FatalDiagnosticError(ErrorCode.COMPONENT_MISSING_TEMPLATE, decorator.node, "component is missing a template");
9599
+ throw new FatalDiagnosticError(ErrorCode.COMPONENT_MISSING_TEMPLATE, decorator.node, "@Component is missing a template. Add either a `template` or `templateUrl`");
9599
9600
  }
9600
9601
  }
9601
9602
  function preloadAndParseTemplate(evaluator, resourceLoader, depTracker, preanalyzeTemplateCache, node, decorator, component, containingFile, defaultPreserveWhitespaces, options, compilationMode) {
@@ -11598,7 +11599,7 @@ function getTypeCheckId(clazz) {
11598
11599
  }
11599
11600
 
11600
11601
  // packages/compiler-cli/src/ngtsc/typecheck/src/completion.js
11601
- import { EmptyExpr, ImplicitReceiver, PropertyRead, SafePropertyRead, TmplAstLetDeclaration, TmplAstReference, TmplAstTextAttribute } from "@angular/compiler";
11602
+ import { EmptyExpr, ImplicitReceiver, PropertyRead, SafePropertyRead, ThisReceiver, TmplAstLetDeclaration, TmplAstReference, TmplAstTextAttribute } from "@angular/compiler";
11602
11603
  import ts51 from "typescript";
11603
11604
  var CompletionEngine = class {
11604
11605
  tcb;
@@ -11677,7 +11678,7 @@ var CompletionEngine = class {
11677
11678
  };
11678
11679
  }
11679
11680
  }
11680
- if (node instanceof PropertyRead && node.receiver instanceof ImplicitReceiver) {
11681
+ if (node instanceof PropertyRead && (node.receiver instanceof ImplicitReceiver || node.receiver instanceof ThisReceiver)) {
11681
11682
  const nodeLocation = findFirstMatchingNode(this.tcb, {
11682
11683
  filter: ts51.isPropertyAccessExpression,
11683
11684
  withSpan: node.sourceSpan
@@ -13082,7 +13083,7 @@ var TypeParameterEmitter = class {
13082
13083
  };
13083
13084
 
13084
13085
  // packages/compiler-cli/src/ngtsc/typecheck/src/host_bindings.js
13085
- import { BindingType, CssSelector as CssSelector2, makeBindingParser, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstHostElement, AbsoluteSourceSpan as AbsoluteSourceSpan2, ParseSpan, PropertyRead as PropertyRead2, ParsedEventType, Call, ThisReceiver, KeyedRead, LiteralPrimitive, RecursiveAstVisitor, ASTWithName, SafeCall, ImplicitReceiver as ImplicitReceiver2 } from "@angular/compiler";
13086
+ import { BindingType, CssSelector as CssSelector2, makeBindingParser, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstHostElement, AbsoluteSourceSpan as AbsoluteSourceSpan2, ParseSpan, PropertyRead as PropertyRead2, ParsedEventType, Call, ThisReceiver as ThisReceiver2, KeyedRead, LiteralPrimitive, RecursiveAstVisitor, ASTWithName, SafeCall, ImplicitReceiver as ImplicitReceiver2 } from "@angular/compiler";
13086
13087
  import ts54 from "typescript";
13087
13088
  var GUARD_COMMENT_TEXT = "hostBindingsBlockGuard";
13088
13089
  function createHostElement(type, selector, sourceNode, literal4, bindingDecorators, listenerDecorators) {
@@ -13180,7 +13181,7 @@ function createNodeFromBindingDecorator(decorator, bindings) {
13180
13181
  }
13181
13182
  const span = new ParseSpan(-1, -1);
13182
13183
  const propertyStart = property.getStart();
13183
- const receiver = new ThisReceiver(span, new AbsoluteSourceSpan2(propertyStart, propertyStart));
13184
+ const receiver = new ThisReceiver2(span, new AbsoluteSourceSpan2(propertyStart, propertyStart));
13184
13185
  const nameSpan = new AbsoluteSourceSpan2(propertyName.getStart(), propertyName.getEnd());
13185
13186
  const read = ts54.isIdentifier(propertyName) ? new PropertyRead2(span, nameSpan, nameSpan, receiver, propertyName.text) : new KeyedRead(span, nameSpan, receiver, new LiteralPrimitive(span, nameSpan, propertyName.text));
13186
13187
  const { attrName, type } = inferBoundAttribute(nameNode.text);
@@ -13198,7 +13199,7 @@ function createNodeFromListenerDecorator(decorator, parser, listeners) {
13198
13199
  const span = new ParseSpan(-1, -1);
13199
13200
  const argNodes = [];
13200
13201
  const methodStart = method.getStart();
13201
- const methodReceiver = new ThisReceiver(span, new AbsoluteSourceSpan2(methodStart, methodStart));
13202
+ const methodReceiver = new ThisReceiver2(span, new AbsoluteSourceSpan2(methodStart, methodStart));
13202
13203
  const nameSpan = new AbsoluteSourceSpan2(method.name.getStart(), method.name.getEnd());
13203
13204
  const receiver = ts54.isIdentifier(method.name) ? new PropertyRead2(span, nameSpan, nameSpan, methodReceiver, method.name.text) : new KeyedRead(span, nameSpan, methodReceiver, new LiteralPrimitive(span, nameSpan, method.name.text));
13204
13205
  if (args.length > 1 && ts54.isArrayLiteralExpression(args[1])) {
@@ -14125,7 +14126,7 @@ import { TmplAstBoundAttribute as TmplAstBoundAttribute3, TmplAstTemplate } from
14125
14126
  import ts65 from "typescript";
14126
14127
 
14127
14128
  // packages/compiler-cli/src/ngtsc/typecheck/src/ops/expression.js
14128
- import { Binary, BindingPipe, Call as Call3, ImplicitReceiver as ImplicitReceiver3, PropertyRead as PropertyRead4, R3Identifiers as R3Identifiers4, SafeCall as SafeCall2, SafePropertyRead as SafePropertyRead3, ThisReceiver as ThisReceiver2, TmplAstLetDeclaration as TmplAstLetDeclaration2 } from "@angular/compiler";
14129
+ import { Binary, BindingPipe, Call as Call3, ImplicitReceiver as ImplicitReceiver3, PropertyRead as PropertyRead4, R3Identifiers as R3Identifiers4, SafeCall as SafeCall2, SafePropertyRead as SafePropertyRead3, ThisReceiver as ThisReceiver3, TmplAstLetDeclaration as TmplAstLetDeclaration2 } from "@angular/compiler";
14129
14130
  import ts64 from "typescript";
14130
14131
 
14131
14132
  // packages/compiler-cli/src/ngtsc/typecheck/src/expression.js
@@ -14560,7 +14561,7 @@ var TcbExpressionTranslator = class {
14560
14561
  * context). This method assists in resolving those.
14561
14562
  */
14562
14563
  resolve(ast) {
14563
- if (ast instanceof PropertyRead4 && ast.receiver instanceof ImplicitReceiver3 && !(ast.receiver instanceof ThisReceiver2)) {
14564
+ if (ast instanceof PropertyRead4 && ast.receiver instanceof ImplicitReceiver3) {
14564
14565
  const target = this.tcb.boundTarget.getExpressionTarget(ast);
14565
14566
  const targetExpression = target === null ? null : this.getTargetNodeExpression(target, ast);
14566
14567
  if (target instanceof TmplAstLetDeclaration2 && !this.isValidLetDeclarationAccess(target, ast)) {
@@ -14570,7 +14571,7 @@ var TcbExpressionTranslator = class {
14570
14571
  }
14571
14572
  }
14572
14573
  return targetExpression;
14573
- } else if (ast instanceof Binary && Binary.isAssignmentOperation(ast.operation) && ast.left instanceof PropertyRead4 && ast.left.receiver instanceof ImplicitReceiver3) {
14574
+ } else if (ast instanceof Binary && Binary.isAssignmentOperation(ast.operation) && ast.left instanceof PropertyRead4 && (ast.left.receiver instanceof ImplicitReceiver3 || ast.left.receiver instanceof ThisReceiver3)) {
14574
14575
  const read = ast.left;
14575
14576
  const target = this.tcb.boundTarget.getExpressionTarget(read);
14576
14577
  if (target === null) {
@@ -14585,7 +14586,7 @@ var TcbExpressionTranslator = class {
14585
14586
  this.tcb.oobRecorder.illegalWriteToLetDeclaration(this.tcb.id, read, target);
14586
14587
  }
14587
14588
  return result;
14588
- } else if (ast instanceof ImplicitReceiver3) {
14589
+ } else if (ast instanceof ImplicitReceiver3 || ast instanceof ThisReceiver3) {
14589
14590
  return ts64.factory.createThis();
14590
14591
  } else if (ast instanceof BindingPipe) {
14591
14592
  const expr = this.translate(ast.exp);
@@ -14617,7 +14618,7 @@ var TcbExpressionTranslator = class {
14617
14618
  addParseSpanInfo(result, ast.sourceSpan);
14618
14619
  return result;
14619
14620
  } else if ((ast instanceof Call3 || ast instanceof SafeCall2) && (ast.receiver instanceof PropertyRead4 || ast.receiver instanceof SafePropertyRead3)) {
14620
- if (ast.receiver.receiver instanceof ImplicitReceiver3 && !(ast.receiver.receiver instanceof ThisReceiver2) && ast.receiver.name === "$any" && ast.args.length === 1) {
14621
+ if (ast.receiver.receiver instanceof ImplicitReceiver3 && ast.receiver.name === "$any" && ast.args.length === 1) {
14621
14622
  const expr = this.translate(ast.args[0]);
14622
14623
  const exprAsAny = ts64.factory.createAsExpression(expr, ts64.factory.createKeywordTypeNode(ts64.SyntaxKind.AnyKeyword));
14623
14624
  const result = ts64.factory.createParenthesizedExpression(exprAsAny);
@@ -15052,7 +15053,7 @@ var TcbSwitchOp = class extends TcbOp {
15052
15053
  };
15053
15054
 
15054
15055
  // packages/compiler-cli/src/ngtsc/typecheck/src/ops/for_block.js
15055
- import { ImplicitReceiver as ImplicitReceiver4, PropertyRead as PropertyRead5, TmplAstVariable } from "@angular/compiler";
15056
+ import { ImplicitReceiver as ImplicitReceiver4, PropertyRead as PropertyRead5, ThisReceiver as ThisReceiver4, TmplAstVariable } from "@angular/compiler";
15056
15057
  import ts71 from "typescript";
15057
15058
  var TcbForOfOp = class extends TcbOp {
15058
15059
  tcb;
@@ -15100,7 +15101,7 @@ var TcbForLoopTrackTranslator = class extends TcbExpressionTranslator {
15100
15101
  }
15101
15102
  }
15102
15103
  resolve(ast) {
15103
- if (ast instanceof PropertyRead5 && ast.receiver instanceof ImplicitReceiver4) {
15104
+ if (ast instanceof PropertyRead5 && (ast.receiver instanceof ImplicitReceiver4 || ast.receiver instanceof ThisReceiver4)) {
15104
15105
  const target = this.tcb.boundTarget.getExpressionTarget(ast);
15105
15106
  if (target !== null && (!(target instanceof TmplAstVariable) || !this.allowedVariables.has(target))) {
15106
15107
  this.tcb.oobRecorder.illegalForLoopTrackAccess(this.tcb.id, this.block, ast);
@@ -15149,10 +15150,13 @@ var formControlInputFields = [
15149
15150
  // Should be kept in sync with the `FormUiControl` bindings,
15150
15151
  // defined in `packages/forms/signals/src/api/control.ts`.
15151
15152
  "errors",
15152
- "invalid",
15153
+ "dirty",
15153
15154
  "disabled",
15154
15155
  "disabledReasons",
15156
+ "hidden",
15157
+ "invalid",
15155
15158
  "name",
15159
+ "pending",
15156
15160
  "readonly",
15157
15161
  "touched",
15158
15162
  "max",
@@ -15200,7 +15204,7 @@ var TcbNativeFieldOp = class extends TcbOp {
15200
15204
  }
15201
15205
  execute() {
15202
15206
  const inputs = this.node instanceof TmplAstHostElement2 ? this.node.bindings : this.node.inputs;
15203
- const fieldBinding = inputs.find((input) => input.type === BindingType3.Property && input.name === "field") ?? null;
15207
+ const fieldBinding = inputs.find((input) => input.type === BindingType3.Property && (input.name === "field" || input.name === "formField")) ?? null;
15204
15208
  if (fieldBinding === null) {
15205
15209
  return null;
15206
15210
  }
@@ -15279,17 +15283,17 @@ var TcbNativeRadioButtonFieldOp = class extends TcbNativeFieldOp {
15279
15283
  return null;
15280
15284
  }
15281
15285
  };
15282
- function expandBoundAttributesForField(directive, node, customFieldType) {
15283
- const fieldBinding = node.inputs.find((input) => input.type === BindingType3.Property && input.name === "field");
15286
+ function expandBoundAttributesForField(directive, node, customFormControlType) {
15287
+ const fieldBinding = node.inputs.find((input) => input.type === BindingType3.Property && (input.name === "field" || input.name === "formField"));
15284
15288
  if (!fieldBinding) {
15285
15289
  return null;
15286
15290
  }
15287
15291
  let boundInputs = null;
15288
15292
  let primaryInput;
15289
- if (customFieldType === "value") {
15290
- primaryInput = getSyntheticFieldBoundInput(directive, "value", "value", fieldBinding, customFieldType);
15291
- } else if (customFieldType === "checkbox") {
15292
- primaryInput = getSyntheticFieldBoundInput(directive, "checked", "value", fieldBinding, customFieldType);
15293
+ if (customFormControlType === "value") {
15294
+ primaryInput = getSyntheticFieldBoundInput(directive, "value", "value", fieldBinding, customFormControlType);
15295
+ } else if (customFormControlType === "checkbox") {
15296
+ primaryInput = getSyntheticFieldBoundInput(directive, "checked", "value", fieldBinding, customFormControlType);
15293
15297
  } else {
15294
15298
  primaryInput = null;
15295
15299
  }
@@ -15298,7 +15302,7 @@ function expandBoundAttributesForField(directive, node, customFieldType) {
15298
15302
  boundInputs.push(primaryInput);
15299
15303
  }
15300
15304
  for (const name of formControlInputFields) {
15301
- const input = getSyntheticFieldBoundInput(directive, name, name, fieldBinding, customFieldType);
15305
+ const input = getSyntheticFieldBoundInput(directive, name, name, fieldBinding, customFormControlType);
15302
15306
  if (input !== null) {
15303
15307
  boundInputs ??= [];
15304
15308
  boundInputs.push(input);
@@ -15307,7 +15311,7 @@ function expandBoundAttributesForField(directive, node, customFieldType) {
15307
15311
  return boundInputs;
15308
15312
  }
15309
15313
  function isFieldDirective(meta) {
15310
- if (meta.name !== "Field") {
15314
+ if (meta.name !== "Field" && meta.name !== "FormField") {
15311
15315
  return false;
15312
15316
  }
15313
15317
  if (meta.ref.bestGuessOwningModule?.specifier === "@angular/forms/signals") {
@@ -15390,7 +15394,19 @@ function extractFieldValue(expression, tcb, scope) {
15390
15394
  return ts73.factory.createCallExpression(ts73.factory.createPropertyAccessExpression(innerCall, "value"), void 0, void 0);
15391
15395
  }
15392
15396
  function hasModelInput(name, meta) {
15393
- return !!meta.inputs.getByBindingPropertyName(name)?.some((v) => v.isSignal) && meta.outputs.hasBindingPropertyName(name + "Change");
15397
+ return meta.inputs.hasBindingPropertyName(name) && meta.outputs.hasBindingPropertyName(name + "Change");
15398
+ }
15399
+ function isFormControl(allDirectiveMatches) {
15400
+ let result = false;
15401
+ for (const match of allDirectiveMatches) {
15402
+ if (match.inputs.hasBindingPropertyName("field")) {
15403
+ if (!isFieldDirective(match)) {
15404
+ return false;
15405
+ }
15406
+ result = true;
15407
+ }
15408
+ }
15409
+ return result;
15394
15410
  }
15395
15411
 
15396
15412
  // packages/compiler-cli/src/ngtsc/typecheck/src/ops/bindings.js
@@ -15478,14 +15494,16 @@ var TcbDirectiveInputsOp = class extends TcbOp {
15478
15494
  scope;
15479
15495
  node;
15480
15496
  dir;
15481
- customControlType;
15482
- constructor(tcb, scope, node, dir, customControlType) {
15497
+ isFormControl;
15498
+ customFormControlType;
15499
+ constructor(tcb, scope, node, dir, isFormControl2 = false, customFormControlType) {
15483
15500
  super();
15484
15501
  this.tcb = tcb;
15485
15502
  this.scope = scope;
15486
15503
  this.node = node;
15487
15504
  this.dir = dir;
15488
- this.customControlType = customControlType;
15505
+ this.isFormControl = isFormControl2;
15506
+ this.customFormControlType = customFormControlType;
15489
15507
  }
15490
15508
  get optional() {
15491
15509
  return false;
@@ -15494,9 +15512,11 @@ var TcbDirectiveInputsOp = class extends TcbOp {
15494
15512
  let dirId = null;
15495
15513
  const seenRequiredInputs = /* @__PURE__ */ new Set();
15496
15514
  const boundAttrs = getBoundAttributes(this.dir, this.node);
15497
- if (this.customControlType !== null) {
15515
+ if (this.customFormControlType !== null) {
15498
15516
  checkUnsupportedFieldBindings(this.node, customFormControlBannedInputFields, this.tcb);
15499
- const additionalBindings = expandBoundAttributesForField(this.dir, this.node, this.customControlType);
15517
+ }
15518
+ if (this.customFormControlType !== null || this.isFormControl) {
15519
+ const additionalBindings = expandBoundAttributesForField(this.dir, this.node, this.customFormControlType);
15500
15520
  if (additionalBindings !== null) {
15501
15521
  boundAttrs.push(...additionalBindings);
15502
15522
  }
@@ -15698,7 +15718,7 @@ var TcbDomSchemaCheckerOp = class extends TcbOp {
15698
15718
  };
15699
15719
 
15700
15720
  // packages/compiler-cli/src/ngtsc/typecheck/src/ops/events.js
15701
- import { ImplicitReceiver as ImplicitReceiver5, ParsedEventType as ParsedEventType2, PropertyRead as PropertyRead7, ThisReceiver as ThisReceiver3, TmplAstElement as TmplAstElement6 } from "@angular/compiler";
15721
+ import { ImplicitReceiver as ImplicitReceiver5, ParsedEventType as ParsedEventType2, PropertyRead as PropertyRead7, TmplAstElement as TmplAstElement6 } from "@angular/compiler";
15702
15722
  import ts76 from "typescript";
15703
15723
  var EVENT_PARAMETER = "$event";
15704
15724
  function tcbEventHandlerExpression(ast, tcb, scope) {
@@ -15858,7 +15878,7 @@ var TcbUnclaimedOutputsOp = class extends TcbOp {
15858
15878
  };
15859
15879
  var TcbEventHandlerTranslator = class extends TcbExpressionTranslator {
15860
15880
  resolve(ast) {
15861
- if (ast instanceof PropertyRead7 && ast.receiver instanceof ImplicitReceiver5 && !(ast.receiver instanceof ThisReceiver3) && ast.name === EVENT_PARAMETER) {
15881
+ if (ast instanceof PropertyRead7 && ast.receiver instanceof ImplicitReceiver5 && ast.name === EVENT_PARAMETER) {
15862
15882
  const event = ts76.factory.createIdentifier(EVENT_PARAMETER);
15863
15883
  addParseSpanInfo(event, ast.nameSpan);
15864
15884
  return event;
@@ -15999,14 +16019,14 @@ var TcbDirectiveCtorOp = class extends TcbOp {
15999
16019
  scope;
16000
16020
  node;
16001
16021
  dir;
16002
- customControlType;
16003
- constructor(tcb, scope, node, dir, customControlType) {
16022
+ customFormControlType;
16023
+ constructor(tcb, scope, node, dir, customFormControlType) {
16004
16024
  super();
16005
16025
  this.tcb = tcb;
16006
16026
  this.scope = scope;
16007
16027
  this.node = node;
16008
16028
  this.dir = dir;
16009
- this.customControlType = customControlType;
16029
+ this.customFormControlType = customFormControlType;
16010
16030
  }
16011
16031
  get optional() {
16012
16032
  return true;
@@ -16022,8 +16042,8 @@ var TcbDirectiveCtorOp = class extends TcbOp {
16022
16042
  } else {
16023
16043
  span = this.node.startSourceSpan || this.node.sourceSpan;
16024
16044
  boundAttrs = getBoundAttributes(this.dir, this.node);
16025
- if (this.customControlType !== null) {
16026
- const additionalBindings = expandBoundAttributesForField(this.dir, this.node, this.customControlType);
16045
+ if (this.customFormControlType !== null) {
16046
+ const additionalBindings = expandBoundAttributesForField(this.dir, this.node, this.customFormControlType);
16027
16047
  if (additionalBindings !== null) {
16028
16048
  boundAttrs.push(...additionalBindings);
16029
16049
  }
@@ -16720,15 +16740,16 @@ var Scope = class _Scope {
16720
16740
  }
16721
16741
  }
16722
16742
  appendDirectiveInputs(dir, node, dirMap, allDirectiveMatches) {
16723
- const customFieldType = allDirectiveMatches.some(isFieldDirective) ? getCustomFieldDirectiveType(dir) : null;
16724
- const directiveOp = this.getDirectiveOp(dir, node, customFieldType);
16743
+ const nodeIsFormControl = isFormControl(allDirectiveMatches);
16744
+ const customFormControlType = nodeIsFormControl ? getCustomFieldDirectiveType(dir) : null;
16745
+ const directiveOp = this.getDirectiveOp(dir, node, customFormControlType);
16725
16746
  const dirIndex = this.opQueue.push(directiveOp) - 1;
16726
16747
  dirMap.set(dir, dirIndex);
16727
16748
  if (isNativeField(dir, node, allDirectiveMatches)) {
16728
16749
  const inputType = node.name === "input" && node.attributes.find((attr) => attr.name === "type")?.value || null;
16729
16750
  this.opQueue.push(inputType === "radio" ? new TcbNativeRadioButtonFieldOp(this.tcb, this, node) : new TcbNativeFieldOp(this.tcb, this, node, inputType));
16730
16751
  }
16731
- this.opQueue.push(new TcbDirectiveInputsOp(this.tcb, this, node, dir, customFieldType));
16752
+ this.opQueue.push(new TcbDirectiveInputsOp(this.tcb, this, node, dir, nodeIsFormControl, customFormControlType));
16732
16753
  }
16733
16754
  getDirectiveOp(dir, node, customFieldType) {
16734
16755
  const dirRef = dir.ref;
@@ -20482,8 +20503,12 @@ function validateAndFlattenComponentImports(imports, expr, isDeferred) {
20482
20503
  const diagnostics = [];
20483
20504
  for (let i = 0; i < imports.length; i++) {
20484
20505
  const ref = imports[i];
20506
+ let refExpr = expr;
20507
+ if (ts90.isArrayLiteralExpression(expr) && expr.elements.length === imports.length && !expr.elements.some(ts90.isSpreadAssignment)) {
20508
+ refExpr = expr.elements[i];
20509
+ }
20485
20510
  if (Array.isArray(ref)) {
20486
- const { imports: childImports, diagnostics: childDiagnostics } = validateAndFlattenComponentImports(ref, expr, isDeferred);
20511
+ const { imports: childImports, diagnostics: childDiagnostics } = validateAndFlattenComponentImports(ref, refExpr, isDeferred);
20487
20512
  flattened.push(...childImports);
20488
20513
  diagnostics.push(...childDiagnostics);
20489
20514
  } else if (ref instanceof Reference) {
@@ -20501,11 +20526,11 @@ function validateAndFlattenComponentImports(imports, expr, isDeferred) {
20501
20526
  } else {
20502
20527
  let diagnosticNode;
20503
20528
  let diagnosticValue;
20504
- if (ref instanceof DynamicValue) {
20529
+ if (ref instanceof DynamicValue && isWithinExpression(ref.node, expr)) {
20505
20530
  diagnosticNode = ref.node;
20506
20531
  diagnosticValue = ref;
20507
- } else if (ts90.isArrayLiteralExpression(expr) && expr.elements.length === imports.length && !expr.elements.some(ts90.isSpreadAssignment) && !imports.some(Array.isArray)) {
20508
- diagnosticNode = expr.elements[i];
20532
+ } else if (refExpr !== expr) {
20533
+ diagnosticNode = refExpr;
20509
20534
  diagnosticValue = ref;
20510
20535
  } else {
20511
20536
  diagnosticNode = expr;
@@ -20516,6 +20541,16 @@ function validateAndFlattenComponentImports(imports, expr, isDeferred) {
20516
20541
  }
20517
20542
  return { imports: flattened, diagnostics };
20518
20543
  }
20544
+ function isWithinExpression(node, expr) {
20545
+ let current = node;
20546
+ while (current !== void 0) {
20547
+ if (current === expr) {
20548
+ return true;
20549
+ }
20550
+ current = current.parent;
20551
+ }
20552
+ return false;
20553
+ }
20519
20554
  function isLikelyModuleWithProviders(value) {
20520
20555
  if (value instanceof SyntheticValue && isResolvedModuleWithProviders(value)) {
20521
20556
  return true;
@@ -455,7 +455,7 @@ import { compileDirectiveFromMetadata, makeBindingParser, ParseLocation, ParseSo
455
455
  // packages/compiler-cli/linker/src/file_linker/partial_linkers/util.js
456
456
  import { createMayBeForwardRefExpression, outputAst as o2 } from "@angular/compiler";
457
457
  import semver from "semver";
458
- var PLACEHOLDER_VERSION = "21.0.6";
458
+ var PLACEHOLDER_VERSION = "21.0.7";
459
459
  function wrapReference(wrapped) {
460
460
  return { value: wrapped, type: wrapped };
461
461
  }
package/bundles/index.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  isTsDiagnostic,
18
18
  performCompilation,
19
19
  readConfiguration
20
- } from "./chunk-ML6J2RBK.js";
20
+ } from "./chunk-SGVDYEOA.js";
21
21
  import {
22
22
  ConsoleLogger,
23
23
  LogLevel
@@ -34,7 +34,7 @@ import {
34
34
  freshCompilationTicket,
35
35
  incrementalFromStateTicket,
36
36
  isDocEntryWithSourceInfo
37
- } from "./chunk-6VDGFZBQ.js";
37
+ } from "./chunk-IVLAY5II.js";
38
38
  import {
39
39
  ActivePerfRecorder,
40
40
  ErrorCode,
@@ -46,7 +46,7 @@ import {
46
46
  getInitializerApiJitTransform,
47
47
  isLocalCompilationDiagnostics,
48
48
  ngErrorCode
49
- } from "./chunk-PUEBQK4X.js";
49
+ } from "./chunk-ULL25HYK.js";
50
50
  import "./chunk-LS5RJ5CS.js";
51
51
  import {
52
52
  InvalidFileSystem,
@@ -77,7 +77,7 @@ import "./chunk-G7GFT6BU.js";
77
77
 
78
78
  // packages/compiler-cli/src/version.js
79
79
  import { Version } from "@angular/compiler";
80
- var VERSION = new Version("21.0.6");
80
+ var VERSION = new Version("21.0.7");
81
81
 
82
82
  // packages/compiler-cli/private/tooling.js
83
83
  var GLOBAL_DEFS_FOR_TERSER = {
@@ -5,7 +5,7 @@
5
5
  import {
6
6
  DiagnosticCategoryLabel,
7
7
  NgCompiler
8
- } from "../chunk-6VDGFZBQ.js";
8
+ } from "../chunk-IVLAY5II.js";
9
9
  import {
10
10
  CompilationMode,
11
11
  DtsMetadataReader,
@@ -32,7 +32,7 @@ import {
32
32
  queryDecoratorNames,
33
33
  reflectObjectLiteral,
34
34
  unwrapExpression
35
- } from "../chunk-PUEBQK4X.js";
35
+ } from "../chunk-ULL25HYK.js";
36
36
  import "../chunk-LS5RJ5CS.js";
37
37
  import {
38
38
  getFileSystem,
@@ -6,7 +6,7 @@ import {
6
6
  ImportedSymbolsTracker,
7
7
  TypeScriptReflectionHost,
8
8
  getInitializerApiJitTransform
9
- } from "../chunk-PUEBQK4X.js";
9
+ } from "../chunk-ULL25HYK.js";
10
10
  import "../chunk-LS5RJ5CS.js";
11
11
  import {
12
12
  InvalidFileSystem,
@@ -4,7 +4,7 @@
4
4
 
5
5
  import {
6
6
  angularJitApplicationTransform
7
- } from "../chunk-PUEBQK4X.js";
7
+ } from "../chunk-ULL25HYK.js";
8
8
  import "../chunk-LS5RJ5CS.js";
9
9
  import "../chunk-JEXAXD23.js";
10
10
  import "../chunk-XYYEESKY.js";
@@ -6,12 +6,12 @@
6
6
  import {
7
7
  main,
8
8
  readCommandLineAndConfiguration
9
- } from "../../chunk-OPZT26MK.js";
9
+ } from "../../chunk-OQOYWATZ.js";
10
10
  import {
11
11
  EmitFlags
12
- } from "../../chunk-ML6J2RBK.js";
13
- import "../../chunk-6VDGFZBQ.js";
14
- import "../../chunk-PUEBQK4X.js";
12
+ } from "../../chunk-SGVDYEOA.js";
13
+ import "../../chunk-IVLAY5II.js";
14
+ import "../../chunk-ULL25HYK.js";
15
15
  import "../../chunk-LS5RJ5CS.js";
16
16
  import {
17
17
  setFileSystem
@@ -5,10 +5,10 @@
5
5
 
6
6
  import {
7
7
  main
8
- } from "../../chunk-OPZT26MK.js";
9
- import "../../chunk-ML6J2RBK.js";
10
- import "../../chunk-6VDGFZBQ.js";
11
- import "../../chunk-PUEBQK4X.js";
8
+ } from "../../chunk-OQOYWATZ.js";
9
+ import "../../chunk-SGVDYEOA.js";
10
+ import "../../chunk-IVLAY5II.js";
11
+ import "../../chunk-ULL25HYK.js";
12
12
  import "../../chunk-LS5RJ5CS.js";
13
13
  import {
14
14
  setFileSystem
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { MaybeForwardRefExpression, outputAst as o, R3DeclareDependencyMetadata, R3DependencyMetadata, R3Reference } from '@angular/compiler';
9
9
  import { AstObject, AstValue } from '../../ast/ast_value';
10
- export declare const PLACEHOLDER_VERSION = "21.0.6";
10
+ export declare const PLACEHOLDER_VERSION = "21.0.7";
11
11
  export declare function wrapReference<TExpression>(wrapped: o.WrappedNodeExpr<TExpression>): R3Reference;
12
12
  /**
13
13
  * Parses the value of an enum from the AST value's symbol name.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/compiler-cli",
3
- "version": "21.0.6",
3
+ "version": "21.0.7",
4
4
  "description": "Angular - the compiler CLI for Node.js",
5
5
  "typings": "index.d.ts",
6
6
  "bin": {
@@ -40,7 +40,7 @@
40
40
  "yargs": "^18.0.0"
41
41
  },
42
42
  "peerDependencies": {
43
- "@angular/compiler": "21.0.6",
43
+ "@angular/compiler": "21.0.7",
44
44
  "typescript": ">=5.9 <6.0"
45
45
  },
46
46
  "peerDependenciesMeta": {
@@ -11,7 +11,7 @@ import { TcbOp } from './base';
11
11
  import { Context } from './context';
12
12
  import type { Scope } from './scope';
13
13
  import { TypeCheckableDirectiveMeta } from '../../api';
14
- import { CustomFieldType } from './signal_forms';
14
+ import { CustomFormControlType } from './signal_forms';
15
15
  /**
16
16
  * A `TcbOp` which constructs an instance of a directive with types inferred from its inputs. The
17
17
  * inputs themselves are not checked here; checking of inputs is achieved in `TcbDirectiveInputsOp`.
@@ -29,8 +29,8 @@ export declare class TcbDirectiveCtorOp extends TcbOp {
29
29
  private scope;
30
30
  private node;
31
31
  private dir;
32
- private customControlType;
33
- constructor(tcb: Context, scope: Scope, node: DirectiveOwner, dir: TypeCheckableDirectiveMeta, customControlType: CustomFieldType | null);
32
+ private customFormControlType;
33
+ constructor(tcb: Context, scope: Scope, node: DirectiveOwner, dir: TypeCheckableDirectiveMeta, customFormControlType: CustomFormControlType | null);
34
34
  get optional(): boolean;
35
35
  execute(): ts.Identifier;
36
36
  circularFallback(): TcbOp;
@@ -11,7 +11,7 @@ import type { Context } from './context';
11
11
  import type { Scope } from './scope';
12
12
  import { TypeCheckableDirectiveMeta } from '../../api';
13
13
  import { TcbOp } from './base';
14
- import { CustomFieldType } from './signal_forms';
14
+ import { CustomFormControlType } from './signal_forms';
15
15
  import { LocalSymbol } from './references';
16
16
  /**
17
17
  * Translates the given attribute binding to a `ts.Expression`.
@@ -28,8 +28,9 @@ export declare class TcbDirectiveInputsOp extends TcbOp {
28
28
  private scope;
29
29
  private node;
30
30
  private dir;
31
- private customControlType;
32
- constructor(tcb: Context, scope: Scope, node: TmplAstTemplate | TmplAstElement | TmplAstComponent | TmplAstDirective, dir: TypeCheckableDirectiveMeta, customControlType: CustomFieldType | null);
31
+ private isFormControl;
32
+ private customFormControlType;
33
+ constructor(tcb: Context, scope: Scope, node: TmplAstTemplate | TmplAstElement | TmplAstComponent | TmplAstDirective, dir: TypeCheckableDirectiveMeta, isFormControl: boolean | undefined, customFormControlType: CustomFormControlType | null);
33
34
  get optional(): boolean;
34
35
  execute(): null;
35
36
  private checkRequiredInputs;
@@ -6,13 +6,13 @@
6
6
  * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
8
  import { DirectiveOwner, TmplAstComponent, TmplAstDirective, TmplAstElement, TmplAstNode, TmplAstTemplate } from '@angular/compiler';
9
+ import { TypeCheckableDirectiveMeta } from '../../api';
9
10
  import { TcbOp } from './base';
11
+ import { TcbBoundAttribute } from './bindings';
10
12
  import type { Context } from './context';
11
13
  import type { Scope } from './scope';
12
- import { TypeCheckableDirectiveMeta } from '../../api';
13
- import { TcbBoundAttribute } from './bindings';
14
- /** Possible types of custom field directives. */
15
- export type CustomFieldType = 'value' | 'checkbox';
14
+ /** Possible types of custom form control directives. */
15
+ export type CustomFormControlType = 'value' | 'checkbox';
16
16
  /** Names of input fields to which users aren't allowed to bind when using a `field` directive. */
17
17
  export declare const customFormControlBannedInputFields: Set<string>;
18
18
  /**
@@ -39,13 +39,20 @@ export declare class TcbNativeRadioButtonFieldOp extends TcbNativeFieldOp {
39
39
  execute(): null;
40
40
  }
41
41
  /** Expands the set of bound inputs with the ones from custom field directives. */
42
- export declare function expandBoundAttributesForField(directive: TypeCheckableDirectiveMeta, node: TmplAstTemplate | TmplAstElement | TmplAstComponent | TmplAstDirective, customFieldType: CustomFieldType): TcbBoundAttribute[] | null;
42
+ export declare function expandBoundAttributesForField(directive: TypeCheckableDirectiveMeta, node: TmplAstTemplate | TmplAstElement | TmplAstComponent | TmplAstDirective, customFormControlType: CustomFormControlType | null): TcbBoundAttribute[] | null;
43
43
  export declare function isFieldDirective(meta: TypeCheckableDirectiveMeta): boolean;
44
44
  /** Determines if a directive is a custom field and its type. */
45
- export declare function getCustomFieldDirectiveType(meta: TypeCheckableDirectiveMeta): CustomFieldType | null;
45
+ export declare function getCustomFieldDirectiveType(meta: TypeCheckableDirectiveMeta): CustomFormControlType | null;
46
46
  /** Determines if a directive usage is on a native field. */
47
47
  export declare function isNativeField(dir: TypeCheckableDirectiveMeta, node: TmplAstNode, allDirectiveMatches: TypeCheckableDirectiveMeta[]): node is TmplAstElement & {
48
48
  name: 'input' | 'select' | 'textarea';
49
49
  };
50
50
  /** Checks whether a node has bindings that aren't supported on fields. */
51
51
  export declare function checkUnsupportedFieldBindings(node: DirectiveOwner, unsupportedBindingFields: Set<string>, tcb: Context): void;
52
+ /**
53
+ * Determines whether a node is a form control based on its matching directives.
54
+ *
55
+ * A node is a form control if it has a matching `Field` directive, and no other directives match
56
+ * the `field` input.
57
+ */
58
+ export declare function isFormControl(allDirectiveMatches: TypeCheckableDirectiveMeta[]): boolean;