Signal functions are marked with a `[SIGNAL]` symbol property, which was
previously set to `true`.
This commit changes the `[SIGNAL]` property to have the `ReactiveNode` as
its value instead. This doesn't change the behavior of the signal library
itself, but exposes the signal internals in a way where developer tooling
can look at any signal and interact with its dependency graph.
PR Close#49529
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 adds a `DeepReadonly` type to the signals API, and makes signal
getters return an immutable version of their value type. This doesn't
prevent all mutation but adds some friction against modifying the values
within signals outside of the proper mutation APIs.
PR Close#49529
The `effect` implemented in the signal library is useful for testing but
does not integrate with Angular. This commit moves that code to the
actual framework package and integrates it with automatic cleanup via
`DestroyRef`. A simpler effect implementation is used in the signal tests to
test the `Watch` primitive.
Further commits will update the scheduling to tie effects together with
change detection.
PR Close#49529
This commit switches the `signal` and `computed` APIs to accept an optional
options argument as their second argument, instead of an equality function
directly. The equality function has moved to an option in the options
argument.
PR Close#49529
This commit renames the `SettableSignal` interface to align with recent
naming changes. `WritableSignal` is considered a more suitable name since
it supports more mutation operations than just directly setting.
PR Close#49529
This commit adds an assertion function to the public API, which allows
authors of functions which rely on `inject` to validate that they're being
called with the right context. This mostly produces a nicer error message
than calling `inject()` and relying on Angular's default error message for
that.
PR Close#49529
When navigating in the Router, the current approach does the redirects
and the creation of the `RouterStateSnapshot` in two separate steps
(applyRedirects and recognize). These two steps duplicate the route
matching logic, resulting in user code on routes being executing twice
(custom `UrlMatcher` and `canMatch` guards). This also duplicates the
complex matching logic in two places, which increases the bundle size
and maintenance burden.
This commit combines the `applyRedirects` and `recognize` steps into a
single matching algorithm.
fixes#26081
PR Close#49163
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
The `moduleId` directive field does not have any effect as of Ivy. In
View Engine it was used for resolving template and styles relative
to the component source location- but ultimately this is not needed
as the Angular compiler knows the source file location at build time,
and at runtime never even consulted `moduleId`. An XHR is always issue
using the extact specified URL.
For Angular CLI users, relative URLs in JIT are still possible because
the CLI has a TS transform that will replace the references with actual
Webpack imports.
`moduleId` does not seem worth keeping in the future, as it's not used
currently, and even if we would consider supporting relative JIT resource
URLs through it, it would be deeply coupled to CommonJS `module.id`.
DEPRECATED: The `@Directive`/`@Component` `moduleId` property is now
deprecated. It did not have any effect for multiple major versions and
will be removed in v17.
PR Close#49496
This diagnostic ensures that the special attribute `ngSkipHydration` is not a binding and has no other value than `"true"` or an empty value.
Fixes#49501
PR Close#49512
When we create a context to inject inside our ngTemplateOutlet, the context was declare as Object, therefore, there are no compilation error.
Now if we add a context, we get error at compile type.
BREAKING CHANGE: If the 'ngTemplateOutletContext' is different from the context, it will result in a compile-time error.
Before the change, the following template was compiling:
```typescript
interface MyContext {
$implicit: string;
}
@Component({
standalone: true,
imports: [NgTemplateOutlet],
selector: 'person',
template: `
<ng-container
*ngTemplateOutlet="
myTemplateRef;
context: { $implicit: 'test', xxx: 'xxx' }
"></ng-container>
`,
})
export class PersonComponent {
myTemplateRef!: TemplateRef<MyContext>;
}
```
However, it does not compile now because the 'xxx' property does not exist in 'MyContext', resulting in the error: 'Type '{ $implicit: string; xxx: string; }' is not assignable to type 'MyContext'.'
The solution is either:
- add the 'xxx' property to 'MyContext' with the correct type or
- add '$any(...)' inside the template to make the error disappear. However, adding '$any(...)' does not correct the error but only preserves the previous behavior of the code.
fix#43510
PR Close#48374
`entryComponents` have been deprecated since version 9, because with Ivy they weren't necessary. These changes remove any remaining references.
BREAKING CHANGE:
* `entryComponents` has been deleted from the `@NgModule` and `@Component` public APIs. Any usages can be removed since they weren't doing anyting.
* `ANALYZE_FOR_ENTRY_COMPONENTS` injection token has been deleted. Any references can be removed.
PR Close#49484
This adds user friendly error messages outlining exactly where hydration
mismatches occur and what was expected with easy to read stringified
DOM. It also includes a pointer to exactly where the mismatch happened
and lets the user know what was expected.
PR Close#49502
This commit removes the `renderApplication` overload that accepts a root component as the first parameter.
BREAKING CHANGE:
`renderApplication` method no longer accepts a root component as first argument. Instead, provide a bootstrapping function that returns a `Promise<ApplicationRef>`.
Before
```ts
const output: string = await renderApplication(RootComponent, options);
```
Now
```ts
const bootstrap = () => bootstrapApplication(RootComponent, appConfig);
const output: string = await renderApplication(bootstrap, options);
```
PR Close#49463
This change makes it possible to remove a previously registered destroy
callback - to do so it is enough to call the unregistration function
returned from the onDestroy method call.
PR Close#49493
Before this change the effect creation function was returning
an instance of the Effect interface with explicit destroy and
schedule operations. This commit makes the following changes
to the return type of effect:
- the interface is renamed from Effect to EffectRef;
- the only available method on this interface is destroy.
We want to tighten the interface in question so only a minimal
set of useful operations is initially exposed.
PR Close#49490
The `i18n` integration size test golden has been updated with
an increase 20hrs ago, but now with the recent Angular update,
it seems back to the previous size, a decrease in size.
https://github.com/angular/angular/pull/49495.
PR Close#49514
Adds support for marking a directive input as required. During template type checking, the compiler will verify that all required inputs have been specified and will raise a diagnostic if one or more are missing. Some specifics:
* Inputs are marked as required by passing an object literal with a `required: true` property to the `Input` decorator or into the `inputs` array.
* Required inputs imply that the directive can't work without them. This is why there's a new check that enforces that all required inputs of a host directive are exposed on the host.
* Required input diagnostics are reported through the `OutOfBandDiagnosticRecorder`, rather than generating a new structure in the TCB, because it allows us to provide a better error message.
* Currently required inputs are only supported during AOT compilation, because knowing which bindings are present during JIT can be tricky and may lead to increased bundle sizes.
Fixes#37706.
PR Close#49468
This reverts commit 13dd614cd1.
This breaks a g3 Typescript compilation tests where diagnostics are
expected for a missing input in the component.
PR Close#49467
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
Adds support for marking a directive input as required. During template type checking, the compiler will verify that all required inputs have been specified and will raise a diagnostic if one or more are missing. Some specifics:
* Inputs are marked as required by passing an object literal with a `required: true` property to the `Input` decorator or into the `inputs` array.
* Required inputs imply that the directive can't work without them. This is why there's a new check that enforces that all required inputs of a host directive are exposed on the host.
* Required input diagnostics are reported through the `OutOfBandDiagnosticRecorder`, rather than generating a new structure in the TCB, because it allows us to provide a better error message.
* Currently required inputs are only supported during AOT compilation, because knowing which bindings are present during JIT can be tricky and may lead to increased bundle sizes.
Fixes#37706.
PR Close#49453
This reverts commit 1a6ca68154.
This breaks tests in google3 which might be depending on private APIs. We
need to update these tests before we can land this PR.
PR Close#49449
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
Adds support for marking a directive input as required. During template type checking, the compiler will verify that all required inputs have been specified and will raise a diagnostic if one or more are missing. Some specifics:
* Inputs are marked as required by passing an object literal with a `required: true` property to the `Input` decorator or into the `inputs` array.
* Required inputs imply that the directive can't work without them. This is why there's a new check that enforces that all required inputs of a host directive are exposed on the host.
* Required input diagnostics are reported through the `OutOfBandDiagnosticRecorder`, rather than generating a new structure in the TCB, because it allows us to provide a better error message.
* Currently required inputs are only supported during AOT compilation, because knowing which bindings are present during JIT can be tricky and may lead to increased bundle sizes.
Fixes#37706.
PR Close#49304
This commit implements hydration support for view containers, which should make `*ngIf`, `*ngFor` and other structural directive work with hydration.
The logic also respects the `ngSkipHydration` flag and skips hydration in such cases.
PR Close#49382
BREAKING CHANGE:
`ComponentFactoryResolver` has been removed from Router APIs.
Component factories are not required to create an instance of a component
dynamically. Passing a factory resolver via resolver argument is no longer needed
and code can instead use `ViewContainerRef.createComponent` without the
factory resolver.
PR Close#49239
With the introduction of `EnvironmentInjector`, we added an operation to run
a function with access to `inject` tokens from that injector. This operation
only worked for `EnvironmentInjector`s and not for element/node injectors.
This commit deprecates `EnvironmentInjector.runInContext` in favor of a
standalone API `runInInjectionContext`, which supports any type of injector.
DEPRECATED: `EnvironmentInjector.runInContext` is now deprecated, with
`runInInjectionContext` functioning as a direct replacement:
```typescript
// Previous method version (deprecated):
envInjector.runInContext(fn);
// New standalone function:
runInInjectionContext(envInjector, fn);
```
PR Close#49396
This commit adds the `provideServerSupport()` function that returns the `EnvironmentProviders` needed to setup server rendering without NgModules.
PR Close#49380
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
add function `provideServiceWorker` to register a service worker in standalone applications without using `ServiceWorkerModule.register()`
PR Close#48247
Prior to this change component styles generated on the server where removed prior to the client side component being rendered and attached it's own styles. In some cases this caused flickering. To mitigate this `initialNavigation: enabledBlocking'` was introduced which allowed the remove of server styles to be defer to a latter stage when the application has finished initialization.
This commit changes the need for this, by not removing the server generated component styles and reuse them for client side rendering.
PR Close#48253
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
This adds the ngSkipHydration annotation, which allows users to
opt hydration boundaries out of hydration. This enables incremental
adoption of hydration by letting users skip hydration on components
that have implementation issues that conflict with hydration.
co-authored-by: AndrewKushnir <akushnir@google.com>
PR Close#49345
This commit incrementally builds on top of #49285 and adds the logic to hydrate <ng-container>s and their contents. This implementation supports simple <ng-container>s 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.
PR Close#49303
The `Router` already has the `getCurrentNavigation()` helper function to
expose information about the ongoing navigation.
`lastSuccessfulNavigation` is actually already exposed in the
`Navigation` object. This commit only _slightly_ extends the current API
surface by providing access to the `lastSuccessfulNavigation` object
outside of an ongoing navigation.
fixes#45685
PR Close#49235
* 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
The `renderApplication` now also accepts a bootstrapping function call with return `Promise<ApplicationRef>`as the first parameter.
Example:
```ts
const bootstrap = () => bootstrapApplication(RootComponent, appConfig);
const output: string = await renderApplication(bootstrap);
```
PR Close#49248
The deprecated `XhrFactory` export from `@angular/common/http` has been removed.
BREAKING CHANGE:
Deprecated `XhrFactory` export from `@angular/common/http` has been removed. Use `XhrFactory` from `@angular/common` instead.
PR Close#49251
The deprecated `renderModuleFactory` has been removed as it is no longer necessary with Ivy.
BREAKING CHANGE: `renderModuleFactory` has been removed. Use `renderModule` instead.
PR Close#49247
This commits add a utility method to merge multiple `ApplicationConfiguration` into one from left to right. This is useful for server rendering were an application might have several configurations.
Usage Example:
```ts
const config = mergeApplicationConfig(appConfig, appServerConfig);
```
PR Close#49253
This is needed to provide the merge configuration method which will reside in core.
DEPRECATED: `ApplicationConfig` has moved, please import `ApplicationConfig` from `@angular/core` instead.
PR Close#49253
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