@angular/core 20.0.0-next.4 → 20.0.0-next.6
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-DQLNOR5l.d.ts +297 -0
- package/discovery.d-CFs2MaLO.d.ts +7383 -0
- package/{event_dispatcher.d-pVP0-wST.d.ts → event_dispatcher.d-DlbccpYq.d.ts} +3 -2
- package/fesm2022/attribute-BWp59EjE.mjs +24 -0
- package/fesm2022/attribute-BWp59EjE.mjs.map +1 -0
- package/fesm2022/core.mjs +586 -36873
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/debug_node-z_3NG8qT.mjs +32079 -0
- package/fesm2022/debug_node-z_3NG8qT.mjs.map +1 -0
- package/fesm2022/primitives/di.mjs +18 -4
- 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 -3
- package/fesm2022/primitives/signals.mjs.map +1 -1
- package/fesm2022/resource-CPPwEcg7.mjs +619 -0
- package/fesm2022/resource-CPPwEcg7.mjs.map +1 -0
- package/fesm2022/root_effect_scheduler-VSXfCzDX.mjs +3847 -0
- package/fesm2022/root_effect_scheduler-VSXfCzDX.mjs.map +1 -0
- package/fesm2022/rxjs-interop.mjs +16 -9
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/{untracked-DkcXpNb_.mjs → signal-B6pMq7KS.mjs} +16 -114
- package/fesm2022/signal-B6pMq7KS.mjs.map +1 -0
- package/fesm2022/testing.mjs +265 -201
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/untracked-Bz5WMeU1.mjs +117 -0
- package/fesm2022/untracked-Bz5WMeU1.mjs.map +1 -0
- package/fesm2022/weak_ref-BaIq-pgY.mjs +12 -0
- package/fesm2022/weak_ref-BaIq-pgY.mjs.map +1 -0
- package/{weak_ref.d-BZ7gyRag.d.ts → graph.d-BcIOep_B.d.ts} +3 -24
- package/index.d.ts +2624 -10909
- package/ng_i18n_closure_mode.d-C9d2CaSt.d.ts +832 -0
- package/package.json +3 -3
- package/primitives/di/index.d.ts +3 -2
- package/primitives/event-dispatch/index.d.ts +3 -3
- package/primitives/signals/index.d.ts +8 -4
- package/rxjs-interop/index.d.ts +10 -7
- package/schematics/bundles/{apply_import_manager-CeNv8GIG.js → apply_import_manager-DnMqg1pY.js} +6 -6
- package/schematics/bundles/{compiler_host-DwM3ugW3.js → change_tracker-UMPkv-eH.js} +3 -121
- package/schematics/bundles/checker-BFBQyesT.js +17719 -0
- package/schematics/bundles/cleanup-unused-imports.js +25 -19
- package/schematics/bundles/{checker-k591b6WQ.js → compiler-BQ7R7w2v.js} +1325 -18286
- package/schematics/bundles/compiler_host-CAfDJO3W.js +129 -0
- package/schematics/bundles/control-flow-migration.js +28 -40
- package/schematics/bundles/document-core.js +96 -0
- package/schematics/bundles/imports-CIX-JgAN.js +1 -1
- package/schematics/bundles/{index-B4OAlHh8.js → index-Cv4Q415G.js} +641 -547
- package/schematics/bundles/{index-BhELUmYx.js → index-D8tMJPKa.js} +35 -34
- package/schematics/bundles/inject-flags.js +14 -13
- package/schematics/bundles/inject-migration.js +29 -10
- package/schematics/bundles/leading_space-D9nQ8UQC.js +1 -1
- package/schematics/bundles/{migrate_ts_type_references-Be0TNYen.js → migrate_ts_type_references-Cq_ZBuT4.js} +21 -20
- package/schematics/bundles/ng_decorators-DznZ5jMl.js +1 -1
- package/schematics/bundles/nodes-B16H9JUd.js +1 -1
- package/schematics/bundles/output-migration.js +88 -25
- package/schematics/bundles/{run_in_devkit-CkvEksWP.js → project_paths-ql6qcf_c.js} +254 -243
- 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/self-closing-tags-migration.js +25 -19
- package/schematics/bundles/signal-input-migration.js +26 -20
- package/schematics/bundles/signal-queries-migration.js +51 -33
- 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 +13 -12
- package/schematics/collection.json +0 -6
- package/schematics/migrations.json +11 -0
- package/signal.d-E0e5nW1p.d.ts +31 -0
- package/testing/index.d.ts +16 -28
- package/weak_ref.d-eGOEP9S1.d.ts +9 -0
- package/fesm2022/injector-BlLwZ2sr.mjs +0 -24
- package/fesm2022/injector-BlLwZ2sr.mjs.map +0 -1
- package/fesm2022/untracked-DkcXpNb_.mjs.map +0 -1
- package/navigation_types.d-DgDrF5rp.d.ts +0 -121
- package/schematics/ng-generate/control-flow-migration/schema.json +0 -20
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v20.0.0-next.
|
|
3
|
+
* @license Angular v20.0.0-next.6
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
var
|
|
10
|
-
var ts = require('typescript');
|
|
11
|
-
var checker = require('./checker-k591b6WQ.js');
|
|
12
|
-
var index = require('./index-B4OAlHh8.js');
|
|
9
|
+
var index = require('./index-Cv4Q415G.js');
|
|
13
10
|
var schematics = require('@angular-devkit/schematics');
|
|
14
11
|
var core = require('@angular-devkit/core');
|
|
15
12
|
var posixPath = require('node:path/posix');
|
|
13
|
+
var os = require('os');
|
|
14
|
+
var ts = require('typescript');
|
|
15
|
+
var checker = require('./checker-BFBQyesT.js');
|
|
16
|
+
require('./compiler-BQ7R7w2v.js');
|
|
16
17
|
require('path');
|
|
17
18
|
var project_tsconfig_paths = require('./project_tsconfig_paths-CDVxT6Ov.js');
|
|
18
19
|
|
|
@@ -33,8 +34,8 @@ function _interopNamespaceDefault(e) {
|
|
|
33
34
|
return Object.freeze(n);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
|
|
37
37
|
var posixPath__namespace = /*#__PURE__*/_interopNamespaceDefault(posixPath);
|
|
38
|
+
var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
|
|
38
39
|
|
|
39
40
|
/// <reference types="node" />
|
|
40
41
|
class NgtscCompilerHost {
|
|
@@ -260,235 +261,6 @@ function getExtendedConfigPathWorker(configFile, extendsValue, host, fs) {
|
|
|
260
261
|
return null;
|
|
261
262
|
}
|
|
262
263
|
|
|
263
|
-
/**
|
|
264
|
-
* By default, Tsurge will always create an Angular compiler program
|
|
265
|
-
* for projects analyzed and migrated. This works perfectly fine in
|
|
266
|
-
* third-party where Tsurge migrations run in Angular CLI projects.
|
|
267
|
-
*
|
|
268
|
-
* In first party, when running against full Google3, creating an Angular
|
|
269
|
-
* program for e.g. plain `ts_library` targets is overly expensive and
|
|
270
|
-
* can result in out of memory issues for large TS targets. In 1P we can
|
|
271
|
-
* reliably distinguish between TS and Angular targets via the `angularCompilerOptions`.
|
|
272
|
-
*/
|
|
273
|
-
function google3UsePlainTsProgramIfNoKnownAngularOption() {
|
|
274
|
-
return process.env['GOOGLE3_TSURGE'] === '1';
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/** Options that are good defaults for Tsurge migrations. */
|
|
278
|
-
const defaultMigrationTsOptions = {
|
|
279
|
-
// Avoid checking libraries to speed up migrations.
|
|
280
|
-
skipLibCheck: true,
|
|
281
|
-
skipDefaultLibCheck: true,
|
|
282
|
-
noEmit: true,
|
|
283
|
-
// Does not apply to g3 and externally is enforced when the app is built by the compiler.
|
|
284
|
-
disableTypeScriptVersionCheck: true,
|
|
285
|
-
};
|
|
286
|
-
/**
|
|
287
|
-
* Creates an instance of a TypeScript program for the given project.
|
|
288
|
-
*/
|
|
289
|
-
function createPlainTsProgram(tsHost, tsconfig, optionOverrides) {
|
|
290
|
-
const program = ts.createProgram({
|
|
291
|
-
rootNames: tsconfig.rootNames,
|
|
292
|
-
options: {
|
|
293
|
-
...tsconfig.options,
|
|
294
|
-
...defaultMigrationTsOptions,
|
|
295
|
-
...optionOverrides,
|
|
296
|
-
},
|
|
297
|
-
});
|
|
298
|
-
return {
|
|
299
|
-
ngCompiler: null,
|
|
300
|
-
program,
|
|
301
|
-
userOptions: tsconfig.options,
|
|
302
|
-
programAbsoluteRootFileNames: tsconfig.rootNames,
|
|
303
|
-
host: tsHost,
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Parses the configuration of the given TypeScript project and creates
|
|
309
|
-
* an instance of the Angular compiler for the project.
|
|
310
|
-
*/
|
|
311
|
-
function createNgtscProgram(tsHost, tsconfig, optionOverrides) {
|
|
312
|
-
const ngtscProgram = new index.NgtscProgram(tsconfig.rootNames, {
|
|
313
|
-
...tsconfig.options,
|
|
314
|
-
...defaultMigrationTsOptions,
|
|
315
|
-
...optionOverrides,
|
|
316
|
-
}, tsHost);
|
|
317
|
-
// Expose an easy way to debug-print ng semantic diagnostics.
|
|
318
|
-
if (process.env['DEBUG_NG_SEMANTIC_DIAGNOSTICS'] === '1') {
|
|
319
|
-
console.error(ts.formatDiagnosticsWithColorAndContext(ngtscProgram.getNgSemanticDiagnostics(), tsHost));
|
|
320
|
-
}
|
|
321
|
-
return {
|
|
322
|
-
ngCompiler: ngtscProgram.compiler,
|
|
323
|
-
program: ngtscProgram.getTsProgram(),
|
|
324
|
-
userOptions: tsconfig.options,
|
|
325
|
-
programAbsoluteRootFileNames: tsconfig.rootNames,
|
|
326
|
-
host: tsHost,
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/** Code of the error raised by TypeScript when a tsconfig doesn't match any files. */
|
|
331
|
-
const NO_INPUTS_ERROR_CODE = 18003;
|
|
332
|
-
/** Parses the given tsconfig file, supporting Angular compiler options. */
|
|
333
|
-
function parseTsconfigOrDie(absoluteTsconfigPath, fs) {
|
|
334
|
-
const tsconfig = readConfiguration(absoluteTsconfigPath, {}, fs);
|
|
335
|
-
// Skip the "No inputs found..." error since we don't want to interrupt the migration if a
|
|
336
|
-
// tsconfig doesn't match a file. This will result in an empty `Program` which is still valid.
|
|
337
|
-
const errors = tsconfig.errors.filter((diag) => diag.code !== NO_INPUTS_ERROR_CODE);
|
|
338
|
-
if (errors.length) {
|
|
339
|
-
throw new Error(`Tsconfig could not be parsed or is invalid:\n\n` + `${errors.map((e) => e.messageText)}`);
|
|
340
|
-
}
|
|
341
|
-
return tsconfig;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/** Creates the base program info for the given tsconfig path. */
|
|
345
|
-
function createBaseProgramInfo(absoluteTsconfigPath, fs, optionOverrides = {}) {
|
|
346
|
-
if (fs === undefined) {
|
|
347
|
-
fs = new checker.NodeJSFileSystem();
|
|
348
|
-
checker.setFileSystem(fs);
|
|
349
|
-
}
|
|
350
|
-
const tsconfig = parseTsconfigOrDie(absoluteTsconfigPath, fs);
|
|
351
|
-
const tsHost = new NgtscCompilerHost(fs, tsconfig.options);
|
|
352
|
-
// When enabled, use a plain TS program if we are sure it's not
|
|
353
|
-
// an Angular project based on the `tsconfig.json`.
|
|
354
|
-
if (google3UsePlainTsProgramIfNoKnownAngularOption() &&
|
|
355
|
-
tsconfig.options['_useHostForImportGeneration'] === undefined) {
|
|
356
|
-
return createPlainTsProgram(tsHost, tsconfig, optionOverrides);
|
|
357
|
-
}
|
|
358
|
-
return createNgtscProgram(tsHost, tsconfig, optionOverrides);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* @private
|
|
363
|
-
*
|
|
364
|
-
* Base class for the possible Tsurge migration variants.
|
|
365
|
-
*
|
|
366
|
-
* For example, this class exposes methods to conveniently create
|
|
367
|
-
* TypeScript programs, while also allowing migration authors to override.
|
|
368
|
-
*/
|
|
369
|
-
class TsurgeBaseMigration {
|
|
370
|
-
/**
|
|
371
|
-
* Advanced Tsurge users can override this method, but most of the time,
|
|
372
|
-
* overriding {@link prepareProgram} is more desirable.
|
|
373
|
-
*
|
|
374
|
-
* By default:
|
|
375
|
-
* - In 3P: Ngtsc programs are being created.
|
|
376
|
-
* - In 1P: Ngtsc or TS programs are created based on the Blaze target.
|
|
377
|
-
*/
|
|
378
|
-
createProgram(tsconfigAbsPath, fs, optionOverrides) {
|
|
379
|
-
return createBaseProgramInfo(tsconfigAbsPath, fs, optionOverrides);
|
|
380
|
-
}
|
|
381
|
-
// Optional function to prepare the base `ProgramInfo` even further,
|
|
382
|
-
// for the analyze and migrate phases. E.g. determining source files.
|
|
383
|
-
prepareProgram(info) {
|
|
384
|
-
const fullProgramSourceFiles = [...info.program.getSourceFiles()];
|
|
385
|
-
const sourceFiles = fullProgramSourceFiles.filter((f) => !f.isDeclarationFile &&
|
|
386
|
-
// Note `isShim` will work for the initial program, but for TCB programs, the shims are no longer annotated.
|
|
387
|
-
!checker.isShim(f) &&
|
|
388
|
-
!f.fileName.endsWith('.ngtypecheck.ts'));
|
|
389
|
-
// Sort it by length in reverse order (longest first). This speeds up lookups,
|
|
390
|
-
// since there's no need to keep going through the array once a match is found.
|
|
391
|
-
const sortedRootDirs = checker.getRootDirs(info.host, info.userOptions).sort((a, b) => b.length - a.length);
|
|
392
|
-
// TODO: Consider also following TS's logic here, finding the common source root.
|
|
393
|
-
// See: Program#getCommonSourceDirectory.
|
|
394
|
-
const primaryRoot = checker.absoluteFrom(info.userOptions.rootDir ?? sortedRootDirs.at(-1) ?? info.program.getCurrentDirectory());
|
|
395
|
-
return {
|
|
396
|
-
...info,
|
|
397
|
-
sourceFiles,
|
|
398
|
-
fullProgramSourceFiles,
|
|
399
|
-
sortedRootDirs,
|
|
400
|
-
projectRoot: primaryRoot,
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* A simpler variant of a {@link TsurgeComplexMigration} that does not
|
|
407
|
-
* fan-out into multiple workers per compilation unit to compute
|
|
408
|
-
* the final migration replacements.
|
|
409
|
-
*
|
|
410
|
-
* This is faster and less resource intensive as workers and TS programs
|
|
411
|
-
* are only ever created once.
|
|
412
|
-
*
|
|
413
|
-
* This is commonly the case when migrations are refactored to eagerly
|
|
414
|
-
* compute replacements in the analyze stage, and then leverage the
|
|
415
|
-
* global unit data to filter replacements that turned out to be "invalid".
|
|
416
|
-
*/
|
|
417
|
-
class TsurgeFunnelMigration extends TsurgeBaseMigration {
|
|
418
|
-
}
|
|
419
|
-
/**
|
|
420
|
-
* Complex variant of a `Tsurge` migration.
|
|
421
|
-
*
|
|
422
|
-
* For example, every analyze worker may contribute to a list of TS
|
|
423
|
-
* references that are later combined. The migrate phase can then compute actual
|
|
424
|
-
* file updates for all individual compilation units, leveraging the global metadata
|
|
425
|
-
* to e.g. see if there are any references from other compilation units that may be
|
|
426
|
-
* problematic and prevent migration of a given file.
|
|
427
|
-
*/
|
|
428
|
-
class TsurgeComplexMigration extends TsurgeBaseMigration {
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/** A text replacement for the given file. */
|
|
432
|
-
class Replacement {
|
|
433
|
-
projectFile;
|
|
434
|
-
update;
|
|
435
|
-
constructor(projectFile, update) {
|
|
436
|
-
this.projectFile = projectFile;
|
|
437
|
-
this.update = update;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
/** An isolated text update that may be applied to a file. */
|
|
441
|
-
class TextUpdate {
|
|
442
|
-
data;
|
|
443
|
-
constructor(data) {
|
|
444
|
-
this.data = data;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
/** Confirms that the given data `T` is serializable. */
|
|
449
|
-
function confirmAsSerializable(data) {
|
|
450
|
-
return data;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* Gets a project file instance for the given file.
|
|
455
|
-
*
|
|
456
|
-
* Use this helper for dealing with project paths throughout your
|
|
457
|
-
* migration. The return type is serializable.
|
|
458
|
-
*
|
|
459
|
-
* See {@link ProjectFile}.
|
|
460
|
-
*/
|
|
461
|
-
function projectFile(file, { sortedRootDirs, projectRoot }) {
|
|
462
|
-
const fs = checker.getFileSystem();
|
|
463
|
-
const filePath = fs.resolve(typeof file === 'string' ? file : file.fileName);
|
|
464
|
-
// Sorted root directories are sorted longest to shortest. First match
|
|
465
|
-
// is the appropriate root directory for ID computation.
|
|
466
|
-
for (const rootDir of sortedRootDirs) {
|
|
467
|
-
if (!isWithinBasePath(fs, rootDir, filePath)) {
|
|
468
|
-
continue;
|
|
469
|
-
}
|
|
470
|
-
return {
|
|
471
|
-
id: fs.relative(rootDir, filePath),
|
|
472
|
-
rootRelativePath: fs.relative(projectRoot, filePath),
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
// E.g. project directory may be `src/`, but files may be looked up
|
|
476
|
-
// from `node_modules/`. This is fine, but in those cases, no root
|
|
477
|
-
// directory matches.
|
|
478
|
-
const rootRelativePath = fs.relative(projectRoot, filePath);
|
|
479
|
-
return {
|
|
480
|
-
id: rootRelativePath,
|
|
481
|
-
rootRelativePath: rootRelativePath,
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Whether `path` is a descendant of the `base`?
|
|
486
|
-
* E.g. `a/b/c` is within `a/b` but not within `a/x`.
|
|
487
|
-
*/
|
|
488
|
-
function isWithinBasePath(fs, base, path) {
|
|
489
|
-
return checker.isLocalRelativePath(fs.relative(base, path));
|
|
490
|
-
}
|
|
491
|
-
|
|
492
264
|
/**
|
|
493
265
|
* Angular compiler file system implementation that leverages an
|
|
494
266
|
* CLI schematic virtual file tree.
|
|
@@ -670,6 +442,174 @@ async function synchronouslyCombineUnitData(migration, unitDatas) {
|
|
|
670
442
|
return combined;
|
|
671
443
|
}
|
|
672
444
|
|
|
445
|
+
/**
|
|
446
|
+
* By default, Tsurge will always create an Angular compiler program
|
|
447
|
+
* for projects analyzed and migrated. This works perfectly fine in
|
|
448
|
+
* third-party where Tsurge migrations run in Angular CLI projects.
|
|
449
|
+
*
|
|
450
|
+
* In first party, when running against full Google3, creating an Angular
|
|
451
|
+
* program for e.g. plain `ts_library` targets is overly expensive and
|
|
452
|
+
* can result in out of memory issues for large TS targets. In 1P we can
|
|
453
|
+
* reliably distinguish between TS and Angular targets via the `angularCompilerOptions`.
|
|
454
|
+
*/
|
|
455
|
+
function google3UsePlainTsProgramIfNoKnownAngularOption() {
|
|
456
|
+
return process.env['GOOGLE3_TSURGE'] === '1';
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/** Options that are good defaults for Tsurge migrations. */
|
|
460
|
+
const defaultMigrationTsOptions = {
|
|
461
|
+
// Avoid checking libraries to speed up migrations.
|
|
462
|
+
skipLibCheck: true,
|
|
463
|
+
skipDefaultLibCheck: true,
|
|
464
|
+
noEmit: true,
|
|
465
|
+
// Does not apply to g3 and externally is enforced when the app is built by the compiler.
|
|
466
|
+
disableTypeScriptVersionCheck: true,
|
|
467
|
+
};
|
|
468
|
+
/**
|
|
469
|
+
* Creates an instance of a TypeScript program for the given project.
|
|
470
|
+
*/
|
|
471
|
+
function createPlainTsProgram(tsHost, tsconfig, optionOverrides) {
|
|
472
|
+
const program = ts.createProgram({
|
|
473
|
+
rootNames: tsconfig.rootNames,
|
|
474
|
+
options: {
|
|
475
|
+
...tsconfig.options,
|
|
476
|
+
...defaultMigrationTsOptions,
|
|
477
|
+
...optionOverrides,
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
return {
|
|
481
|
+
ngCompiler: null,
|
|
482
|
+
program,
|
|
483
|
+
userOptions: tsconfig.options,
|
|
484
|
+
programAbsoluteRootFileNames: tsconfig.rootNames,
|
|
485
|
+
host: tsHost,
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Parses the configuration of the given TypeScript project and creates
|
|
491
|
+
* an instance of the Angular compiler for the project.
|
|
492
|
+
*/
|
|
493
|
+
function createNgtscProgram(tsHost, tsconfig, optionOverrides) {
|
|
494
|
+
const ngtscProgram = new index.NgtscProgram(tsconfig.rootNames, {
|
|
495
|
+
...tsconfig.options,
|
|
496
|
+
...defaultMigrationTsOptions,
|
|
497
|
+
...optionOverrides,
|
|
498
|
+
}, tsHost);
|
|
499
|
+
// Expose an easy way to debug-print ng semantic diagnostics.
|
|
500
|
+
if (process.env['DEBUG_NG_SEMANTIC_DIAGNOSTICS'] === '1') {
|
|
501
|
+
console.error(ts.formatDiagnosticsWithColorAndContext(ngtscProgram.getNgSemanticDiagnostics(), tsHost));
|
|
502
|
+
}
|
|
503
|
+
return {
|
|
504
|
+
ngCompiler: ngtscProgram.compiler,
|
|
505
|
+
program: ngtscProgram.getTsProgram(),
|
|
506
|
+
userOptions: tsconfig.options,
|
|
507
|
+
programAbsoluteRootFileNames: tsconfig.rootNames,
|
|
508
|
+
host: tsHost,
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/** Code of the error raised by TypeScript when a tsconfig doesn't match any files. */
|
|
513
|
+
const NO_INPUTS_ERROR_CODE = 18003;
|
|
514
|
+
/** Parses the given tsconfig file, supporting Angular compiler options. */
|
|
515
|
+
function parseTsconfigOrDie(absoluteTsconfigPath, fs) {
|
|
516
|
+
const tsconfig = readConfiguration(absoluteTsconfigPath, {}, fs);
|
|
517
|
+
// Skip the "No inputs found..." error since we don't want to interrupt the migration if a
|
|
518
|
+
// tsconfig doesn't match a file. This will result in an empty `Program` which is still valid.
|
|
519
|
+
const errors = tsconfig.errors.filter((diag) => diag.code !== NO_INPUTS_ERROR_CODE);
|
|
520
|
+
if (errors.length) {
|
|
521
|
+
throw new Error(`Tsconfig could not be parsed or is invalid:\n\n` + `${errors.map((e) => e.messageText)}`);
|
|
522
|
+
}
|
|
523
|
+
return tsconfig;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/** Creates the base program info for the given tsconfig path. */
|
|
527
|
+
function createBaseProgramInfo(absoluteTsconfigPath, fs, optionOverrides = {}) {
|
|
528
|
+
if (fs === undefined) {
|
|
529
|
+
fs = new checker.NodeJSFileSystem();
|
|
530
|
+
checker.setFileSystem(fs);
|
|
531
|
+
}
|
|
532
|
+
const tsconfig = parseTsconfigOrDie(absoluteTsconfigPath, fs);
|
|
533
|
+
const tsHost = new NgtscCompilerHost(fs, tsconfig.options);
|
|
534
|
+
// When enabled, use a plain TS program if we are sure it's not
|
|
535
|
+
// an Angular project based on the `tsconfig.json`.
|
|
536
|
+
if (google3UsePlainTsProgramIfNoKnownAngularOption() &&
|
|
537
|
+
tsconfig.options['_useHostForImportGeneration'] === undefined) {
|
|
538
|
+
return createPlainTsProgram(tsHost, tsconfig, optionOverrides);
|
|
539
|
+
}
|
|
540
|
+
return createNgtscProgram(tsHost, tsconfig, optionOverrides);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* @private
|
|
545
|
+
*
|
|
546
|
+
* Base class for the possible Tsurge migration variants.
|
|
547
|
+
*
|
|
548
|
+
* For example, this class exposes methods to conveniently create
|
|
549
|
+
* TypeScript programs, while also allowing migration authors to override.
|
|
550
|
+
*/
|
|
551
|
+
class TsurgeBaseMigration {
|
|
552
|
+
/**
|
|
553
|
+
* Advanced Tsurge users can override this method, but most of the time,
|
|
554
|
+
* overriding {@link prepareProgram} is more desirable.
|
|
555
|
+
*
|
|
556
|
+
* By default:
|
|
557
|
+
* - In 3P: Ngtsc programs are being created.
|
|
558
|
+
* - In 1P: Ngtsc or TS programs are created based on the Blaze target.
|
|
559
|
+
*/
|
|
560
|
+
createProgram(tsconfigAbsPath, fs, optionOverrides) {
|
|
561
|
+
return createBaseProgramInfo(tsconfigAbsPath, fs, optionOverrides);
|
|
562
|
+
}
|
|
563
|
+
// Optional function to prepare the base `ProgramInfo` even further,
|
|
564
|
+
// for the analyze and migrate phases. E.g. determining source files.
|
|
565
|
+
prepareProgram(info) {
|
|
566
|
+
const fullProgramSourceFiles = [...info.program.getSourceFiles()];
|
|
567
|
+
const sourceFiles = fullProgramSourceFiles.filter((f) => !f.isDeclarationFile &&
|
|
568
|
+
// Note `isShim` will work for the initial program, but for TCB programs, the shims are no longer annotated.
|
|
569
|
+
!checker.isShim(f) &&
|
|
570
|
+
!f.fileName.endsWith('.ngtypecheck.ts'));
|
|
571
|
+
// Sort it by length in reverse order (longest first). This speeds up lookups,
|
|
572
|
+
// since there's no need to keep going through the array once a match is found.
|
|
573
|
+
const sortedRootDirs = checker.getRootDirs(info.host, info.userOptions).sort((a, b) => b.length - a.length);
|
|
574
|
+
// TODO: Consider also following TS's logic here, finding the common source root.
|
|
575
|
+
// See: Program#getCommonSourceDirectory.
|
|
576
|
+
const primaryRoot = checker.absoluteFrom(info.userOptions.rootDir ?? sortedRootDirs.at(-1) ?? info.program.getCurrentDirectory());
|
|
577
|
+
return {
|
|
578
|
+
...info,
|
|
579
|
+
sourceFiles,
|
|
580
|
+
fullProgramSourceFiles,
|
|
581
|
+
sortedRootDirs,
|
|
582
|
+
projectRoot: primaryRoot,
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* A simpler variant of a {@link TsurgeComplexMigration} that does not
|
|
589
|
+
* fan-out into multiple workers per compilation unit to compute
|
|
590
|
+
* the final migration replacements.
|
|
591
|
+
*
|
|
592
|
+
* This is faster and less resource intensive as workers and TS programs
|
|
593
|
+
* are only ever created once.
|
|
594
|
+
*
|
|
595
|
+
* This is commonly the case when migrations are refactored to eagerly
|
|
596
|
+
* compute replacements in the analyze stage, and then leverage the
|
|
597
|
+
* global unit data to filter replacements that turned out to be "invalid".
|
|
598
|
+
*/
|
|
599
|
+
class TsurgeFunnelMigration extends TsurgeBaseMigration {
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Complex variant of a `Tsurge` migration.
|
|
603
|
+
*
|
|
604
|
+
* For example, every analyze worker may contribute to a list of TS
|
|
605
|
+
* references that are later combined. The migrate phase can then compute actual
|
|
606
|
+
* file updates for all individual compilation units, leveraging the global metadata
|
|
607
|
+
* to e.g. see if there are any references from other compilation units that may be
|
|
608
|
+
* problematic and prevent migration of a given file.
|
|
609
|
+
*/
|
|
610
|
+
class TsurgeComplexMigration extends TsurgeBaseMigration {
|
|
611
|
+
}
|
|
612
|
+
|
|
673
613
|
/*!
|
|
674
614
|
* @license
|
|
675
615
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -677,24 +617,30 @@ async function synchronouslyCombineUnitData(migration, unitDatas) {
|
|
|
677
617
|
* Use of this source code is governed by an MIT-style license that can be
|
|
678
618
|
* found in the LICENSE file at https://angular.dev/license
|
|
679
619
|
*/
|
|
620
|
+
exports.MigrationStage = void 0;
|
|
621
|
+
(function (MigrationStage) {
|
|
622
|
+
/** The migration is analyzing an entrypoint */
|
|
623
|
+
MigrationStage[MigrationStage["Analysis"] = 0] = "Analysis";
|
|
624
|
+
/** The migration is about to migrate an entrypoint */
|
|
625
|
+
MigrationStage[MigrationStage["Migrate"] = 1] = "Migrate";
|
|
626
|
+
})(exports.MigrationStage || (exports.MigrationStage = {}));
|
|
680
627
|
/** Runs a Tsurge within an Angular Devkit context. */
|
|
681
628
|
async function runMigrationInDevkit(config) {
|
|
682
629
|
const { buildPaths, testPaths } = await project_tsconfig_paths.getProjectTsConfigPaths(config.tree);
|
|
683
630
|
if (!buildPaths.length && !testPaths.length) {
|
|
684
631
|
throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run the migration.');
|
|
685
632
|
}
|
|
633
|
+
const tsconfigPaths = [...buildPaths, ...testPaths];
|
|
686
634
|
const fs = new DevkitMigrationFilesystem(config.tree);
|
|
687
635
|
checker.setFileSystem(fs);
|
|
688
636
|
const migration = config.getMigration(fs);
|
|
689
637
|
const unitResults = [];
|
|
690
|
-
const
|
|
691
|
-
|
|
638
|
+
const isFunnelMigration = migration instanceof TsurgeFunnelMigration;
|
|
639
|
+
for (const tsconfigPath of tsconfigPaths) {
|
|
640
|
+
config.beforeProgramCreation?.(tsconfigPath, exports.MigrationStage.Analysis);
|
|
692
641
|
const baseInfo = migration.createProgram(tsconfigPath, fs);
|
|
693
642
|
const info = migration.prepareProgram(baseInfo);
|
|
694
|
-
config.afterProgramCreation?.(info, fs);
|
|
695
|
-
return { info, tsconfigPath };
|
|
696
|
-
});
|
|
697
|
-
for (const { info, tsconfigPath } of programInfos) {
|
|
643
|
+
config.afterProgramCreation?.(info, fs, exports.MigrationStage.Analysis);
|
|
698
644
|
config.beforeUnitAnalysis?.(tsconfigPath);
|
|
699
645
|
unitResults.push(await migration.analyze(info));
|
|
700
646
|
}
|
|
@@ -706,12 +652,16 @@ async function runMigrationInDevkit(config) {
|
|
|
706
652
|
}
|
|
707
653
|
const globalMeta = await migration.globalMeta(combined);
|
|
708
654
|
let replacements;
|
|
709
|
-
if (
|
|
655
|
+
if (isFunnelMigration) {
|
|
710
656
|
replacements = (await migration.migrate(globalMeta)).replacements;
|
|
711
657
|
}
|
|
712
658
|
else {
|
|
713
659
|
replacements = [];
|
|
714
|
-
for (const
|
|
660
|
+
for (const tsconfigPath of tsconfigPaths) {
|
|
661
|
+
config.beforeProgramCreation?.(tsconfigPath, exports.MigrationStage.Migrate);
|
|
662
|
+
const baseInfo = migration.createProgram(tsconfigPath, fs);
|
|
663
|
+
const info = migration.prepareProgram(baseInfo);
|
|
664
|
+
config.afterProgramCreation?.(info, fs, exports.MigrationStage.Migrate);
|
|
715
665
|
const result = await migration.migrate(globalMeta, info);
|
|
716
666
|
replacements.push(...result.replacements);
|
|
717
667
|
}
|
|
@@ -735,6 +685,67 @@ async function runMigrationInDevkit(config) {
|
|
|
735
685
|
config.whenDone?.(await migration.stats(globalMeta));
|
|
736
686
|
}
|
|
737
687
|
|
|
688
|
+
/** A text replacement for the given file. */
|
|
689
|
+
class Replacement {
|
|
690
|
+
projectFile;
|
|
691
|
+
update;
|
|
692
|
+
constructor(projectFile, update) {
|
|
693
|
+
this.projectFile = projectFile;
|
|
694
|
+
this.update = update;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
/** An isolated text update that may be applied to a file. */
|
|
698
|
+
class TextUpdate {
|
|
699
|
+
data;
|
|
700
|
+
constructor(data) {
|
|
701
|
+
this.data = data;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/** Confirms that the given data `T` is serializable. */
|
|
706
|
+
function confirmAsSerializable(data) {
|
|
707
|
+
return data;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Gets a project file instance for the given file.
|
|
712
|
+
*
|
|
713
|
+
* Use this helper for dealing with project paths throughout your
|
|
714
|
+
* migration. The return type is serializable.
|
|
715
|
+
*
|
|
716
|
+
* See {@link ProjectFile}.
|
|
717
|
+
*/
|
|
718
|
+
function projectFile(file, { sortedRootDirs, projectRoot }) {
|
|
719
|
+
const fs = checker.getFileSystem();
|
|
720
|
+
const filePath = fs.resolve(typeof file === 'string' ? file : file.fileName);
|
|
721
|
+
// Sorted root directories are sorted longest to shortest. First match
|
|
722
|
+
// is the appropriate root directory for ID computation.
|
|
723
|
+
for (const rootDir of sortedRootDirs) {
|
|
724
|
+
if (!isWithinBasePath(fs, rootDir, filePath)) {
|
|
725
|
+
continue;
|
|
726
|
+
}
|
|
727
|
+
return {
|
|
728
|
+
id: fs.relative(rootDir, filePath),
|
|
729
|
+
rootRelativePath: fs.relative(projectRoot, filePath),
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
// E.g. project directory may be `src/`, but files may be looked up
|
|
733
|
+
// from `node_modules/`. This is fine, but in those cases, no root
|
|
734
|
+
// directory matches.
|
|
735
|
+
const rootRelativePath = fs.relative(projectRoot, filePath);
|
|
736
|
+
return {
|
|
737
|
+
id: rootRelativePath,
|
|
738
|
+
rootRelativePath: rootRelativePath,
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Whether `path` is a descendant of the `base`?
|
|
743
|
+
* E.g. `a/b/c` is within `a/b` but not within `a/x`.
|
|
744
|
+
*/
|
|
745
|
+
function isWithinBasePath(fs, base, path) {
|
|
746
|
+
return checker.isLocalRelativePath(fs.relative(base, path));
|
|
747
|
+
}
|
|
748
|
+
|
|
738
749
|
exports.Replacement = Replacement;
|
|
739
750
|
exports.TextUpdate = TextUpdate;
|
|
740
751
|
exports.TsurgeComplexMigration = TsurgeComplexMigration;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v20.0.0-next.
|
|
3
|
+
* @license Angular v20.0.0-next.6
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
@@ -9,11 +9,13 @@
|
|
|
9
9
|
var schematics = require('@angular-devkit/schematics');
|
|
10
10
|
var fs = require('fs');
|
|
11
11
|
var p = require('path');
|
|
12
|
-
var
|
|
12
|
+
var change_tracker = require('./change_tracker-UMPkv-eH.js');
|
|
13
13
|
var project_tsconfig_paths = require('./project_tsconfig_paths-CDVxT6Ov.js');
|
|
14
|
+
var compiler_host = require('./compiler_host-CAfDJO3W.js');
|
|
14
15
|
var ts = require('typescript');
|
|
15
|
-
var checker = require('./checker-
|
|
16
|
+
var checker = require('./checker-BFBQyesT.js');
|
|
16
17
|
var property_name = require('./property_name-BBwFuqMe.js');
|
|
18
|
+
require('./compiler-BQ7R7w2v.js');
|
|
17
19
|
require('os');
|
|
18
20
|
require('@angular-devkit/core');
|
|
19
21
|
require('module');
|
|
@@ -156,7 +158,7 @@ function migrateFileToLazyRoutes(sourceFile, program) {
|
|
|
156
158
|
const typeChecker = program.getTypeChecker();
|
|
157
159
|
const reflector = new checker.TypeScriptReflectionHost(typeChecker);
|
|
158
160
|
const printer = ts.createPrinter();
|
|
159
|
-
const tracker = new
|
|
161
|
+
const tracker = new change_tracker.ChangeTracker(printer);
|
|
160
162
|
const routeArraysToMigrate = findRoutesArrayToMigrate(sourceFile, typeChecker);
|
|
161
163
|
if (routeArraysToMigrate.length === 0) {
|
|
162
164
|
return { pendingChanges: [], skippedRoutes: [], migratedRoutes: [] };
|
|
@@ -347,7 +349,7 @@ function migrate(options) {
|
|
|
347
349
|
const basePath = process.cwd();
|
|
348
350
|
// TS and Schematic use paths in POSIX format even on Windows. This is needed as otherwise
|
|
349
351
|
// string matching such as `sourceFile.fileName.startsWith(pathToMigrate)` might not work.
|
|
350
|
-
const pathToMigrate =
|
|
352
|
+
const pathToMigrate = change_tracker.normalizePath(p.join(basePath, options.path));
|
|
351
353
|
if (!buildPaths.length) {
|
|
352
354
|
throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run the route lazy loading migration.');
|
|
353
355
|
}
|