821 Commits

Author SHA1 Message Date
Kristiyan Kostadinov 3aa45a2fa1 fix(core): resolve forward-referenced host directives during directive matching (#58492) (#58500)
When the compiler generates the `HostDirectivesFeature`, it generates either an eager call (`ɵɵHostDirectivesFeature([])`) or a lazy call (`ɵɵHostDirectivesFeature(() => [])`. The lazy call is necessary when there are forward references within the `hostDirectives` array. Currently we resolve the lazy variant when the component definition is created which has been enough for most cases, however if the host is injected by one of its host directives, we can run into a reference error because DI is synchronous and the host's class hasn't been defined yet.

These changes resolve the issue by pushing the lazy resolution later during directive matching when all classes are guanrateed to exist.

Fixes #58485.

PR Close #58492

PR Close #58500
2024-11-04 17:18:52 +01:00
Kristiyan Kostadinov 46bafb0b0a fix(core): clean up afterRender after it is executed (#58119)
We stop tracking `afterRender` hooks as soon as they execute, but their on destroy callbacks stay registered until either the injector is destroyed or the user calls `destroy` manually. This was leading to memory leaks in the `@defer` triggers based on top of `afterRender` when placed inside long-lived views, because the callback would execute, but its destroy logic was waiting for the view to be destroyed.

These changes resolve the issue by destroying the `AfterRenderRef` once it is executed.

PR Close #58119
2024-10-08 13:27:07 -07:00
Kristiyan Kostadinov 2f347ef8fc fix(core): provide flag to opt into manual cleanup for after render hooks (#57917)
Adds a `manualCleanup` flag to `afterRender` and `afterNextRender`, similarly to `effect`. The reason is that currently if the hook is created outside of an injection context, it requires an injector to be passed in. In some cases that injector might be an injector that is never destroyed (e.g. `EnvironmentInjector`) which can give a false sense of security users thinking that the hook will be cleaned up automatically. We fell into this in the CDK which caused a memory leak (see https://github.com/angular/components/pull/29709). With the `manualCleanup` option users explicitly opt into cleaning the hook up themselves.

PR Close #57917
2024-09-26 14:20:55 -07:00
Joey Perrott 03ac3c299d refactor: update license text to point to angular.dev (#57902)
Update license text to point to angular.dev instead of angular.io

PR Close #57902
2024-09-24 15:28:46 +02:00
Kristiyan Kostadinov df42d2be16 test: avoid leaking some LViews in tests (#57546)
We had some tests that were leaking LViews, because we were testing things like `createComponent`, but not destroying them afterwards. These changes clean up most of them, although there are a handful still left that I didn't have time to fully track down.

PR Close #57546
2024-08-27 13:29:09 -07:00
Alex Rickabaugh 6059ca8f1f refactor(core): restructure AfterRenderManager to connect related phases (#57453) (#57504)
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
2024-08-23 12:48:01 -07:00
Kristiyan Kostadinov 513a4fe05e refactor(core): replace usages of removeChild (#57203)
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
2024-08-07 16:46:09 +00:00
Andrew Scott 7919982063 feat(core): Add whenStable helper on ApplicationRef (#57190)
This commit adds a `whenStable` function to `ApplicationRef` to cover
the most common use-case for the `isStable` observable.

PR Close #57190
2024-08-06 21:28:16 +00:00
Andrew Scott 3459289ef0 feat(core): bootstrapModule can configure NgZone in providers (#57060)
This commit allows configuring `NgZone` through the providers for
`bootstrapModule`. Prior to this change, developers had to configure
`NgZone` in the `BootstrapOptions`.

PR Close #57060
2024-07-30 18:03:35 +00:00
Matthieu Riegler 7d4b2d2413 fix(core): afterNextRender hooks return that callback value. (#57031)
`afterRender` was working fine but `afterNextRender` wasn't

PR Close #57031
2024-07-19 13:40:59 -07:00
Kristiyan Kostadinov e504ad97d4 fix(core): not all callbacks running when registered at the same time (#56981)
Fixes that only the first callback was firing when multiple are registered in the same call to `afterNextRender`, e.g. `afterNextRender({earlyRead: fn, read: fn});`

Fixes #56979.

PR Close #56981
2024-07-16 08:42:26 -07:00
Paul Gschwendtner 7f550ea0c8 refactor(compiler-cli): move JIT transforms into ngtsc (#56892)
This commit moves the JIT transforms into the ngtsc folder. They existed
outside of ngtsc mostly as an historic artifact— and now with compiler
relying on them even more deeply, it makes sense to move them into
`ngtsc/transform`.

PR Close #56892
2024-07-10 17:29:20 +02:00
Andrew Kushnir c1e3262119 test(core): simplify @defer-based test to make CI more stable (#56904)
This commit updates one of the `@defer`-based test to use the `on immediate` trigger to make a test mor
e stable without the need to add mocks for the `on idle` (default) condition.

PR Close #56904
2024-07-09 09:36:11 +02:00
Andrew Kushnir 00d9cd240d fix(core): establish proper defer injector hierarchy for components attached to ApplicationRef (#56763)
This commit updates the logic that create an injector for defer blocks (when it's needed) to account for a situation when a component is instantiated without a connection to the current component tree. This can happen if a component is created using its factory function or via `createComponent()` call.

Resolves #56372.

PR Close #56763
2024-07-03 14:08:43 +00:00
Kristiyan Kostadinov 2a1291e942 fix(compiler): give precedence to local let declarations over parent ones (#56752)
Currently the logic that maps a name to a variable looks at the variables in their definition order. This means that `@let` declarations from parent views will always come before local ones, because the local ones are declared inline whereas the parent ones are hoisted to the top of the function.

These changes resolve the issue by giving precedence to the local variables.

Fixes #56737.

PR Close #56752
2024-07-01 14:03:57 +00:00
Matthieu Riegler d23aa878a0 test(core): Add testing for defer error block (#56561)
In #56558 it was raised that we used an devMode function in a prod scope.
This commit adds a test when an defer error block is missing in devMode and prodMode

PR Close #56561
2024-06-27 15:53:19 +00:00
Kristiyan Kostadinov 0a48d584f2 feat(core): add support for let syntax (#56715)
Enables the new `@let` syntax by default.

`@let` declarations are defined as:
1. The `@let` keyword.
2. Followed by one or more whitespaces.
3. Followed by a valid JavaScript name and zero or more whitespaces.
4. Followed by the `=` symbol and zero or more whitespaces.
5. Followed by an Angular expression which can be multi-line.
6. Terminated by the `;` symbol.

Example usage:
```
@let user = user$ | async;
@let greeting = user ? 'Hello, ' + user.name : 'Loading';
<h1>{{greeting}}</h1>
```

Fixes #15280.

PR Close #56715
2024-06-26 12:37:02 -07:00
Kristiyan Kostadinov bbe39c1738 refactor(core): integrate let instructions into the runtime (#56527)
Adds the implementation of the following new instructions:
* `declareLet` - creation-time instruction that initializes the slot for a let declaration.
* `storeLet` - update-time instruction that stores the current value of a let declaration.
* `readContextLet` - instruction that reads the stored value of a let declaration from a different view.

On top of the instructions, it also introduces a new `LetDeclaration` TNode type.
The new TNode is nececessary for DI to work correctly in pipes inside the let expression,
as well as for proper hydration support.

PR Close #56527
2024-06-26 08:48:31 -07:00
Andrew Kushnir 088e6c73bf refactor(core): avoid exposing OutletInjector in injector resolution path (#56394)
Router's `OutletInjector` required a special handling in cases when `@defer` is used, see https://github.com/angular/angular/pull/55374 for additional info. As a result, the `ChainedInjector` that represents an `OutletInjector` instance is currently exposed via `getInjectorResolutionPath` function. This creates a problem, because other debug APIs used by DevTools can not interact with `ChainedInjector`s. This commit updates the logic around `getInjectorResolutionPath` utility to avoid exposing `OutletInjector`in the resolution path.

Resolves #56331.

PR Close #56394
2024-06-17 09:05:11 -07:00
Paul Gschwendtner 352e0782ec feat(core): expose signal input metadata in ComponentMirror (#56402)
This commit starts exposing `isSignal` for inputs in the
`ComponentMirror`. We initially had this as a draft when rolling out
signal inputs, but there were no good use-cases, so we skipped it.

Now, inside G3, for the testing infrastructure and rolling out
advancements for signal inputs, having this information is necessary and
allows identifying signal inputs without "accessing fields" on the class
that may cause side-effects (like triggering setters).

PR Close #56402
2024-06-13 10:12:06 -07:00
Andrew Scott 4c7d5d8acd fix(core): signals should be tracked when embeddedViewRef.detectChanges is called (#55719)
This commit fixes an issue where signals in embedded views are not
tracked if they are refreshed with `EmbeddedViewRef.detectChanges`
directly. We had previously assumed that embedded views were always
refreshed along with their hosts.

PR Close #55719
2024-06-11 12:35:02 -07:00
Miles Malerba 38effcc63e fix(core): Add back phase flag option as a deprecated API (#55648)
Adds back the ability to set the phase of an `afterRender` /
`afterNextRender` callback using the `phase` option. However, this API
is now deprecated, and the phase should instead be specified by passing
a spec object rather than a callback function.

PR Close #55648
2024-06-10 13:53:39 -07:00
Miles Malerba a655e46447 feat(core): Redesign the afterRender & afterNextRender phases API (#55648)
Previously `afterRender` and `afterNextRender` allowed the user to pass
a phase to run the callback in as part of the `AfterRenderOptions`. This
worked, but made it cumbersome to coordinate work between phases.

```ts
let size: DOMRect|null = null;

afterRender(() => {
  size = nativeEl.getBoundingClientRect();
}, {phase: AfterRenderPhase.EarlyRead});

afterRender(() => {
  otherNativeEl.style.width = size!.width + 'px';
}, {phase: AfterRenderPhase.Write});
```

This PR replaces the old phases API with a new one that allows passing a
callback per phase in a single `afterRender` / `afterNextRender` call.
The return value of each phase's callback is passed to the subsequent
callbacks that were part of that `afterRender` call.

```ts
afterRender({
  earlyRead: () => nativeEl.getBoundingClientRect(),
  write: (rect) => {
    otherNativeEl.style.width = rect.width + 'px';
  }
});
```

This API also retains the ability to pass a single callback, which will
be run in the `mixedReadWrite` phase.

```ts
afterRender(() => {
  // read some stuff ...
  // write some stuff ...
});
```

PR Close #55648
2024-06-10 13:53:39 -07:00
Kristiyan Kostadinov e5a6f91722 feat(core): support TypeScript 5.5 (#56096)
Updates the repo to add support for TypeScript 5.5. Includes resolving some compilation errors and broken tests.

PR Close #56096
2024-05-29 15:33:33 +02:00
Matthieu Riegler b2445a0953 fix(core): link errors to ADEV (#55554) (#56038)
Console error links will now point to adev.

PR Close #55554

PR Close #56038
2024-05-28 12:50:53 +02:00
Pawel Kozlowski 760207b254 Revert "fix(core): link errors to ADEV (#55554)" (#56031)
This reverts commit dd0700ff1d.
We will need G3 patch cleanup before this one can land.

PR Close #56031
2024-05-23 13:57:53 +02:00
Matthieu Riegler dd0700ff1d fix(core): link errors to ADEV (#55554)
Console error links will now point to adev.

PR Close #55554
2024-05-23 11:58:54 +02:00
Andrew Scott cae0d3167d fix(core): exhaustive checkNoChanges should only do a single pass (#55839)
Because exhaustive checks traverse the whole tree regardless of the
dirty state, it breaks some expectations around how change detection
should be running. When a view has transplanted views, it
unconditionally marks all ancestors for traversal, assuming this is fine
because the loop will just traverse them and find nothing dirty.
However, exhaustive checkNoChanages actually refreshes everything during
traversal.

This update ensures the exhaustive check only does a single pass and
also prevents some unnecessary marking of transplanted views for
refresh since we know they're going to be reached.

PR Close #55839
2024-05-17 12:24:36 -07:00
cexbrayat 3d5c3d9fff fix(core): error about provideExperimentalCheckNoChangesForDebug uses wrong name (#55824)
The error about `provideExperimentalCheckNoChangesForDebug` mentions `provideCheckNoChangesForDebug` instead.

PR Close #55824
2024-05-16 09:02:28 -07:00
Andrew Scott 84b2351d50 refactor(core): Update error for both zone and zoneless to be only for apps (#55813)
Developers may want to enable zoneless for all tests by default by
adding the zoneless provider to `initTestEnvironment` and then
temporarily disabling it for individual tests with the zone provider
until they can be made zoneless compatible.

PR Close #55813
2024-05-15 13:27:26 -07:00
Andrew Scott ca6cdcd269 refactor(core): feature for potential zoneless-compatibility debug check (#55663)
This commit adds a feature that is useful for determining if an
application is zoneless-ready. The way this works is generally only
useful right now when zoneless is enabled. Some version of this may be useful in
the future as a general configuration option to change detection to make
`checkNoChanges` pass always exhaustive as an opt-in to address #45612.

Because this is an experimental, debug-only feature, it is okay to merge
during the RC period.

PR Close #55663
2024-05-07 13:39:13 -07:00
Andrew Scott abbaf8f639 refactor(core): Throw a runtime error if both zone and zoneless are provided (#55410)
This commit adds a dev-mode error if both the zone and zoneless
providers are used together.

PR Close #55410
2024-05-07 13:37:42 -07:00
Matthieu Riegler e5331107fd fix(platform-browser): Use the right namespace for mathML. (#55622)
Prior to this change, MathML element were created with the wrong namespace resulting in regular DOM `Element`.

This commit fixes this.

Related to #55608 (but doesn't fix it entirely).

PR Close #55622
2024-05-03 08:07:31 -07:00
Andrew Scott 7c1b4a49ae fix(core): afterRender hooks registered outside change detection can mark views dirty (#55623)
This commit fixes an error in the looping logic of `ApplicationRef.tick`
when the tick skips straight to render hooks. In this case, if a render
hook makes a state update that requires a view refresh, we would never
actually refresh the view and just loop until we hit the loop limit.

PR Close #55623
2024-05-02 10:58:28 -07:00
Andrew Scott 024e9bf54d refactor(core): Ensure animations are flushed before running render hooks (#55564)
This commit ensures we flush animations by calling renderFactory
begin/end in cases where the ApplicationRef._tick happens in a mode that
skips straight to the render hooks.

PR Close #55564
2024-04-30 15:39:56 -07:00
Joey Perrott 31fdf0fbea refactor: migrate core to prettier formatting (#55488)
Migrate formatting to prettier for core from clang-format

PR Close #55488
2024-04-29 09:49:19 -07:00
Kristiyan Kostadinov 97eea8d50e fix(core): resolve error for multiple component instances that use fallback content (#55478)
Currently fallback content for `ng-content` gets declared and rendered out in one go. This breaks down if multiple instances of the same component are used where one doesn't render the fallback content while the other one does, because the `TNode` for the content has to be created during the first creation pass.

These changes resolve the issue by always _declaring_ the template, but only rendering it if the slot is empty.

Fixes #55466.

PR Close #55478
2024-04-25 09:04:01 -07:00
Andrew Kushnir e3d5607caf Revert "refactor(core): Ensure DOM removal happens when no app views need refresh (#55132)" (#55524)
This reverts commit a07ea069e5.

PR Close #55524
2024-04-24 16:35:57 -07:00
Andrew Kushnir 28905ab9ae Revert "refactor(animations): Ensure async animations applies changes when loaded in zoneless (#55132)" (#55524)
This reverts commit 9ab36cfe0a.

PR Close #55524
2024-04-24 16:35:57 -07:00
Pawel Kozlowski ac863ded48 feat(core): provide ExperimentalPendingTasks API (#55487)
The new ExperimentalPendingTasks API lets developers to add and remove
tasks that control applications stability: a pending task prevents
application from being stable.

This API is important for all the use-cases that depend on the concept
of stability and SSR serialization is a notable example.

Closes #53381

PR Close #55487
2024-04-24 11:23:10 -07:00
Andrew Scott 9ab36cfe0a refactor(animations): Ensure async animations applies changes when loaded in zoneless (#55132)
Async animations currently works in Zones because the render factory
promise resolve causes change detection to happen.

fixes #54919

PR Close #55132
2024-04-24 10:33:47 -07:00
Andrew Scott a07ea069e5 refactor(core): Ensure DOM removal happens when no app views need refresh (#55132)
This change ensures that `ApplicationRef.tick` flushes animations by
calling `rendererFactory2.end`. This might not have happened before if
there were no views that needed to be refreshed.

This is also likely to fix a potential regression caused by #53718 even
in zone apps where animations don't get flushed when no views attached
to ApplicationRef are dirty.

PR Close #55132
2024-04-24 10:33:47 -07:00
Andrew Kushnir 9894278e71 fix(core): make ActivatedRoute inject correct instance inside @defer blocks (#55374)
`RouterOutlet` uses a unique injector logic that returns a value that correspond to the `ActivatedRoute` token dynamically. This logic breaks when a component/directive/pipe that injects the `ActivatedRoute` is located within a `@defer` block, because defer creates an `EnvironmentInjector` instance, which doesn't have that dynamic logic.

We've added some special handling of the `OutletInjector` in one of the previous commits, but it was incomplete and it was not covering cases when different routes use the same component. This commit updates defer logic to re-establish this dynamic behavior for `ActivatedRoute` by creating an instance of the `OutletInjector` when a parent injector was also an instance of `OutletInjector`.

This fix is a short-term solution and longer term we should find a way to achieve the dynamic behavior that Router relies on, but without adding a special case logic into defer.

Resolves #54864.

PR Close #55374
2024-04-22 12:01:36 -07:00
Pawel Kozlowski 832fafc6b5 refactor(core): warn developers about collection re-creation in @for loop (#55314)
This commit introduces a check plus an associated warning for situations where
the combination of the collection change and the tracking expression resulted
in the entire view structure managed by @for to be re-created.

The check uses the following conditions before raising a warning:
- the entire collection was re-created and there were no other operations (ex.: move);
- views in a collection are considered "expensive" to re-create;
- a developer is using tracking by identity.

The last condition tries to capture cases where changes to immutable data
collections can cause significent performance and / or corectness problems.

Note that this warning might be "overreacting" and report cases where
the collection re-creation is the intended behavior. Still, the assumption is that
most of the time it is undesired.

PR Close #55314
2024-04-22 11:24:11 -07:00
Pawel Kozlowski e67a730688 refactor(core): warn about duplicated keys when using built-in @for (#55243)
This commit a new check that warn users about duplicated keys detected given
a tracking expression and a collection iterated over with @for. Duplicated keys
should be avoided as those are more expensive to manage and can result in
incorrect UI display.

PR Close #55243
2024-04-19 06:28:58 -07:00
Gerald Monaco 5f06ca8f55 feat(core): add HOST_TAG_NAME token (#54751)
For ideal DOM usage, you would not unwrap an ElementRef outside of the browser. However, it's reasonable to want to find the tag name of the host node on the server, and so this introduces a HOST_TAG_NAME token that can be injected to read this value.

PR Close #54751
2024-04-17 15:50:31 -07:00
Alex Rickabaugh a5623dc14b Revert "refactor(core): warn about duplicated keys when using built-in @for (#55243)" (#55373)
This reverts commit 9f7b9ed87a. Reason: g3
users reported a bug in the logic that produces false warnings in some
cases.

PR Close #55373
2024-04-16 17:11:08 -07:00
Pawel Kozlowski 9f7b9ed87a refactor(core): warn about duplicated keys when using built-in @for (#55243)
This commit a new check that warn users about duplicated keys detected given
a tracking expression and a collection iterated over with @for. Duplicated keys
should be avoided as those are more expensive to manage and can result in
incorrect UI display.

PR Close #55243
2024-04-15 16:10:27 +02:00
Leon Senft f2f2c2acc0 test(core): fix expectations that accidentally used incorrect matchers (#55294)
Expect that the number of template executions is `===` to a number, rather than expect that it
does not contain a number. As they were, these expectations would pass regardless of the expected
value.

PR Close #55294
2024-04-12 07:38:52 +02:00
Andrew Scott 19a238dfee Revert "refactor(core): warn about duplicated keys when using built-in @for (#55243)" (#55293)
This reverts commit e3696ad0d6.
caused a test failure internally

PR Close #55293
2024-04-10 13:45:49 -07:00