Commit Graph

2929 Commits

Author SHA1 Message Date
Paul Gschwendtner 5d61221ed7 fix(core): disallow using effect inside reactive contexts (#52138)
Using an `effect` inside a `computed` is a clear violation of
the conceptual idea of computed's being pure/ side-effect free.
Additionally, scheduling new effects from an existing actively
running effect is likely unintended as this could degrage application
performance or result in unintentional behaviors. Multiple long-living
effects would be scheduled every time the effect expressions runs.

For these reasons, we are explicitly preventing this pitfal, by
disallowing using `effect` inside reactive contexts.

PR Close #52138
2023-10-10 13:56:56 -07:00
AleksanderBodurri 50ad074505 fix(core): framework debug APIs getDependenciesForTokenInInjector and getInjectorMetadata (#51719)
Previously getDependenciesForTokenInInjector was unable to determine which node on a view serviced a specific injection. Now it is able to filter out those injections that did not come from the specific node for the NodeInjector passed into it.

Previously getInjectorMetadata was incorrectly looking up DOM elements for some directives (for example NgForOf) where an LContainer was created. Now the LContainer case is handled, and the non LContainer case uses `getFirstNativeNode` to more accurately get the element we want.

PR Close #51719
2023-10-10 13:10:50 -07:00
Thabo add0bd364c docs: correct wording for Directive's decorator host property key description (#51977)
PR Close #51977
2023-10-10 11:22:18 -07:00
Phalgun Vaddepalli 644f3f2241 docs(core): add an example of configuring APP_INITIALIZER token in context of standalone components (#52084)
docs(core): fix formatting

PR Close #52084
2023-10-10 11:18:37 -07:00
Kristiyan Kostadinov d5dad3eb4c fix(core): viewport trigger deregistering callbacks multiple times (#52115)
Adds a check to the viewport cleanup function to prevent it from re-processing elements that have been fully cleaned up, because it can lead to the `IntersectionObserver` being destroyed even though there are still pending triggers. This can happen, because we have cleanup callbacks both for the block is loaded, but also when the placeholder view is destroyed.

Fixes #52113.

PR Close #52115
2023-10-10 09:51:20 -07:00
Matthieu Riegler 40113f653c feat(core): Remove deprecated CompilerOptions.useJit andCompilerOptions.missingTranslation. (#49672)
Both properties have been deprecated in v13 and are unused in v16.

PR Close #49672
2023-10-10 09:35:55 -07:00
Andrew Kushnir 2eebd47733 refactor(core): make timer-related @defer logic tree-shakable (#52042)
This commit updates `@defer` logic related to handling `after` and `minimum` parameters tree-shakable.

If `after` or `minimum` was used on a `@loading` or `@placeholder` blocks, compiler generates an extra argument for the `ɵɵdefer` instruction. This extra argument is a reference to a function that brings timer-related code.

PR Close #52042
2023-10-09 15:57:59 -07:00
Payam Valadkhan 68ba798ae3 feat(core): revamp the runtime error message for orphan components to include full component info (#51919)
The error message now contains the code location of the component. It now looks like: "Error: NG01001: Orphan component found! Trying to render the component Main (at $PROJECT_ROOT/src/main.ts:8) without first loading the NgModule ..."

PR Close #51919
2023-10-09 15:57:03 -07:00
Payam Valadkhan f12e1ef479 refactor(core): add a new stringifier for runtime errors which includes debug info such as the file path and line number (#51919)
The current error stringifier only includes the class name. In this change a new stringifier is added which returns a more helpful string which includes the file path and line number. Note that this is only the case with components, and for other class types (directive, pipes) it will fallback to the current stringifier. Subsequent changes can cover the case of directive and pipes as well.

PR Close #51919
2023-10-09 15:57:03 -07:00
Payam Valadkhan 9e7d243455 refactor(core): implement the runtime ɵsetClassDebugInfo for components (#51919)
A new field `debugInfo` is added to the component definition. Now the runtime  ɵsetClassDebugInfo stores the debug info for components in this new field.

PR Close #51919
2023-10-09 15:57:03 -07:00
Payam Valadkhan 7f9b32caee refactor(core): add an empty implementation for the runtime ɵsetClassDebugInfo (#51919)
This runtime will set the runtime debug info for the given angular class

PR Close #51919
2023-10-09 15:57:03 -07:00
Andrew Scott 0ec66b85e6 refactor(core): Use flag instead of counter for dirty child transplanted views (#51515)
This commit updates the tracking of dirty child views to be a flag
rather than a counter. This is a much more simple method and less likely
to get into the same 'always-wrong' situation that could happen with the
counter (if it is off by 1 once, it's off by 1 forever and you either
get infinite change detection or your view is never refreshed).

PR Close #51515
2023-10-09 14:44:01 -07:00
Kristiyan Kostadinov 7368b8aaeb fix(core): host directive validation not picking up duplicate directives on component node (#52073)
Fixes that, depending on the matching and import order, in some cases we weren't throwing the error saying that a directive matched multiple times on the same element.

Fixes #52072.

PR Close #52073
2023-10-09 12:39:19 -07:00
Andrew Kushnir 422e8582c4 refactor(core): support OnPush components in @defer blocks (#52095)
This commit adds the code to mark newly created embedded views (that represent `@defer` block states) as dirty to indicate that the view sgould be checked during the next change detection cycle.

Resolves #52094.

PR Close #52095
2023-10-09 10:55:38 -07:00
Pawel Kozlowski 00128e3853 fix(core): drop mutate function from the signals public API (#51821) (#51986)
This change removes the `mutate` method from the `WritableSignal` interface and
completely drops it from the public API surface.

The initial API proposal for Angular signals included the mutate method, allowing
in-place modification of JS objects, without changing their references (identity).
This was based on the reasoning that identity change on modification is not necessary
as we can send the “modified” notification through the signals graph.
Unfortunately the signal-specific change notification is lost as soon as we read
signal value outside of a reactive context (outside of a reactive graph).
In other words - any code outside of the Angular signals library can’t know
that an object is modified.

Secondly, to make the mutate method work, we’ve defaulted the signal value equality function
to the one that considers non-primitive values as always different.
This is unfortunate for people working with immutable data structures
(this is notably the case for the popular state management libraries)
as the default equality function de-optimizes memoization in computed,
making the application less performant.

Given the above reasons we prefer to remove the mutate method in the signals library -
at least for now. There are just too many sharp edges and tradeoffs that we don’t fully
understand yet.

BREAKING CHANGE:

The  `mutate` method was removed from the `WritableSignal` interface and completely
dropped from the public API surface. As an alternative please use the update method and
make immutable changes to the object.

Example before:

```typescript
items.mutate(itemsArray => itemsArray.push(newItem));
```

Example after:

```typescript
items.update(itemsArray => [itemsArray, …newItem]);
```

PR Close #51986
2023-10-06 15:12:00 -07:00
Alex Rickabaugh 8f5cbcc845 refactor: move signals code into primitives package (#51986)
This commit reorganizes the Angular code a bit, and moves signals into a
newly defined `@angular/core/primitives` location. This will be used inside
g3 to allow non-Angular targets to depend on the signals core without
incurring a dependency on the whole framework.

PR Close #51986
2023-10-06 15:12:00 -07:00
Alex Rickabaugh b91d143fe4 refactor(core): extract signals API away from the 'signals' package (#51986)
This commit refactors the signals API surface of Angular out of the
//packages/core/src/signals package. This is done in preparation of moving
the core signals package into a new 'primitives' package that's decoupled
from the public API.

PR Close #51986
2023-10-06 15:11:59 -07:00
Alex Castle 048f400efc feat(core): add warnings for oversized images and lazy-lcp (#51846)
Add warnings for two image-related performance problems that apply beyond just apps using NgOptimizedImage.

PR Close #51846
2023-10-06 12:14:32 -07:00
Matthieu Riegler 7dde42a5df feat(http): allow customization of the HttpTransferCache. (#52029)
`provideClientHydration()` accepts new `HydrationFeature` : `HttpTransferCacheOptions`.

`withHttpTransferCacheOptions` accepts an option object:
* `includeHeaders` : list of headers entries to keep in the cache with the request
* `filter` a callback to determine if a request should be cached
* `includePostRequests`: to include POST requests in the allowed methods

Implements some of the features requested in #50117

PR Close #52029
2023-10-06 12:12:47 -07:00
Andrew Scott b6b9eae7e7 Revert "fix(core): drop mutate function from the signals public API (#51821)" (#52081)
This reverts commit c7ff9dff2c.
requires cleanup of 2 uses internally first

PR Close #52081
2023-10-06 10:31:48 -07:00
Andrew Kushnir 486cc611a5 refactor(core): add focusin event to on hover trigger of @defer block (#52059)
This commit adds the `focusin` event to `on hover` trigger of `@defer` block to improve compatibility with screen readers.

PR Close #52059
2023-10-06 08:46:21 -07:00
Pawel Kozlowski 5b88d136af feat(core): mark core signal APIs as stable (#51821)
This change marks core signal APIs as stable and exit
developer preview for the main signal building blocks.

PR Close #51821
2023-10-05 14:40:50 -07:00
Pawel Kozlowski c7ff9dff2c fix(core): drop mutate function from the signals public API (#51821)
This change removes the `mutate` method from the `WritableSignal` interface and
completely drops it from the public API surface.

The initial API proposal for Angular signals included the mutate method, allowing
in-place modification of JS objects, without changing their references (identity).
This was based on the reasoning that identity change on modification is not necessary
as we can send the “modified” notification through the signals graph.
Unfortunately the signal-specific change notification is lost as soon as we read
signal value outside of a reactive context (outside of a reactive graph).
In other words - any code outside of the Angular signals library can’t know
that an object is modified.

Secondly, to make the mutate method work, we’ve defaulted the signal value equality function
to the one that considers non-primitive values as always different.
This is unfortunate for people working with immutable data structures
(this is notably the case for the popular state management libraries)
as the default equality function de-optimizes memoization in computed,
making the application less performant.

Given the above reasons we prefer to remove the mutate method in the signals library -
at least for now. There are just too many sharp edges and tradeoffs that we don’t fully
understand yet.

BREAKING CHANGE:

The  `mutate` method was removed from the `WritableSignal` interface and completely
dropped from the public API surface. As an alternative please use the update method and
make immutable changes to the object.

Example before:

```typescript
items.mutate(itemsArray => itemsArray.push(newItem));
```

Example after:

```typescript
items.update(itemsArray => [itemsArray, …newItem]);
```

PR Close #51821
2023-10-05 14:40:50 -07:00
Andrew Kushnir caa8eb28d5 refactor(core): add after and minimum parameter support to @defer blocks (#52009)
This commit adds runtime code to support `after` and `minimum` parameters in the `@placeholder` and `@loading` blocks. The code uses the `TimerScheduler` service added earlier for `on timer` triggers.

PR Close #52009
2023-10-05 13:35:42 -07:00
Paul Gschwendtner 4427e1ebc2 feat(core): create function to assert not running inside reactive context (#52049)
Some functions or code should never run inside reactive contexts. A
function to assert that will help putting guard rails in place.

PR Close #52049
2023-10-05 11:08:05 -07:00
Andrew Kushnir 706838950c refactor(core): allow nested @defer block to contain the same dependency (#51964)
Currently, if there are 2 nested @defer blocks with the same dependency, Angular throws an error at runtime to indicate that there was a duplicate component def in the registry. This commit updates the logic to only append dependencies when they didn't previously exist in the registry.

PR Close #51964
2023-10-04 09:00:23 -07:00
Paul Gschwendtner 9b9e11fcaf refactor(core): deprecate allowing full context object to be replaced in EmbeddedViewRef (#51887)
This partially reverts commit a3e17190e7
and deprecates behavior added.

The context of an embedded view ref at some point was switched from a
getter to an actual assignable property. This is something we revert
as it introduces additional complexity for our generated code
(in terms of closures capturing the `ctx`), creates technical
limitations for Angular's internals and the usage pattern is rarely
used (and can be addressed via simple assignments, `Object.assign` or
the use of a proxy if replacing the full context object is still
desirable)

DEPRECATED: Swapping out the context object for `EmbeddedViewRef`
is no longer supported. Support for this was introduced with v12.0.0, but
this pattern is rarely used. There is no replacement, but you can use
simple assignments in most cases, or `Object.assign , or alternatively
still replace the full object by using a `Proxy` (see `NgTemplateOutlet`
as an example).

Also adds a warning if the deprecated

PR Close #51887
2023-10-04 08:14:35 -07:00
Andrew Scott d77c4b2aae refactor(core): Update view flags so only one number needs adjustment (#51839)
When adding a new view flag, you currently need to adjust the last number of the last
3 flags. All of these share the same number so the shifting ones can just use
the base-10 IndexWithinInitPhaseShift.

PR Close #51839
2023-10-04 07:29:13 -07:00
Andrew Kushnir 650ab4f218 refactor(core): add support for on timer trigger in @defer blocks (#51974)
This commit adds the logic to support `on timer` triggers in `@defer` blocks in both rendering and prefetching conditions.

PR Close #51974
2023-10-04 07:27:45 -07:00
Pawel Kozlowski 7d42dc3c02 feat(core): the new list reconciliation algorithm for built-in for (#51980)
This commit plugs the new list reconciliation into the new built-in repeater.

PR Close #51980
2023-10-03 19:40:35 -07:00
Pawel Kozlowski 4f04d1cdab feat(core): add new list reconcilation algorithm (#51980)
The new list reconcilation algorithm, an alternative to
the DefaultIterableListDiffer. It works by performing updates
in place instead of creating intermediate data describing changes
to apply. For lists expressed as an Array it performs additional
optimizations for the moves and swap scenarios.

The new list diffing approach is meant to be used in the new control
flow and should me much faster as compared to the ngFor with the
DefaultIterableListDiffer.

PR Close #51980
2023-10-03 19:40:35 -07:00
Dylan Hunn 07602eb298 refactor(compiler): Implement basic support for defer in Template Pipeline (#51942)
The template pipeline now supports basic forms of `defer` blocks. This includes the `loading`, `placeholder`, and `error` blocks, as well as the loading and placeholder configuration options.

Lazy dependencies and prefetch are not yet implemented.

PR Close #51942
2023-10-03 19:40:04 -07:00
Dylan Hunn 489ec15e1d refactor(compiler): Fix pipeBinding variable offsets in template pipeline (#51961)
This is a deceptively simple fix for a deep issue. Consider the following template:

```
<button [title]="myTitle" [id]="(auth().identity() | async)" [tabindex]="1">
```

`TemplateDefinitionBuilder` allocates the following variable (binding) slots:

v[0] = [title] binding
v[1] = [id] binding
v[2] = [tabindex] binding
v[3] = pipe binding
v[4] = pipe binding

As you can see, all three top-level property bindings were assigned variable indices. Then, variables for nested expressions were assigned.

Before this change, Template Pipeline would choose the following order:

v[0] = [title] binding
v[1] = [id] binding
v[2] = pipe binding
v[3] = pipe binding
v[4] = [tabindex] binding

With this order, nested expressions have their variables counted and assigned before subsequent top-level property bindings. This results in different variable indices for `pipeBinding` expressions that are not inside the final property binding.

However, this is not just different -- it's actually incorrect! Consider a case like the following:

```
<button [p1]="c ? (a | pipe) : 3" [p2]="b | pipe">
```

These pipe bindings are executed *conditionally*. This means that, because we don't count and assign all the "fixed" variable slots first, i.e. those belonging to the property bindings, their indices might end up incorrect, depending on whether or not a pipeBinding happened as part of the update block.

With this change, we count all variables on top-level ops first, and then descend into all expressions.

PR Close #51961
2023-10-02 16:58:03 -07:00
Kristiyan Kostadinov 5419af6192 build: fix compilation error due to conflict (#51981)
Fixes a compilation error that happened, because a couple of related PRs landed at the same time.

PR Close #51981
2023-10-02 10:55:46 -07:00
Kristiyan Kostadinov 4f69d620d9 fix(core): deferred blocks not removing content immediately when animations are enabled (#51971)
Fixes an issue where if animations are enabled, deferred blocks don't remove their placeholder blocks immediately from the DOM. The problem is that we register the event handlers in `afterRender` which runs outside the zone, but the logic that removes the DOM nodes during animations is tied to change detection.

These changes resolve the issue by binding the listeners inside the zone. This was the intention from the beginning, I just forgot that `afterRender` runs outside the zone.

Fixes #51970.

PR Close #51971
2023-10-02 09:12:48 -07:00
Andrew Kushnir e368d81896 refactor(core): invoke @defer (on idle) callback in NgZone (#51975)
Currently, there is no change detection scheduled after triggering `on idle` condition, since `requestIdleCallback` is not patched by Zone.js. This commit invokes the callback in NgZone, so that the code that is invoked within the callback can use zones and a new change detection round is scheduled as needed.

Fixes #51973.

PR Close #51975
2023-10-02 08:35:07 -07:00
AleksanderBodurri a54713c831 feat(core): implement ɵgetInjectorMetadata debug API (#51900)
This API allows for inspection of a given injector to determine it's type (Element, Environment, Null) as well as it's "source".

- For Environment injectors the source is the source of the injector; `injector.source`.
- For Element injectors the name is the DOM Element that created the injector.
- For the Null Injector this is the string `"Null Injector"`.

PR Close #51900
2023-09-29 15:22:34 -07:00
Andrew Kushnir 6b6a44c473 refactor(core): add hydration support for built-in for (#51920)
This commit adds hydration support for repeaters (for loops) and empty blocks. The logic looks up a dehydrated view and use this information for hydration. Otherwise, DOM elements for a view are created from scratch.

PR Close #51920
2023-09-29 15:21:21 -07:00
Alan Agius 8413b64a6b refactor(core): add whenStable private API (#51807)
Prior to this change `this.isStable.pipe(first((isStable) => isStable)).toPromise()` had to be done in multiple places across the framework and the Angular CLI see https://github.com/angular/angular-cli/pull/25856#discussion_r1328158846. In the majority of cases an Observable based `isStable` API is not needed. This also removes the need for RXJS operator imports.

PR Close #51807
2023-09-27 10:31:56 -07:00
Andrew Kushnir 7a731c9536 refactor(core): add hydration support for built-in if and switch (#51915)
This commit updates the `if` and `switch` logic to support hydration. The logic attempts to find dehydrated views in containers while processing `if` and `switch` instructions. If a dehydrated is found, its used to further match elements. Otherwise, DOM elements for a view are created from scratch.

PR Close #51915
2023-09-27 10:29:07 -07:00
Andrew Kushnir f483aed86a refactor(core): populate dehydrated views in template instruction (#51915)
Previously, dehydrated views lookup was triggered only when ViewContainerRef was injected. The new control flow logic uses lower level APIs, thus having the code only in the ViewContainerRef is not sufficient.

This commit adds the logic to invoke the process of dehydrated views lookup from the `template` instruction, thus enabling it for new control flow instructions as well.

PR Close #51915
2023-09-27 10:29:07 -07:00
Andrew Kushnir a39010f6ce refactor(core): avoid an empty array allocation during hydration (#51917)
This commit updates hydration runtime code to avoid creating an empty array when we can avoid it. Instead, we just check whether the field is `null` directly (without using nullish coalescing).

PR Close #51917
2023-09-27 09:22:48 -07:00
Andrew Kushnir 4b38e9a1ab refactor(core): add batching for defer blocks with on idle conditions (#51750)
This commit updates runtime logic of defer blocks to schedule a single `requestIdleCallback` for a group of defer blocks created within a single change detection cycle (for example, as a result of a defer block being defined in a for loop).

PR Close #51750
2023-09-26 15:20:34 -07:00
Kristiyan Kostadinov 8be2c48b7c feat(core): implement new block syntax (#51891)
Switches the syntax for blocks from `{#block}{/block}` to `@block {}` based on the feedback from the community.

Read more about the decision-making process in our blog: https://blog.angular.io/meet-angulars-new-control-flow-a02c6eee7843

The existing block types changed in the following ways:

**Conditional blocks:**
```html
<!-- Before -->
{#if cond}
  Main content
  {:else if otherCond}
    Else if content
  {:else}
    Else content
{/if}

<!-- After -->
@if (cond) {
  Main content
} @else if (otherCond) {
  Else if content
} @else {
  Else content
}
```

**Deferred blocks**
```html
<!-- Before -->
{#defer when isLoaded}
  Main content
  {:loading} Loading...
  {:placeholder} <icon>pending</icon>
  {:error} Failed to load
{/defer}

<!-- After -->
@defer (when isLoaded) {
  Main content
} @loading {
  Loading...
} @placeholder {
  <icon>pending</icon>
} @error {
  Failed to load
}
```

**Switch blocks:**
```html
<!-- Before -->
{#switch value}
  {:case 1}
    One
  {:case 2}
    Two
  {:default}
    Default
{/switch}

<!-- After -->
@switch (value) {
  @case (1) {
    One
  }

  @case (2) {
    Two
  }

  @default {
    Default
  }
}
```

**For loops**
```html
<!-- Before -->
{#for item of items; track item}
  {{item.name}}
  {:empty} No items
{/for}

<!-- After -->
@for (item of items; track item) {
  {{item.name}}
} @empty {
  No items
}
```

PR Close #51891
2023-09-26 09:10:04 -07:00
Andrew Kushnir baaaa6daf6 refactor(core): add on immediate support for defer blocks (#51630)
This commit adds a logic to handle `on immediate` conditions both as a main condition, as well as a prefetching condition (i.e. `prefetch on immediate`).

PR Close #51630
2023-09-25 09:17:55 -07:00
Kristiyan Kostadinov 16f5fc40a4 feat(core): support deferred viewport triggers (#51874)
Adds support for `on viewport` and `prefetch on viewport` triggers which will load the deferred content when the element comes into the view.

PR Close #51874
2023-09-25 09:17:03 -07:00
Kristiyan Kostadinov 687b96186c feat(core): support deferred hover triggers (#51874)
Adds support for `on hover` and `prefetch on hover` triggers. Some code had to be moved around so it could be reused from the `on interaction` triggers.

PR Close #51874
2023-09-25 09:17:03 -07:00
Kristiyan Kostadinov 3cbb2a8ecf feat(core): implement deferred block interaction triggers (#51830)
Adds the implementation for the `on interaction` and `prefetch on interaction` triggers.

PR Close #51830
2023-09-22 12:17:54 -07:00
Kristiyan Kostadinov 00e6013661 refactor(compiler): implement final instruction generation for interaction triggers (#51830)
Updates the logic that generates the instructions for the `on interaction` and `prefetch on interaction` triggers to their final shape. Now the instructions take two arguments:
1. `triggerIndex` - index at which to find the trigger in the view where it will be rendered.
2. `walkUpTimes` - tells the runtime how many views up it needs to go to find the trigger element. If the argument is omitted, it means that the trigger is in the same view as the deferred block. A positive number means that the runtime needs to go up X amount of times to find the trigger. A negative number means that the trigger is inside the root view of the placeholder block. Negative numbers are capped at -1 since the placeholder is always in the same position at runtime.

PR Close #51830
2023-09-22 12:17:54 -07:00
Matthieu Riegler 6610c4fb10 refactor(core): Use the Writable type when overwriting readonly properties. (#49754)
The `Writable` type is usefull when we want overwrite readonly properties and we still want to maintain code navigation/reference. It should be use instead of `any` type assertions for example.

PR Close #49754
2023-09-22 10:02:13 -07:00