@angular/core 21.0.0-next.0 → 21.0.0-next.10
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.
- package/fesm2022/_attribute-chunk.mjs +12 -0
- package/fesm2022/_attribute-chunk.mjs.map +1 -0
- package/fesm2022/_debug_node-chunk.mjs +18469 -0
- package/fesm2022/_debug_node-chunk.mjs.map +1 -0
- package/fesm2022/_effect-chunk.mjs +423 -0
- package/fesm2022/_effect-chunk.mjs.map +1 -0
- package/fesm2022/_effect-chunk2.mjs +2951 -0
- package/fesm2022/_effect-chunk2.mjs.map +1 -0
- package/fesm2022/_not_found-chunk.mjs +39 -0
- package/fesm2022/_not_found-chunk.mjs.map +1 -0
- package/fesm2022/_resource-chunk.mjs +378 -0
- package/fesm2022/_resource-chunk.mjs.map +1 -0
- package/fesm2022/_untracked-chunk.mjs +96 -0
- package/fesm2022/_untracked-chunk.mjs.map +1 -0
- package/fesm2022/_weak_ref-chunk.mjs +10 -0
- package/fesm2022/_weak_ref-chunk.mjs.map +1 -0
- package/fesm2022/core.mjs +2499 -4185
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives-di.mjs +23 -0
- package/fesm2022/primitives-di.mjs.map +1 -0
- package/fesm2022/primitives-event-dispatch.mjs +788 -0
- package/fesm2022/primitives-event-dispatch.mjs.map +1 -0
- package/fesm2022/primitives-signals.mjs +187 -0
- package/fesm2022/primitives-signals.mjs.map +1 -0
- package/fesm2022/rxjs-interop.mjs +210 -308
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/testing.mjs +2309 -3170
- package/fesm2022/testing.mjs.map +1 -1
- package/package.json +18 -12
- package/resources/best-practices.md +56 -0
- package/schematics/bundles/add-bootstrap-context-to-server-main.cjs +117 -0
- package/schematics/bundles/application-config-core.cjs +84 -0
- package/schematics/bundles/{apply_import_manager-DR9xXCle.cjs → apply_import_manager-1Zs_gpB6.cjs} +4 -5
- package/schematics/bundles/bootstrap-options-migration.cjs +598 -0
- package/schematics/bundles/cleanup-unused-imports.cjs +9 -13
- package/schematics/bundles/common-to-standalone-migration.cjs +381 -0
- package/schematics/bundles/{compiler_host-BXBP7CE2.cjs → compiler_host-DBwYMlTo.cjs} +10 -11
- package/schematics/bundles/control-flow-migration.cjs +122 -119
- package/schematics/bundles/{imports-CIX-JgAN.cjs → imports-DP72APSx.cjs} +6 -1
- package/schematics/bundles/{index-CfTQUOiz.cjs → index-B7I9sIUx.cjs} +36 -39
- package/schematics/bundles/inject-migration.cjs +148 -70
- package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
- package/schematics/bundles/{migrate_ts_type_references-6NtAj-Wk.cjs → migrate_ts_type_references-UGIUl7En.cjs} +500 -24
- package/schematics/bundles/ng_component_template-Dsuq1Lw7.cjs +185 -0
- package/schematics/bundles/{ng_decorators-B5HCqr20.cjs → ng_decorators-DSFlWYQY.cjs} +2 -2
- package/schematics/bundles/ngclass-to-class-migration.cjs +542 -0
- package/schematics/bundles/ngstyle-to-style-migration.cjs +487 -0
- package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
- package/schematics/bundles/output-migration.cjs +16 -19
- package/schematics/bundles/parse_html-8VLCL37B.cjs +132 -0
- package/schematics/bundles/{project_paths-DcaODbky.cjs → project_paths-DvD50ouC.cjs} +14 -247
- package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +90 -0
- package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
- package/schematics/bundles/route-lazy-loading.cjs +54 -26
- package/schematics/bundles/router-current-navigation.cjs +7 -18
- package/schematics/bundles/router-last-successful-navigation.cjs +7 -18
- package/schematics/bundles/router-testing-module-migration.cjs +502 -0
- package/schematics/bundles/self-closing-tags-migration.cjs +17 -216
- package/schematics/bundles/signal-input-migration.cjs +93 -29
- package/schematics/bundles/signal-queries-migration.cjs +22 -25
- package/schematics/bundles/signals.cjs +10 -13
- package/schematics/bundles/standalone-migration.cjs +135 -102
- package/schematics/bundles/{symbol-VPWguRxr.cjs → symbol-BObKoqes.cjs} +3 -2
- package/schematics/collection.json +23 -0
- package/schematics/migrations/common-to-standalone-migration/schema.json +14 -0
- package/schematics/migrations/ngclass-to-class-migration/schema.json +20 -0
- package/schematics/migrations/ngstyle-to-style-migration/schema.json +20 -0
- package/schematics/migrations/router-testing-module-migration/schema.json +14 -0
- package/schematics/migrations.json +16 -2
- package/{api.d.d.ts → types/_api-chunk.d.ts} +9 -6
- package/{chrome_dev_tools_performance.d.d.ts → types/_chrome_dev_tools_performance-chunk.d.ts} +26 -31
- package/{discovery.d.d.ts → types/_discovery-chunk.d.ts} +135 -98
- package/{signal.d.d.ts → types/_effect-chunk.d.ts} +14 -5
- package/{event_dispatcher.d.d.ts → types/_event_dispatcher-chunk.d.ts} +2 -2
- package/{graph.d.d.ts → types/_formatter-chunk.d.ts} +40 -7
- package/{weak_ref.d.d.ts → types/_weak_ref-chunk.d.ts} +2 -2
- package/{index.d.ts → types/core.d.ts} +233 -305
- package/{primitives/di/index.d.ts → types/primitives-di.d.ts} +2 -2
- package/{primitives/event-dispatch/index.d.ts → types/primitives-event-dispatch.d.ts} +4 -4
- package/{primitives/signals/index.d.ts → types/primitives-signals.d.ts} +7 -8
- package/{rxjs-interop/index.d.ts → types/rxjs-interop.d.ts} +8 -6
- package/{testing/index.d.ts → types/testing.d.ts} +7 -7
- package/fesm2022/attribute.mjs +0 -24
- package/fesm2022/attribute.mjs.map +0 -1
- package/fesm2022/debug_node.mjs +0 -31833
- package/fesm2022/debug_node.mjs.map +0 -1
- package/fesm2022/not_found.mjs +0 -56
- package/fesm2022/not_found.mjs.map +0 -1
- package/fesm2022/primitives/di.mjs +0 -23
- package/fesm2022/primitives/di.mjs.map +0 -1
- package/fesm2022/primitives/event-dispatch.mjs +0 -1622
- package/fesm2022/primitives/event-dispatch.mjs.map +0 -1
- package/fesm2022/primitives/signals.mjs +0 -89
- package/fesm2022/primitives/signals.mjs.map +0 -1
- package/fesm2022/resource.mjs +0 -633
- package/fesm2022/resource.mjs.map +0 -1
- package/fesm2022/root_effect_scheduler.mjs +0 -4007
- package/fesm2022/root_effect_scheduler.mjs.map +0 -1
- package/fesm2022/signal.mjs +0 -560
- package/fesm2022/signal.mjs.map +0 -1
- package/fesm2022/untracked.mjs +0 -117
- package/fesm2022/untracked.mjs.map +0 -1
- package/fesm2022/weak_ref.mjs +0 -12
- package/fesm2022/weak_ref.mjs.map +0 -1
- package/schematics/bundles/index-esqfDjNB.cjs +0 -22074
- package/schematics/bundles/project_tsconfig_paths-CS-eSeHC.cjs +0 -51062
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v21.0.0-next.
|
|
3
|
+
* @license Angular v21.0.0-next.10
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
var ts = require('typescript');
|
|
10
|
-
require('
|
|
11
|
-
var
|
|
12
|
-
var index = require('./index-esqfDjNB.cjs');
|
|
13
|
-
require('path');
|
|
10
|
+
var compilerCli = require('@angular/compiler-cli');
|
|
11
|
+
var migrations = require('@angular/compiler-cli/private/migrations');
|
|
14
12
|
require('node:path');
|
|
15
|
-
var project_paths = require('./project_paths-
|
|
13
|
+
var project_paths = require('./project_paths-DvD50ouC.cjs');
|
|
14
|
+
var compiler = require('@angular/compiler');
|
|
16
15
|
|
|
17
16
|
function getMemberName(member) {
|
|
18
17
|
if (member.name === undefined) {
|
|
@@ -189,7 +188,7 @@ function lookupPropertyAccess(checker, type, path, options = {}) {
|
|
|
189
188
|
* This resolution is important to be able to migrate references to inputs
|
|
190
189
|
* that will be migrated to signal inputs.
|
|
191
190
|
*/
|
|
192
|
-
class TemplateReferenceVisitor extends
|
|
191
|
+
class TemplateReferenceVisitor extends compiler.TmplAstRecursiveVisitor {
|
|
193
192
|
result = [];
|
|
194
193
|
/**
|
|
195
194
|
* Whether we are currently descending into HTML AST nodes
|
|
@@ -236,21 +235,21 @@ class TemplateReferenceVisitor extends project_tsconfig_paths.RecursiveVisitor {
|
|
|
236
235
|
// of signal calls in templates.
|
|
237
236
|
// TODO: Remove with: https://github.com/angular/angular/pull/55456.
|
|
238
237
|
this.templateAttributeReferencedFields = [];
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
compiler.tmplAstVisitAll(this, template.attributes);
|
|
239
|
+
compiler.tmplAstVisitAll(this, template.templateAttrs);
|
|
241
240
|
// If we are dealing with a microsyntax template, do not check
|
|
242
241
|
// inputs and outputs as those are already passed to the children.
|
|
243
242
|
// Template attributes may contain relevant expressions though.
|
|
244
243
|
if (template.tagName === 'ng-template') {
|
|
245
|
-
|
|
246
|
-
|
|
244
|
+
compiler.tmplAstVisitAll(this, template.inputs);
|
|
245
|
+
compiler.tmplAstVisitAll(this, template.outputs);
|
|
247
246
|
}
|
|
248
247
|
const referencedInputs = this.templateAttributeReferencedFields;
|
|
249
248
|
this.templateAttributeReferencedFields = null;
|
|
250
249
|
this.descendAndCheckForNarrowedSimilarReferences(referencedInputs, () => {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
250
|
+
compiler.tmplAstVisitAll(this, template.children);
|
|
251
|
+
compiler.tmplAstVisitAll(this, template.references);
|
|
252
|
+
compiler.tmplAstVisitAll(this, template.variables);
|
|
254
253
|
});
|
|
255
254
|
}
|
|
256
255
|
visitIfBlockBranch(block) {
|
|
@@ -317,7 +316,7 @@ class TemplateReferenceVisitor extends project_tsconfig_paths.RecursiveVisitor {
|
|
|
317
316
|
* This resolution is important to be able to migrate references to inputs
|
|
318
317
|
* that will be migrated to signal inputs.
|
|
319
318
|
*/
|
|
320
|
-
class TemplateExpressionReferenceVisitor extends
|
|
319
|
+
class TemplateExpressionReferenceVisitor extends compiler.RecursiveAstVisitor {
|
|
321
320
|
typeChecker;
|
|
322
321
|
templateTypeChecker;
|
|
323
322
|
componentClass;
|
|
@@ -364,7 +363,7 @@ class TemplateExpressionReferenceVisitor extends project_tsconfig_paths.Recursiv
|
|
|
364
363
|
super.visitPropertyRead(ast, context);
|
|
365
364
|
}
|
|
366
365
|
visitBinary(ast, context) {
|
|
367
|
-
if (ast.operation === '=' && ast.left instanceof
|
|
366
|
+
if (ast.operation === '=' && ast.left instanceof compiler.PropertyRead) {
|
|
368
367
|
this._inspectPropertyAccess(ast.left, true, [...context, ast, ast.left]);
|
|
369
368
|
}
|
|
370
369
|
else {
|
|
@@ -402,7 +401,7 @@ class TemplateExpressionReferenceVisitor extends project_tsconfig_paths.Recursiv
|
|
|
402
401
|
return false;
|
|
403
402
|
}
|
|
404
403
|
const symbol = this.templateTypeChecker.getSymbolOfNode(ast, this.componentClass);
|
|
405
|
-
if (symbol?.kind !==
|
|
404
|
+
if (symbol?.kind !== migrations.SymbolKind.Expression || symbol.tsSymbol === null) {
|
|
406
405
|
return false;
|
|
407
406
|
}
|
|
408
407
|
// Dangerous: Type checking symbol retrieval is a totally different `ts.Program`,
|
|
@@ -464,7 +463,7 @@ class TemplateExpressionReferenceVisitor extends project_tsconfig_paths.Recursiv
|
|
|
464
463
|
_isPartOfNarrowingTernary(read) {
|
|
465
464
|
// Note: We do not safe check that the reads are fully matching 1:1. This is acceptable
|
|
466
465
|
// as worst case we just skip an input from being migrated. This is very unlikely too.
|
|
467
|
-
return this.insideConditionalExpressionsWithReads.some((r) => (r instanceof
|
|
466
|
+
return this.insideConditionalExpressionsWithReads.some((r) => (r instanceof compiler.PropertyRead || r instanceof compiler.SafePropertyRead) && r.name === read.name);
|
|
468
467
|
}
|
|
469
468
|
}
|
|
470
469
|
/**
|
|
@@ -474,11 +473,11 @@ class TemplateExpressionReferenceVisitor extends project_tsconfig_paths.Recursiv
|
|
|
474
473
|
function traverseReceiverAndLookupSymbol(readOrWrite, componentClass, checker) {
|
|
475
474
|
const path = [readOrWrite.name];
|
|
476
475
|
let node = readOrWrite;
|
|
477
|
-
while (node.receiver instanceof
|
|
476
|
+
while (node.receiver instanceof compiler.PropertyRead) {
|
|
478
477
|
node = node.receiver;
|
|
479
478
|
path.unshift(node.name);
|
|
480
479
|
}
|
|
481
|
-
if (!(node.receiver instanceof
|
|
480
|
+
if (!(node.receiver instanceof compiler.ImplicitReceiver || node.receiver instanceof compiler.ThisReceiver)) {
|
|
482
481
|
return null;
|
|
483
482
|
}
|
|
484
483
|
const classType = checker.getTypeAtLocation(componentClass.name);
|
|
@@ -490,8 +489,8 @@ function traverseReceiverAndLookupSymbol(readOrWrite, componentClass, checker) {
|
|
|
490
489
|
}
|
|
491
490
|
/** Whether the given node refers to a two-way binding AST node. */
|
|
492
491
|
function isTwoWayBindingNode(node) {
|
|
493
|
-
return ((node instanceof
|
|
494
|
-
(node instanceof
|
|
492
|
+
return ((node instanceof compiler.TmplAstBoundAttribute && node.type === compiler.BindingType.TwoWay) ||
|
|
493
|
+
(node instanceof compiler.TmplAstBoundEvent && node.type === compiler.ParsedEventType.TwoWay));
|
|
495
494
|
}
|
|
496
495
|
|
|
497
496
|
/** Possible types of references to known fields detected. */
|
|
@@ -534,7 +533,7 @@ function identifyHostBindingReferences(node, programInfo, checker, reflector, re
|
|
|
534
533
|
if (decorators === null) {
|
|
535
534
|
return;
|
|
536
535
|
}
|
|
537
|
-
const angularDecorators =
|
|
536
|
+
const angularDecorators = migrations.getAngularDecorators(decorators, ['Directive', 'Component'],
|
|
538
537
|
/* isAngularCore */ false);
|
|
539
538
|
if (angularDecorators.length === 0) {
|
|
540
539
|
return;
|
|
@@ -544,15 +543,15 @@ function identifyHostBindingReferences(node, programInfo, checker, reflector, re
|
|
|
544
543
|
if (ngDecorator.args?.length !== 1) {
|
|
545
544
|
return;
|
|
546
545
|
}
|
|
547
|
-
const metadataNode =
|
|
546
|
+
const metadataNode = migrations.unwrapExpression(ngDecorator.args[0]);
|
|
548
547
|
if (!ts.isObjectLiteralExpression(metadataNode)) {
|
|
549
548
|
return;
|
|
550
549
|
}
|
|
551
|
-
const metadata =
|
|
550
|
+
const metadata = migrations.reflectObjectLiteral(metadataNode);
|
|
552
551
|
if (!metadata.has('host')) {
|
|
553
552
|
return;
|
|
554
553
|
}
|
|
555
|
-
let hostField =
|
|
554
|
+
let hostField = migrations.unwrapExpression(metadata.get('host'));
|
|
556
555
|
// Special-case in case host bindings are shared via a variable.
|
|
557
556
|
// e.g. Material button shares host bindings as a constant in the same target.
|
|
558
557
|
if (ts.isIdentifier(hostField)) {
|
|
@@ -570,7 +569,7 @@ function identifyHostBindingReferences(node, programInfo, checker, reflector, re
|
|
|
570
569
|
if (hostField === undefined || !ts.isObjectLiteralExpression(hostField)) {
|
|
571
570
|
return;
|
|
572
571
|
}
|
|
573
|
-
const hostMap =
|
|
572
|
+
const hostMap = migrations.reflectObjectLiteral(hostField);
|
|
574
573
|
const expressionResult = [];
|
|
575
574
|
const expressionVisitor = new TemplateExpressionReferenceVisitor(checker, null, node, knownFields, fieldNamesToConsiderForReferenceLookup);
|
|
576
575
|
for (const [rawName, expression] of hostMap.entries()) {
|
|
@@ -583,11 +582,11 @@ function identifyHostBindingReferences(node, programInfo, checker, reflector, re
|
|
|
583
582
|
if (!isPropertyBinding && !isEventBinding) {
|
|
584
583
|
continue;
|
|
585
584
|
}
|
|
586
|
-
const parser =
|
|
587
|
-
const sourceSpan = new
|
|
585
|
+
const parser = compiler.makeBindingParser();
|
|
586
|
+
const sourceSpan = new compiler.ParseSourceSpan(
|
|
588
587
|
// Fake source span to keep parsing offsets zero-based.
|
|
589
588
|
// We then later combine these with the expression TS node offsets.
|
|
590
|
-
new
|
|
589
|
+
new compiler.ParseLocation({ content: '', url: '' }, 0, 0, 0), new compiler.ParseLocation({ content: '', url: '' }, 0, 0, 0));
|
|
591
590
|
const name = rawName.substring(1, rawName.length - 1);
|
|
592
591
|
let parsed = undefined;
|
|
593
592
|
if (isEventBinding) {
|
|
@@ -630,9 +629,9 @@ function identifyHostBindingReferences(node, programInfo, checker, reflector, re
|
|
|
630
629
|
*/
|
|
631
630
|
function attemptExtractTemplateDefinition(node, checker, reflector, resourceLoader) {
|
|
632
631
|
const classDecorators = reflector.getDecoratorsOfDeclaration(node);
|
|
633
|
-
const evaluator = new
|
|
632
|
+
const evaluator = new migrations.PartialEvaluator(reflector, checker, null);
|
|
634
633
|
const ngDecorators = classDecorators !== null
|
|
635
|
-
?
|
|
634
|
+
? migrations.getAngularDecorators(classDecorators, ['Component'], /* isAngularCore */ false)
|
|
636
635
|
: [];
|
|
637
636
|
if (ngDecorators.length === 0 ||
|
|
638
637
|
ngDecorators[0].args === null ||
|
|
@@ -640,7 +639,7 @@ function attemptExtractTemplateDefinition(node, checker, reflector, resourceLoad
|
|
|
640
639
|
!ts.isObjectLiteralExpression(ngDecorators[0].args[0])) {
|
|
641
640
|
return null;
|
|
642
641
|
}
|
|
643
|
-
const properties =
|
|
642
|
+
const properties = migrations.reflectObjectLiteral(ngDecorators[0].args[0]);
|
|
644
643
|
const templateProp = properties.get('template');
|
|
645
644
|
const templateUrlProp = properties.get('templateUrl');
|
|
646
645
|
const containingFile = node.getSourceFile().fileName;
|
|
@@ -651,7 +650,6 @@ function attemptExtractTemplateDefinition(node, checker, reflector, resourceLoad
|
|
|
651
650
|
return {
|
|
652
651
|
isInline: true,
|
|
653
652
|
expression: templateProp,
|
|
654
|
-
interpolationConfig: project_tsconfig_paths.DEFAULT_INTERPOLATION_CONFIG,
|
|
655
653
|
preserveWhitespaces: false,
|
|
656
654
|
resolvedTemplateUrl: containingFile,
|
|
657
655
|
templateUrl: containingFile,
|
|
@@ -665,7 +663,6 @@ function attemptExtractTemplateDefinition(node, checker, reflector, resourceLoad
|
|
|
665
663
|
if (typeof templateUrl === 'string') {
|
|
666
664
|
return {
|
|
667
665
|
isInline: false,
|
|
668
|
-
interpolationConfig: project_tsconfig_paths.DEFAULT_INTERPOLATION_CONFIG,
|
|
669
666
|
preserveWhitespaces: false,
|
|
670
667
|
templateUrlExpression: templateUrlProp,
|
|
671
668
|
templateUrl,
|
|
@@ -685,7 +682,7 @@ function attemptExtractTemplateDefinition(node, checker, reflector, resourceLoad
|
|
|
685
682
|
* all of the references to inputs.
|
|
686
683
|
*/
|
|
687
684
|
function identifyTemplateReferences(programInfo, node, reflector, checker, evaluator, templateTypeChecker, resourceLoader, options, result, knownFields, fieldNamesToConsiderForReferenceLookup) {
|
|
688
|
-
const template = templateTypeChecker.getTemplate(node,
|
|
685
|
+
const template = templateTypeChecker.getTemplate(node, compilerCli.OptimizeFor.WholeProgram) ??
|
|
689
686
|
// If there is no template registered in the TCB or compiler, the template may
|
|
690
687
|
// be skipped due to an explicit `jit: true` setting. We try to detect this case
|
|
691
688
|
// and parse the template manually.
|
|
@@ -714,7 +711,7 @@ function identifyTemplateReferences(programInfo, node, reflector, checker, evalu
|
|
|
714
711
|
node: res.context,
|
|
715
712
|
isObjectShorthandExpression: res.isObjectShorthandExpression,
|
|
716
713
|
originatingTsFile: project_paths.projectFile(node.getSourceFile(), programInfo),
|
|
717
|
-
templateFile: project_paths.projectFile(
|
|
714
|
+
templateFile: project_paths.projectFile(compilerCli.absoluteFrom(templateFilePath), programInfo),
|
|
718
715
|
isLikelyPartOfNarrowing: res.isLikelyNarrowed,
|
|
719
716
|
isWrite: res.isWrite,
|
|
720
717
|
},
|
|
@@ -740,14 +737,14 @@ function extractTemplateWithoutCompilerAnalysis(node, checker, reflector, resour
|
|
|
740
737
|
if (tmplDef === null) {
|
|
741
738
|
return null;
|
|
742
739
|
}
|
|
743
|
-
return
|
|
740
|
+
return migrations.extractTemplate(node, tmplDef, evaluator, null, resourceLoader, {
|
|
744
741
|
enableBlockSyntax: true,
|
|
745
742
|
enableLetSyntax: true,
|
|
746
743
|
usePoisonedData: true,
|
|
747
744
|
enableI18nLegacyMessageIdFormat: options.enableI18nLegacyMessageIdFormat !== false,
|
|
748
745
|
i18nNormalizeLineEndingsInICUs: options.i18nNormalizeLineEndingsInICUs === true,
|
|
749
746
|
enableSelectorless: false,
|
|
750
|
-
},
|
|
747
|
+
}, migrations.CompilationMode.FULL).nodes;
|
|
751
748
|
}
|
|
752
749
|
|
|
753
750
|
/** Gets the pattern and property name for a given binding element. */
|
|
@@ -1,33 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v21.0.0-next.
|
|
3
|
+
* @license Angular v21.0.0-next.10
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
var schematics = require('@angular-devkit/schematics');
|
|
10
|
-
var
|
|
11
|
-
var compiler_host = require('./compiler_host-
|
|
10
|
+
var path = require('path');
|
|
11
|
+
var compiler_host = require('./compiler_host-DBwYMlTo.cjs');
|
|
12
12
|
var ts = require('typescript');
|
|
13
|
-
var ng_decorators = require('./ng_decorators-
|
|
14
|
-
var imports = require('./imports-
|
|
13
|
+
var ng_decorators = require('./ng_decorators-DSFlWYQY.cjs');
|
|
14
|
+
var imports = require('./imports-DP72APSx.cjs');
|
|
15
15
|
var nodes = require('./nodes-B16H9JUd.cjs');
|
|
16
16
|
var leading_space = require('./leading_space-D9nQ8UQC.cjs');
|
|
17
|
-
var project_tsconfig_paths = require('./project_tsconfig_paths-
|
|
18
|
-
require('
|
|
19
|
-
require('fs');
|
|
20
|
-
require('module');
|
|
21
|
-
require('url');
|
|
17
|
+
var project_tsconfig_paths = require('./project_tsconfig_paths-CDVxT6Ov.cjs');
|
|
18
|
+
require('@angular/compiler-cli/private/migrations');
|
|
22
19
|
require('@angular-devkit/core');
|
|
23
20
|
|
|
24
|
-
/*!
|
|
25
|
-
* @license
|
|
26
|
-
* Copyright Google LLC All Rights Reserved.
|
|
27
|
-
*
|
|
28
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
29
|
-
* found in the LICENSE file at https://angular.dev/license
|
|
30
|
-
*/
|
|
31
21
|
/** Names of decorators that enable DI on a class declaration. */
|
|
32
22
|
const DECORATORS_SUPPORTING_DI = new Set([
|
|
33
23
|
'Component',
|
|
@@ -346,13 +336,6 @@ function isInlineFunction(node) {
|
|
|
346
336
|
return (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node));
|
|
347
337
|
}
|
|
348
338
|
|
|
349
|
-
/*!
|
|
350
|
-
* @license
|
|
351
|
-
* Copyright Google LLC All Rights Reserved.
|
|
352
|
-
*
|
|
353
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
354
|
-
* found in the LICENSE file at https://angular.dev/license
|
|
355
|
-
*/
|
|
356
339
|
/**
|
|
357
340
|
* Finds class property declarations without initializers whose constructor-based initialization
|
|
358
341
|
* can be inlined into the declaration spot after migrating to `inject`. For example:
|
|
@@ -820,66 +803,161 @@ function migrateClass(node, constructor, superCall, options, memberIndentation,
|
|
|
820
803
|
* @param afterSuper Statements to be added after the `super` call.
|
|
821
804
|
*/
|
|
822
805
|
function migrateParameter(node, options, localTypeChecker, printer, tracker, superCall, usedInSuper, usedInConstructor, usesOtherParams, memberIndentation, innerIndentation, prependToConstructor, propsToAdd, afterSuper) {
|
|
823
|
-
|
|
806
|
+
const context = {
|
|
807
|
+
node,
|
|
808
|
+
options,
|
|
809
|
+
localTypeChecker,
|
|
810
|
+
printer,
|
|
811
|
+
tracker,
|
|
812
|
+
superCall,
|
|
813
|
+
usedInSuper,
|
|
814
|
+
usedInConstructor,
|
|
815
|
+
usesOtherParams,
|
|
816
|
+
memberIndentation,
|
|
817
|
+
innerIndentation,
|
|
818
|
+
prependToConstructor,
|
|
819
|
+
propsToAdd,
|
|
820
|
+
afterSuper,
|
|
821
|
+
};
|
|
822
|
+
if (ts.isIdentifier(node.name)) {
|
|
823
|
+
migrateIdentifierParameter(context, node.name);
|
|
824
|
+
}
|
|
825
|
+
else if (ts.isObjectBindingPattern(node.name)) {
|
|
826
|
+
migrateObjectBindingParameter(context, node.name);
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
824
829
|
return;
|
|
825
830
|
}
|
|
826
|
-
|
|
831
|
+
}
|
|
832
|
+
function migrateIdentifierParameter(context, name) {
|
|
833
|
+
const { node, options, localTypeChecker, printer, tracker, usedInConstructor, usesOtherParams } = context;
|
|
827
834
|
const replacementCall = createInjectReplacementCall(node, options, localTypeChecker, printer, tracker);
|
|
828
835
|
const declaresProp = parameterDeclaresProperty(node);
|
|
829
836
|
// If the parameter declares a property, we need to declare it (e.g. `private foo: Foo`).
|
|
830
837
|
if (declaresProp) {
|
|
831
|
-
|
|
832
|
-
// other parameters. See the logic further below for the initialization.
|
|
833
|
-
const canInitialize = !usedInSuper && !usesOtherParams;
|
|
834
|
-
const prop = ts.factory.createPropertyDeclaration(cloneModifiers(node.modifiers?.filter((modifier) => {
|
|
835
|
-
// Strip out the DI decorators, as well as `public` which is redundant.
|
|
836
|
-
return !ts.isDecorator(modifier) && modifier.kind !== ts.SyntaxKind.PublicKeyword;
|
|
837
|
-
})), name,
|
|
838
|
-
// Don't add the question token to private properties since it won't affect interface implementation.
|
|
839
|
-
node.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.PrivateKeyword)
|
|
840
|
-
? undefined
|
|
841
|
-
: node.questionToken, canInitialize ? undefined : node.type, canInitialize ? ts.factory.createIdentifier(PLACEHOLDER) : undefined);
|
|
842
|
-
propsToAdd.push(memberIndentation +
|
|
843
|
-
replaceNodePlaceholder(node.getSourceFile(), prop, replacementCall, printer));
|
|
838
|
+
handlePropertyDeclaration(context, name, replacementCall);
|
|
844
839
|
}
|
|
845
840
|
// If the parameter is referenced within the constructor, we need to declare it as a variable.
|
|
846
841
|
if (usedInConstructor) {
|
|
847
|
-
|
|
848
|
-
// Usages of `this` aren't allowed before `super` calls so we need to
|
|
849
|
-
// create a variable which calls `inject()` directly instead...
|
|
850
|
-
prependToConstructor.push(`${innerIndentation}const ${name} = ${replacementCall};`);
|
|
851
|
-
// ...then we can initialize the property after the `super` call.
|
|
852
|
-
if (declaresProp) {
|
|
853
|
-
afterSuper.push(`${innerIndentation}this.${name} = ${name};`);
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
else if (declaresProp) {
|
|
857
|
-
// If the parameter declares a property (`private foo: foo`) and is used inside the class
|
|
858
|
-
// at the same time, we need to ensure that it's initialized to the value from the variable
|
|
859
|
-
// and that we only reference `this` after the `super` call.
|
|
860
|
-
const initializer = `${innerIndentation}const ${name} = this.${name};`;
|
|
861
|
-
if (superCall === null) {
|
|
862
|
-
prependToConstructor.push(initializer);
|
|
863
|
-
}
|
|
864
|
-
else {
|
|
865
|
-
afterSuper.push(initializer);
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
else {
|
|
869
|
-
// If the parameter is only referenced in the constructor, we
|
|
870
|
-
// don't need to declare any new properties.
|
|
871
|
-
prependToConstructor.push(`${innerIndentation}const ${name} = ${replacementCall};`);
|
|
872
|
-
}
|
|
842
|
+
handleConstructorUsage(context, name.text, replacementCall, declaresProp);
|
|
873
843
|
}
|
|
874
844
|
else if (usesOtherParams && declaresProp) {
|
|
875
|
-
|
|
845
|
+
handleParameterWithDependencies(context, name.text, replacementCall);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
function handlePropertyDeclaration(context, name, replacementCall) {
|
|
849
|
+
const { node, memberIndentation, propsToAdd } = context;
|
|
850
|
+
const canInitialize = !context.usedInSuper && !context.usesOtherParams;
|
|
851
|
+
const prop = ts.factory.createPropertyDeclaration(cloneModifiers(node.modifiers?.filter((modifier) => {
|
|
852
|
+
return !ts.isDecorator(modifier) && modifier.kind !== ts.SyntaxKind.PublicKeyword;
|
|
853
|
+
})), name, node.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.PrivateKeyword)
|
|
854
|
+
? undefined
|
|
855
|
+
: node.questionToken, canInitialize ? undefined : node.type, canInitialize ? ts.factory.createIdentifier(PLACEHOLDER) : undefined);
|
|
856
|
+
propsToAdd.push(memberIndentation +
|
|
857
|
+
replaceNodePlaceholder(node.getSourceFile(), prop, replacementCall, context.printer));
|
|
858
|
+
}
|
|
859
|
+
function handleConstructorUsage(context, name, replacementCall, declaresProp) {
|
|
860
|
+
const { innerIndentation, prependToConstructor, afterSuper, superCall } = context;
|
|
861
|
+
if (context.usedInSuper) {
|
|
862
|
+
// Usages of `this` aren't allowed before `super` calls so we need to
|
|
863
|
+
// create a variable which calls `inject()` directly instead...
|
|
864
|
+
prependToConstructor.push(`${innerIndentation}const ${name} = ${replacementCall};`);
|
|
865
|
+
if (declaresProp) {
|
|
866
|
+
afterSuper.push(`${innerIndentation}this.${name} = ${name};`);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
else if (declaresProp) {
|
|
870
|
+
// If the parameter declares a property (`private foo: foo`) and is used inside the class
|
|
871
|
+
// at the same time, we need to ensure that it's initialized to the value from the variable
|
|
872
|
+
// and that we only reference `this` after the `super` call.
|
|
873
|
+
const initializer = `${innerIndentation}const ${name} = this.${name};`;
|
|
876
874
|
if (superCall === null) {
|
|
877
|
-
prependToConstructor.push(
|
|
875
|
+
prependToConstructor.push(initializer);
|
|
878
876
|
}
|
|
879
877
|
else {
|
|
880
|
-
afterSuper.push(
|
|
878
|
+
afterSuper.push(initializer);
|
|
881
879
|
}
|
|
882
880
|
}
|
|
881
|
+
else {
|
|
882
|
+
// If the parameter is only referenced in the constructor, we
|
|
883
|
+
// don't need to declare any new properties.
|
|
884
|
+
prependToConstructor.push(`${innerIndentation}const ${name} = ${replacementCall};`);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
function handleParameterWithDependencies(context, name, replacementCall) {
|
|
888
|
+
const { innerIndentation, prependToConstructor, afterSuper, superCall } = context;
|
|
889
|
+
const toAdd = `${innerIndentation}this.${name} = ${replacementCall};`;
|
|
890
|
+
if (superCall === null) {
|
|
891
|
+
prependToConstructor.push(toAdd);
|
|
892
|
+
}
|
|
893
|
+
else {
|
|
894
|
+
afterSuper.push(toAdd);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
function migrateObjectBindingParameter(context, bindingPattern) {
|
|
898
|
+
const { node, options, localTypeChecker, printer, tracker } = context;
|
|
899
|
+
const replacementCall = createInjectReplacementCall(node, options, localTypeChecker, printer, tracker);
|
|
900
|
+
for (const element of bindingPattern.elements) {
|
|
901
|
+
if (ts.isBindingElement(element) && ts.isIdentifier(element.name)) {
|
|
902
|
+
migrateBindingElement(context, element, element.name, replacementCall);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
function migrateBindingElement(context, element, elementName, replacementCall) {
|
|
907
|
+
const propertyName = elementName.text;
|
|
908
|
+
// Determines how to access the property
|
|
909
|
+
const propertyAccess = element.propertyName
|
|
910
|
+
? `${replacementCall}.${element.propertyName.getText()}`
|
|
911
|
+
: `${replacementCall}.${propertyName}`;
|
|
912
|
+
createPropertyForBindingElement(context, propertyName, propertyAccess);
|
|
913
|
+
if (context.usedInConstructor) {
|
|
914
|
+
handleConstructorUsageBindingElement(context, element, propertyName);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
function handleConstructorUsageBindingElement(context, element, propertyName) {
|
|
918
|
+
const { tracker, localTypeChecker, node: paramNode } = context;
|
|
919
|
+
const constructorDecl = paramNode.parent;
|
|
920
|
+
// Check in constructor or exist body content
|
|
921
|
+
if (!ts.isConstructorDeclaration(constructorDecl) || !constructorDecl.body) {
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
// Get the unique "symbol" for our unstructured property.
|
|
925
|
+
const symbol = localTypeChecker.getSymbolAtLocation(element.name);
|
|
926
|
+
if (!symbol) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
// Visit recursive function navigate constructor
|
|
930
|
+
const visit = (node) => {
|
|
931
|
+
// Check if current node is identifier (variable)
|
|
932
|
+
if (ts.isIdentifier(node)) {
|
|
933
|
+
// Using the type checker, verify that this identifier refers
|
|
934
|
+
// exactly to our destructured parameter and is not the node of the original declaration.
|
|
935
|
+
if (localTypeChecker.getSymbolAtLocation(node) === symbol && node !== element.name) {
|
|
936
|
+
// If the identifier is used as a shorthand property in an object literal (e.g., { myVar }),
|
|
937
|
+
// must replace the entire `ShorthandPropertyAssignment` node
|
|
938
|
+
// with a `PropertyAssignment` (e.g., myVar: this.myVar).
|
|
939
|
+
if (ts.isShorthandPropertyAssignment(node.parent)) {
|
|
940
|
+
tracker.replaceNode(node.parent, ts.factory.createPropertyAssignment(node, ts.factory.createPropertyAccessExpression(ts.factory.createThis(), propertyName)));
|
|
941
|
+
}
|
|
942
|
+
else {
|
|
943
|
+
// Otherwise, replace the identifier with `this.propertyName`.
|
|
944
|
+
tracker.replaceNode(node, ts.factory.createPropertyAccessExpression(ts.factory.createThis(), propertyName));
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
ts.forEachChild(node, visit);
|
|
949
|
+
};
|
|
950
|
+
visit(constructorDecl.body);
|
|
951
|
+
}
|
|
952
|
+
function createPropertyForBindingElement(context, propertyName, propertyAccess) {
|
|
953
|
+
const { node, memberIndentation, propsToAdd } = context;
|
|
954
|
+
const prop = ts.factory.createPropertyDeclaration(cloneModifiers(node.modifiers?.filter((modifier) => {
|
|
955
|
+
return !ts.isDecorator(modifier) && modifier.kind !== ts.SyntaxKind.PublicKeyword;
|
|
956
|
+
})), propertyName, node.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.PrivateKeyword)
|
|
957
|
+
? undefined
|
|
958
|
+
: node.questionToken, undefined, ts.factory.createIdentifier(PLACEHOLDER));
|
|
959
|
+
propsToAdd.push(memberIndentation +
|
|
960
|
+
replaceNodePlaceholder(node.getSourceFile(), prop, propertyAccess, context.printer));
|
|
883
961
|
}
|
|
884
962
|
/**
|
|
885
963
|
* Creates a replacement `inject` call from a function parameter.
|
|
@@ -1247,7 +1325,7 @@ function migrate(options) {
|
|
|
1247
1325
|
const { buildPaths, testPaths } = await project_tsconfig_paths.getProjectTsConfigPaths(tree);
|
|
1248
1326
|
const basePath = process.cwd();
|
|
1249
1327
|
const allPaths = [...buildPaths, ...testPaths];
|
|
1250
|
-
const pathToMigrate = compiler_host.normalizePath(
|
|
1328
|
+
const pathToMigrate = compiler_host.normalizePath(path.join(basePath, options.path));
|
|
1251
1329
|
if (!allPaths.length) {
|
|
1252
1330
|
throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run the inject migration.');
|
|
1253
1331
|
}
|
|
@@ -1271,7 +1349,7 @@ function runInjectMigration(tree, tsconfigPath, basePath, pathToMigrate, schemat
|
|
|
1271
1349
|
for (const sourceFile of sourceFiles) {
|
|
1272
1350
|
const changes = migrateFile(sourceFile, schematicOptions);
|
|
1273
1351
|
if (changes.length > 0) {
|
|
1274
|
-
const update = tree.beginUpdate(
|
|
1352
|
+
const update = tree.beginUpdate(path.relative(basePath, sourceFile.fileName));
|
|
1275
1353
|
for (const change of changes) {
|
|
1276
1354
|
if (change.removeLength != null) {
|
|
1277
1355
|
update.remove(change.start, change.removeLength);
|