Previously, effects were queued in the global microtask queue and executed
directly. This had an undesired consequence: whichever effect scheduled
first determined the zone in which all other effects would run, *and* that
zone depended on where the signal happened to be set which triggered that
first effect. This behavior would be extremely unpredictable.
This commit adds zone awareness to the effect API. effects now capture the
current zone when they're created, and this zone is used to run the effect
callback regardless of which zone set the signal.
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
This fixes two cases where DOM node navigation during hydration would be broken. It also fixes an infinite loop on clearing DOM during skip hydration blocks
PR Close#49615
This commit implements a simple tracker of the pending tasks during initial rendering. The class allows adding and removing tasks from the set. The class also exposes a promise that gets resolved once the last task is removed.
This tracker is needed to keep track of ongoing processes like Router navigation (and potentially HTTP requests) and acts as a signaling mechanism to SSR and hydration that the application is in the "stable" state and a serialization can be performed.
This class would also act as a future replacement for the `ApplicationRef.isStable` for zoneless applications.
PR Close#49576
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
`ComponentRef.setInput` currently sets the input on the component regardless
of the previous value the method was called with. This results in
different behavior from bindings in templates, which only set inputs
when the value differs in the `Object.is` check from its previous value.
BREAKING CHANGE: ComponentRef.setInput will only set the input on the
component if it is different from the previous value (based on `Object.is`
equality). If code relies on the input always being set, it should be
updated to copy objects or wrap primitives in order to ensure the input
value differs from the previous call to `setInput`.
PR Close#49607
Currently we are unsafely unquoting CSS values which in some cases causes valid values to become invalid and invalid values to become valid.
Example:
```html
<div style="width:"1px;""></div>
```
In the above case, `width` has an invalid value of `"1px"`, however the compiler will transform it to `1px` which makes it valid.
On the other hand, in the below case
```html
<div style="content:"foo""></div>
```
`content` has a valid value of `"foo"`, but since the compiler unwraps it to `foo` it becomes invalid. For correctness, we should not remove quotes.
```js
const div = document.createElement('div');
div.style.width='"1px"';
div.style.content='foo';
div.style.width; // ''
div.style.content; // ''
div.style.width='1px';
div.style.content='"foo"';
div.style.width; // '1px'
div.style.content; // '"foo"'
```
More information about values can be found https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
PR Close#49460
Currently when the value of a styling property that has a unit is empty string a invalid value is generated.
Example:
`[style.width.px] = ""` will generate a value of `"px"`, when instead it should be `""`.
This causes browser to reset the value to an empty string. This is however not the case in Domino with changes in bfc9114d1e.
This commit fixes the issues and generate correct values.
PR Close#49460
The class-based guard and resolver interfaces are deprecated. The
`Router` types only support functional guards definitions. Classes can
still be used as the underlying implementation of functional guards and
resolvers but there will not be an interface requiring a specific structure
for those classes.
There are also helper functions like `mapToCanActivate` that allow
converting the existing class-based guards directly to functional guards
at the route definition. This will be done in a separate migration.
PR Close#49337
This commit updates the serialization logic to avoid serializing a path for a node that was content projected (based on template information), but is not present in the DOM. This can happen if a <ng-content> is used with the *ngIf="false", for example: `<ng-content *ngIf="false" />`.
PR Close#49590
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
Close#49110
From jest 29 and jest-preset-angular v13, the module transform logic
changed, and now jest-preset-angular use the use the tsconfig target
other than the hardcoded one, https://github.com/thymikee/jest-preset-angular/issues/2010
But jest-angular-preset doesn't introduce the @babel/plugin-transform-async-to-generator
which is needed by angular since `async/await` still need to be transformed
to promise for ES2017+ target.
So for now, we disable to output the uncaught error console log for a temp solution,
until jest-preset-angular find a proper solution.
PR Close#49325
Close#47209
Remove legacy browsers support, so we don't need to patch EventTarget
for very old browsers and cause issues in the new environment.
PR Close#49327
The preloading strategy did not handle a `loadComponent` on a route with
a static `children`. It only preloaded children if they were also
`loadChildren` or both were not lazy loaded.
fixes#49558
PR Close#49571
We are no longer publishing Angular Bazel to npm, but we are still
using it in the components repo. We should still publish it to
benefit from e.g. the APF v16 changes.
PR Close#49583
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
Previously, we've annotated all disconnected DOM nodes, even if they are not used in content projection. However, this situation is only possible in content projection and if it happens in other cases (for example, when a node was removed using direct DOM manipulations), this should be a mismatch error.
PR Close#49549
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 commit patches `ts_library` to be able to produce `ES2022`. Also, updates the build tsconfig and sets `useDefineForClassFields` to `false` to keep the same behaviour of `ng_module`.
PR Close#49559
This commit updates parts of the FW to be ES2022 complaint.
These changes are needed to fix the following problems problems with using properties before they are initialized.
Example
```ts
class Foo {
bar = this.buz;
constructor(private buz: unknown){}
}
```
PR Close#49559
Several updates to Angular Package Format.
BREAKING CHANGE:
Several changes to the Angular Package Format (APF)
- Removal of FESM2015
- Replacing ES2020 with ES2022
- Replacing FESM2020 with FESM2022
PR Close#49559