@angular/core 19.0.0-rc.1 → 19.0.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/fesm2022/core.mjs +13164 -13060
  2. package/fesm2022/core.mjs.map +1 -1
  3. package/fesm2022/primitives/event-dispatch.mjs +2 -2
  4. package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
  5. package/fesm2022/primitives/signals.mjs +1 -1
  6. package/fesm2022/rxjs-interop.mjs +1 -1
  7. package/fesm2022/testing.mjs +4 -4
  8. package/index.d.ts +74 -13
  9. package/package.json +1 -1
  10. package/primitives/event-dispatch/index.d.ts +1 -1
  11. package/primitives/signals/index.d.ts +1 -1
  12. package/rxjs-interop/index.d.ts +1 -1
  13. package/schematics/bundles/{checker-9ca42e51.js → checker-e3da3b0a.js} +95 -54
  14. package/schematics/bundles/{combine_units-a16385aa.js → combine_units-2adebceb.js} +97 -28
  15. package/schematics/bundles/{compiler_host-31afa4ed.js → compiler_host-d642e87e.js} +2 -2
  16. package/schematics/bundles/control-flow-migration.js +3 -3
  17. package/schematics/bundles/explicit-standalone-flag.js +3 -3
  18. package/schematics/bundles/imports-4ac08251.js +1 -1
  19. package/schematics/bundles/inject-migration.js +3 -3
  20. package/schematics/bundles/leading_space-d190b83b.js +1 -1
  21. package/schematics/bundles/{migrate_ts_type_references-b2a28742.js → migrate_ts_type_references-ed2c0669.js} +527 -31
  22. package/schematics/bundles/nodes-0e7d45ca.js +1 -1
  23. package/schematics/bundles/output-migration.js +17 -14
  24. package/schematics/bundles/pending-tasks.js +3 -3
  25. package/schematics/bundles/{program-71beec0b.js → program-f984ab63.js} +45 -52
  26. package/schematics/bundles/project_tsconfig_paths-e9ccccbf.js +1 -1
  27. package/schematics/bundles/provide-initializer.js +3 -3
  28. package/schematics/bundles/route-lazy-loading.js +3 -3
  29. package/schematics/bundles/signal-input-migration.js +48 -35
  30. package/schematics/bundles/signal-queries-migration.js +21 -14
  31. package/schematics/bundles/signals.js +5 -5
  32. package/schematics/bundles/standalone-migration.js +159 -75
  33. package/schematics/ng-generate/signals/schema.json +1 -0
  34. package/testing/index.d.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.1
3
+ * @license Angular v19.0.0-rc.3
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -14,18 +14,18 @@ var signalInputMigration = require('./signal-input-migration.js');
14
14
  var outputMigration = require('./output-migration.js');
15
15
  require('./project_tsconfig_paths-e9ccccbf.js');
16
16
  require('@angular-devkit/core');
17
- require('./combine_units-a16385aa.js');
17
+ require('./combine_units-2adebceb.js');
18
18
  require('node:path/posix');
19
19
  require('os');
20
20
  require('typescript');
21
- require('./checker-9ca42e51.js');
21
+ require('./checker-e3da3b0a.js');
22
22
  require('fs');
23
23
  require('module');
24
24
  require('path');
25
25
  require('url');
26
- require('./program-71beec0b.js');
26
+ require('./program-f984ab63.js');
27
+ require('./migrate_ts_type_references-ed2c0669.js');
27
28
  require('assert');
28
- require('./migrate_ts_type_references-b2a28742.js');
29
29
  require('./leading_space-d190b83b.js');
30
30
 
31
31
  function migrate(options) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.1
3
+ * @license Angular v19.0.0-rc.3
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -11,11 +11,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
11
11
  var schematics = require('@angular-devkit/schematics');
12
12
  require('os');
13
13
  var ts = require('typescript');
