Commit Graph

2726 Commits

Author SHA1 Message Date
Gerald Monaco 9d8af457e3 refactor(core): run internal work outside of public afterRender phases (#52145)
Public afterRender phases have specific API guarantees which can be invalidated if the internal framework is implemented using them. Instead, the framework should use dedicated internal functions.

PR Close #52145
2023-10-16 12:24:00 +02:00
Kristiyan Kostadinov 262d4d52b5 refactor(core): tree shake depepdency interceptor token (#52199)
We have the `DEFER_BLOCK_DEPENDENCY_INTERCEPTOR` DI token that we use in tests to intercept the dependency loading function from deferred blocks, however we were referencing it in a way that caused it to be retained in production bundles as well.

These changes guard the call site with `ngDevMode` since the token is only used for testing.

PR Close #52199
2023-10-16 11:17:24 +02:00
Thomas Wilkinson 479e3f1441 refactor(router): Introduce StateManager interface (#52171)
Move existing logic into `HistoryStateManager`

PR Close #52171
2023-10-13 13:48:17 +02:00
Andrew Kushnir efea62fc41 test(core): verify directive order inside and outside of @defer blocks (#52194)
This test verifies that the order does not change when a particular part of code is wrapped by the `@defer` block.

PR Close #52194
2023-10-13 11:10:20 +02:00
Matthieu Riegler 1c4a3677eb refactor(animations): make AnimationBuilder tree-shakable (#52097)
This commit allows also to use the `AnimationBuilder` when using `provideAnimationsAsync()`

fixes #52096

PR Close #52097
2023-10-12 18:13:22 +02:00
Andrew Kushnir 908f660a72 refactor(core): better organization of @defer runtime code (#52152)
This commit splits the `render3/instructions/defer.ts` file (that contained most of the runtime code) into smalle
r files that are easier to maintain.

There are no functional changes in this PR, just organizing code.

PR Close #52152
2023-10-12 12:43:54 +02:00
Payam Valadkhan 1a4aee7e49 feat(core): show runtime error for orphan component rendering (#52061)
A runtime error will be thrown if a non-standalone component is being rendered without its NgModule loaded in the browser. This error is thrown only in dev mode and only if the Angular option `forbidOrphanComponents` is set to true. The error contains useful info to find the orphan component in the source code.

PR Close #52061
2023-10-10 15:30:26 -07:00
Payam Valadkhan 3047bdd36c refactor(core): add an API to deps tracker to check if a component is orphan (#52061)
A new method `isOrphanComponent` is added to the deps tracker API to check if the NgModule declaring this component, if exists, is loaded into the browser.

PR Close #52061
2023-10-10 15:30:26 -07:00
Payam Valadkhan 5fba8902d8 refactor(core): add forbidOrphanRendering option to class debug info (#52061)
The flag `forbidOrphanRendering` is only set for non-standalone components, and indicates that the dev mode runtime should through error if the component is rendered without its ngModule loaded in the browser. This runtime error can help with further debugging.

PR Close #52061
2023-10-10 15:30:26 -07:00
Paul Gschwendtner df58c0b714 fix(core): disallow afterRender in reactive contexts (#52138)
Using `afterRender` schedules long-living lifecycle hooks. Scheduling
such hooks inside reactive contexts could mean that many of the
same hooks would be scheduled, quickly piling up every time a
consumed signal changes. This is likely unintended and could degrade
application performance or result in unexpected behavior.

Additionally, scheduling `afterRender` inside a `computed` is considered
a side effect. Computed expressions are expected to be pure/ i.e. free
of side effects. We can avoid this caveat by detecting the reactive
context in development.

PR Close #52138
2023-10-10 13:56:56 -07:00
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
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
Kristiyan Kostadinov 861ce3a7c5 fix(compiler): pipes using DI not working in blocks (#52112)
Fixes that the new block syntax was generating instructions in the wrong order which meant that pipes were being declared too early. This meant that if the block is first in the template, any pipes used in it won't be able to inject things like `ChangeDetectorRef`.

These changes update the compiler and add a bunch of tests to ensure that pipes work as expected.

Fixes #52102.

PR Close #52112
2023-10-10 09:48:37 -07:00
Kristiyan Kostadinov 229331e11b build: fix broken symbols test
Fixes a symbol test that broke on the main branch.
2023-10-10 09:12:28 +02: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
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
Kristiyan Kostadinov 753eb2459e build: fix broken symbols test (#52092)
Fixes a test that is broken on the main branch.

PR Close #52092
2023-10-09 08:06:11 -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
Andrew Kushnir 2e16b0e0ea ci: update @defer symbol test golden file (#52088)
This commit updates `@defer` symbol test golden file to account for an extra symbol that was added in a different PR.

PR Close #52088
2023-10-06 13:04:55 -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 Kushnir b88cc9eccb test(core): add symbol tracking for @defer feature (#52065)
This commit adds a bundling test, which also includes symbol tracking for `@defer` feature.

PR Close #52065
2023-10-06 12:11:29 -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
Andrew Kushnir f06d97e86d test(core): await all async work to be completed before checking test results (#52064)
This change should help make currently flaky test more stable.

PR Close #52064
2023-10-06 08:33:38 -07:00
Pawel Kozlowski 05d1fac41f test(core): more tests around built-in for (#52045)
Add some more tests around list diffing (created in
a different branch while working in the list diffing).

PR Close #52045
2023-10-05 16:21:58 -07:00
Pawel Kozlowski 0fb742402e test(core): move control flow acceptance tests (#52045)
Moves each control flow test (if, switch, for) into their
corresponding file.

PR Close #52045
2023-10-05 16:21:58 -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
Alex Castle dde3fdabbd feat(common): upgrade warning to logged error for lazy-loaded LCP images using NgOptimizedImage (#52004)
Upgrade the existing warning so it now logs an error instead, when an LCP element is determined to not be usings the `priority` attribute. Error is logged, not thrown.

PR Close #52004
2023-10-04 11:36:01 -07:00
Joey Perrott 5269cae788 build: lock file maintenance (#51834)
Update the lock file.

PR Close #51834
2023-10-04 11:31:27 -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 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
Kristiyan Kostadinov 43e6fb0606 feat(core): enable block syntax (#51994)
Enables the new `@` block syntax by default by removing the `enabledBlockTypes` flags. There are still some internal flags that allow special use cases to opt out of the block syntax, like during XML parsing and when compiling older libraries (see #51979).

PR Close #51994
2023-10-03 15:26:05 -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 367b075d15 test(core): enable previously failing @defer tests (#51965)
This commit re-enables previously flaky tests. The original issue was resolved by mocking `requestIdleCallback` in tests.

PR Close #51965
2023-10-02 08:35:51 -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
Matthieu Riegler e753278faa feat(animations): Add the possibility of lazy loading animations code. (#50738)
`provideLazyLoadedAnimations()` returns providers which allow the lazy loading of the animation module.

Lazy loading of the animation code can shave off up to 16KB gzipped of the main bundle.

PR Close #50738
2023-09-29 10:49:39 -07:00
Kristiyan Kostadinov e2e3d69a27 feat(core): support deferred triggers with implicit triggers (#51922)
Adds support for defining `viewport`, `interaction` and `hover` triggers with no parameters. If the framework encounters such a case, it resolves the trigger to the root element of the `@placeholder` block. Triggers with no parameters have the following restrictions:
1. They have to be placed on an `@defer` block that has an `@placeholder`.
2. The `@placeholder` can only have one root node.
3. The root placeholder node has to be an element.

PR Close #51922
2023-09-27 12:59:34 -07:00