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

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 (39) hide show
  1. package/fesm2022/core.mjs +201 -349
  2. package/fesm2022/core.mjs.map +1 -1
  3. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  4. package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
  5. package/fesm2022/primitives/signals.mjs +1 -1
  6. package/fesm2022/primitives/signals.mjs.map +1 -1
  7. package/fesm2022/rxjs-interop.mjs +1 -1
  8. package/fesm2022/rxjs-interop.mjs.map +1 -1
  9. package/fesm2022/testing.mjs +6 -6
  10. package/fesm2022/testing.mjs.map +1 -1
  11. package/index.d.ts +16 -51
  12. package/package.json +1 -1
  13. package/primitives/event-dispatch/index.d.ts +1 -1
  14. package/primitives/signals/index.d.ts +1 -1
  15. package/rxjs-interop/index.d.ts +1 -1
  16. package/schematics/bundles/{checker-2451e7c5.js → checker-9ca42e51.js} +163 -150
  17. package/schematics/bundles/combine_units-a16385aa.js +1634 -0
  18. package/schematics/bundles/{compiler_host-f54f8309.js → compiler_host-31afa4ed.js} +8 -5
  19. package/schematics/bundles/control-flow-migration.js +3 -3
  20. package/schematics/bundles/explicit-standalone-flag.js +5 -5
  21. package/schematics/bundles/{imports-44987700.js → imports-4ac08251.js} +1 -1
  22. package/schematics/bundles/inject-migration.js +131 -37
  23. package/schematics/bundles/{leading_space-6e7a8ec6.js → leading_space-d190b83b.js} +1 -1
  24. package/schematics/bundles/{migrate_ts_type_references-ab18a7c3.js → migrate_ts_type_references-b2a28742.js} +5 -5
  25. package/schematics/bundles/{ng_decorators-3ad437d2.js → nodes-0e7d45ca.js} +15 -2
  26. package/schematics/bundles/output-migration.js +20 -6895
  27. package/schematics/bundles/pending-tasks.js +5 -5
  28. package/schematics/bundles/{program-58424797.js → program-71beec0b.js} +109 -42
  29. package/schematics/bundles/{project_tsconfig_paths-6c9cde78.js → project_tsconfig_paths-e9ccccbf.js} +1 -1
  30. package/schematics/bundles/provide-initializer.js +17 -28
  31. package/schematics/bundles/route-lazy-loading.js +10 -5
  32. package/schematics/bundles/signal-input-migration.js +7 -7
  33. package/schematics/bundles/signal-queries-migration.js +12 -12
  34. package/schematics/bundles/signals.js +7 -7
  35. package/schematics/bundles/standalone-migration.js +13 -14
  36. package/schematics/migrations.json +1 -1
  37. package/testing/index.d.ts +1 -1
  38. package/schematics/bundles/combine_units-c52492ab.js +0 -31202
  39. package/schematics/bundles/nodes-ffdce442.js +0 -27
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.0
3
+ * @license Angular v19.0.0-rc.1
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
7
7
  'use strict';
8
8
 
9
9
  var ts = require('typescript');
10
- var checker = require('./checker-2451e7c5.js');
10
+ var checker = require('./checker-9ca42e51.js');
11
11
  require('os');
12
12
  var p = require('path');
13
13
 
