Previously, with `mergeMap` we did not cancel previous subscriptions to zoneIsStable which caused the application to be stablized before hand.
Closes: #50562
PR Close#50573
This commit updates the `ApplicationRef.isStable` API to account for
pending rendering task. This is needed as once a pending rendering task
is done, new macrotask and microtask could be created which previously caused these not
to be intercepted and thus ignored when doing SSR.
PR Close#50425
Rather than maintaining separate traversal functions that act differently, this change
updates the change detection traversal to share more code and use different modes
to control the type of traversal being performed.
PR Close#50005
It's likely that the flag and counters used to track transplanted views
needing a refresh will be reused to signal views as well. The two follow
a similar rule: While the parents might not be "Dirty", there is still a
child/descendant view somewhere that needs to be refreshed during change
detection.
PR Close#50000
This change explicitly resets a reactive consumer before setting inputs
on directive instances. This is to assure that any potential input setters
do _not_ run in the reactive context.
PR Close#49906
This commits updates the render to able to handle the slight differences between platform-server and platform-browser.
This is needed to eventually be able to remove `ServerRendererFactory2` and `EmulatedEncapsulationServerRenderer2` from platform-server.
PR Close#49630
Angular lifecycle hooks should never be run as part of the reactive
context: we do not expect that signal reads in lifecycle hooks
report to any consumers.
In the current Angular some of the lifecycle hooks can be flushed
early, while executting template update pass. We need to make sure
that signal reads in those lifecycle hooks do not register as part
of the effect that marks components for check.
"
PR Close#49701
`ComponentRef.setInput` internally calls `markDirtyIfOnPush` which only marks
the given view as dirty but does not mark parents dirty like `ChangeDetectorRef.markForCheck` would.
https://github.com/angular/angular/blob/f071224720f8affb97fd32fb5aeaa13155b13693/packages/core/src/render3/instructions/shared.ts#L1018-L1024
`markDirtyIfOnPush` has an assumption that it’s being called from the parent’s template. That is, we don’t need to mark dirty to the root, because we’ve already traversed down to it.
The function used to only be called during template execution for input
bindings but was added to `setInput` later. It's not a good fit because
it means that if you are responding to events such as an emit from an `Observable`
and call `setInput`, the view of your `ComponentRef` won't necessarily get checked
when change detection runs next. If this lives inside some `OnPush` component tree
that's not already dirty, it only gets refreshed if you also call
`ChangeDetectorRef.markForCheck` in the host component (because it will be "shielded" be a non-dirty parent).
PR Close#49711
* Prevent reads of signals during the notification process. This shouldn't
ever be triggered by user code but is more of a preventative for
internal misuse. Reading a signal during notification would/could create
glitches where the values being read are not updated to reflect the
values being updated by the notification.
* Prevent signal writes inside of computed's. These are meant to be
derived values and should not have any side-effects like writing new
values to other signals
* Prevent signal writes inside of effects by default. Writing to signal
values during the execution of an effect can lead to the
`ExpressionChangedAfterItHasBeenCheckedError` if writing to signals
that represent global state which is read in a parent component. This is
mostly just a problem for `OnPush`/`CheckAlways` components, but with
signals being new and pure signal components not even available yet,
it will be the majority for a long time.
PR Close#49631
This commit removed the deprecated `EventManager` method `addGlobalEventListener`.
BREAKING CHANGE: Deprecated `EventManager` method `addGlobalEventListener` has been removed as it is not used by Ivy.
PR Close#49645
This commit updates the `effect` primitive and significantly changes the
timing of effect execution.
Previously, effects were scheduled via the microtask queue. This commit
changes effects to run throughout the change detection process instead.
Running effects this way avoids needing additional rounds of change
detection to resolve effects, with the tradeoff that they're harder to use
for model-to-model synchronization (which can be seen as a good thing).
PR Close#49641
Previously the signals implementation maintained separate interfaces for
`Producer` and `Consumer` nodes, with implementers choosing to implement
one or both interfaces. Operations defined against those interfaces were
exposed as importable functions to be called with the object implementing
the relevant contract as the first argument.
This commit refactors the implementation to merge both abstractions into a
single `ReactiveNode` base class, which represents both producers and
consumers in the graph. Implementers choose to interact with a subset of the
`ReactiveNode` API depending on their role in the graph. Operations are now
available as protected methods on the base class, instead of separate
functions.
PR Close#49529
This commit updates the `LView` in Angular to be a `Consumer` of
signals. If a signal is read when executing a template, it marks the
view dirty. In addition, if a signal is read when executing host
bindings, it also marks views dirty.
One interesting thing about signal reads in host bindings
is that they perform a bit better than what we can do with today's
APIs. In order to re-execute host bindings for an `OnPush` component that
might have changed, you would probably inject `ChangeDetectorRef` and call
`markForCheck`. This will mark the _current component_ and parents
dirty. However, host bindings are executed as part of refreshing the
_parent_ so there is really no need to re-execute the current component
if the only thing that changed is the host bindings. When a signal is
read in host bindings, it marks the parent dirty and not the component
that defined the host binding.
Additionally, this commit avoids allocating a full consumer for each
`LView` by re-using a consumer until template execution results in a
signal read. At this point, we assign that consumer to the `LView` and
create a new consumer to "tentatively" use for the future `LView`
template executions.
Co-authored-by: Dylan Hunn <github@dylanhunn.com>
PR Close#49153
Angular uses inline styles to insert the styles associated with a component. This violates the strict styles [Content Security Policy](https://web.dev/strict-csp/) which doesn't allow inline styles by default. One way to allow the styles to be applied is to set a `nonce` attribute on them, but because the code for inserting the stylesheets is deep inside the framework, users weren't able to provide it without accessing private APIs.
These changes add a new `CSP_NONCE` injection token that will allow users to provide a nonce, if their app is using CSP. If the token isn't provided, the framework will look for an `ngCspNonce` attribute on the app's root node instead. The latter approach is provided as a convenience for apps that render the `index.html` through a server, e.g. `<app ngCspNonce="{% randomNonceAddedByTheServer %}"></app>`.
This PR addresses adding the nonce to framework-generated styles. There will be follow-up PRs that add support for it in critical CSS tags in the CLI, and in Angular Material.
Fixes#6361.
PR Close#49444
The mentioned 2 classes have been combined since it is no longer required to have a separate `SharedStylesHost` for SSR. This changes also reduces the memory usage footprint as remove 1 Map that stores the CSS strings.
PR Close#49424
During DOM serialization, empty text nodes are lost when the client parses the DOM. To solve this problem comment nodes are added where the empty nodes are located right before serialization. Those comments then get replaced during hydration with the proper empty text nodes.
PR Close#49419
Prior to this change, a random application ID was generated each time which forced users using server rendering to provide an application ID themselves. This was needed to handle rare cases when multiple Angular applications are rendered on the same page.
With this change the application ID is no longer generated randomly and instead it is hard coded.
BREAKING CHANGE:
The `APP_ID` token value is no longer randomly generated. If you are bootstrapping multiple application on the same page you will need to set to provide the `APP_ID` yourself.
```ts
bootstrapApplication(ComponentA, {
providers: [
{ provide: APP_ID, useValue: 'app-a' },
// ... other providers ...
]
});
```
PR Close#49422
This commit deprecated ` BrowserModule.withServerTransition` instead `APP_ID` should be used instead to configure the app id.
DEPRECATED: `BrowserModule.withServerTransition` has been deprecated. `APP_ID` should be used instead to set the application ID.
NB: Unless, you render multiple Angular applications on the same page, setting an application ID is not necessary.
Before:
```ts
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
...
]
```
After:
```ts
imports: [
BrowserModule,
{ provide: APP_ID, useValue: 'serverApp' },
...
],
```
PR Close#49422
This commit moves the providers for `NgZone`-based change detection to a
single provider function. This function is currently called by default
in all places where `NgZone` was provided
(`bootstrapApplication`, `bootstrapModule`, and `TestBed`).
When we want to make Angular applications zoneless by default, we
can make a public provider method that has to be used in order to enable
the zone change detection features. When this method is not called,
Angular would use `NoopNgZone` by default and not initialize any
subscriptions to the `NgZone` stability events.
Side note: There are actually two places that `NgZone` is provided for `TestBed`
(providers in `compileTestModule` and `BrowserTestingModule`). This
likely doesn't need to be in both locations.
PR Close#49373
Prior to this change the component IDs where generated based on a counter. This is problematic as there is no guarantee that a component will get the same ID that was assigned on the server when generated on the client side.
This is paramount to be able to re-use the component styles generated on the server.
PR Close#48253
Before this change `ɵɵdefineDirective` called `ɵɵdefineComponent` under the hood. This is problematic for the consistent component id generation as it could result in hash collisions for certain directives. Directives however do not require an id.
This changes moves common definition generation logic into a separate function that is re-used in `ɵɵdefineDirective` and `ɵɵdefineComponent`.
PR Close#49350
This commit incrementally builds on top of https://github.com/angular/angular/pull/49271 and adds the logic to hydrate elements and text nodes that don't have any Angular features (like *ngIf/*ngFor, etc) and are not content-projected.
The subsequent commits will extend the logic further to support more complex scenarios.
Co-authored-by: Jessica Janiuk <jessicajaniuk@google.com>
Co-authored-by: Andrew Kushnir <akushnir@google.com>
PR Close#49285
**Important note**: this is a first commit in a series of commits that will be needed
to support non-destructive hydration. Stay tuned for further updates!
This commit lays the foundation on top of which more hydration logic will be
added in follow up PRs. This PR includes:
* Initial serialization of hydration data
* Data transfer of hydration annotations from server side to client
* Accessing hydration info and populating internal data structures
* Initial APIs (currently private) that enable hydration (in a tree-shakable manner)
* Cleanup of annotations post hydration
* Initial test infrastructure and basic test cases
This commit does **not** expose any public APIs. They'll be exposed later, when
more hydration logic is implemented to a state when it can cover most common
use-cases.
Co-authored-by: Jessica Janiuk <jessicajaniuk@google.com>
Co-authored-by: Andrew Kushnir <akushnir@google.com>
PR Close#49271
* With tsc improvements some types can be refined.
* Removing unnecessary non-null assertions.
* Using std native methods instand of custom functions
* Using @ts-expect-error instead of `any` type assertion to keep code navigation.
PR Close#49206
DestroyRef represents a concept of lifecycle scope where destroy
callbacks can be registered. Such callbacks are automatically
executed when a given scope ends it lifecycle.
In practice the most common lifecycle scopes would be represented by:
- a component or en embedded view;
- instance of `EnvironnementInjector`.
PR Close#49158
While unlikely, prior to this change it was possible to provide a nested array of styles to the render. This required the framework to handle this by doing a flatten operation. This change also renames the `flattenStyles` method as it no longer flattens the styles.
BREAKING CHANGE: `RendererType2.styles` no longer accepts a nested arrays.
Closes#48317
PR Close#49072
Currently style of components using `encapsulation`, `None` or `Emulated` will not be removed from the DOM once the component get destroyed.
This change addresses this by keeping track of the number of times a component is rendered, when the component is destroyed the counter is decreased and once this reaches zero the style element is removed from the DOM.
Currently, this new behaviour is on opt-in bases, but it will be changed in the next major version.
To opt-in, set the `REMOVE_STYLES_ON_COMPONENT_DESTROY` DI token to `true`.
Example
```ts
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule
],
providers: [
{ provide: REMOVE_STYLES_ON_COMPONENT_DESTROY, useValue: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
```
Closes#16670
PR Close#48298
The terser update included various changes, including changes to the
inline optimizations. Constants like for the bloom filter are no longer
inlined multiple times, but instead the constant is preserved and used
with a shortened/mangled name.
Note this also applies to other symbols like `SimpleChanges` too.
This means that such new variables now show up in the symbols goldens.
Concrete examples of inlined & no-longer inlined constants can be
seen in the PR description: https://github.com/angular/angular/pull/49000#issue-1576416106
PR Close#49000
When injecting the `ChangeDetectorRef` into a node that matches a component, we create a new ref using the component's LView. This breaks down for host directives, because they run before the component's LView has been created.
These changes resolve the issue by creating the LView before creating the node injector for the directives.
Fixes#48249.
PR Close#48355
This commit introduces a new type `EnvironmentProviders` which can be used
in contexts where Angular accepted `Provider`s destined for
`EnvironmentInjector`s. This includes contexts such as `@NgModule.providers`
and `Route.providers`.
The new type is useful for preventing such providers from accidentally
ending up in `@Component.providers`. It can be used as the return type of
provider functions (such as `provideRouter`) to enforce this safety.
Because `Provider` allows `any[]` nested arrays, the compile-time safety
provided by `EnvironmentProviders` is easily circumvented. However, the
runtime shape of `EnvironmentProviders` is not compatible with component
injectors and will result in a runtime error if it leaks through (NG0207).
A new function `makeEnvironmentProviders` is used to construct this new type
from an array of providers.
The existing `importProvidersFrom` operation previously returned a very
similar type `ImportedNgModuleProviders` which had the same goal. This
machinery is switched over to use the new `EnvironmentProviders` interface
instead (in fact, `ImportedNgModuleProviders` is now just an alias to
`EnvironmentProviders`).
PR Close#47669
This commit modifies `R3Injector` and other code in Angular that deals with
providers, to handle `EnvironmentProviders` objects as well as normal
`Provider` types. There is no user-visible impact to this change, but it
prepares the core of the DI system for the introduction of
`EnvironmentProviders` as a public feature.
PR Close#47669
Adds the logic that will filter out unexposed inputs/outputs and apply the aliases that the author specified when writing the host directives.
PR Close#47536
Currently the code that creates a root component assumes that it's always going to deal with a single component definition which won't work with host directives. These changes rework the code so that it's able to apply multiple directives, allowing us to eventually add support for host directives.
I also tried to make the root component creation easier to follow by breaking it up into smaller functions.
PR Close#47530
This commit applies the changes similar to the ones performed for the `inject()` function in https://github.com/angular/angular/pull/46649/commits/df246bb2358794e3aad53870f1554d84bbe390b2.
The `TestBed.inject` function is updated to use previously added object-based API for options: now the flags argument supports passing an object which configures injection flags.
DEPRECATED:
The bit field signature of `TestBed.inject()` has been deprecated, in favor of the new options object.
PR Close#46761
In a previous refactor, the `RootContext` was update to only contain a reference to a component. This commit perform further refactoring to get rid of the `RootContext` altogether, while storing component reference directly on the root view (without the `RootContext` wrapper).
PR Close#47056
prior to this change the stagger timing was being built during the
ast building instead of dynamically when visiting the stagger animation,
thus it could not handle params correctly, this change makes it so that
during ast building a timing ast is built instead and that ast is used
dynammically to build animations which can handle params correctly
resolves#19786
PR Close#47208
We used to track all modules in a top-level constant called `autoRegisterModuleById` which was used by `getRegisteredNgModuleType`. As of #45024 the constant isn't being used anymore so we can remove it.
PR Close#47066
The `RootContext` implementation contained a number of fields that were needed to support an experimental `renderComponent` function. The `renderComponent` function was removed, which allows us to cleanup the `RootContext` further.
The only field that remains on the `RootContext` is the list of bootstrapped components. This list is presumably mostly unused right now (it just contains the current component) and further refactoring can happen in a followup PR.
PR Close#46806
On MacOS, pressing the alt key and another key turns into symbols, and
doesn't match the intended behavior. For example, `keydown.alt.s`
reports instead as `keydown.alt.ß`. We rely on the `key` field and not
the `code` field, which properly reports the code for S in this case.
This change adds support to allow users to specify they want to look at
the `code` field instead of the `key` field within their event string.
Example: `keydown.code.alt.leftshift` would only match the LeftShift and
not the right shift based on code values. It would also allow the user
to specify `keydown.code.alt.keys` to match S instead of ß when alt /
option is pressed on MacOS and would also work on Windows.
Fixes#45992
PR Close#46030