The `afterRender` infrastructure was first implemented around the idea of
independent, singular hooks. It was later updated to support a spec of
multiple hooks that pass values from one to another as they execute, but the
implementation still worked in terms of singular hooks under the hood. This
creates a number of maintenance issues, and a few bugs. For example, when
one hook fails, further hooks in the pipeline should no longer execute, but
this was hard to ensure under the old design.
This refactoring restructures `afterRender` infrastructure significantly to
introduce the concept of a "sequence", a collection of hooks of different
phases that execute together. Overall, the implementation is simplified
while making it more resilient to issues and future use cases, such as the
upcoming `afterRenderEffect`.
As part of this refactoring, the `internalAfterNextRender` concept is
removed, as well as the unused `queueStateUpdate` concept which used it.
PR Close#57453
PR Close#57504
Previously the zoneless scheduler had a concept of whether views needed to
be refreshed or not, based on the notification type that was received. It
tracked this information as a boolean.
This commit refactors things to track dirtiness in `ApplicationRef` itself,
as a `dirtyFlags` field with bits corresponding to either view tree
dirtiness or after-render hooks.
PR Close#57453
PR Close#57504
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 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
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
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
PR Close#57323
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
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
This changes the migration so that we don't generate `_1` suffixes when
a temporary variable wouldn't conflict with any variables in the lexical
scope.
In addition, if we discover conflicts, we try alternative suffixes that
seem more natural and follow style guides. E.g. `Value`, `Val` or
`Input`.
PR Close#57292
These changes replace most usages of `removeChild` with `remove`. The latter has the advantage of not having to look up the `parentNode` and ensure that the child being removed actually belongs to the specific parent.
The refactor should be fairly safe since all the browsers we cover support `remove`. [Something similar was done in Components](https://github.com/angular/components/pull/23592) some time ago and there haven't been any bug reports as a result.
PR Close#57203
From the internal issue on the matter:
> When using the standard Jasmine version of it promises returned by the body function are automatically awaited. The Catalyst version of it is fake-async, so awaiting the promise does not make sense; however it would be nice if Catalyst automatically flushed the promise to replicate the experience of using standard it. This would allow users to do the following:
```
it('should fail later', async () => {
await new Promise(r => setTimeout(r));
fail('failure');
});
```
> In Catalyst today the above test will pass. If this proposal to automatically flush the resulting promise were implemented it would fail.
Flushing after the tests complete has been the default behavior inside
Google since 2020. Very few tests remain that use the old behavior of
only flushing microtasks. The example above would actually fail with
`fakeAsync` due to the pending timer, but the argument still remains the
same. We might as well just flush if we're going to fail the test
anyways by throwing if there's no flush at the end.
BREAKING CHANGE: `fakeAsync` will now flush pending timers at the end of
the given function by default. To opt-out of this, you can use `{flush:
false}` in options parameter of `fakeAsync`
PR Close#57240
From the internal issue on the matter:
> When using the standard Jasmine version of it promises returned by the body function are automatically awaited. The Catalyst version of it is fake-async, so awaiting the promise does not make sense; however it would be nice if Catalyst automatically flushed the promise to replicate the experience of using standard it. This would allow users to do the following:
```
it('should fail later', async () => {
await new Promise(r => setTimeout(r));
fail('failure');
});
```
> In Catalyst today the above test will pass. If this proposal to automatically flush the resulting promise were implemented it would fail.
Flushing after the tests complete has been the default behavior inside
Google since 2020. Very few tests remain that use the old behavior of
only flushing microtasks. The example above would actually fail with
`fakeAsync` due to the pending timer, but the argument still remains the
same. We might as well just flush if we're going to fail the test
anyways by throwing if there's no flush at the end.
PR Close#57239
This was an old feature that mapped shift + click (et al) to "clickmod". This doesn't really make sense to add to Angular, so let's remove it.
PR Close#57201
Lock file maintenance updated Terser, which impacts the bundle
optimizations being tested via the symbol golden tests.
There was a small noticable change in the symbol golden where
`withDomHydration` is now preserved, and the underlying function
that was previously detected is gone. Seemingly Terser now inlines
this function and had to preserve `withDomHydration` as the entry point.
PR Close#57205
Rather than leaving the timers around as no-ops, this commit updates the
logic to also attempt to clear or cancel the timers. This is helpful for
the eventual goal of running the scheduler in the `fakeAsync` zone (if
the test is running in `fakeAsync`) rather than scheduling in the root
zone and making it impossible to flush.
PR Close#57186
This creates a private option that can be used internally while we
migrate this to the default and only behavior. ~200 tests in TGP have errors
that are being swallowed (console.log) and not causing the test to fail.
We can first explicitly opt those out, flip the default internally, then
"fix" them by adding expect...toThrow.
PR Close#57153
This commit adds the `ImagePerformanceWarning` to the common bootstrap
code rather than only starting it when using `bootstrapApplication`.
PR Close#57060
This commit de-duplicates the code for bootstrapping between
`bootstrapApplication` and `bootstrapModule`. A majority of the
bootstrap code was identical between the two, with some minor
differences that can be handled with a function overload.
PR Close#57060