Introduces a simpler, smaller variant of the current `Tsurge` migration
class. The difference is simply that for the migration phase (the third
stage), some migrations do not need a full set of workers re-analyzing
every compilation unit again to compute the "final migration
replacements".
This can be the case, for example, if a migration eagerly computes all
replacements in the analyze stage, visiting every unit, and then after
deriving the global metadata, problematic replacements are simply
filtered (e.g. via some unique IDs again).
PR Close#57484
This commit adds an internal util method that allows to detect:
* which selectors are matching nodes in a template
* which pipes are present in a template
Both directives and pipes are split into 2 buckets: eagerly used and the ones that might potentially be defer-loaded.
PR Close#57466
Previously, style elements within a template were used directly and not provided
to the optional transformation step that may be present on the resource host interface.
This causes such styles to not be processed by the Angular CLI's stylesheet pipeline
and could cause the styles to not work properly on all browsers. The style elements
are now processed in the same manner as inline styles within a component's metadata.
Link elements within a stylesheet were already being processed as `styleUrls`
equivalent and there is no behavior change in that regard.
PR Close#57429
This commit simplifies the batching support for the signal input
migration by using the new tsurge framework we've built.
This allows for consistent setup across all possible entry-points and
also simplifies the 1P setup given that we can simply use the Tsurge
macros, instead of having to maintain our own Go-based runner.
PR Close#57451
* Improves some of the generic assignability for tsurge. Anything is
allowed to be returned from an overridden `prepareProgram` method.
This is useful for the signal input migration.
* Passes the absolute root paths to migrations. This is helpful for the
signal input migration and there is no other way to access it. It's
better to pass specifically, compared to passing the whole unsafe
`ParsedConfiguration` object.
PR Close#57451
Introduces a migration framework to build batchable migrations that
can run in Large Scale mode against e.g. all of Google, using workers.
This is the original signal input migration infrastructure extracted
into a more generic framework that we can use for writing additional
ones for output, signal queries etc, while making sure those are not
scoped to a single `ts.Program` that limits them to per-directory
execution in very large projects (e.g. G3).
The migration will be updated to use this, and in 1P we will add
helpers to easily integrate such migrations into a Go-based pipeline
runner.
PR Close#57396
The migration was migrating all files in a project (like most migrations).
As there is no gain in migrating components used in test files. Excluding the test files reduces the migration noise.
PR Close#57317
This commit fully integrates the `autoDetect` feature into
`ApplicationRef.tick` without special handling for errors.
This commit also shares the method of autoDetect for change detection between
the zoneless and zone component fixture implementations. The difference
is now limited to:
* autoDetect is defaulted to true with zoneless
* detectChanges with zoneless is AppRef.tick while it is
ChangeDetectorRef.detectChanges with zones. This should likely
converge more in the future. Not going through AppRef.tick means that
the zone fixture does not get guaranteed `afterRender` executions and
does not get the rerunning behavior if the fixture is marked dirty by
a render hook.
BREAKING CHANGE: The `autoDetect` feature of `ComponentFixture` will now
attach the fixture to the `ApplicationRef`. As a result, errors during
automatic change detection of the fixture be reported to the `ErrorHandler`.
This change may cause custom error handlers to observe new failures that were previously unreported.
PR Close#55228
The zoneless scheduler callback was executed in the root zone rather
than simply in `runOutsideAngular` to allow us to land the hybrid mode
change detection (scheduler always enabled, even for zones) without
breaking a ton of existing `fakeAsync` tests that could/would fail with
the "timer(s) still in queue" error. However, this caused another
problem: when a test executes inside `fakeAsync`, it cannot flush the
scheduled time. A similar problem exists with event and run coalescing (#56767).
This change would allow `fakeAsync` to flush the zoneless-scheduled
change detections and minimize breaking existing tests
by flushing pending timers at the end of the test, which actually now
matches what's done internally.
PR Close#56932
Updates the migration so that it passes the type as a generic in the case of `@Inject(SOME_TOKEN) foo: SomeType`. This is done for two reasons:
1. It's a fairly common pattern and it ensures that the code can still be compiled.
2. It avoids leaving behind unused imports.
PR Close#57389
This commit fixes an issue when hydration serialization tries to calculate DOM path to a content projection node (`<ng-content>`), but such nodes do not have DOM representation.
Resolves#56750.
PR Close#57383
Makes it so the inject migration preserves the optional token when declaring a parameter. This came up in some testing as something that can be potentially breaking for classes that implement interfaces.
PR Close#57367
This commit fixes an issue that happens when an i18n block is defined as a projectable content, but a parent component doesn't project it. With an extra check added in this commit, the code will be taking a regular "creation" pass instead of attempting hydration.
Resolves#57301.
PR Close#57356
Signal inputs are no longer updated by assignment, unlike `@Input()`, so
a good practice is adding `readonly` for the `InputSignal`— which should
never be swapped out.
This is a safe operation because the migration skips all inputs that are
being written anyway.
PR Close#57368
In some cases, the migration can detect when `input()` as a shorthand
may be usable. This commit adds such detection and migrates inputs to
this form when possible.
PR Close#57368
Components with `jit: true` are not processed by the Angular compiler,
so we cannot ask the template checker for the parsed template; simply
because the template wasn't attempted to be parsed.
We still can migrate simple cases of such components, commonly seen in
unit tests. We do this by manually parsing the template and making use
of the reference fallback resolution that is also used for host bindings
(where we don't have any type check block information).
PR Close#57347
Instead of exposing just the `ts.CompilerOptions`, we should expose the
actual Angular compiler options throuhgout the signal input migration.
This will be useful for parsing templates, in cases of JIT-opted
components.
PR Close#57347
As of this commit, the migration will also inspect safe property reads
and migrate them, if they reference an input that is being migrated.
PR Close#57318
Instead of revisiting each source file, and each of its child nodes
twice, we now visit them together using a grouped AST visitor that only
traverses each source file once.
This seemed to speed up migration by 6-8% locally, but is likely
noticable better with large compilation scopes.
PR Close#57318
Instead of fiddling manually with the imports, which worked well, but
comes at a cost of complexity— we are now using the canonical import
manager. This simplifies deletion, insertion and updating of imports.
Notably, our import manager is not super great at preserving whitespaces
right now, but we assume a formatter runs over migrated code anyway.
PR Close#57318
Introduces a best effort mode for the signal input migration. This mode
can be used to aggresively migrate as much as possible, ignoring most
of the incompatibility reasons, like "writes to the input".
PR Close#57318
Errors during change detection from `ApplicationRef.tick` are only
reported to the `ErrorHandler`. By default, this only logs the error to
console. As a result, these errors can be missed/ignored and allow tests
to pass when they should not. This change ensures that the errors are
surfaced. Note that this is already the behavior when zoneless is
enabled.
BREAKING CHANGE: Errors that are thrown during `ApplicationRef.tick`
will now be rethrown when using `TestBed`. These errors should be
resolved by ensuring the test environment is set up correctly to
complete change detection successfully. There are two alternatives to
catch the errors:
* Instead of waiting for automatic change detection to happen, trigger
it synchronously and expect the error. For example, a jasmine test
could write `expect(() => TestBed.inject(ApplicationRef).tick()).toThrow()`
* `TestBed` will reject any outstanding `ComponentFixture.whenStable` promises. A jasmine test,
for example, could write `expectAsync(fixture.whenStable()).toBeRejected()`.
As a last resort, you can configure errors to _not_ be rethrown by
setting `rethrowApplicationErrors` to `false` in `TestBed.configureTestingModule`.
PR Close#57200
This change aligns the behavior of the error handler in the
`ExtraOptions` of `RouterModule.forRoot` with the error handler in
`withNavigationErrorHandler`. The changes are:
* Slightly different timing: The handler is called before the
`NavigationError` emits
* Runs in the injection context, meaning it is more configurable at the
config location rather than needing to assign the value to the
`Router.errorHandler` later to get access to injectables
* Can now return `RedirectCommand` to recover from the error and
redirect without emitting `NavigationError`
* No longer allows arbitrarily overriding return value of the navigation
promise
BREAKING CHANGE: The `Router.errorHandler` property has been removed.
Adding an error handler should be configured in either
`withNavigationErrorHandler` with `provideRouter` or the `errorHandler`
property in the extra options of `RouterModule.forRoot`. In addition,
the error handler cannot be used to change the return value of the
router navigation promise or prevent it from rejecting. Instead, if you
want to prevent the promise from rejecting, use `resolveNavigationPromiseOnError`.
PR Close#57050
This commit updates the interface of `Resolve` to allow for
`RedirectCommand`, as was done with `ResolveFn` in v18.
fixes#57131
BREAKING CHANGE: The return type of the `Resolve` interface now includes
`RedirectCommand`.
PR Close#57309
This commit adds an input to `RouterOutlet` that allows developers to
pass data from a parent component to the outlet components.
Setting the `routerOutletData` input on `RouterOutlet` makes the value
available to the child component injectors via the `ROUTER_OUTLET_DATA`
token. This token uses a `Signal` type to allow updating the input value
and propogating it to the token rather than needing to make the value
static.
resolves#46283
PR Close#57051
This commit updates serialization and hydration i18n logic to take into account situations when i18n blocks are located within "skip hydration" blocks.
Resolves#57105.
PR Close#57299
Previously, if a component injects a `ViewContainerRef`, the post-hydration cleanup process doesn't visit inner views to cleanup dehydrated views in nested LContainers. This commit updates the logic to recognize this situation and enter host LView to complete cleanup.
Resolves#56989.
PR Close#57300
By default, we don't migrate inputs if they are part of e.g. `@if` for
now. That is because we don't have the template narrowing feature
available yet.
To improve impact of the migration until we have the narrowing, we add
some additional checks that allow us to migrate instances of inputs that
are part of e.g. `@if` but are actually not used inside (and hence are
guaranteed to be _not_ narrowed).
PR Close#57308
This commit updates the inside/outside NgZone detection of the hybrid CD
scheduling to track the actual instance of the NgZone being used rather
than the name "Angular" (how `isInsideAngularZone` works). This allows
the scheduling to work correctly when there are multiple versions of
Angular running on the page.
fixes#57261
PR Close#57267
Currently in some scenarios the compiler generates code like `null as any ? foo : bar` which will be invalid with [an upcoming TypeScript change](https://devblogs.microsoft.com/typescript/announcing-typescript-5-6-beta/#disallowed-nullish-and-truthy-checks). These changes switch to generating `0 as any` which is exempt from the change.
**Note:** I'm not starting the work to fully get us on TS 5.6 until the 18.2 release comes out, but this change is necessary to unblock an internal team.
PR Close#57303