Commit Graph

4398 Commits

Author SHA1 Message Date
Andrew Scott da616ee773 test(core): Ensure signals can be read after view creation during change detection (#52495)
These tests ensure signals can be read in a template after embedded
views are created in the middle of template execution of an update pass.
The embedded view templates are executed in create mode in the middle of
the component template being executed in update mode. This behavior was
found to not work correctly in past implementations of the reactive
template consumers.

PR Close #52495
2023-11-13 18:24:41 +00:00
Jessica Janiuk 0e7b1daa8d fix(migrations): Fixes issue with multiple if elses with same template (#52863)
This should fix the issue where if the same ng-template is used with multiple if / else statements, it replaces all usages properly.
fixes: #52854

PR Close #52863
2023-11-13 18:23:55 +00:00
AleksanderBodurri 6aef0f6fc8 fix(core): handle non-container environment injector cases (#52774)
Previously we had logic for a special case where a root injector in standalone apps would skip the import paths calculation step for the `getEnvironmentInjectorProviders` function.

This commit intends to fix this for two other cases, namely:
- When an injector is created by a route (via the `providers` field and lazy loading).
- When an injector is manually created and attached to the injector tree

It does this by assuming that any environment injector it cannot find a provider imports container for was created without one, and simply returns the raw provider records without the import paths calculation.

PR Close #52774
2023-11-13 16:21:03 +00:00
Jessica Janiuk da97bbc762 fix(migrations): passed in paths will be respected in nx workspaces (#52796)
This fixes a bug where if you have multiple tsconfig files, the migration would not find anything to migrate at the passed in path.
fixes: #52787

PR Close #52796
2023-11-13 15:21:36 +00:00
Jessica Janiuk 17adf0f917 fix(migrations): Add support for removing imports post migration (#52763)
This update removes imports from component decorators and at the top of the files. It only removes standalone imports though. It does not remove CommonModule if that is the only import.

PR Close #52763
2023-11-13 15:21:06 +00:00
Jessica Janiuk beb18fb01c refactor(migrations): code clean up and add comments on exported functions (#52755)
This cleans up a bit of code to make maintenance easier. It also adds comments for all the exported methods so they are clear to anyone in the future.

PR Close #52755
2023-11-09 22:55:50 +00:00
Pawel Kozlowski 6c8776ff71 fix(core): limit rate of markers invocations (#52742)
This PR assures that the performance markers are invoked
only once for a given feature.

Closes #52524

PR Close #52742
2023-11-09 19:58:26 +00:00
Mikhail Filin 867161f204 docs: remove broken link pill in dynamic component page (#52744)
PR Close #52744
2023-11-09 19:18:29 +00:00
Andrew Kushnir 55d2c427c2 refactor(core): delay applying component metadata until it's needed in tests (#52708)
When a component contains `@defer` blocks, Angular compiler generates the code to apply component metadata (from the `@Component` decorator) after resolving all dynamic dependencies. Currently, this function is invoked eagerly at runtime, which causes dynamic imports to be kicked off earlier than expected. With the change in this commit, Angular will start resolving async metadata when it becomes necessary during testing.

PR Close #52708
2023-11-09 16:58:06 +00:00
Pawel Kozlowski ea8c9b61d2 fix(core): properly update collection with repeated keys in @for (#52697)
This change fixes a bug in the new list reconcilation algorithm
that could lead to an infinite loop in certain situations.

More specifically, it adjusts the internal MultiMap implementation
such that an entry returned from the .get call is the same entry
(for an identical key) removed by the .delete call.

The existing logic of the MultiMap was leading to a situation where
one view was requested and attached to LContainer, but a very different
view was removed from the MultiMap. This was leaving an attached LView
in a collection that was supposed to hold only detached views.

Closes #52524

PR Close #52697
2023-11-09 15:44:53 +00:00
cexbrayat cc68b0e9f5 fix(core): error code in image performance warning (#52727)
The warnings link to https://angular.io/errors/NG2965 which is a 404
The proper error page is https://angular.io/errors/NG0913

PR Close #52727
2023-11-09 15:44:24 +00:00
Jessica Janiuk 12f979d5c6 fix(migrations): Add support for ng-templates with i18n attributes (#52597)
This makes sure that i18n attributes are preserved on ng-templates being removed during the migration.

fixes: #52517

PR Close #52597
2023-11-08 10:26:20 -08:00
cexbrayat c745ca2a61 refactor(core): sanitize reactivity tests (#52632)
It was intriguing to see a double `fixture.detectChanges()` introduced by 38c9f08c8d
It turns out this is not needed.

PR Close #52632
2023-11-08 08:51:50 -08:00
Andrew Scott 33da677ecc refactor(core): Remove RootViewRef<T> because it is the same as ViewRef<T> (#52430)
`RootViewRef<T>` extends `ViewRef<T>` and overrides 3 methods with behavior
that is identical to `ViewRef<T>`. This commit removes `RootViewRef<T>`
because it is not needed.

PR Close #52430
2023-11-08 08:50:50 -08:00
Andrew Scott 8592585f6a test(core): Add test to ensure writing to signals in afterRender hooks throws error (#52475)
We do not yet handle running change detection again if `afterRender`
hooks write to signals.

PR Close #52475
2023-11-08 08:48:44 -08:00
Jessica Janiuk b9e2893e5c fix(migrations): Switches to multiple passes to fix several reported bugs (#52592)
Rather than migrate all in one pass, this now migrates in a separate pass per control flow item plus one for templates at the end. This resolves issues with multiple control flow items on a single element as well as making sure ng-templates are fully migrated before being moved to new locations.

fixes: #52518
fixes: #52516
fixes: #52513

PR Close #52592
2023-11-08 08:47:10 -08:00
Andrew Scott f887792c83 refactor(core): Add warning when signal equality is false for object.is (#52532)
This commit adds a warning when a signal equality function returns
`false` but `Object.is` returns `true`.

PR Close #52532
2023-11-06 15:53:09 -08:00
Andrew Scott a8071ffcbd refactor(core): Remove change detection flag used in g3 (#52530)
This has now been cleaned up internally and is no longer needed

PR Close #52530
2023-11-06 11:42:15 -08:00
Jessica Janiuk 0207801953 fix(migrations): Fixes a bug in the ngFor pre-v5 alias translation (#52531)
The logic that transformed the value to get the alias name was incorrect.

fixes: #52522

PR Close #52531
2023-11-06 09:47:36 -08:00
Jessica Janiuk f2fbe869f0 fix(migrations): Update regex to better match ng-templates (#52529)
This addresses an edge case where an ng-template name matches an opening element name, preventing the template from being removed.

fixes #52523

PR Close #52529
2023-11-06 09:05:55 -08:00
Kristiyan Kostadinov 9cfd35a594 fix(compiler): ng-template directive invoke twice at the root of control flow (#52515)
Discovered this while validating #52414 against Angular Material. We were projecting `<ng-template>` nodes at the root of `@if` and `@for` with the `ng-template` tag name which enables directive matching and applies the directive to the control flow node.

These changes fix the issue by never passing along the `ng-template` tag name.

PR Close #52515
2023-11-06 09:03:45 -08:00
Kristiyan Kostadinov cc4dc52703 fix(migrations): account for separator characters inside strings (#52525)
Fixes that the control flow migrations wasn't accounting for separator characters used inside string literals.

PR Close #52525
2023-11-06 09:00:23 -08:00
Kristiyan Kostadinov 44341ca25d fix(migrations): handle comma-separated syntax in ngFor (#52525)
This is something that came up when running the script against the Components repo. The `ngFor` syntax can be delimited either by semicolons or by commas, but the migration only accounted for commas.

PR Close #52525
2023-11-06 09:00:23 -08:00
AleksanderBodurri 3d73b0cbfb fix(core): use TNode instead of LView for mapping injector providers (#52436)
Previously, LViews were used here to be consistent with other debug APIs. Using LViews for tracking injector providers does not work because providers only get configured once per TNode type.

Now we use the TNode as the key to track element injector providers, allowing the injector for each item rendered in a list (`ngFor` or `@for`) to be targeted with debug APIs for inspecting providers

PR Close #52436
2023-11-03 09:36:00 -07:00
Kristiyan Kostadinov 1da4a2407e fix(migrations): handle ngIf else condition with no whitespaces (#52504)
Fixes that the control flow migration wasn't migrating an `*ngIf` with an `else` condition that doesn't have spaces before the `else`.

Fixes #52502.

PR Close #52504
2023-11-03 09:32:47 -07:00
Aanchal Agarwal 25600375a3 docs: omit repetitions (#52413)
PR Close #52413
2023-11-03 07:46:54 -07:00
Alan Agius d4bd3f198b build: configure tslint to ban performance.mark usages (#52505)
While `performance.mark` is available on all supported browsers and node.js version this API is not available in JSDOM which is used by Jest and Cloudflare worker.

PR Close #52505
2023-11-03 07:43:36 -07:00
Alan Agius 93d32a9acb fix(core): guard usages of performance.mark (#52505)
While `performance.mark` is available on all supported browsers and node.js version this API is not available in JSDOM which is used by Jest and Cloudflare worker.

This commit, updates the usage to a safer variant.

PR Close #52505
2023-11-03 07:43:36 -07:00
Alex Rickabaugh 1f528f1e8d refactor(core): mark effect as developer preview again (#52490)
Re-add the `@developerPreview` flags to `effect()`. While we don't expect
the `effect` API itself to change, we may change how other FW APIs interact
with `effect`s. Also, add a missing export for one of those effect APIs.

PR Close #52490
2023-11-02 15:29:44 -07:00
Andrew Scott 83a3b85c35 refactor(core): Do not refresh view if producers did not actually change (#52476)
Producers represent values which can deliver change notifications.
When a producer value is changed, a change notification is propagated through the graph,
notifying live consumers which depend on the producer of the potential update.
Note here that this is a _potential_ update.

A producer may not have actually "changed" based on its equality function. With
this commit, before refreshing a view that is only marked for refresh
because its consumer is dirty, we poll producers for change to see if
they really have. If not, we can skip the refresh. The example test in this commit
shows that a `computed` which depends on a `signal` that is updated but
produces a value that is the same as before will _not_ cause the
component's template to refresh.

fixes #51797

PR Close #52476
2023-11-02 13:23:49 -07:00
Andrew Scott 164cfc0acf refactor(core): Update LView consumer to use only 1 consumer for a component (#52476)
This commit updates the reactive consumer used for `LView`s to be shared
between a component and its embedded views. This allows us to use the
consumer flag directly for a dirty indicator rather than needing to
find a component view for updating its flags.

In the future, this will also allow us to effectively poll producers to see if
they really changed before refreshing a view.

PR Close #52476
2023-11-02 13:23:49 -07:00
Andrew Scott 58d74a29f8 refactor(core): Remove warning about signal set during template execution (#52476)
The significance of the combination of #51854 and #52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.

fixes #50320

PR Close #52476
2023-11-02 13:23:49 -07:00
arturovt 9dbc5d7b0e refactor(core): do not run CDs when setting up image perf warnings (#52482)
This commit wraps the `load` event listener with `runOutsideAngular` to avoid
running unnecessary change detections on asynchronous tasks spawned within the
scope of the `ImagePerformanceWarning` functionality. This was previously causing
extra change detection cycles in development mode and interfering with debugging.

PR Close #52482
2023-11-02 11:03:42 -07:00
Jeremy Elbourn a3abe1671c build: add target to generate api manifest (#52472)
This adds a target to generate a manifest of all public api symbols. The majority of inputs are generated from the extraction rules, but API entries that don't have a TypeScript source symbol (elements and blocks) are defined in hand-written json collections.

PR Close #52472
2023-11-02 11:00:59 -07:00
Pawel Kozlowski 91ee2697c0 refactor(core): short-circuits invocations of signals equality (#52465)
This change skips signal equality calls on set / update when the
two values (current and the new one) are referentially identical.
The assumption is that equality function implementation should
never return false for 2 values that are the same (according to
the Object.is logic).

PR Close #52465
2023-11-02 10:59:59 -07:00
Alex Rickabaugh 664099b50e refactor(core): add a flag for whether we skip logic in checkNoChanges (#52488)
This can be used to patch different behavior in g3.

PR Close #52488
2023-11-01 21:43:21 -07:00
Alex Rickabaugh cce84d2178 Revert "refactor(core): Remove RootViewRef<T> because it is the same as ViewRef<T> (#52430)" (#52484)
This reverts commit a3028e2340 as it breaks
tests in g3.

PR Close #52484
2023-11-01 10:13:12 -07:00
Alex Rickabaugh 01b79356fb Revert "refactor(core): rename ViewRef<T> to InternalViewRef<T> and remove existing InternalViewRef (#52430)" (#52484)
This reverts commit a568bc5d97 as it breaks
tests in g3.

PR Close #52484
2023-11-01 10:13:12 -07:00
Alex Rickabaugh ee9605f3c8 fix(core): effects wait for ngOnInit for their first run (#52473)
When an effect is created in a component constructor, it might read signals
which are derived from component inputs. These signals may be unreliable or
(in the case of the proposed input signals) may throw if accessed before the
component is first change detected (which is what makes required inputs
available).

Depending on the scenario involved, the effect may or may not run before
this initialization takes place, which isn't a great developer experience.
In particular, effects created during CD (e.g. via control flow) work fine,
as do effects created in bootstrap thanks to the sync CD it performs. When
an effect is created through dynamic component creation outside of CD though
(such as on router navigations), it runs before the component is first CD'd,
causing the issue.

In fact, in the signal components RFC we described how effects would wait
until ngOnInit for their first execution for exactly this reason, but this
behavior was never implemented as it was thought our effect scheduling
design made it unnecessary. This is true of the regular execution of effects
but the above scenario shows that *creation* of the effect is still
vulnerable. Thus, this logic is needed.

This commit makes effects sensitive to their creation context, by injecting
`ChangeDetectorRef` optionally. An effect created with an injector that's
tied to a component will wait until that component is initialized before
initially being scheduled. TestBed effect flushing is also adjusted to
account for the additional interaction with change detection.

PR Close #52473
2023-11-01 08:07:35 -07:00
Alex Rickabaugh 7bb3ffb77f fix(core): add rejectErrors option to toSignal (#52474)
By default, `toSignal` transforms an `Observable` into a `Signal`, including
the error channel of the Observable. When an error is received, the signal
begins throwing the error.

`toSignal` is intended to serve the same purpose as the `async` pipe, but
the async pipe has a different behavior with errors: it rejects them
outright, throwing them back into RxJS. Rx then propagates the error into
the browser's uncaught error handling logic. In the case of Angular, the
error is then caught by zone.js and reported via the application's
`ErrorHandler`.

This commit introduces a new option for `toSignal` called `rejectErrors`.
With that flag set, `toSignal` copies the async pipe's behavior, allowing
for easier migrations.

Fixes #51949

PR Close #52474
2023-10-31 14:59:26 -07:00
AleksanderBodurri 4df04b6546 refactor(core): ignore ENVIRONMENT_INTIIALIZER and INJECTOR_DEF_TYPES provides in getInjectorProviders (#52458)
These special providers are configured when `walkProviderTree` is called. Because of this, they do not maintain any equality between subsequent runs of `walkProviderTree`. This prevents us from being able to compare the provider objects for equality between runs.

This commit changes the behaviour of getInjectorProviders to ignore these providers. In the future we will consider another approach for differentiating these providers from ones provided by users rather than the framework.

PR Close #52458
2023-10-31 14:55:04 -07:00
Kristiyan Kostadinov eb15358479 fix(compiler): project control flow root elements into correct slot (#52414)
With the directive-based control flow users were able to conditionally project content using the `*` syntax. E.g. `<div *ngIf="expr" projectMe></div>` will be projected into `<ng-content select="[projectMe]"/>`, because the attributes and tag name from the `div` are copied to the template via the template creation instruction. With `@if` and `@for` that is not the case, because the conditional is placed *around* elements, rather than *on* them. The result is that content projection won't work in the same way if a user converts from `*ngIf` to `@if`.

These changes aim to cover the most common case by doing the same copying when a control flow node has *one and only one* root element or template node.

This approach comes with some caveats:
1. As soon as any other node is added to the root, the copying behavior won't work anymore. A diagnostic will be added to flag cases like this and to explain how to work around it.
2. If `preserveWhitespaces` is enabled, it's very likely that indentation will break this workaround, because it'll include an additional text node as the first child. We can work around it here, but in a discussion it was decided not to, because the user explicitly opted into preserving the whitespace and we would have to drop it from the generated code. The diagnostic mentioned point #1 will flag such cases to users.

Fixes #52277.

PR Close #52414
2023-10-31 14:52:30 -07:00
AleksanderBodurri 078ebeab00 fix(core): mutation bug in getDependenciesFromInjectable (#52450)
Previously, we would modified `dep.flags` directly to convert injection flags to booleans. This caused a mutation bug where subsequent calls to `getDependenciesFromInjectable` would result in the flags object containing false for every injection flag.

Now, we stop modifying `dep.flags` directly and instead assign the converted flags to a new object.

PR Close #52450
2023-10-31 14:21:36 -07:00
Alan Agius 19a426d54e build: update node.js engines version to be more explicate about v20 support (#52448)
This commit adds Node.js 20 as explicitly supported version to match the Angular CLI engines.

See: https://github.com/angular/angular-cli/pull/26173

PR Close #52448
2023-10-31 14:18:36 -07:00
cexbrayat c5980d6b5f fix(core): handle aliased index with no space in control flow migration (#52444)
The current regexp supposes that there is at least one space between the `=` and the aliased variable.
As it is possible to write `let myIndex=index`, this commit updates the regexp to handle such a case.

PR Close #52444
2023-10-31 13:45:00 -07:00
Swami 6c274ec2ed docs(core): remove documentation of mutate function (#52435)
PR Close #52435
2023-10-31 13:42:14 -07:00
Andrew Scott 75725fb69f docs(core): Deprecate ChangeDetectorRef.checkNoChanges (#52431)
The `checkNoChanges` method does not belong in the API of production interface. `checkNoChanges` is
limited to testing and should not be used in any application code. Test
code should use `ComponentFixture` instead of `ChangeDetectorRef`.
Additionally, it is not desirable to have the `checkNoChanges` API
available in a context where `detectChanges` is not run first.

DEPRECATED: `ChangeDetectorRef.checkNoChanges` is deprecated.

Test code should use `ComponentFixture` instead of `ChangeDetectorRef`.
Application code should not call `ChangeDetectorRef.checkNoChanges` directly.

PR Close #52431
2023-10-31 13:38:44 -07:00
Andrew Scott a3028e2340 refactor(core): Remove RootViewRef<T> because it is the same as ViewRef<T> (#52430)
`RootViewRef<T>` extends `ViewRef<T>` and overrides 3 methods with behavior
that is identical to `ViewRef<T>`. This commit removes `RootViewRef<T>`
because it is not needed.

PR Close #52430
2023-10-31 13:22:56 -07:00
Andrew Scott a568bc5d97 refactor(core): rename ViewRef<T> to InternalViewRef<T> and remove existing InternalViewRef (#52430)
The `ViewRef<T>` interface extends `InternalViewRef` and is already not
part of the public API. There is no need for the extra `InternalViewRef`
interface. This confusing setup is likely leftover from the types
necessary to support both Ivy and ViewEngine.

PR Close #52430
2023-10-31 13:22:56 -07:00
Alex Rickabaugh 62161a630f refactor(core): global epoch to optimize non-live signal reads (#52420)
This commit adds a global epoch to the reactive graph, which can optimize
non-live reads.

When a non-live read occurs, a computed must poll its dependencies to check
if they've changed, and this operation is transitive and not cacheable.
Since non-live computeds don't receive dirty notifications, they're forced
to assume potential dirtiness on each and every read.

Using a global epoch, we can add an important optimization: if *no* signals
have been set globally since the last time it polled its dependencies, then
we *can* assume a clean state. This significantly improves performance of
large unwatched graphs when repeatedly reading values.

PR Close #52420
2023-10-31 13:12:18 -07:00