empty ngSwitchCase generate `case ()` which isn't valid syntax therefore adding quotes will help prevent us migrate empty case if no condition was provided
fix angular#56030
PR Close#56105
This makes events bubble! This change also contains changes to
dispatcher and event_dispatcher to make replay synchronous,
so that we avoid odd timing issues. This can be split out though.
Lastly, we have one cleanup change to move the mapping from
event type to functions on the element itself.
PR Close#56036
Previously, the event replay serialization logic was located before we verify that a `TNode` exists. `TNode`s may not exist in `tView.data` array in several cases, including cases when there is a local ref used on an element: in this case an extra slot in `LView` contains a reference to the same element and `TNode` is not needed. This commit moves the event replay serialization logic a bit lower, after we check for TNode presence.
Resolves#56073.
PR Close#56076
Currently we optimize methods that pass both `$index` and the item into a method. We can take this a step further by also optimizing calls that only pass `$index` into the first parameter.
PR Close#55872
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
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
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
Developers may want to enable zoneless for all tests by default by
adding the zoneless provider to `initTestEnvironment` and then
temporarily disabling it for individual tests with the zone provider
until they can be made zoneless compatible.
PR Close#55813
With this change, If an async validator that should have emitted was cancelled by a non-emitting validator, the status change will be reported on the `AbstractControl.events` observable.
This issue can happen when a `FormControl` is added to a `FormGroup` and a FormGroupDirective/FormControlDirective trigger a non-emitting validation (which cancels the initial validator execution).
Note: The behavior remains the same of the existing `statusChanges` observable as the change was too breaking to land in G3.
fixes: angular#41519
PR Close#55134
This was mistakenly implemented automatically by the override without
filling in the default value of `true` like it is for the zone-based
fixture.
PR Close#55800
The migration was breaking tests with test modules that imported `HttpClientTestingModule`,
as it removed the JS imports without migrating the module imports.
The migration now handles the case where `HttpClientTestingModule` is used in test modules,
by replacing the module import with the `provideHttpClient` and `provideHttpClientTesting` providers.
Before:
```ts
import { HttpClientTestingModule } from '@angular/common/http/testing';
@NgModule({
declarations: [AppComponent],
imports: [HttpClientTestingModule],
})
export class TestModule {}
```
After:
```ts
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
@NgModule({
declarations: [AppComponent],
imports: [],
providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
})
export class TestModule {}
```
PR Close#55803
Angular has long had the ability to use different interpolation delimiters
(by default `{{` and `}}`). This concept was copied over from AngularJS,
where AngularJS syntax is included in HTML sent over the network to the
browser. Occasionally developers would use SSR frameworks which _also_ have
interpolation syntaxes of their own, so there was a need to change the
delimiters used by AngularJS to avoid conflicts.
Since Angular templates are always processed by our compiler and the
interpolation characters are never processed by other systems first, this
option is vestigial in Angular and only increases the complexity of our
parser.
DEPRECATED: `@Component.interpolation` is deprecated. Use Angular's
delimiters instead.
PR Close#55778
The `HttpClientModule` migration was dropping the existing properties other than imports and providers when updating an `@NgModule`, `@Component` or `configureTestingModule`.
PR Close#55777