14
- var checker = require('./checker-9ca42e51.js');
15
- var program = require('./program-71beec0b.js');
14
+ var checker = require('./checker-e3da3b0a.js');
15
+ var program = require('./program-f984ab63.js');
16
16
  var p = require('path');
17
17
  var fs = require('fs');
18
- var compiler_host = require('./compiler_host-31afa4ed.js');
18
+ var compiler_host = require('./compiler_host-d642e87e.js');
19
19
  var project_tsconfig_paths = require('./project_tsconfig_paths-e9ccccbf.js');
20
20
  var nodes = require('./nodes-0e7d45ca.js');
21
21
  var imports = require('./imports-4ac08251.js');
@@ -32,7 +32,7 @@ var ts__default = /*#__PURE__*/_interopDefaultLegacy(ts);
32
32
  * @description
33
33
  * Entry point for all public APIs of the compiler-cli package.
34
34
  */
35
- new checker.Version('19.0.0-rc.1');
35
+ new checker.Version('19.0.0-rc.3');
36
36
 
37
37
  function createProgram({ rootNames, options, host, oldProgram, }) {
38
38
  return new program.NgtscProgram(rootNames, options, host, oldProgram);
@@ -48,6 +48,20 @@ var LogLevel;
48
48
 
49
49
  checker.setFileSystem(new checker.NodeJSFileSystem());
50
50
 
51
+ /** Checks whether a node is referring to a specific import specifier. */
52
+ function isReferenceToImport(typeChecker, node, importSpecifier) {
53
+ // If this function is called on an identifier (should be most cases), we can quickly rule out
54
+ // non-matches by comparing the identifier's string and the local name of the import specifier
55
+ // which saves us some calls to the type checker.
56
+ if (ts__default["default"].isIdentifier(node) && node.text !== importSpecifier.name.text) {
57
+ return false;
58
+ }
59
+ const nodeSymbol = typeChecker.getTypeAtLocation(node).getSymbol();
60
+ const importSymbol = typeChecker.getTypeAtLocation(importSpecifier).getSymbol();
61
+ return (!!(nodeSymbol?.declarations?.[0] && importSymbol?.declarations?.[0]) &&
62
+ nodeSymbol.declarations[0] === importSymbol.declarations[0]);
63
+ }
64
+
51
65
  /*!
52
66
  * @license
53
67
  * Copyright Google LLC All Rights Reserved.
@@ -73,6 +87,9 @@ class UniqueItemTracker {
73
87
  getEntries() {
74
88
  return this._nodes.entries();
75
89
  }
90
+ isEmpty() {
91
+ return this._nodes.size === 0;
92
+ }
76
93
  }
77
94
  /** Resolves references to nodes. */
78
95
  class ReferenceResolver {
@@ -294,19 +311,37 @@ function isClassReferenceInAngularModule(node, className, moduleName, typeChecke
294
311
  : className.test(closestClass.name.text);
295
312
  });
296
313
  }
