The `bootstrap()` phase might fail e.g. due to an rejected promise in some `APP_INIIALIZER`.
If `PlatformRef` is not destroyed, then the main app's injector is not destroyed and therefore `ngOnDestroy` hooks of singleton services is not called on the end (failure) of SSR.
This could lead to possible memory leaks in custom SSR apps, if their singleton services' `ngOnDestroy` hooks contained an important teardown logic (e.g. unsubscribing from RxJS observable).
Note: I needed to fix by the way another thing too: now we destroy `moduleRef` when `platformInjector` is destroyed - by setting a `PLATFORM_DESTROY_LISTENER`
Patch port of #58112
PR Close#58135
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
I’ve noticed that there was a loop inside a loop. Since we’re already iterating through
`images` using `forEach`, it was running a `for` loop through `images` again. This was
probably a mistake made when the functionality was initially added. The test actually
verified that `logs.length` is `1`, but in the real environment, it logs twice
(which is quite obvious due to the code).
I’ve also added the missing file to the Bazel target.
PR Close#58021
Prior to this commit, the `ImagePerformanceWarning` class was checking all `img`
elements in the DOM to determine whether they were oversized after the DOM loading
was complete. We should not check SVGs because they are vector-based and can scale
infinitely without losing quality.
Closes#57941
PR Close#57966
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
`@angular/upgrade` writes to inputs when downgrading an Angular 2+ component
into an Angular.JS adapter. Previously, it wrote directly to the input
property, which isn't compatible with input signals. It also handles
`ngOnChanges` directly.
The correct way to support input signals would be to refactor upgrade to use
`ComponentRef.setInput`, which also handles `ngOnChanges` internally.
However, this refactoring might be more breaking since it would change the
timing of certain operations. Instead, this commit updates the code to
recognize `InputSignal` and write it through the `InputSignalNode`. This
avoids the above breaking changes for now, until a bigger refactoring can be
tested.
Fixes#56860.
PR Close#57020
Before this commit, `@let` decleration with an array where mistaken for a component in the lView and throwing an unexpected error.
This commit fixes this.
PR Close#57816
Remove hash in link for correct view
Fixes#57349
docs(docs-infra): change the link
Change the link with name of class and method
docs: fix the link name
PR Close#57351
When we create the LView for a component, we track it in the `TRACKED_LVIEWS` map. It gets untracked when it is destroy, but if it throws during creation, the user won't have access to a `ComponentRef` in order to clean it up.
These changes automatically untrack the related LViews if the component couldn't be created.
PR Close#57546
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
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
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
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
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
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
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
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 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
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
Fixes that we were throwing an assertion error during hydration if a `@let` declaration is used before and immediately inside of a container.
Fixes#57160.
PR Close#57173
The behavior of `ComponentFixture` for zoneless tests was decided somewhat through guesswork, trial, and error. In addition, working on the zoneless fixture revealed oddities in the behavior of the zone-based fixture, or behaviors that we felt were counterintuitive. The most consequential difference is how change detection works: `detectChanges` goes through ApplicationRef.tick in zoneless while it is `changeDetectorRef.detectChanges` in the zone fixture.
We felt that running change detection through `ApplicationRef.tick` was important for several reasons:
* Aligning application behavior more closely with the test behavior (almost all views are attached to application ref in reality)
* Ensuring that afterRender* hooks are executed when calling `fixture.detectChanges`
* Ensuring that the change detection runs again if render hooks update state
This change, however, has some noticeable consequences that will break some tests, mostly around how errors are handled. `ApplicationRef.tick` catches errors that happen during change detection and reports them to the ErrorHandler from DI. The default error handler only logs the error to the console. This will break tests which have `expect(() => fixture.detectChanges()).toThrow()`. In addition, it allows tests to pass when there are real errors encountered during change detection.
This change ensures that errors from `ApplicationRef.tick` are rethrown
and will fail the test. We should also do a follow-up investigation to
determine whether we can/should also do this for the zone-based
`ComponentFixture`.
fixes#56977
PR Close#56993
This option was introduced out of caution as a way for developers to opt out of the new behavior in v18 which schedule change detection for the above events when they occur outside the Zone. After monitoring the results post-release, we have determined that this feature is working as desired and do not believe it should ever be disabled by setting this option to `true`.
PR Close#57029
There are existing usages that inject the renderer to manualy listen (often for event
delegation purposes). These should contribute as well.
PR Close#56799
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
This is the first step towards combining `EarlyEventContract` and `EventContract`. It contains a few refactors, such as making names more consistent.
The goal of this refactor is to remove the `EarlyEventContract` class altogether, as well as `EventContract`.
To install the early event contract with the default events in early script tag, users will call:
`bootstrapGlobalEarlyEventContract()`
And for boostraping:
`registerGlobalDispatcher(dispatcher)`
PR Close#56900
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
This should make things somewhat faster, since setAttribute can be slower than addEventListener. Jsaction attribute is still needed for SSR though.
PR Close#56747
These values are inlined in ActionFlow internally in google3, and are no longer used.
Do some additional cleanup to only define the properties once.
PR Close#56590
This replaces all addEventListener calls with a stashing function,
and installs an event listener on the document body to retrieve
the stashed function;
PR Close#56247
`EventContract` usages in Angular now use `false` for
`useActionResolver`. Tests have been updated, with functionality that
depends on `ActionResolver` moving to dispatcher_test.ts.
PR Close#56369
PR Close#56369