Prior to this commit, event listener options were mutated directly, for example,
`options.signal = undefined` or `options.once = false`.
This issue arises in apps using third-party libraries where the responsibility lies
with the library provider. Some libraries, like WalletConnect, pass an abort controller
as `addEventListener` options. Because the abort controller has the `signal` property,
this is a valid case. Thus, mutating options would throw an error since `signal`
is a readonly property.
Even though zone.js is being deprecated as Angular moves towards zoneless change detection,
this fix is necessary for apps that still use zone.js and cannot migrate to zoneless change
detection because they rely on third-party libraries and are not responsible for the code
used in them.
Closes#54142
PR Close#55796
`EventDispatcher` emulates the browser's event dispatch (mostly).
It supports:
- Bubbling and `stopPropagation`/`stopImmediatePropagation`.
- `currentTarget` during dispatch.
- Throwing errors for `preventDefault` if the event is being dispatched
in replay.
- Throwing errors for `composedPath()` if event is being dispatched in
replay.
PR Close#55837
fix(docs-infra): calculate the list of Angular Docs versions based on VERSION, append --config=release to docs build and serve the script. Support displaying the right color of navigation for the deprecated state.
fix(docs-infra): add scrollbar to version picker
fix(docs-infra): set initial adev docs version to 18
fix(docs-infra): remove --config=release from scripts for local development, write unit tests
fix(docs-infra): update CI tests step
fix(docs-infra): remove rc from the list
fix(docs-infra): update unit test to check count of versions
PR Close#56002
This commit updates the `ngswAppInitializer` implementation and removes the `controllerchange`
listener upon the destruction of the `ApplicationRef`. This adjustment aims to prevent memory
leaks. In a zone.js environment, neglecting to do so could lead to the perpetual creation of
a zone task, which captures the zone and obstructs proper garbage collection.
PR Close#55365
This will prevent running `ActionResolver` logic multiple times while
migrating to use `Dispatcher` to resolve actions rather than
`EventContract`.
PR Close#55864
The compiler now checks if a signal is properly called on dom property bindings.
The ideal solution would be for the compiler to check if dom property bindings in general are properly typed,
but this is currently not the case, and it is a bigger task to land this change.
In the meantime, the signal diagnostic is augmented to catch cases like the following:
```
<div [id]="mySignal"></div>
```
PR Close#54324
Users may be using zoneless, but are still loading Zone.js in which case they won't get the full benefits like reduced bundle size. These changes detect such a case and log a warning.
PR Close#55769
The SecondaryNavigation component was updating state outside of an event handler
without notifying about this change. Modeling state as signal should take
care of proper UI updates (note that I did just a mechanical change here, maybe
there are better ways of dealing with this animations case).
PR Close#55830
Provide a thorough explanation of why third-party libraries should be created outside
of the Angular zone. Using a statement like "authored with Zone.js in mind" may seem
unusual because third-party libraries typically do not have knowledge of Zone.js, nor
should they be developed with it in mind. Therefore, we revise this explanation accordingly.
Additionally, include a section on handling events originating from third-party APIs.
PR Close#55876
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
When an `@if` expression has an alias, only the type of the alias is
currently narrowed. So for example, suppose `value` is `string|undefined`:
```
@if (value; as alias) {
{{ value.length }} <!-- error, value may be undefined -->
{{ alias.length }} <!-- no error, alias is narrowed -->
}
```
This is especially noticeable when the expression contains guards which are
preconditions for the aliased expression:
```
@if (a && b; as alias) {...}
```
In this case, `a` would not be narrowed within the body, even though the
`@if` condition forces it to be truthy. This is a bug.
The reason is that aliased expressions were previously type-checked as:
```
var alias = a && b;
if (alias) {
// nothing other than alias is narrowed
...
}
```
One option considered was to emit `const alias` instead of `var alias`.
TypeScript _does_ trace `const` expressions and narrow their individual
components when the overall expression is guarded:
```
const alias = a && b;
if (alias) {
// a, b are also narrowed
}
```
However, this narrowing has different semantics than if `a && b` appeared
directly in the guard expression. For example, object properties aren't
narrowed with this approach, so component properties (which are referenced
as e.g. `this.a`) would not be narrowed.
Instead, we amend the guard expression to include both the expression _and_ the
alias variable, enforcing that both are narrowed.
```
var alias = a && b;
if ((a && b) && alias) {
// a, b, and alias all narrowed correctly.
}
```
This form ensures all conditions within the guard expression get narrowed
while also narrowing the alias variable type.
Fixes#52855
PR Close#55835
Currently when attempting to retrieve a TCB symbol for an input binding
that refers to a signal input with e.g. `protected`, while the
`honorAccessModifiersForInputBindings` flag is `false`, Angular will
throw a runtime exception because the symbol retrieval code always
expects a proper field access in the TCB.
This is not the case with `honorAccessModifiersForInputBindings =
false`, as TCB will allocate a temporary variable when ignoring the
field access. This will then trigger the runtime exception (which we
added to flag such "unexpected" cases). This commit handles it
gracefully, as it's valid TCB, but we simply cannot generate a proper
TCB symbol (yet). This is similar to `@Input` decorator inputs.
In the future we may implement logic to build up TCB symbols for
non-property access bindings, for both signal inputs or `@Input`
inputs. This commit just avoids a build exception.
Related to: #54324.
PR Close#55774
The Angular CLI documentation topic for migrating to the new build system
now has a navigation label of "Migrating to new build system" instead of
"esbuild". This new label better reflects the action a user may want to
take rather than one of the tools used by the new build system.
PR Close#55782