297
-
298
- /** Checks whether a node is referring to a specific import specifier. */
299
- function isReferenceToImport(typeChecker, node, importSpecifier) {
300
- // If this function is called on an identifier (should be most cases), we can quickly rule out
301
- // non-matches by comparing the identifier's string and the local name of the import specifier
302
- // which saves us some calls to the type checker.
303
- if (ts__default["default"].isIdentifier(node) && node.text !== importSpecifier.name.text) {
304
- return false;
305
- }
306
- const nodeSymbol = typeChecker.getTypeAtLocation(node).getSymbol();
307
- const importSymbol = typeChecker.getTypeAtLocation(importSpecifier).getSymbol();
308
- return (!!(nodeSymbol?.declarations?.[0] && importSymbol?.declarations?.[0]) &&
309
- nodeSymbol.declarations[0] === importSymbol.declarations[0]);
314
+ /**
315
+ * Finds the imports of testing libraries in a file.
316
+ */
317
+ function getTestingImports(sourceFile) {
318
+ return {
319
+ testBed: imports.getImportSpecifier(sourceFile, '@angular/core/testing', 'TestBed'),
320
+ catalyst: imports.getImportSpecifier(sourceFile, /testing\/catalyst(\/(fake_)?async)?$/, 'setupModule'),
321
+ };
322
+ }
323
+ /**
324
+ * Determines if a node is a call to a testing API.
325
+ * @param typeChecker Type checker to use when resolving references.
326
+ * @param node Node to check.
327
+ * @param testBedImport Import of TestBed within the file.
328
+ * @param catalystImport Import of Catalyst within the file.
329
+ */
330
+ function isTestCall(typeChecker, node, testBedImport, catalystImport) {
331
+ const isObjectLiteralCall = ts__default["default"].isCallExpression(node) &&
332
+ node.arguments.length > 0 &&
333
+ // `arguments[0]` is the testing module config.
334
+ ts__default["default"].isObjectLiteralExpression(node.arguments[0]);
335
+ const isTestBedCall = isObjectLiteralCall &&
336
+ testBedImport &&
337
+ ts__default["default"].isPropertyAccessExpression(node.expression) &&
338
+ node.expression.name.text === 'configureTestingModule' &&
339
+ isReferenceToImport(typeChecker, node.expression.expression, testBedImport);
340
+ const isCatalystCall = isObjectLiteralCall &&
341
+ catalystImport &&
342
+ ts__default["default"].isIdentifier(node.expression) &&
343
+ isReferenceToImport(typeChecker, node.expression, catalystImport);
344
+ return !!(isTestBedCall || isCatalystCall);
310
345
  }
311
346
 
312
347
  /*!
@@ -322,10 +357,10 @@ function isReferenceToImport(typeChecker, node, importSpecifier) {
322
357
  * @param program
323
358
  * @param printer
324
359
  * @param fileImportRemapper Optional function that can be used to remap file-level imports.
325
- * @param componentImportRemapper Optional function that can be used to remap component-level
360
+ * @param declarationImportRemapper Optional function that can be used to remap declaration-level
326
361
  * imports.
327
362
  */
328
- function toStandalone(sourceFiles, program, printer, fileImportRemapper, componentImportRemapper) {
363
+ function toStandalone(sourceFiles, program, printer, fileImportRemapper, declarationImportRemapper) {
329
364
  const templateTypeChecker = program.compiler.getTemplateTypeChecker();
330
365
  const typeChecker = program.getTsProgram().getTypeChecker();
331
366
  const modulesToMigrate = new Set();
@@ -346,7 +381,7 @@ function toStandalone(sourceFiles, program, printer, fileImportRemapper, compone
346
381
  testObjects.forEach((obj) => testObjectsToMigrate.add(obj));
347
382
  }
348
383
  for (const declaration of declarations) {
349
- convertNgModuleDeclarationToStandalone(declaration, declarations, tracker, templateTypeChecker, componentImportRemapper);
384
+ convertNgModuleDeclarationToStandalone(declaration, declarations, tracker, templateTypeChecker, declarationImportRemapper);
350
385
  }
351
386
  for (const node of modulesToMigrate) {
352
387
  migrateNgModuleClass(node, declarations, tracker, typeChecker, templateTypeChecker);
@@ -408,7 +443,7 @@ function getComponentImportExpressions(decl, allDeclarations, tracker, typeCheck
408
443
  resolvedDependencies.push(importLocation);
409
444
  }
410
445
  }
411
- return potentialImportsToExpressions(resolvedDependencies, decl, tracker, importRemapper);
446
+ return potentialImportsToExpressions(resolvedDependencies, decl.getSourceFile(), tracker, importRemapper);
412
447
  }
413
448
  /**
414
449
  * Converts an array of potential imports to an array of expressions that can be
@@ -418,19 +453,19 @@ function getComponentImportExpressions(decl, allDeclarations, tracker, typeCheck
418
453
  * @param tracker
419
454
  * @param importRemapper
420
455
  */
421
- function potentialImportsToExpressions(potentialImports, component, tracker, importRemapper) {
456
+ function potentialImportsToExpressions(potentialImports, toFile, tracker, importRemapper) {
422
457
  const processedDependencies = importRemapper
423
- ? importRemapper(potentialImports, component)
458
+ ? importRemapper(potentialImports)
424
459
  : potentialImports;
425
460
  return processedDependencies.map((importLocation) => {
426
461
  if (importLocation.moduleSpecifier) {
427
- return tracker.addImport(component.getSourceFile(), importLocation.symbolName, importLocation.moduleSpecifier);
462
+ return tracker.addImport(toFile, importLocation.symbolName, importLocation.moduleSpecifier);
428
463
  }
429
464
  const identifier = ts__default["default"].factory.createIdentifier(importLocation.symbolName);
430
465
  if (!importLocation.isForwardReference) {
431
466
  return identifier;
432
467
  }
433
- const forwardRefExpression = tracker.addImport(component.getSourceFile(), 'forwardRef', '@angular/core');
468
+ const forwardRefExpression = tracker.addImport(toFile, 'forwardRef', '@angular/core');
434
469
  const arrowFunction = ts__default["default"].factory.createArrowFunction(undefined, undefined, [], undefined, undefined, identifier);
435
470
  return ts__default["default"].factory.createCallExpression(forwardRefExpression, undefined, [arrowFunction]);
436
471
  });
@@ -611,12 +646,12 @@ function isNamedPropertyAssignment(node) {
611
646
  /**
612
647
  * Finds the import from which to bring in a template dependency of a component.
613
648
  * @param target Dependency that we're searching for.
614
- * @param inComponent Component in which the dependency is used.
649
+ * @param inContext Component in which the dependency is used.
615
650
  * @param importMode Mode in which to resolve the import target.
616
651
  * @param typeChecker
617
652
  */
618
- function findImportLocation(target, inComponent, importMode, typeChecker) {
619
- const importLocations = typeChecker.getPotentialImportsFor(target, inComponent, importMode);
653
+ function findImportLocation(target, inContext, importMode, typeChecker) {
654
+ const importLocations = typeChecker.getPotentialImportsFor(target, inContext, importMode);
620
655
  let firstSameFileImport = null;
621
656
  let firstModuleImport = null;
622
657
  for (const location of importLocations) {
@@ -669,25 +704,11 @@ function findNgModuleClassesToMigrate(sourceFile, typeChecker) {
669
704
  /** Finds all testing object literals that need to be migrated. */
670
705
  function findTestObjectsToMigrate(sourceFile, typeChecker) {
671
706
  const testObjects = [];
672
- const testBedImport = imports.getImportSpecifier(sourceFile, '@angular/core/testing', 'TestBed');
673
- const catalystImport = imports.getImportSpecifier(sourceFile, /testing\/catalyst$/, 'setupModule');
674
- if (testBedImport || catalystImport) {
707
+ const { testBed, catalyst } = getTestingImports(sourceFile);
708
+ if (testBed || catalyst) {
675
709
  sourceFile.forEachChild(function walk(node) {
676
- const isObjectLiteralCall = ts__default["default"].isCallExpression(node) &&
677
- node.arguments.length > 0 &&
678
- // `arguments[0]` is the testing module config.
679
- ts__default["default"].isObjectLiteralExpression(node.arguments[0]);
680
- const config = isObjectLiteralCall ? node.arguments[0] : null;
681
- const isTestBedCall = isObjectLiteralCall &&
682
- testBedImport &&
683
- ts__default["default"].isPropertyAccessExpression(node.expression) &&
684
- node.expression.name.text === 'configureTestingModule' &&
685
- isReferenceToImport(typeChecker, node.expression.expression, testBedImport);
686
- const isCatalystCall = isObjectLiteralCall &&
687
- catalystImport &&
688
- ts__default["default"].isIdentifier(node.expression) &&
689
- isReferenceToImport(typeChecker, node.expression, catalystImport);
690
- if ((isTestBedCall || isCatalystCall) && config) {
710
+ if (isTestCall(typeChecker, node, testBed, catalyst)) {
711
+ const config = node.arguments[0];
691
712
  const declarations = findLiteralProperty(config, 'declarations');
692
713
  if (declarations &&
693
714
  ts__default["default"].isPropertyAssignment(declarations) &&
@@ -922,7 +943,7 @@ function isStandaloneDeclaration(node, declarationsInMigration, templateTypeChec
922
943
  * Use of this source code is governed by an MIT-style license that can be
923
944
  * found in the LICENSE file at https://angular.dev/license
924
945
  */
925
- function pruneNgModules(program, host, basePath, rootFileNames, sourceFiles, printer, importRemapper, referenceLookupExcludedFiles, componentImportRemapper) {
946
+ function pruneNgModules(program, host, basePath, rootFileNames, sourceFiles, printer, importRemapper, referenceLookupExcludedFiles, declarationImportRemapper) {
926
947
  const filesToRemove = new Set();
927
948
  const tracker = new compiler_host.ChangeTracker(printer, importRemapper);
928
949
  const tsProgram = program.getTsProgram();
@@ -938,10 +959,11 @@ function pruneNgModules(program, host, basePath, rootFileNames, sourceFiles, pri
938
959
  const classesToRemove = new Set();
939
960
  const barrelExports = new UniqueItemTracker();
940
961
  const componentImportArrays = new UniqueItemTracker();
962
+ const testArrays = new UniqueItemTracker();
941
963
  const nodesToRemove = new Set();
942
964
  sourceFiles.forEach(function walk(node) {
943
965
  if (ts__default["default"].isClassDeclaration(node) && canRemoveClass(node, typeChecker)) {
944
- collectChangeLocations(node, removalLocations, componentImportArrays, templateTypeChecker, referenceResolver, program);
966
+ collectChangeLocations(node, removalLocations, componentImportArrays, testArrays, templateTypeChecker, referenceResolver, program);
945
967
  classesToRemove.add(node);
946
968
  }
947
969
  else if (ts__default["default"].isExportDeclaration(node) &&
@@ -958,7 +980,8 @@ function pruneNgModules(program, host, basePath, rootFileNames, sourceFiles, pri
958
980
  }
959
981
  node.forEachChild(walk);
960
982
  });
961
- replaceInImportsArray(componentImportArrays, classesToRemove, tracker, typeChecker, templateTypeChecker, componentImportRemapper);
983
+ replaceInComponentImportsArray(componentImportArrays, classesToRemove, tracker, typeChecker, templateTypeChecker, declarationImportRemapper);
984
+ replaceInTestImportsArray(testArrays, removalLocations, classesToRemove, tracker, typeChecker, templateTypeChecker, declarationImportRemapper);
962
985
  // We collect all the places where we need to remove references first before generating the
963
986
  // removal instructions since we may have to remove multiple references from one node.
964
987
  removeArrayReferences(removalLocations.arrays, tracker);
@@ -997,12 +1020,14 @@ function pruneNgModules(program, host, basePath, rootFileNames, sourceFiles, pri
997
1020
  * @param ngModule Module being removed.
998
1021
  * @param removalLocations Tracks the different places from which the class should be removed.
999
1022
  * @param componentImportArrays Set of `imports` arrays of components that need to be adjusted.
1023
+ * @param testImportArrays Set of `imports` arrays of tests that need to be adjusted.
1000
1024
  * @param referenceResolver
1001
1025
  * @param program
1002
1026
  */
1003
- function collectChangeLocations(ngModule, removalLocations, componentImportArrays, templateTypeChecker, referenceResolver, program) {
1027
+ function collectChangeLocations(ngModule, removalLocations, componentImportArrays, testImportArrays, templateTypeChecker, referenceResolver, program) {
1004
1028
  const refsByFile = referenceResolver.findReferencesInProject(ngModule.name);
1005
1029
  const tsProgram = program.getTsProgram();
1030
+ const typeChecker = tsProgram.getTypeChecker();
1006
1031
  const nodes$1 = new Set();
1007
1032
  for (const [fileName, refs] of refsByFile) {
1008
1033
  const sourceFile = tsProgram.getSourceFile(fileName);
@@ -1014,20 +1039,31 @@ function collectChangeLocations(ngModule, removalLocations, componentImportArray
1014
1039
  const closestArray = nodes.closestNode(node, ts__default["default"].isArrayLiteralExpression);
1015
1040
  if (closestArray) {
1016
1041
  const closestAssignment = nodes.closestNode(closestArray, ts__default["default"].isPropertyAssignment);
1017
- // If the module was flagged as being removable, but it's still being used in a standalone
1018
- // component's `imports` array, it means that it was likely changed outside of the migration
1019
- // and deleting it now will be breaking. Track it separately so it can be handled properly.
1020
1042
  if (closestAssignment && isInImportsArray(closestAssignment, closestArray)) {
1021
- const closestDecorator = nodes.closestNode(closestAssignment, ts__default["default"].isDecorator);
1022
- const closestClass = closestDecorator
1023
- ? nodes.closestNode(closestDecorator, ts__default["default"].isClassDeclaration)
1024
- : null;
1025
- const directiveMeta = closestClass
1026
- ? templateTypeChecker.getDirectiveMetadata(closestClass)
1027
- : null;
1028
- if (directiveMeta && directiveMeta.isComponent && directiveMeta.isStandalone) {
1029
- componentImportArrays.track(closestArray, node);
1030
- continue;
1043
+ const closestCall = nodes.closestNode(closestAssignment, ts__default["default"].isCallExpression);
1044
+ if (closestCall) {
1045
+ const closestDecorator = nodes.closestNode(closestCall, ts__default["default"].isDecorator);
1046
+ const closestClass = closestDecorator
1047
+ ? nodes.closestNode(closestDecorator, ts__default["default"].isClassDeclaration)
1048
+ : null;
1049
+ const directiveMeta = closestClass
1050
+ ? templateTypeChecker.getDirectiveMetadata(closestClass)
1051
+ : null;
1052
+ // If the module was flagged as being removable, but it's still being used in a
1053
+ // standalone component's `imports` array, it means that it was likely changed
1054
+ // outside of the migration and deleting it now will be breaking. Track it
1055
+ // separately so it can be handled properly.
1056
+ if (directiveMeta && directiveMeta.isComponent && directiveMeta.isStandalone) {
1057
+ componentImportArrays.track(closestArray, node);
1058
+ continue;
1059
+ }
1060
+ // If the module is removable and used inside a test's `imports`,
1061
+ // we track it separately so it can be replaced with its `exports`.
1062
+ const { testBed, catalyst } = getTestingImports(node.getSourceFile());
1063
+ if (isTestCall(typeChecker, closestCall, testBed, catalyst)) {
1064
+ testImportArrays.track(closestArray, node);
1065
+ continue;
1066
+ }
1031
1067
  }
1032
1068
  }
1033
1069
  removalLocations.arrays.track(closestArray, node);
@@ -1047,7 +1083,7 @@ function collectChangeLocations(ngModule, removalLocations, componentImportArray
1047
1083
  }
1048
1084
  }
1049
1085
  /**
1050
- * Replaces all the leftover modules in imports arrays with their exports.
1086
+ * Replaces all the leftover modules in component `imports` arrays with their exports.
1051
1087
  * @param componentImportArrays All the imports arrays and their nodes that represent NgModules.
1052
1088
  * @param classesToRemove Set of classes that were marked for removal.
1053
1089
  * @param tracker
@@ -1055,7 +1091,7 @@ function collectChangeLocations(ngModule, removalLocations, componentImportArray
1055
1091
  * @param templateTypeChecker
1056
1092
  * @param importRemapper
1057
1093
  */
1058
- function replaceInImportsArray(componentImportArrays, classesToRemove, tracker, typeChecker, templateTypeChecker, importRemapper) {
1094
+ function replaceInComponentImportsArray(componentImportArrays, classesToRemove, tracker, typeChecker, templateTypeChecker, importRemapper) {
1059
1095
  for (const [array, toReplace] of componentImportArrays.getEntries()) {
1060
1096
  const closestClass = nodes.closestNode(array, ts__default["default"].isClassDeclaration);
1061
1097
  if (!closestClass) {
@@ -1081,21 +1117,65 @@ function replaceInImportsArray(componentImportArrays, classesToRemove, tracker,
1081
1117
  }
1082
1118
  }
1083
1119
  }
1084
- replaceModulesInImportsArray(array, closestClass, replacements, tracker, templateTypeChecker, importRemapper);
1120
+ replaceModulesInImportsArray(array, replacements, tracker, templateTypeChecker, importRemapper);
1121
+ }
1122
+ }
1123
+ /**
1124
+ * Replaces all the leftover modules in testing `imports` arrays with their exports.
1125
+ * @param testImportArrays All test `imports` arrays and their nodes that represent modules.
1126
+ * @param classesToRemove Classes marked for removal by the migration.
1127
+ * @param tracker
1128
+ * @param typeChecker
1129
+ * @param templateTypeChecker
1130
+ * @param importRemapper
1131
+ */
1132
+ function replaceInTestImportsArray(testImportArrays, removalLocations, classesToRemove, tracker, typeChecker, templateTypeChecker, importRemapper) {
1133
+ for (const [array, toReplace] of testImportArrays.getEntries()) {
1134
+ const replacements = new UniqueItemTracker();
1135
+ for (const node of toReplace) {
1136
+ const moduleDecl = findClassDeclaration(node, typeChecker);
1137
+ if (moduleDecl) {
1138
+ const moduleMeta = templateTypeChecker.getNgModuleMetadata(moduleDecl);
1139
+ if (moduleMeta) {
1140
+ // Since we don't have access to the template type checker in tests,
1141
+ // we copy over all the `exports` that aren't flagged for removal.
1142
+ const exports = moduleMeta.exports.filter((exp) => !classesToRemove.has(exp.node));
1143
+ if (exports.length > 0) {
1144
+ exports.forEach((exp) => replacements.track(node, exp));
1145
+ }
1146
+ else {
1147
+ removalLocations.arrays.track(array, node);
1148
+ }
1149
+ }
1150
+ else {
1151
+ // It's unlikely not to have module metadata at this point, but just in
1152
+ // case unmark the class for removal to reduce the chance of breakages.
1153
+ classesToRemove.delete(moduleDecl);
1154
+ }
1155
+ }
1156
+ }
1157
+ replaceModulesInImportsArray(array, replacements, tracker, templateTypeChecker, importRemapper);
1085
1158
  }
1086
1159
  }
1087
1160
  /**
1088
- * Replaces any leftover modules in `imports` arrays with their exports that are used within a
1089
- * component.
1161
+ * Replaces any leftover modules in an `imports` arrays with a set of specified exports
1090
1162
  * @param array Imports array which is being migrated.
1091
- * @param componentClass Class that the imports array belongs to.
1092
1163
  * @param replacements Map of NgModule references to their exports.
1093
1164
  * @param tracker
1094
1165
  * @param templateTypeChecker
1095
1166
  * @param importRemapper
1096
1167
  */
1097
- function replaceModulesInImportsArray(array, componentClass, replacements, tracker, templateTypeChecker, importRemapper) {
1168
+ function replaceModulesInImportsArray(array, replacements, tracker, templateTypeChecker, importRemapper) {
1169
+ if (replacements.isEmpty()) {
1170
+ return;
1171
+ }
1098
1172
  const newElements = [];
1173
+ const identifiers = new Set();
1174
+ for (const element of array.elements) {
1175
+ if (ts__default["default"].isIdentifier(element)) {
1176
+ identifiers.add(element.text);
1177
+ }
1178
+ }
1099
1179
  for (const element of array.elements) {
1100
1180
  const replacementRefs = replacements.get(element);
1101
1181
  if (!replacementRefs) {
@@ -1104,12 +1184,16 @@ function replaceModulesInImportsArray(array, componentClass, replacements, track
1104
1184
  }
1105
1185
  const potentialImports = [];
1106
1186
  for (const ref of replacementRefs) {
1107
- const importLocation = findImportLocation(ref, componentClass, checker.PotentialImportMode.Normal, templateTypeChecker);
1187
+ const importLocation = findImportLocation(ref, array, checker.PotentialImportMode.Normal, templateTypeChecker);
1108
1188
  if (importLocation) {
1109
1189
  potentialImports.push(importLocation);
1110
1190
  }
1111
1191
  }
1112
- newElements.push(...potentialImportsToExpressions(potentialImports, componentClass, tracker, importRemapper));
1192
+ potentialImportsToExpressions(potentialImports, array.getSourceFile(), tracker, importRemapper).forEach((expr) => {
1193
+ if (!ts__default["default"].isIdentifier(expr) || !identifiers.has(expr.text)) {
1194
+ newElements.push(expr);
1195
+ }
1196
+ });
1113
1197
  }
1114
1198
  tracker.replaceNode(array, ts__default["default"].factory.updateArrayLiteralExpression(array, newElements));
1115
1199
  }
@@ -1344,7 +1428,7 @@ function isInImportsArray(closestAssignment, closestArray) {
1344
1428
  * Use of this source code is governed by an MIT-style license that can be
1345
1429
  * found in the LICENSE file at https://angular.dev/license
1346
1430
  */
1347
- function toStandaloneBootstrap(program, host, basePath, rootFileNames, sourceFiles, printer, importRemapper, referenceLookupExcludedFiles, componentImportRemapper) {
1431
+ function toStandaloneBootstrap(program, host, basePath, rootFileNames, sourceFiles, printer, importRemapper, referenceLookupExcludedFiles, declarationImportRemapper) {
1348
1432
  const tracker = new compiler_host.ChangeTracker(printer, importRemapper);
1349
1433
  const typeChecker = program.getTsProgram().getTypeChecker();
1350
1434
  const templateTypeChecker = program.compiler.getTemplateTypeChecker();
@@ -1379,7 +1463,7 @@ function toStandaloneBootstrap(program, host, basePath, rootFileNames, sourceFil
1379
1463
  // The previous migrations explicitly skip over bootstrapped
1380
1464
  // declarations so we have to migrate them now.
1381
1465
  for (const declaration of allDeclarations) {
1382
- convertNgModuleDeclarationToStandalone(declaration, allDeclarations, tracker, templateTypeChecker, componentImportRemapper);
1466
+ convertNgModuleDeclarationToStandalone(declaration, allDeclarations, tracker, templateTypeChecker, declarationImportRemapper);
1383
1467
  }
1384
1468
  migrateTestDeclarations(testObjects, allDeclarations, tracker, templateTypeChecker, typeChecker);
1385
1469
  return tracker.recordChanges();
@@ -8,6 +8,7 @@
8
8
  "type": "array",
9
9
  "default": [
10
10
  "inputs",
11
+ "outputs",
11
12
  "queries"
12
13
  ],
13
14
  "items": {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v19.0.0-rc.1
2
+ * @license Angular v19.0.0-rc.3
3
3
  * (c) 2010-2024 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */