Currently `TNode.inputs`/`TNode.outputs` store all of the available bindings on that node, no matter if they came from a directive that the user applied directly or from a host directive. This has a couple of drawbacks:
1. We need to store more information that necessary. For example, the only reason we have strings in the arrays is to facilitate host directive aliasing.
2. It doesn't allow us to distinguish which host directives belong to which selector-matched directives.
These changes are a step towards resolving both issues by storing the host directive binding information in separate data structures.
PR Close#60036
Reworks the functions that create the `initialInputs`, `inputs` and `outputs` structures to initilize them within the function, instead of returning them to be initialized later. This will simplify future refactors where they'll produce more than one piece of information.
PR Close#60036
This refactoring consolidates logic around detecting ngNonBindable
mode - previously those checks were done in two separate places.
By doing the check in one place we can simplify the directive resolution
logic.
PR Close#60048
Currently the values in `DirectiveDef.inputs` are either strings or arrays, depending if there are flags. This makes it a bit hard to work with, because each time it's read, the consumer needs to account for both cases.
These changes rework it so the values are always an arrays.
PR Close#59980
Adjusts the code we generate for HMR so that it passes in the HMR ID and `import.meta` to the `replaceMetadata` call. This is necessary so we can do better logging of errors.
PR Close#59854
The refactoring of `resource()` to use `linkedSignal()` introduced the
potential for a race condition where resources would get stuck and not update
in response to a request change. This occurred under a specific condition:
1. The request changes while the resource is still in loading state
2. The resource resolves the previous load before its `effect()` reacts to the
request change.
In practice, the window for this race is small, because the request change in
(1) will schedule the effect in (2) immediately. However, it's easier to
trigger this sequencing in tests, especially when one resource depends on the
output of another.
To fix the race condition, the resource impl is refactored to track the request
in its state, and ignore resolved values or streams for stale requests. This
refactoring actually makes the resource code simpler and easier to follow as
well.
Fixes#59842
PR Close#59851
Previously, using `Validators.required`, `Validators.minLength` and `Validators.maxLength` validators don't work with sets because a set has the `size` property instead of the `length` property. This change enables the validators to be working with sets.
PR Close#45793
This change removes some code and logic duplication by
re-using the existing functionality. It also pulls some
code into separate methods for clarity.
PR Close#59806
When a resource first starts up, even if it transitions immediately to
`Loading` it should report a `previous.state` of `Idle`. It was reporting
`Loading` as the previous state in such a case because of an oversight in
the migration to `linkedSignal` which this commit addresses.
PR Close#59708
We already have a function called `isDetachedByI18n` which checks whether a `tNode` is in `isDetached` state; as thus, there's no reason to apply those checks manually.
PR Close#59668
Before `resource()` resolves, its value is in an unknown state. By default
it returns `undefined` in these scenarios, so the type of `.value()`
includes `undefined`.
This commit adds a `defaultValue` option to `resource()` and `rxResource()`
which overrides this default. When provided, an unresolved resource will
return this value instead of `undefined`, which simplifies the typing of
`.value()`.
PR Close#59655
This commit adds support for creating `resource()`s with streaming response
data. A streaming resource is defined by a `stream` option instead of a
`loader`, with `stream` being a function returning
`Promise<Signal<{value: T}|{error: unknown}>>`. Once the streaming loader
resolves to a `Signal`, it can continue to update that signal over time, and
the values (or errors) will be delivered to via the resource's state.
`rxResource()` is updated to leverage this new functionality to handle
multiple responses from the underlying Observable.
PR Close#59573
Currently during HMR we swap out the entire module definition (e.g. `MyComp.ɵcmp = newDef`). In standalone components and most module-based ones this works fine, however in some cases (e.g. circular dependencies) the compiler can produce a `setComponentScope` call for a module-based component. This call doesn't make it into the HMR replacement function, because it is defined in the module's file, not the component's. As a result, the dependencies of these components are cleared out upon replacement.
A secondary problem is that the `directiveDefs` and `pipeDefs` fields can save references to definitions that later become stale as a result of HMR.
These changes resolve both issues by:
1. Performing the replacement by copying the properties from the new definition onto the old one, while keeping it in place.
2. Preserving the initial `directiveDefs`, `pipeDefs` and `setInput`.
Fixes#59639.
PR Close#59644
When a component is created with shadow DOM encapsulation, we attach a shadow root to it. When the component is re-created during HMR, it was throwing an error because only one shadow root can be attached to a node at a time.
Since there's no way to detach a shadow root from a node, these changes resolve the issue by making a shallow clone of the element, replacing it and using the clone for any future updates.
Fixes#59588.
PR Close#59597
If a component injects `ViewContainerRef`, its `LView` gets wrapped in an empty `LContainer` and the container's host becomes the `LView`. The HMR logic wasn't accounting for this which meant that such components wouldn't be replaced.
Fixes#59592.
PR Close#59596
This change refactor how the dynamically created component
deals with attributes in order to reuse the existing
setupStaticAttributes logic (instead of having specific
and similar code).
PR Close#59572
When the reactive `request` of a resource() notifies, it transitions to the
Loading state, fires the loader, and eventually transitions to Resolved.
With the prior implementation, a change of the `request` will queue the
effect, but the state remains unchanged until the effect actually runs. For
a brief period, the resource is in a state where the request has changed,
but the state has yet to update.
This is problematic if we want to use resources in certain contexts where we
care about the state of the resource in a synchronous way. For example, an
async validator backed by a resource might be checked after an update:
```
value.set(123);
if (validator.value()) {
// value is still valid, even though the resource is dirty and will soon
// flip to loading state (returning value(): undefined) while revalidating
}
```
To address this timing concern, `linkedSignal()` is used within the
`resource()` to synchronously transition the state in response to the
request changing. This ensures any followup reads see a consistent view of
the resource regardless of whether the effect has run.
This also addresses a race condition where `.set()` behaves differently on a
`resource()` depending on whether or not the effect has run.
PR Close#59024
Prevent leaking signal reads and exceptions from a custom `equal`
function of a producer `computed()` to a consumer.
Upstream https://github.com/tc39/proposal-signals/pull/90 with a notable
change: Angular does **not** track reactive reads in custom `equal`
implementations.
PR Close#55818
Fixes that in some cases the HMR replacement function was being run outside the zone which meant that change detection would break down after a replacement.
Fixes#59559.
PR Close#59562
This is first of a series of refactorings that moves code
around such that logic from the shared instruction file
is dispatched to the relevant functional parts.
PR Close#59453
The set of profiler events was recently extended. This commit plugs
newly created events dispatch into the approriate places
of the Angular core.
PR Close#59233
We change the `enum` to a plain `const` to eliminate extra bytes, as `enum` is not really required. We might not be able to switch to `const enum` due to single-file compilation restrictions.
PR Close#59469
The set of profiler events was recently extended. This commit plugs
newly created events dispatch into the approriate places
of the Angular core.
PR Close#59233
In this commit, we switch from decorators (which also produce redundant metadata, such as in the
`declareFactory` instruction) to the `inject` function to drop the `BROWSER_MODULE_PROVIDERS_MARKER`
token in production. This token is actually provided only in development mode but is still
referenced in the constructor due to the `@Inject(BROWSER_MODULE_PROVIDERS_MARKER)` decorator.
PR Close#59412
Prior to this commit, the compiler produced:
```js
No = (function (e) {
return (
(e[(e.None = 0)] = "None"),
(e[(e.HasTransplantedViews = 2)] = "HasTransplantedViews"),
e
);
})(No || {});
```
Changing to `const enum` allows it to be entirely dropped and inline values.
PR Close#59416