@angular/core 20.0.0-next.3 → 20.0.0-next.5
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/api.d-mxcXqDpA.d.ts +297 -0
- package/discovery.d-CyYpOJ7j.d.ts +7393 -0
- package/event_dispatcher.d-PWnbqZDx.d.ts +346 -0
- package/fesm2022/attribute-B17mgaqe.mjs +24 -0
- package/fesm2022/attribute-B17mgaqe.mjs.map +1 -0
- package/fesm2022/core.mjs +579 -36730
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/debug_node-xKpCIZm-.mjs +32070 -0
- package/fesm2022/debug_node-xKpCIZm-.mjs.map +1 -0
- package/fesm2022/primitives/di.mjs +2 -2
- package/fesm2022/primitives/di.mjs.map +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +2 -16
- package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +5 -609
- package/fesm2022/primitives/signals.mjs.map +1 -1
- package/fesm2022/resource-BPpYEDic.mjs +621 -0
- package/fesm2022/resource-BPpYEDic.mjs.map +1 -0
- package/fesm2022/root_effect_scheduler-D0_b1cf_.mjs +3816 -0
- package/fesm2022/root_effect_scheduler-D0_b1cf_.mjs.map +1 -0
- package/fesm2022/rxjs-interop.mjs +91 -7
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/signal-DhRAAi7R.mjs +522 -0
- package/fesm2022/signal-DhRAAi7R.mjs.map +1 -0
- package/fesm2022/testing.mjs +105 -103
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/untracked-DaaW3JJm.mjs +117 -0
- package/fesm2022/untracked-DaaW3JJm.mjs.map +1 -0
- package/fesm2022/weak_ref-DrMdAIDh.mjs +1 -1
- package/graph.d-StYigYp1.d.ts +195 -0
- package/index.d.ts +2616 -10854
- package/ng_i18n_closure_mode.d-DLxSUiDr.d.ts +832 -0
- package/package.json +3 -3
- package/primitives/di/index.d.ts +3 -2
- package/primitives/event-dispatch/index.d.ts +5 -340
- package/primitives/signals/index.d.ts +7 -209
- package/rxjs-interop/index.d.ts +16 -4
- package/schematics/bundles/{apply_import_manager-BXQEjo09.js → apply_import_manager-C-ysxahq.js} +3 -3
- package/schematics/bundles/{compiler_host-Bk3repE2.js → change_tracker-0Ktek5Xl.js} +3 -121
- package/schematics/bundles/checker-DqUKCGda.js +17702 -0
- package/schematics/bundles/cleanup-unused-imports.js +6 -5
- package/schematics/bundles/{checker-BHb19MHt.js → compiler-CuoiHqkc.js} +578 -18086
- package/schematics/bundles/compiler_host-CAfDJO3W.js +129 -0
- package/schematics/bundles/control-flow-migration.js +59 -50
- package/schematics/bundles/document-core.js +96 -0
- package/schematics/bundles/imports-CIX-JgAN.js +1 -1
- package/schematics/bundles/{index-BL9kAIe5.js → index-CwFQSYXZ.js} +30 -29
- package/schematics/bundles/{index-I8VbxQcO.js → index-WFXCe5Q0.js} +527 -524
- package/schematics/bundles/inject-flags.js +6 -5
- package/schematics/bundles/inject-migration.js +29 -10
- package/schematics/bundles/leading_space-D9nQ8UQC.js +1 -1
- package/schematics/bundles/{migrate_ts_type_references-KlOTWeDl.js → migrate_ts_type_references-BNuHufqZ.js} +6 -5
- package/schematics/bundles/ng_decorators-DznZ5jMl.js +1 -1
- package/schematics/bundles/nodes-B16H9JUd.js +1 -1
- package/schematics/bundles/output-migration.js +15 -10
- package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.js +1 -1
- package/schematics/bundles/property_name-BBwFuqMe.js +1 -1
- package/schematics/bundles/route-lazy-loading.js +7 -5
- package/schematics/bundles/{run_in_devkit-C0JPtK2u.js → run_in_devkit-CmHxABFr.js} +4 -3
- package/schematics/bundles/self-closing-tags-migration.js +10 -9
- package/schematics/bundles/signal-input-migration.js +8 -7
- package/schematics/bundles/signal-queries-migration.js +27 -14
- package/schematics/bundles/signals.js +8 -7
- package/schematics/bundles/standalone-migration.js +11 -9
- package/schematics/bundles/symbol-VPWguRxr.js +1 -1
- package/schematics/bundles/test-bed-get.js +5 -4
- package/schematics/collection.json +0 -6
- package/schematics/migrations.json +11 -0
- package/signal.d-BeaTIeOE.d.ts +31 -0
- package/testing/index.d.ts +13 -9
- package/weak_ref.d-ttyj86RV.d.ts +1 -1
- package/navigation_types.d-u4EOrrdZ.d.ts +0 -121
- package/schematics/ng-generate/control-flow-migration/schema.json +0 -20
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* @license Angular v20.0.0-next.5
|
|
4
|
+
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
|
+
* License: MIT
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
var p = require('path');
|
|
10
|
+
var ts = require('typescript');
|
|
11
|
+
|
|
12
|
+
function _interopNamespaceDefault(e) {
|
|
13
|
+
var n = Object.create(null);
|
|
14
|
+
if (e) {
|
|
15
|
+
Object.keys(e).forEach(function (k) {
|
|
16
|
+
if (k !== 'default') {
|
|
17
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
18
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () { return e[k]; }
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
n.default = e;
|
|
26
|
+
return Object.freeze(n);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var p__namespace = /*#__PURE__*/_interopNamespaceDefault(p);
|
|
30
|
+
|
|
31
|
+
function parseTsconfigFile(tsconfigPath, basePath) {
|
|
32
|
+
const { config } = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
|
|
33
|
+
const parseConfigHost = {
|
|
34
|
+
useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
|
|
35
|
+
fileExists: ts.sys.fileExists,
|
|
36
|
+
readDirectory: ts.sys.readDirectory,
|
|
37
|
+
readFile: ts.sys.readFile,
|
|
38
|
+
};
|
|
39
|
+
// Throw if incorrect arguments are passed to this function. Passing relative base paths
|
|
40
|
+
// results in root directories not being resolved and in later type checking runtime errors.
|
|
41
|
+
// More details can be found here: https://github.com/microsoft/TypeScript/issues/37731.
|
|
42
|
+
if (!p__namespace.isAbsolute(basePath)) {
|
|
43
|
+
throw Error('Unexpected relative base path has been specified.');
|
|
44
|
+
}
|
|
45
|
+
return ts.parseJsonConfigFileContent(config, parseConfigHost, basePath, {});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Creates a TypeScript program instance for a TypeScript project within
|
|
50
|
+
* the virtual file system tree.
|
|
51
|
+
* @param tree Virtual file system tree that contains the source files.
|
|
52
|
+
* @param tsconfigPath Virtual file system path that resolves to the TypeScript project.
|
|
53
|
+
* @param basePath Base path for the virtual file system tree.
|
|
54
|
+
* @param fakeFileRead Optional file reader function. Can be used to overwrite files in
|
|
55
|
+
* the TypeScript program, or to add in-memory files (e.g. to add global types).
|
|
56
|
+
* @param additionalFiles Additional file paths that should be added to the program.
|
|
57
|
+
*/
|
|
58
|
+
function createMigrationProgram(tree, tsconfigPath, basePath, fakeFileRead, additionalFiles) {
|
|
59
|
+
const { rootNames, options, host } = createProgramOptions(tree, tsconfigPath, basePath, fakeFileRead);
|
|
60
|
+
return ts.createProgram(rootNames, options, host);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Creates the options necessary to instantiate a TypeScript program.
|
|
64
|
+
* @param tree Virtual file system tree that contains the source files.
|
|
65
|
+
* @param tsconfigPath Virtual file system path that resolves to the TypeScript project.
|
|
66
|
+
* @param basePath Base path for the virtual file system tree.
|
|
67
|
+
* @param fakeFileRead Optional file reader function. Can be used to overwrite files in
|
|
68
|
+
* the TypeScript program, or to add in-memory files (e.g. to add global types).
|
|
69
|
+
* @param additionalFiles Additional file paths that should be added to the program.
|
|
70
|
+
* @param optionOverrides Overrides of the parsed compiler options.
|
|
71
|
+
*/
|
|
72
|
+
function createProgramOptions(tree, tsconfigPath, basePath, fakeFileRead, additionalFiles, optionOverrides) {
|
|
73
|
+
// Resolve the tsconfig path to an absolute path. This is needed as TypeScript otherwise
|
|
74
|
+
// is not able to resolve root directories in the given tsconfig. More details can be found
|
|
75
|
+
// in the following issue: https://github.com/microsoft/TypeScript/issues/37731.
|
|
76
|
+
tsconfigPath = p.resolve(basePath, tsconfigPath);
|
|
77
|
+
const parsed = parseTsconfigFile(tsconfigPath, p.dirname(tsconfigPath));
|
|
78
|
+
const options = optionOverrides ? { ...parsed.options, ...optionOverrides } : parsed.options;
|
|
79
|
+
const host = createMigrationCompilerHost(tree, options, basePath, fakeFileRead);
|
|
80
|
+
return { rootNames: parsed.fileNames.concat([]), options, host };
|
|
81
|
+
}
|
|
82
|
+
function createMigrationCompilerHost(tree, options, basePath, fakeRead) {
|
|
83
|
+
const host = ts.createCompilerHost(options, true);
|
|
84
|
+
const defaultReadFile = host.readFile;
|
|
85
|
+
// We need to overwrite the host "readFile" method, as we want the TypeScript
|
|
86
|
+
// program to be based on the file contents in the virtual file tree. Otherwise
|
|
87
|
+
// if we run multiple migrations we might have intersecting changes and
|
|
88
|
+
// source files.
|
|
89
|
+
host.readFile = (fileName) => {
|
|
90
|
+
const treeRelativePath = p.relative(basePath, fileName);
|
|
91
|
+
let result = fakeRead?.(treeRelativePath);
|
|
92
|
+
if (typeof result !== 'string') {
|
|
93
|
+
// If the relative path resolved to somewhere outside of the tree, fall back to
|
|
94
|
+
// TypeScript's default file reading function since the `tree` will throw an error.
|
|
95
|
+
result = treeRelativePath.startsWith('..')
|
|
96
|
+
? defaultReadFile.call(host, fileName)
|
|
97
|
+
: tree.read(treeRelativePath)?.toString();
|
|
98
|
+
}
|
|
99
|
+
// Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset,
|
|
100
|
+
// which breaks the CLI UpdateRecorder.
|
|
101
|
+
// See: https://github.com/angular/angular/pull/30719
|
|
102
|
+
return typeof result === 'string' ? result.replace(/^\uFEFF/, '') : undefined;
|
|
103
|
+
};
|
|
104
|
+
return host;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Checks whether a file can be migrate by our automated migrations.
|
|
108
|
+
* @param basePath Absolute path to the project.
|
|
109
|
+
* @param sourceFile File being checked.
|
|
110
|
+
* @param program Program that includes the source file.
|
|
111
|
+
*/
|
|
112
|
+
function canMigrateFile(basePath, sourceFile, program) {
|
|
113
|
+
// We shouldn't migrate .d.ts files, files from an external library or type checking files.
|
|
114
|
+
if (sourceFile.fileName.endsWith('.ngtypecheck.ts') ||
|
|
115
|
+
sourceFile.isDeclarationFile ||
|
|
116
|
+
program.isSourceFileFromExternalLibrary(sourceFile)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
// Our migrations are set up to create a `Program` from the project's tsconfig and to migrate all
|
|
120
|
+
// the files within the program. This can include files that are outside of the Angular CLI
|
|
121
|
+
// project. We can't migrate files outside of the project, because our file system interactions
|
|
122
|
+
// go through the CLI's `Tree` which assumes that all files are within the project. See:
|
|
123
|
+
// https://github.com/angular/angular-cli/blob/0b0961c9c233a825b6e4bb59ab7f0790f9b14676/packages/angular_devkit/schematics/src/tree/host-tree.ts#L131
|
|
124
|
+
return !p.relative(basePath, sourceFile.fileName).startsWith('..');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
exports.canMigrateFile = canMigrateFile;
|
|
128
|
+
exports.createMigrationProgram = createMigrationProgram;
|
|
129
|
+
exports.createProgramOptions = createProgramOptions;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v20.0.0-next.
|
|
3
|
+
* @license Angular v20.0.0-next.5
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
@@ -8,13 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
var schematics = require('@angular-devkit/schematics');
|
|
10
10
|
var p = require('path');
|
|
11
|
-
var compiler_host = require('./compiler_host-
|
|
12
|
-
var
|
|
11
|
+
var compiler_host = require('./compiler_host-CAfDJO3W.js');
|
|
12
|
+
var compiler = require('./compiler-CuoiHqkc.js');
|
|
13
13
|
var ts = require('typescript');
|
|
14
|
-
require('
|
|
15
|
-
require('
|
|
16
|
-
require('module');
|
|
17
|
-
require('url');
|
|
14
|
+
var project_tsconfig_paths = require('./project_tsconfig_paths-CDVxT6Ov.js');
|
|
15
|
+
require('@angular-devkit/core');
|
|
18
16
|
|
|
19
17
|
function lookupIdentifiersInSourceFile(sourceFile, names) {
|
|
20
18
|
const results = new Set();
|
|
@@ -273,7 +271,7 @@ class AnalyzedFile {
|
|
|
273
271
|
}
|
|
274
272
|
}
|
|
275
273
|
/** Finds all non-control flow elements from common module. */
|
|
276
|
-
class CommonCollector extends
|
|
274
|
+
class CommonCollector extends compiler.RecursiveVisitor$1 {
|
|
277
275
|
count = 0;
|
|
278
276
|
visitElement(el) {
|
|
279
277
|
if (el.attrs.length > 0) {
|
|
@@ -312,7 +310,7 @@ class CommonCollector extends checker.RecursiveVisitor {
|
|
|
312
310
|
}
|
|
313
311
|
}
|
|
314
312
|
/** Finds all elements that represent i18n blocks. */
|
|
315
|
-
class i18nCollector extends
|
|
313
|
+
class i18nCollector extends compiler.RecursiveVisitor$1 {
|
|
316
314
|
elements = [];
|
|
317
315
|
visitElement(el) {
|
|
318
316
|
if (el.attrs.find((a) => a.name === 'i18n') !== undefined) {
|
|
@@ -322,7 +320,7 @@ class i18nCollector extends checker.RecursiveVisitor {
|
|
|
322
320
|
}
|
|
323
321
|
}
|
|
324
322
|
/** Finds all elements with ngif structural directives. */
|
|
325
|
-
class ElementCollector extends
|
|
323
|
+
class ElementCollector extends compiler.RecursiveVisitor$1 {
|
|
326
324
|
_attributes;
|
|
327
325
|
elements = [];
|
|
328
326
|
constructor(_attributes = []) {
|
|
@@ -375,7 +373,7 @@ class ElementCollector extends checker.RecursiveVisitor {
|
|
|
375
373
|
}
|
|
376
374
|
}
|
|
377
375
|
/** Finds all elements with ngif structural directives. */
|
|
378
|
-
class TemplateCollector extends
|
|
376
|
+
class TemplateCollector extends compiler.RecursiveVisitor$1 {
|
|
379
377
|
elements = [];
|
|
380
378
|
templates = new Map();
|
|
381
379
|
visitElement(el) {
|
|
@@ -589,7 +587,7 @@ function parseTemplate(template) {
|
|
|
589
587
|
// interpolated text as text nodes containing a mixture of interpolation tokens and text tokens,
|
|
590
588
|
// rather than turning them into `BoundText` nodes like the Ivy AST does. This allows us to
|
|
591
589
|
// easily get the text-only ranges without having to reconstruct the original text.
|
|
592
|
-
parsed = new
|
|
590
|
+
parsed = new compiler.HtmlParser().parse(template, '', {
|
|
593
591
|
// Allows for ICUs to be parsed.
|
|
594
592
|
tokenizeExpansionForms: true,
|
|
595
593
|
// Explicitly disable blocks so that their characters are treated as plain text.
|
|
@@ -627,7 +625,7 @@ function validateMigratedTemplate(migrated, fileName) {
|
|
|
627
625
|
}
|
|
628
626
|
function validateI18nStructure(parsed, fileName) {
|
|
629
627
|
const visitor = new i18nCollector();
|
|
630
|
-
|
|
628
|
+
compiler.visitAll$1(visitor, parsed.rootNodes);
|
|
631
629
|
const parents = visitor.elements.filter((el) => el.children.length > 0);
|
|
632
630
|
for (const p of parents) {
|
|
633
631
|
for (const el of visitor.elements) {
|
|
@@ -680,9 +678,6 @@ function calculateNesting(visitor, hasLineBreaks) {
|
|
|
680
678
|
}
|
|
681
679
|
}
|
|
682
680
|
}
|
|
683
|
-
function escapeRegExp(val) {
|
|
684
|
-
return val.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
|
685
|
-
}
|
|
686
681
|
/**
|
|
687
682
|
* determines if a given template string contains line breaks
|
|
688
683
|
*/
|
|
@@ -710,19 +705,43 @@ function getTemplates(template) {
|
|
|
710
705
|
const parsed = parseTemplate(template);
|
|
711
706
|
if (parsed.tree !== undefined) {
|
|
712
707
|
const visitor = new TemplateCollector();
|
|
713
|
-
|
|
714
|
-
// count usages of each ng-template
|
|
708
|
+
compiler.visitAll$1(visitor, parsed.tree.rootNodes);
|
|
715
709
|
for (let [key, tmpl] of visitor.templates) {
|
|
716
|
-
|
|
717
|
-
const regex = new RegExp(`[^a-zA-Z0-9-<(\']${escapeKey}\\W`, 'gm');
|
|
718
|
-
const matches = template.match(regex);
|
|
719
|
-
tmpl.count = matches?.length ?? 0;
|
|
710
|
+
tmpl.count = countTemplateUsage(parsed.tree.rootNodes, key);
|
|
720
711
|
tmpl.generateContents(template);
|
|
721
712
|
}
|
|
722
713
|
return visitor.templates;
|
|
723
714
|
}
|
|
724
715
|
return new Map();
|
|
725
716
|
}
|
|
717
|
+
function countTemplateUsage(nodes, templateName) {
|
|
718
|
+
let count = 0;
|
|
719
|
+
let isReferencedInTemplateOutlet = false;
|
|
720
|
+
for (const node of nodes) {
|
|
721
|
+
if (node.attrs) {
|
|
722
|
+
for (const attr of node.attrs) {
|
|
723
|
+
if (attr.name === '*ngTemplateOutlet' && attr.value === templateName.slice(1)) {
|
|
724
|
+
isReferencedInTemplateOutlet = true;
|
|
725
|
+
break;
|
|
726
|
+
}
|
|
727
|
+
if (attr.name.trim() === templateName) {
|
|
728
|
+
count++;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
if (node.children) {
|
|
733
|
+
if (node.name === 'for') {
|
|
734
|
+
for (const child of node.children) {
|
|
735
|
+
if (child.value?.includes(templateName.slice(1))) {
|
|
736
|
+
count++;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
count += countTemplateUsage(node.children, templateName);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
return isReferencedInTemplateOutlet ? count + 2 : count;
|
|
744
|
+
}
|
|
726
745
|
function updateTemplates(template, templates) {
|
|
727
746
|
const updatedTemplates = getTemplates(template);
|
|
728
747
|
for (let [key, tmpl] of updatedTemplates) {
|
|
@@ -772,8 +791,8 @@ function processNgTemplates(template, sourceFile) {
|
|
|
772
791
|
else {
|
|
773
792
|
template = template.replace(replaceRegex, t.children);
|
|
774
793
|
}
|
|
775
|
-
|
|
776
|
-
if (t.count === matches.length
|
|
794
|
+
const dist = matches.filter((obj, index, self) => index === self.findIndex((t) => t.input === obj.input));
|
|
795
|
+
if ((t.count === dist.length || t.count - matches.length === 1) && safeToRemove) {
|
|
777
796
|
const refsInComponentFile = getViewChildOrViewChildrenNames(sourceFile);
|
|
778
797
|
if (refsInComponentFile?.length > 0) {
|
|
779
798
|
const templateRefs = getTemplateReferences(template);
|
|
@@ -862,7 +881,7 @@ function canRemoveCommonModule(template) {
|
|
|
862
881
|
let removeCommonModule = false;
|
|
863
882
|
if (parsed.tree !== undefined) {
|
|
864
883
|
const visitor = new CommonCollector();
|
|
865
|
-
|
|
884
|
+
compiler.visitAll$1(visitor, parsed.tree.rootNodes);
|
|
866
885
|
removeCommonModule = visitor.count === 0;
|
|
867
886
|
}
|
|
868
887
|
return removeCommonModule;
|
|
@@ -985,7 +1004,7 @@ function generateI18nMarkers(tmpl) {
|
|
|
985
1004
|
let parsed = parseTemplate(tmpl);
|
|
986
1005
|
if (parsed.tree !== undefined) {
|
|
987
1006
|
const visitor = new i18nCollector();
|
|
988
|
-
|
|
1007
|
+
compiler.visitAll$1(visitor, parsed.tree.rootNodes);
|
|
989
1008
|
for (const [ix, el] of visitor.elements.entries()) {
|
|
990
1009
|
// we only care about elements with children and i18n tags
|
|
991
1010
|
// elements without children have nothing to translate
|
|
@@ -1187,7 +1206,7 @@ function migrateCase(template) {
|
|
|
1187
1206
|
}
|
|
1188
1207
|
let result = template;
|
|
1189
1208
|
const visitor = new ElementCollector(cases);
|
|
1190
|
-
|
|
1209
|
+
compiler.visitAll$1(visitor, parsed.tree.rootNodes);
|
|
1191
1210
|
calculateNesting(visitor, hasLineBreaks(template));
|
|
1192
1211
|
// this tracks the character shift from different lengths of blocks from
|
|
1193
1212
|
// the prior directives so as to adjust for nested block replacement during
|
|
@@ -1284,7 +1303,7 @@ function migrateFor(template) {
|
|
|
1284
1303
|
}
|
|
1285
1304
|
let result = template;
|
|
1286
1305
|
const visitor = new ElementCollector(fors);
|
|
1287
|
-
|
|
1306
|
+
compiler.visitAll$1(visitor, parsed.tree.rootNodes);
|
|
1288
1307
|
calculateNesting(visitor, hasLineBreaks(template));
|
|
1289
1308
|
// this tracks the character shift from different lengths of blocks from
|
|
1290
1309
|
// the prior directives so as to adjust for nested block replacement during
|
|
@@ -1489,7 +1508,7 @@ function migrateIf(template) {
|
|
|
1489
1508
|
}
|
|
1490
1509
|
let result = template;
|
|
1491
1510
|
const visitor = new ElementCollector(ifs);
|
|
1492
|
-
|
|
1511
|
+
compiler.visitAll$1(visitor, parsed.tree.rootNodes);
|
|
1493
1512
|
calculateNesting(visitor, hasLineBreaks(template));
|
|
1494
1513
|
// this tracks the character shift from different lengths of blocks from
|
|
1495
1514
|
// the prior directives so as to adjust for nested block replacement during
|
|
@@ -1682,7 +1701,7 @@ function migrateSwitch(template) {
|
|
|
1682
1701
|
}
|
|
1683
1702
|
let result = template;
|
|
1684
1703
|
const visitor = new ElementCollector(switches);
|
|
1685
|
-
|
|
1704
|
+
compiler.visitAll$1(visitor, parsed.tree.rootNodes);
|
|
1686
1705
|
calculateNesting(visitor, hasLineBreaks(template));
|
|
1687
1706
|
// this tracks the character shift from different lengths of blocks from
|
|
1688
1707
|
// the prior directives so as to adjust for nested block replacement during
|
|
@@ -1713,11 +1732,11 @@ function migrateSwitch(template) {
|
|
|
1713
1732
|
}
|
|
1714
1733
|
function assertValidSwitchStructure(children) {
|
|
1715
1734
|
for (const child of children) {
|
|
1716
|
-
if (child instanceof
|
|
1735
|
+
if (child instanceof compiler.Text && child.value.trim() !== '') {
|
|
1717
1736
|
throw new Error(`Text node: "${child.value}" would result in invalid migrated @switch block structure. ` +
|
|
1718
1737
|
`@switch can only have @case or @default as children.`);
|
|
1719
1738
|
}
|
|
1720
|
-
else if (child instanceof
|
|
1739
|
+
else if (child instanceof compiler.Element$1) {
|
|
1721
1740
|
let hasCase = false;
|
|
1722
1741
|
for (const attr of child.attrs) {
|
|
1723
1742
|
if (cases.includes(attr.name)) {
|
|
@@ -1815,20 +1834,17 @@ function migrateTemplate(template, templateType, node, file, format = true, anal
|
|
|
1815
1834
|
return { migrated, errors };
|
|
1816
1835
|
}
|
|
1817
1836
|
|
|
1818
|
-
function migrate(
|
|
1837
|
+
function migrate() {
|
|
1819
1838
|
return async (tree, context) => {
|
|
1839
|
+
const { buildPaths, testPaths } = await project_tsconfig_paths.getProjectTsConfigPaths(tree);
|
|
1820
1840
|
const basePath = process.cwd();
|
|
1821
|
-
const
|
|
1822
|
-
let allPaths = [];
|
|
1823
|
-
if (pathToMigrate.trim() !== '') {
|
|
1824
|
-
allPaths.push(pathToMigrate);
|
|
1825
|
-
}
|
|
1841
|
+
const allPaths = [...buildPaths, ...testPaths];
|
|
1826
1842
|
if (!allPaths.length) {
|
|
1827
|
-
throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run the
|
|
1843
|
+
throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run the http providers migration.');
|
|
1828
1844
|
}
|
|
1829
1845
|
let errors = [];
|
|
1830
1846
|
for (const tsconfigPath of allPaths) {
|
|
1831
|
-
const migrateErrors = runControlFlowMigration(tree, tsconfigPath, basePath
|
|
1847
|
+
const migrateErrors = runControlFlowMigration(tree, tsconfigPath, basePath);
|
|
1832
1848
|
errors = [...errors, ...migrateErrors];
|
|
1833
1849
|
}
|
|
1834
1850
|
if (errors.length > 0) {
|
|
@@ -1839,18 +1855,11 @@ function migrate(options) {
|
|
|
1839
1855
|
}
|
|
1840
1856
|
};
|
|
1841
1857
|
}
|
|
1842
|
-
function runControlFlowMigration(tree, tsconfigPath, basePath
|
|
1843
|
-
if (schematicOptions.path.startsWith('..')) {
|
|
1844
|
-
throw new schematics.SchematicsException('Cannot run control flow migration outside of the current project.');
|
|
1845
|
-
}
|
|
1858
|
+
function runControlFlowMigration(tree, tsconfigPath, basePath) {
|
|
1846
1859
|
const program = compiler_host.createMigrationProgram(tree, tsconfigPath, basePath);
|
|
1847
1860
|
const sourceFiles = program
|
|
1848
1861
|
.getSourceFiles()
|
|
1849
|
-
.filter((sourceFile) =>
|
|
1850
|
-
compiler_host.canMigrateFile(basePath, sourceFile, program));
|
|
1851
|
-
if (sourceFiles.length === 0) {
|
|
1852
|
-
throw new schematics.SchematicsException(`Could not find any files to migrate under the path ${pathToMigrate}. Cannot run the control flow migration.`);
|
|
1853
|
-
}
|
|
1862
|
+
.filter((sourceFile) => compiler_host.canMigrateFile(basePath, sourceFile, program));
|
|
1854
1863
|
const analysis = new Map();
|
|
1855
1864
|
const migrateErrors = new Map();
|
|
1856
1865
|
for (const sourceFile of sourceFiles) {
|
|
@@ -1868,7 +1877,7 @@ function runControlFlowMigration(tree, tsconfigPath, basePath, pathToMigrate, sc
|
|
|
1868
1877
|
for (const { start, end, node, type } of ranges) {
|
|
1869
1878
|
const template = content.slice(start, end);
|
|
1870
1879
|
const length = (end ?? content.length) - start;
|
|
1871
|
-
const { migrated, errors } = migrateTemplate(template, type, node, file,
|
|
1880
|
+
const { migrated, errors } = migrateTemplate(template, type, node, file, true, analysis);
|
|
1872
1881
|
if (migrated !== null) {
|
|
1873
1882
|
update.remove(start, length);
|
|
1874
1883
|
update.insertLeft(start, migrated);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* @license Angular v20.0.0-next.5
|
|
4
|
+
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
|
+
* License: MIT
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
require('./compiler-CuoiHqkc.js');
|
|
10
|
+
require('typescript');
|
|
11
|
+
var checker = require('./checker-DqUKCGda.js');
|
|
12
|
+
require('os');
|
|
13
|
+
var apply_import_manager = require('./apply_import_manager-C-ysxahq.js');
|
|
14
|
+
require('./index-WFXCe5Q0.js');
|
|
15
|
+
require('path');
|
|
16
|
+
var run_in_devkit = require('./run_in_devkit-CmHxABFr.js');
|
|
17
|
+
var imports = require('./imports-CIX-JgAN.js');
|
|
18
|
+
require('@angular-devkit/core');
|
|
19
|
+
require('node:path/posix');
|
|
20
|
+
require('fs');
|
|
21
|
+
require('module');
|
|
22
|
+
require('url');
|
|
23
|
+
require('@angular-devkit/schematics');
|
|
24
|
+
require('./project_tsconfig_paths-CDVxT6Ov.js');
|
|
25
|
+
|
|
26
|
+
/** Migration that moves the import of `DOCUMENT` from `core` to `common`. */
|
|
27
|
+
class DocumentCoreMigration extends run_in_devkit.TsurgeFunnelMigration {
|
|
28
|
+
async analyze(info) {
|
|
29
|
+
const replacements = [];
|
|
30
|
+
let importManager = null;
|
|
31
|
+
for (const sourceFile of info.sourceFiles) {
|
|
32
|
+
const specifier = imports.getImportSpecifier(sourceFile, '@angular/common', 'DOCUMENT');
|
|
33
|
+
if (specifier === null) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
importManager ??= new checker.ImportManager({
|
|
37
|
+
// Prevent the manager from trying to generate a non-conflicting import.
|
|
38
|
+
generateUniqueIdentifier: () => null,
|
|
39
|
+
shouldUseSingleQuotes: () => true,
|
|
40
|
+
});
|
|
41
|
+
importManager.removeImport(sourceFile, 'DOCUMENT', '@angular/common');
|
|
42
|
+
importManager.addImport({
|
|
43
|
+
exportSymbolName: 'DOCUMENT',
|
|
44
|
+
exportModuleSpecifier: '@angular/core',
|
|
45
|
+
requestedFile: sourceFile,
|
|
46
|
+
unsafeAliasOverride: specifier.propertyName ? specifier.name.text : undefined,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (importManager !== null) {
|
|
50
|
+
apply_import_manager.applyImportManagerChanges(importManager, replacements, info.sourceFiles, info);
|
|
51
|
+
}
|
|
52
|
+
return run_in_devkit.confirmAsSerializable({ replacements });
|
|
53
|
+
}
|
|
54
|
+
async migrate(globalData) {
|
|
55
|
+
return run_in_devkit.confirmAsSerializable(globalData);
|
|
56
|
+
}
|
|
57
|
+
async combine(unitA, unitB) {
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
const combined = [];
|
|
60
|
+
[unitA.replacements, unitB.replacements].forEach((replacements) => {
|
|
61
|
+
replacements.forEach((current) => {
|
|
62
|
+
const { position, end, toInsert } = current.update.data;
|
|
63
|
+
const key = current.projectFile.id + '/' + position + '/' + end + '/' + toInsert;
|
|
64
|
+
if (!seen.has(key)) {
|
|
65
|
+
seen.add(key);
|
|
66
|
+
combined.push(current);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
return run_in_devkit.confirmAsSerializable({ replacements: combined });
|
|
71
|
+
}
|
|
72
|
+
async globalMeta(combinedData) {
|
|
73
|
+
return run_in_devkit.confirmAsSerializable(combinedData);
|
|
74
|
+
}
|
|
75
|
+
async stats() {
|
|
76
|
+
return { counters: {} };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/*!
|
|
81
|
+
* @license
|
|
82
|
+
* Copyright Google LLC All Rights Reserved.
|
|
83
|
+
*
|
|
84
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
85
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
86
|
+
*/
|
|
87
|
+
function migrate() {
|
|
88
|
+
return async (tree) => {
|
|
89
|
+
await run_in_devkit.runMigrationInDevkit({
|
|
90
|
+
tree,
|
|
91
|
+
getMigration: () => new DocumentCoreMigration(),
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
exports.migrate = migrate;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v20.0.0-next.
|
|
3
|
+
* @license Angular v20.0.0-next.5
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
var ts = require('typescript');
|
|
10
10
|
require('os');
|
|
11
|
-
var checker = require('./checker-
|
|
12
|
-
var
|
|
11
|
+
var checker = require('./checker-DqUKCGda.js');
|
|
12
|
+
var compiler = require('./compiler-CuoiHqkc.js');
|
|
13
|
+
var index = require('./index-WFXCe5Q0.js');
|
|
13
14
|
require('path');
|
|
14
|
-
var run_in_devkit = require('./run_in_devkit-
|
|
15
|
+
var run_in_devkit = require('./run_in_devkit-CmHxABFr.js');
|
|
15
16
|
|
|
16
17
|
function getMemberName(member) {
|
|
17
18
|
if (member.name === undefined) {
|
|
@@ -188,7 +189,7 @@ function lookupPropertyAccess(checker, type, path, options = {}) {
|
|
|
188
189
|
* This resolution is important to be able to migrate references to inputs
|
|
189
190
|
* that will be migrated to signal inputs.
|
|
190
191
|
*/
|
|
191
|
-
class TemplateReferenceVisitor extends
|
|
192
|
+
class TemplateReferenceVisitor extends compiler.RecursiveVisitor {
|
|
192
193
|
result = [];
|
|
193
194
|
/**
|
|
194
195
|
* Whether we are currently descending into HTML AST nodes
|
|
@@ -235,21 +236,21 @@ class TemplateReferenceVisitor extends checker.RecursiveVisitor$1 {
|
|
|
235
236
|
// of signal calls in templates.
|
|
236
237
|
// TODO: Remove with: https://github.com/angular/angular/pull/55456.
|
|
237
238
|
this.templateAttributeReferencedFields = [];
|
|
238
|
-
|
|
239
|
-
|
|
239
|
+
compiler.visitAll(this, template.attributes);
|
|
240
|
+
compiler.visitAll(this, template.templateAttrs);
|
|
240
241
|
// If we are dealing with a microsyntax template, do not check
|
|
241
242
|
// inputs and outputs as those are already passed to the children.
|
|
242
243
|
// Template attributes may contain relevant expressions though.
|
|
243
244
|
if (template.tagName === 'ng-template') {
|
|
244
|
-
|
|
245
|
-
|
|
245
|
+
compiler.visitAll(this, template.inputs);
|
|
246
|
+
compiler.visitAll(this, template.outputs);
|
|
246
247
|
}
|
|
247
248
|
const referencedInputs = this.templateAttributeReferencedFields;
|
|
248
249
|
this.templateAttributeReferencedFields = null;
|
|
249
250
|
this.descendAndCheckForNarrowedSimilarReferences(referencedInputs, () => {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
251
|
+
compiler.visitAll(this, template.children);
|
|
252
|
+
compiler.visitAll(this, template.references);
|
|
253
|
+
compiler.visitAll(this, template.variables);
|
|
253
254
|
});
|
|
254
255
|
}
|
|
255
256
|
visitIfBlockBranch(block) {
|
|
@@ -316,7 +317,7 @@ class TemplateReferenceVisitor extends checker.RecursiveVisitor$1 {
|
|
|
316
317
|
* This resolution is important to be able to migrate references to inputs
|
|
317
318
|
* that will be migrated to signal inputs.
|
|
318
319
|
*/
|
|
319
|
-
class TemplateExpressionReferenceVisitor extends
|
|
320
|
+
class TemplateExpressionReferenceVisitor extends compiler.RecursiveAstVisitor {
|
|
320
321
|
typeChecker;
|
|
321
322
|
templateTypeChecker;
|
|
322
323
|
componentClass;
|
|
@@ -382,7 +383,7 @@ class TemplateExpressionReferenceVisitor extends checker.RecursiveAstVisitor {
|
|
|
382
383
|
!this.fieldNamesToConsiderForReferenceLookup.has(ast.name)) {
|
|
383
384
|
return;
|
|
384
385
|
}
|
|
385
|
-
const isWrite = !!(ast instanceof
|
|
386
|
+
const isWrite = !!(ast instanceof compiler.PropertyWrite ||
|
|
386
387
|
(this.activeTmplAstNode && isTwoWayBindingNode(this.activeTmplAstNode)));
|
|
387
388
|
this._checkAccessViaTemplateTypeCheckBlock(ast, isWrite, astPath) ||
|
|
388
389
|
this._checkAccessViaOwningComponentClassType(ast, isWrite, astPath);
|
|
@@ -459,9 +460,9 @@ class TemplateExpressionReferenceVisitor extends checker.RecursiveAstVisitor {
|
|
|
459
460
|
_isPartOfNarrowingTernary(read) {
|
|
460
461
|
// Note: We do not safe check that the reads are fully matching 1:1. This is acceptable
|
|
461
462
|
// as worst case we just skip an input from being migrated. This is very unlikely too.
|
|
462
|
-
return this.insideConditionalExpressionsWithReads.some((r) => (r instanceof
|
|
463
|
-
r instanceof
|
|
464
|
-
r instanceof
|
|
463
|
+
return this.insideConditionalExpressionsWithReads.some((r) => (r instanceof compiler.PropertyRead ||
|
|
464
|
+
r instanceof compiler.PropertyWrite ||
|
|
465
|
+
r instanceof compiler.SafePropertyRead) &&
|
|
465
466
|
r.name === read.name);
|
|
466
467
|
}
|
|
467
468
|
}
|
|
@@ -469,18 +470,18 @@ class TemplateExpressionReferenceVisitor extends checker.RecursiveAstVisitor {
|
|
|
469
470
|
* Emulates an access to a given field using the TypeScript `ts.Type`
|
|
470
471
|
* of the given class. The resolved symbol of the access is returned.
|
|
471
472
|
*/
|
|
472
|
-
function traverseReceiverAndLookupSymbol(readOrWrite, componentClass, checker
|
|
473
|
+
function traverseReceiverAndLookupSymbol(readOrWrite, componentClass, checker) {
|
|
473
474
|
const path = [readOrWrite.name];
|
|
474
475
|
let node = readOrWrite;
|
|
475
|
-
while (node.receiver instanceof
|
|
476
|
+
while (node.receiver instanceof compiler.PropertyRead || node.receiver instanceof compiler.PropertyWrite) {
|
|
476
477
|
node = node.receiver;
|
|
477
478
|
path.unshift(node.name);
|
|
478
479
|
}
|
|
479
|
-
if (!(node.receiver instanceof
|
|
480
|
+
if (!(node.receiver instanceof compiler.ImplicitReceiver || node.receiver instanceof compiler.ThisReceiver)) {
|
|
480
481
|
return null;
|
|
481
482
|
}
|
|
482
|
-
const classType = checker
|
|
483
|
-
return (lookupPropertyAccess(checker
|
|
483
|
+
const classType = checker.getTypeAtLocation(componentClass.name);
|
|
484
|
+
return (lookupPropertyAccess(checker, classType, path, {
|
|
484
485
|
// Necessary to avoid breaking the resolution if there is
|
|
485
486
|
// some narrowing involved. E.g. `myClass ? myClass.input`.
|
|
486
487
|
ignoreNullability: true,
|
|
@@ -488,8 +489,8 @@ function traverseReceiverAndLookupSymbol(readOrWrite, componentClass, checker$1)
|
|
|
488
489
|
}
|
|
489
490
|
/** Whether the given node refers to a two-way binding AST node. */
|
|
490
491
|
function isTwoWayBindingNode(node) {
|
|
491
|
-
return ((node instanceof
|
|
492
|
-
(node instanceof
|
|
492
|
+
return ((node instanceof compiler.BoundAttribute && node.type === compiler.BindingType.TwoWay) ||
|
|
493
|
+
(node instanceof compiler.BoundEvent && node.type === compiler.ParsedEventType.TwoWay));
|
|
493
494
|
}
|
|
494
495
|
|
|
495
496
|
/** Possible types of references to known fields detected. */
|
|
@@ -581,11 +582,11 @@ function identifyHostBindingReferences(node, programInfo, checker$1, reflector,
|
|
|
581
582
|
if (!isPropertyBinding && !isEventBinding) {
|
|
582
583
|
continue;
|
|
583
584
|
}
|
|
584
|
-
const parser =
|
|
585
|
-
const sourceSpan = new
|
|
585
|
+
const parser = compiler.makeBindingParser();
|
|
586
|
+
const sourceSpan = new compiler.ParseSourceSpan(
|
|
586
587
|
// Fake source span to keep parsing offsets zero-based.
|
|
587
588
|
// We then later combine these with the expression TS node offsets.
|
|
588
|
-
new
|
|
589
|
+
new compiler.ParseLocation({ content: '', url: '' }, 0, 0, 0), new compiler.ParseLocation({ content: '', url: '' }, 0, 0, 0));
|
|
589
590
|
const name = rawName.substring(1, rawName.length - 1);
|
|
590
591
|
let parsed = undefined;
|
|
591
592
|
if (isEventBinding) {
|
|
@@ -649,7 +650,7 @@ function attemptExtractTemplateDefinition(node, checker$1, reflector, resourceLo
|
|
|
649
650
|
return {
|
|
650
651
|
isInline: true,
|
|
651
652
|
expression: templateProp,
|
|
652
|
-
interpolationConfig:
|
|
653
|
+
interpolationConfig: compiler.DEFAULT_INTERPOLATION_CONFIG,
|
|
653
654
|
preserveWhitespaces: false,
|
|
654
655
|
resolvedTemplateUrl: containingFile,
|
|
655
656
|
templateUrl: containingFile,
|
|
@@ -663,7 +664,7 @@ function attemptExtractTemplateDefinition(node, checker$1, reflector, resourceLo
|
|
|
663
664
|
if (typeof templateUrl === 'string') {
|
|
664
665
|
return {
|
|
665
666
|
isInline: false,
|
|
666
|
-
interpolationConfig:
|
|
667
|
+
interpolationConfig: compiler.DEFAULT_INTERPOLATION_CONFIG,
|
|
667
668
|
preserveWhitespaces: false,
|
|
668
669
|
templateUrlExpression: templateUrlProp,
|
|
669
670
|
templateUrl,
|