@@ -83,11 +83,14 @@ class ChangeTracker {
83
83
  /**
84
84
  * Removes the text of an AST node from a file.
85
85
  * @param node Node whose text should be removed.
86
+ * @param useFullOffsets Whether to remove the node using its full offset (e.g. `getFullStart`
87
+ * rather than `fullStart`). This has the advantage of removing any comments that may be tied
88
+ * to the node, but can lead to too much code being deleted.
86
89
  */
87
- removeNode(node) {
90
+ removeNode(node, useFullOffsets = false) {
88
91
  this._trackChange(node.getSourceFile(), {
89
- start: node.getStart(),
90
- removeLength: node.getWidth(),
92
+ start: useFullOffsets ? node.getFullStart() : node.getStart(),
93
+ removeLength: useFullOffsets ? node.getFullWidth() : node.getWidth(),
91
94
  text: '',
92
95
  });
93
96
  }
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.0
3
+ * @license Angular v19.0.0-rc.1
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -10,8 +10,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
10
10
 
11
11
  var schematics = require('@angular-devkit/schematics');
12
12
  var p = require('path');
13
- var compiler_host = require('./compiler_host-f54f8309.js');
14
- var checker = require('./checker-2451e7c5.js');
13
+ var compiler_host = require('./compiler_host-31afa4ed.js');
14
+ var checker = require('./checker-9ca42e51.js');
15
15
  var ts = require('typescript');
16
16
  require('os');
17
17
  require('fs');
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.0
3
+ * @license Angular v19.0.0-rc.1
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -10,12 +10,12 @@ Object.defineProperty(exports, '__esModule', { value: true });
10
10
 
11
11
  var schematics = require('@angular-devkit/schematics');
12
12
  var p = require('path');
13
- var project_tsconfig_paths = require('./project_tsconfig_paths-6c9cde78.js');
14
- var compiler_host = require('./compiler_host-f54f8309.js');
13
+ var project_tsconfig_paths = require('./project_tsconfig_paths-e9ccccbf.js');
14
+ var compiler_host = require('./compiler_host-31afa4ed.js');
15
15
  var ts = require('typescript');
16
- var imports = require('./imports-44987700.js');
16
+ var imports = require('./imports-4ac08251.js');
17
17
  require('@angular-devkit/core');
18
- require('./checker-2451e7c5.js');
18
+ require('./checker-9ca42e51.js');
19
19
  require('os');
20
20
  require('fs');
21
21
  require('module');
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.0
3
+ * @license Angular v19.0.0-rc.1
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.0
3
+ * @license Angular v19.0.0-rc.1
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -10,13 +10,12 @@ Object.defineProperty(exports, '__esModule', { value: true });
10
10
 
11
11
  var schematics = require('@angular-devkit/schematics');
12
12
  var p = require('path');
13
- var compiler_host = require('./compiler_host-f54f8309.js');
13
+ var compiler_host = require('./compiler_host-31afa4ed.js');
14
14
  var ts = require('typescript');
15
- var ng_decorators = require('./ng_decorators-3ad437d2.js');
16
- var imports = require('./imports-44987700.js');
17
- var nodes = require('./nodes-ffdce442.js');
18
- var leading_space = require('./leading_space-6e7a8ec6.js');
19
- require('./checker-2451e7c5.js');
15
+ var nodes = require('./nodes-0e7d45ca.js');
16
+ var imports = require('./imports-4ac08251.js');
17
+ var leading_space = require('./leading_space-d190b83b.js');
18
+ require('./checker-9ca42e51.js');
20
19
  require('os');
21
20
  require('fs');
22
21
  require('module');
@@ -56,7 +55,7 @@ const DI_PARAM_SYMBOLS = new Set([
56
55
  * @param sourceFile File which to analyze.
57
56
  * @param localTypeChecker Type checker scoped to the specific file.
58
57
  */
59
- function analyzeFile(sourceFile, localTypeChecker) {
58
+ function analyzeFile(sourceFile, localTypeChecker, options) {
60
59
  const coreSpecifiers = imports.getNamedImports(sourceFile, '@angular/core');
61
60
  // Exit early if there are no Angular imports.
62
61
  if (coreSpecifiers === null || coreSpecifiers.elements.length === 0) {
@@ -106,12 +105,15 @@ function analyzeFile(sourceFile, localTypeChecker) {
106
105
  }
107
106
  }
108
107
  else if (ts__default["default"].isClassDeclaration(node)) {
109
- const decorators = ng_decorators.getAngularDecorators(localTypeChecker, ts__default["default"].getDecorators(node) || []);
108
+ const decorators = nodes.getAngularDecorators(localTypeChecker, ts__default["default"].getDecorators(node) || []);
109
+ const isAbstract = !!node.modifiers?.some((m) => m.kind === ts__default["default"].SyntaxKind.AbstractKeyword);
110
110
  const supportsDI = decorators.some((dec) => DECORATORS_SUPPORTING_DI.has(dec.name));
111
111
  const constructorNode = node.members.find((member) => ts__default["default"].isConstructorDeclaration(member) &&
112
112
  member.body != null &&
113
113
  member.parameters.length > 0);
114
- if (supportsDI && constructorNode) {
114
+ // Don't migrate abstract classes by default, because
115
+ // their parameters aren't guaranteed to be injectable.
116
+ if (supportsDI && constructorNode && (!isAbstract || options.migrateAbstractClasses)) {
115
117
  classes.push({
116
118
  node,
117
119
  constructor: constructorNode,
@@ -308,8 +310,8 @@ function findUninitializedPropertiesToCombine(node, constructor, localTypeChecke
308
310
  if (memberInitializers.has(name)) {
309
311
  const initializer = memberInitializers.get(name);
310
312
  if (!hasLocalReferences(initializer, constructor, localTypeChecker)) {
311
- toCombine = toCombine || new Map();
312
- toCombine.set(membersToDeclarations.get(name), initializer);
313
+ toCombine ??= [];
314
+ toCombine.push({ declaration: membersToDeclarations.get(name), initializer });
313
315
  }
314
316
  }
315
317
  else {
@@ -333,6 +335,76 @@ function findUninitializedPropertiesToCombine(node, constructor, localTypeChecke
333
335
  // If no members need to be combined, none need to be hoisted either.
334
336
  return toCombine === null ? null : { toCombine, toHoist };
335
337
  }
338
+ /**
339
+ * In some cases properties may be declared out of order, but initialized in the correct order.
340
+ * The internal-specific migration will combine such properties which will result in a compilation
341
+ * error, for example:
342
+ *
343
+ * ```
344
+ * class MyClass {
345
+ * foo: Foo;
346
+ * bar: Bar;
347
+ *
348
+ * constructor(bar: Bar) {
349
+ * this.bar = bar;
350
+ * this.foo = this.bar.getFoo();
351
+ * }
352
+ * }
353
+ * ```
354
+ *
355
+ * Will become:
356
+ *
357
+ * ```
358
+ * class MyClass {
359
+ * foo: Foo = this.bar.getFoo();
360
+ * bar: Bar = inject(Bar);
361
+ * }
362
+ * ```
363
+ *
364
+ * This function determines if cases like this can be saved by reordering the properties so their
365
+ * declaration order matches the order in which they're initialized.
366
+ *
367
+ * @param toCombine Properties that are candidates to be combined.
368
+ * @param constructor
369
+ */
370
+ function shouldCombineInInitializationOrder(toCombine, constructor) {
371
+ let combinedMemberReferenceCount = 0;
372
+ let otherMemberReferenceCount = 0;
373
+ const injectedMemberNames = new Set();
374
+ const combinedMemberNames = new Set();
375
+ // Collect the name of constructor parameters that declare new properties.
376
+ // These can be ignored since they'll be hoisted above other properties.
377
+ constructor.parameters.forEach((param) => {
378
+ if (parameterDeclaresProperty(param) && ts__default["default"].isIdentifier(param.name)) {
379
+ injectedMemberNames.add(param.name.text);
380
+ }
381
+ });
382
+ // Collect the names of the properties being combined. We should only reorder
383
+ // the properties if at least one of them refers to another one.
384
+ toCombine.forEach(({ declaration: { name } }) => {
385
+ if (ts__default["default"].isStringLiteralLike(name) || ts__default["default"].isIdentifier(name)) {
386
+ combinedMemberNames.add(name.text);
387
+ }
388
+ });
389
+ // Visit all the initializers and check all the property reads in the form of `this.<name>`.
390
+ // Skip over the ones referring to injected parameters since they're going to be hoisted.
391
+ const walkInitializer = (node) => {
392
+ if (ts__default["default"].isPropertyAccessExpression(node) && node.expression.kind === ts__default["default"].SyntaxKind.ThisKeyword) {
393
+ if (combinedMemberNames.has(node.name.text)) {
394
+ combinedMemberReferenceCount++;
395
+ }
396
+ else if (!injectedMemberNames.has(node.name.text)) {
397
+ otherMemberReferenceCount++;
398
+ }
399
+ }
400
+ node.forEachChild(walkInitializer);
401
+ };
402
+ toCombine.forEach((candidate) => walkInitializer(candidate.initializer));
403
+ // If at the end there is at least one reference between a combined member and another,
404
+ // and there are no references to any other class members, we can safely reorder the
405
+ // properties based on how they were initialized.
406
+ return combinedMemberReferenceCount > 0 && otherMemberReferenceCount === 0;
407
+ }
336
408
  /**
337
409
  * Finds the expressions from the constructor that initialize class members, for example:
338
410
  *
@@ -460,7 +532,7 @@ function migrateFile(sourceFile, options) {
460
532
  // 2. All the necessary information for this migration is local so using a file-specific type
461
533
  // checker should speed up the lookups.
462
534
  const localTypeChecker = getLocalTypeChecker(sourceFile);
463
- const analysis = analyzeFile(sourceFile, localTypeChecker);
535
+ const analysis = analyzeFile(sourceFile, localTypeChecker, options);
464
536
  if (analysis === null || analysis.classes.length === 0) {
465
537
  return [];
466
538
  }
@@ -469,11 +541,13 @@ function migrateFile(sourceFile, options) {
469
541
  analysis.classes.forEach(({ node, constructor, superCall }) => {
470
542
  const memberIndentation = leading_space.getLeadingLineWhitespaceOfNode(node.members[0]);
471
543
  const prependToClass = [];
544
+ const afterInjectCalls = [];
472
545
  const removedStatements = new Set();
546
+ const removedMembers = new Set();
473
547
  if (options._internalCombineMemberInitializers) {
474
- applyInternalOnlyChanges(node, constructor, localTypeChecker, tracker, printer, removedStatements, prependToClass, memberIndentation);
548
+ applyInternalOnlyChanges(node, constructor, localTypeChecker, tracker, printer, removedStatements, removedMembers, prependToClass, afterInjectCalls, memberIndentation);
475
549
  }
476
- migrateClass(node, constructor, superCall, options, memberIndentation, prependToClass, removedStatements, localTypeChecker, printer, tracker);
550
+ migrateClass(node, constructor, superCall, options, memberIndentation, prependToClass, afterInjectCalls, removedStatements, removedMembers, localTypeChecker, printer, tracker);
477
551
  });
478
552
  DI_PARAM_SYMBOLS.forEach((name) => {
479
553
  // Both zero and undefined are fine here.
@@ -491,18 +565,14 @@ function migrateFile(sourceFile, options) {
491
565
  * @param options Options used to configure the migration.
492
566
  * @param memberIndentation Indentation string of the members of the class.
493
567
  * @param prependToClass Text that should be prepended to the class.
568
+ * @param afterInjectCalls Text that will be inserted after the newly-added `inject` calls.
494
569
  * @param removedStatements Statements that have been removed from the constructor already.
570
+ * @param removedMembers Class members that have been removed by the migration.
495
571
  * @param localTypeChecker Type checker set up for the specific file.
496
572
  * @param printer Printer used to output AST nodes as strings.
497
573
  * @param tracker Object keeping track of the changes made to the file.
498
574
  */
499
- function migrateClass(node, constructor, superCall, options, memberIndentation, prependToClass, removedStatements, localTypeChecker, printer, tracker) {
500
- const isAbstract = !!node.modifiers?.some((m) => m.kind === ts__default["default"].SyntaxKind.AbstractKeyword);
501
- // Don't migrate abstract classes by default, because
502
- // their parameters aren't guaranteed to be injectable.
503
- if (isAbstract && !options.migrateAbstractClasses) {
504
- return;
505
- }
575
+ function migrateClass(node, constructor, superCall, options, memberIndentation, prependToClass, afterInjectCalls, removedStatements, removedMembers, localTypeChecker, printer, tracker) {
506
576
  const sourceFile = node.getSourceFile();
507
577
  const unusedParameters = getConstructorUnusedParameters(constructor, localTypeChecker, removedStatements);
508
578
  const superParameters = superCall
@@ -514,7 +584,6 @@ function migrateClass(node, constructor, superCall, options, memberIndentation,
514
584
  const innerIndentation = leading_space.getLeadingLineWhitespaceOfNode(innerReference);
515
585
  const prependToConstructor = [];
516
586
  const afterSuper = [];
517
- const removedMembers = new Set();
518
587
  for (const param of constructor.parameters) {
519
588
  const usedInSuper = superParameters !== null && superParameters.has(param);
520
589
  const usedInConstructor = !unusedParameters.has(param);
@@ -525,13 +594,13 @@ function migrateClass(node, constructor, superCall, options, memberIndentation,
525
594
  for (const member of node.members) {
526
595
  if (ts__default["default"].isConstructorDeclaration(member) && member !== constructor) {
527
596
  removedMembers.add(member);
528
- tracker.replaceText(sourceFile, member.getFullStart(), member.getFullWidth(), '');
597
+ tracker.removeNode(member, true);
529
598
  }
530
599
  }
531
600
  if (canRemoveConstructor(options, constructor, removedStatementCount, superCall)) {
532
601
  // Drop the constructor if it was empty.
533
602
  removedMembers.add(constructor);
534
- tracker.replaceText(sourceFile, constructor.getFullStart(), constructor.getFullWidth(), '');
603
+ tracker.removeNode(constructor, true);
535
604
  }
536
605
  else {
537
606
  // If the constructor contains any statements, only remove the parameters.
@@ -564,6 +633,9 @@ function migrateClass(node, constructor, superCall, options, memberIndentation,
564
633
  tracker.insertText(sourceFile, constructor.getFullStart(), '\n' + extraSignature);
565
634
  }
566
635
  }
636
+ // Push the block of code that should appear after the `inject`
637
+ // calls now once all the members have been generated.
638
+ prependToClass.push(...afterInjectCalls);
567
639
  if (prependToClass.length > 0) {
568
640
  if (removedMembers.size === node.members.length) {
569
641
  tracker.insertText(sourceFile, constructor.getEnd() + 1, `${prependToClass.join('\n')}\n`);
@@ -654,7 +726,7 @@ function migrateParameter(node, options, localTypeChecker, printer, tracker, sup
654
726
  function createInjectReplacementCall(param, options, localTypeChecker, printer, tracker) {
655
727
  const moduleName = '@angular/core';
656
728
  const sourceFile = param.getSourceFile();
657
- const decorators = ng_decorators.getAngularDecorators(localTypeChecker, ts__default["default"].getDecorators(param) || []);
729
+ const decorators = nodes.getAngularDecorators(localTypeChecker, ts__default["default"].getDecorators(param) || []);
658
730
  const literalProps = [];
659
731
  const type = param.type;
660
732
  let injectedType = '';
@@ -927,24 +999,46 @@ function getNextPreservedStatement(startNode, removedStatements) {
927
999
  * @param tracker Object keeping track of the changes.
928
1000
  * @param printer Printer used to output AST nodes as text.
929
1001
  * @param removedStatements Statements that have been removed by the migration.
1002
+ * @param removedMembers Class members that have been removed by the migration.
930
1003
  * @param prependToClass Text that will be prepended to a class.
1004
+ * @param afterInjectCalls Text that will be inserted after the newly-added `inject` calls.
931
1005
  * @param memberIndentation Indentation string of the class' members.
932
1006
  */
933
- function applyInternalOnlyChanges(node, constructor, localTypeChecker, tracker, printer, removedStatements, prependToClass, memberIndentation) {
1007
+ function applyInternalOnlyChanges(node, constructor, localTypeChecker, tracker, printer, removedStatements, removedMembers, prependToClass, afterInjectCalls, memberIndentation) {
934
1008
  const result = findUninitializedPropertiesToCombine(node, constructor, localTypeChecker);
935
- result?.toCombine.forEach((initializer, property) => {
936
- const statement = nodes.closestNode(initializer, ts__default["default"].isStatement);
937
- if (!statement) {
938
- return;
1009
+ if (result === null) {
1010
+ return;
1011
+ }
1012
+ const preserveInitOrder = shouldCombineInInitializationOrder(result.toCombine, constructor);
1013
+ // Sort the combined members based on the declaration order of their initializers, only if
1014
+ // we've determined that would be safe. Note that `Array.prototype.sort` is in-place so we
1015
+ // can just call it conditionally here.
1016
+ if (preserveInitOrder) {
1017
+ result.toCombine.sort((a, b) => a.initializer.getStart() - b.initializer.getStart());
1018
+ }
1019
+ result.toCombine.forEach(({ declaration, initializer }) => {
1020
+ const initializerStatement = nodes.closestNode(initializer, ts__default["default"].isStatement);
1021
+ const newProperty = ts__default["default"].factory.createPropertyDeclaration(cloneModifiers(declaration.modifiers), cloneName(declaration.name), declaration.questionToken, declaration.type, initializer);
1022
+ // If the initialization order is being preserved, we have to remove the original
1023
+ // declaration and re-declare it. Otherwise we can do the replacement in-place.
1024
+ if (preserveInitOrder) {
1025
+ tracker.removeNode(declaration, true);
1026
+ removedMembers.add(declaration);
1027
+ afterInjectCalls.push(memberIndentation +
1028
+ printer.printNode(ts__default["default"].EmitHint.Unspecified, newProperty, declaration.getSourceFile()));
1029
+ }
1030
+ else {
1031
+ tracker.replaceNode(declaration, newProperty);
1032
+ }
1033
+ // This should always be defined, but null check it just in case.
1034
+ if (initializerStatement) {
1035
+ tracker.removeNode(initializerStatement, true);
1036
+ removedStatements.add(initializerStatement);
939
1037
  }
940
- const newProperty = ts__default["default"].factory.createPropertyDeclaration(cloneModifiers(property.modifiers), cloneName(property.name), property.questionToken, property.type, initializer);
941
- tracker.replaceText(statement.getSourceFile(), statement.getFullStart(), statement.getFullWidth(), '');
942
- tracker.replaceNode(property, newProperty);
943
- removedStatements.add(statement);
944
1038
  });
945
- result?.toHoist.forEach((decl) => {
1039
+ result.toHoist.forEach((decl) => {
946
1040
  prependToClass.push(memberIndentation + printer.printNode(ts__default["default"].EmitHint.Unspecified, decl, decl.getSourceFile()));
947
- tracker.replaceText(decl.getSourceFile(), decl.getFullStart(), decl.getFullWidth(), '');
1041
+ tracker.removeNode(decl, true);
948
1042
  });
949
1043
  // If we added any hoisted properties, separate them visually with a new line.
950
1044
  if (prependToClass.length > 0) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.0
3
+ * @license Angular v19.0.0-rc.1
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -1,18 +1,18 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.0
3
+ * @license Angular v19.0.0-rc.1
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
7
7
  'use strict';
8
8
 
9
- var checker = require('./checker-2451e7c5.js');
9
+ var checker = require('./checker-9ca42e51.js');
10
10
  var ts = require('typescript');
11
11
  require('os');
12
12
  var assert = require('assert');
13
- var combine_units = require('./combine_units-c52492ab.js');
14
- var leading_space = require('./leading_space-6e7a8ec6.js');
15
- require('./program-58424797.js');
13
+ var combine_units = require('./combine_units-a16385aa.js');
14
+ var leading_space = require('./leading_space-d190b83b.js');
15
+ require('./program-71beec0b.js');
16
16
  require('path');
17
17
 
18
18
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-rc.0
3
+ * @license Angular v19.0.0-rc.1
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
7
7
  'use strict';
8
8
 
9
9
  var ts = require('typescript');
10
- var imports = require('./imports-44987700.js');
10
+ var imports = require('./imports-4ac08251.js');
11
11
 
12
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
13
 
@@ -40,4 +40,17 @@ function getAngularDecorators(typeChecker, decorators) {
40
40
  }));
41
41
  }
42
42
 
43
+ /** Find the closest parent node of a particular kind. */
44
+ function closestNode(node, predicate) {
45
+ let current = node.parent;
46
+ while (current && !ts__default["default"].isSourceFile(current)) {
47
+ if (predicate(current)) {
48
+ return current;
49
+ }
50
+ current = current.parent;
51
+ }
52
+ return null;
53
+ }
54
+
55
+ exports.closestNode = closestNode;
43
56
  exports.getAngularDecorators = getAngularDecorators;