Commit graph

1652 commits

Author SHA1 Message Date
Alex Rickabaugh
38c9f08c8d refactor(core): decouple effects from change detection (#51049)
Previously effects were queued as they became dirty, and this queue was
flushed at various checkpoints during the change detection cycle. The result
was that change detection _was_ the effect runner, and without executing CD,
effects would not execute. This leads a particular tradeoff:

* effects are subject to unidirectional data flow (bad for dx)
* effects don't cause a new round of CD (good/bad depending on use case)
* effects can be used to implement control flow efficiently (desirable)

This commit changes the scheduling mechanism. Effects are now scheduled via
the microtask queue. This changes the tradeoffs:

* effects are no longer limited by unidirectional data flow (easy dx)
* effects registered in the Angular zone will trigger CD after they run
  (same as `Promise.resolve` really)
* the public `effect()` type of effect probably isn't a good building block
  for our built-in control flow, and we'll need a new internal abstraction.

As `effect()` is in developer preview, changing the execution timing is not
considered breaking even though it may impact current users.

PR Close #51049
2023-09-12 08:12:56 -07:00
Gerald Monaco
5277cb408b refactor(core): delegate afterRender errors to an ErrorHandler (#51662)
Improves the error handling story for after*Render by delegating errors to an ErrorHandler, so that one failure does not break every callback.

PR Close #51662
2023-09-08 10:29:33 -07:00
Andrew Kushnir
970d68fe76 refactor(core): add prefetch on idle support for defer blocks (#51629)
This commit updates the logic to add `prefetch on idle` support for defer blocks. Previously, the `on idle` logic was already implemented for the main loading and rendering. This commit reuses the same logic to bring it to the prefetching mechanism.

PR Close #51629
2023-09-05 20:49:56 +00:00
Kristiyan Kostadinov
05a16b973d refactor(compiler): add support for advanced tracking expressions (#51618)
These changes build on top of #51514 to add support for advanced expressions inside the `track` parameter of `for` loop blocks. There are two different outputs that the compiler can generate:

1. If the tracking function only references the item or `$index`, the compiler generates a pure arrow function as a constant references in the `repeaterCreate` instruction.
2. If the tracking function has references to properties outside of the `for` loop block, the compiler will rewrite those references to go through `this` and generate a function declaration. The runtime will `bind` the declaration to the current component instance so that the rewritten `this` references are resolved correctly.

Advanced tracking expression come with the following limitations to ensure the best possible performance:
1. They can only reference the item, `$index` and properties directly on the component instance. This means that there'll be an error when accessing this like local template variables and references. While we could get this to work, we would have to traverse the context tree at runtime which will degrade the performance of the loop, because it's a linear time operation that is performed on each comparison. Furthermore, allowing local references would require us re-evaluate the list when any one of them has changed.
2. Pipes aren't allowed inside the tracking function.
3. Object literals and pipes used inside the tracking expression will be recreated on each invocation.

PR Close #51618
2023-09-05 14:19:18 +00:00
Kristiyan Kostadinov
f36cdd6d1a refactor(core): add instruction to reference component instance (#51618)
Adds an instruction that allows us to access the containing component instance directly instead of having to traverse the context tree. This will be necessary for the tracking function of `for` loop blocks.

PR Close #51618
2023-09-05 14:19:18 +00:00
Andrew Kushnir
1aff106a87 refactor(core): adjust defer block behavior on the server (#51530)
This commit updates the runtime implementation of defer blocks to avoid their triggering on the server. This behavior was described in the RFC (https://github.com/angular/angular/discussions/50716, see "Server Side Rendering Behavior" section): only a placeholder is rendered on the server at this moment. This commit also updates the logic to make sure that the placeholder content is hydrated after SSR.

PR Close #51530
2023-09-01 19:15:16 +00:00
Andrew Scott
40bb45f329 fix(core): Respect OnPush change detection strategy for dynamically created components (#51356)
This commit fixes a bug in the change detection algorithm that would
ignore the `OnPush`/dirty flag of a component's host when it is created
dynamically. That is, `OnPush` components that were not marked dirty but
were created as embedded views would have their host bindings and `ngDoCheck`
function always run even if they were not dirty.

BREAKING CHANGE: `OnPush` components that are created dynamically now
only have their host bindings refreshed and `ngDoCheck run` during change
detection if they are dirty.
Previously, a bug in the change detection would result in the `OnPush`
configuration of dynamically created components to be ignored when
executing host bindings and the `ngDoCheck` function. This is
rarely encountered but can happen if code has a handle on the
`ComponentRef` instance and updates values read in the `OnPush`
component template without then calling either `markForCheck` or
`detectChanges` on that component's `ChangeDetectorRef`.

PR Close #51356
2023-09-01 17:28:27 +00:00
hiepxanh
5a323265cb docs: fix missing information in createComponent (#51493)
PR Close #51493
2023-09-01 16:15:12 +00:00
Alex Rickabaugh
201ab9d247 refactor(core): switch signals to a refcounting algorithm (#51226)
This commit switches the signals library from a bidirectional symmetric
dependency graph using weak references, to a bidirectional _asymmetric_
graph which uses strong references. This is made possible with a reference
counting algorithm which only tracks producer -> consumer references for
effect-like "live" consumers, preventing memory leaks.

The new algorithm should be simpler and faster than the previous
implementation as weak references are fairly slow to create and traverse.
A tradeoff is that non-live consumers must now poll their producers when
read, as they cannot rely on dirty notifications.

As part of this refactoring, the `ReactiveNode` class is replaced with an
interface instead, and methods are moved to standalone functions. This is
paired with instantiating individual signals/computeds via `Object.create`
against a prototype node which contains static or initial values. This
technique, in conjunction with the rest, greatly improves the performance
of node creation.

PR Close #51226
2023-09-01 14:18:41 +00:00
Pawel Kozlowski
b9ba6e6a16 refactor(core): remove duplicated access to TView (#51610)
Tiny refactoring to remove repeated field access to LView.

PR Close #51610
2023-09-01 14:18:06 +00:00
Matthieu Riegler
05e4dbb859 refactor(core): Use intersections on branded types. (#49702)
An Intersection on a branded type allows us to remove some unecessary type assertions.

PR Close #49702
2023-08-31 20:22:12 +00:00
Gerald Monaco
0839885a50 refactor(core): make AfterRenderEventManager tree-shakable (#51541)
In preparation for adding support for phases to after*Render, which will increase the implementation size, this commit splits out the optional logic so that it can be tree-shaken and dynamically loaded.

PR Close #51541
2023-08-31 18:56:23 +00:00
Kristiyan Kostadinov
685d01e106 perf(core): chain template instructions (#51546)
With the new control flow and defer blocks it'll be common for several template instructions to be declare one after another. These changes add support for chaining to the `template` instruction which will allow us to save some bytes.

PR Close #51546
2023-08-29 16:38:52 +00:00
Kristiyan Kostadinov
d83dfaa8ea refactor(compiler): generate for loop block instructions (#51514)
Adds the initial implementation to generate the instructions for the `for` loop block.

**Note:** the expressions we support in the `track` paramateter are currently limited to tracking by identity or index, or a specific property of the item. Supporting more advanced expression will require additional work that I'll do in a follow-up PR.

PR Close #51514
2023-08-29 16:38:22 +00:00
Andrew Kushnir
006577f39c fix(core): handle hydration of view containers that use component hosts as anchors (#51456)
This commit fixes an issue where serialization of a view container fails in case it uses a component host as an anchor. This fix is similar to the fix from #51247, but for cases when we insert a component (that acts as a host for a view container) deeper in a hierarchy.

Resolves #51318.

PR Close #51456
2023-08-29 16:37:50 +00:00
Andrew Kushnir
ba32d6ffd1 refactor(core): add basic prefetching runtime mechanism for defer blocks (#51529)
This commit adds runtime implementation of a basic preloading mechanism for defer blocks. The base prefetching logic invokes a dependency loading function (generated by the compiler) when a corresponding `prefetch when` condition is triggered. The `prefetch on` triggers would be implemented in followup PRs.

We plan to explore additional prefetching techniques and will followup with more PRs later (based on the research).

PR Close #51529
2023-08-28 23:53:32 +00:00
Gerald Monaco
3a19d6b743 fix(core): run afterRender callbacks outside of the Angular zone (#51385)
afterRender should run outside of the Angular zone so that it does not trigger further CD cycles

PR Close #51385
2023-08-28 23:02:28 +00:00
Pawel Kozlowski
cdcfa09ab3 refactor(core): built-in control flow - repeaters (#51422)
Draft of the runtime implementation for the built-in repeaters.

PR Close #51422
2023-08-28 20:49:18 +00:00
Andrew Kushnir
c4deaac5b0 refactor(core): initial implementation of {#defer} block runtime (#51347)
This commit adds an initial implementation of the `{#defer}` block runtime, which supports the `when` conditions. More conditions and basic prefetching support will be added in followup PRs.

PR Close #51347
2023-08-28 17:09:52 +00:00
Kristiyan Kostadinov
0c4c773fca refactor(compiler): generate switch block instructions (#51380)
Adds the logic to generate the instructions for `switch` instructions. For the following block:

```html
{#switch value()}
  {:case 0} case 0
  {:case 1} case 1
  {:case 2} case 2
  {:default} default
{/switch}
```

The compiler will produce the following output:

```ts
function App_Template(rf, ctx) {
  if (rf & 1) {
    ɵɵtemplate(0, App_Case_0_Template, 1, 0);
    ɵɵtemplate(1, App_Case_1_Template, 1, 0);
    ɵɵtemplate(2, App_Case_2_Template, 1, 0);
    ɵɵtemplate(3, App_Case_3_Template, 1, 0);
  }
  if (rf & 2) {
    let App_contFlowTmp;
    ɵɵconditional(0, (App_contFlowTmp = ctx.value()) === 0 ? 0 : App_contFlowTmp === 1 ? 1 : App_contFlowTmp === 2 ? 2 : 3);
  }
}
```

PR Close #51380
2023-08-18 10:01:02 -07:00
Payam Valadkhan
8798abb744 refactor(core): implement runtime logic to compute component dependencies in local compilation mode (#51377)
The runtime `ɵɵsetNgModuleScope` is modified to accept raw scope info as passed to it in local compilation mode. The runtime further registers the ng-module in the deps tracker. Then the runtime `ɵɵgetComponentDepsFactory` is implemented to use the deps tracker to get the component dependencies which leads to a valid and working Angular code.

PR Close #51377
2023-08-17 14:01:51 -07:00
Payam Valadkhan
e69e41ecf8 refactor(core): more accurate types for standalone component imports in deps tracker (#51377)
The standalone components import as passed to the deps tracker will be the raw import, i.e., it is either a Type or a module with providers or a factory of these. So we use the existing type `RawScopeInfoFromDecorator` for these imports instead of the current one to be more realistic.

PR Close #51377
2023-08-17 14:01:51 -07:00
Payam Valadkhan
56e0b8526a refactor(core): allow empty raw import info for standalone components in the runtime deps tracker (#51377)
The current logic requires that standalone component always provide an array of raw imports. But such array could be dropped from the downstream tools if the component has no imports. So it is more natural to allow undefined raw imports for standalone components and treat it as empty array.

PR Close #51377
2023-08-17 14:01:51 -07:00
Payam Valadkhan
8b431a0164 refactor(core): kill circular deps by moving scope runtime functions to a new scope.ts file (#51377)
This refactoring is needed for next commit not to produce circular deps as we start using the `depsTracker` inside `ɵɵsetNgModuleScope`. The runtime `ɵɵsetComponentScope` is not needed to move but it moved to the new file just for consistency sake.

PR Close #51377
2023-08-17 14:01:51 -07:00
Andrew Kushnir
bcc3c43fca refactor(core): update TestBed to handle async component metadata (#51182)
This commit updates TestBed to wait for async component metadata resolution before compiling components.
Async metadata is added by the compiler in case a component uses defer blocks, which contain deferrable
symbols.

PR Close #51182
2023-08-15 11:32:09 -07:00
Andrew Kushnir
c41a1950fd refactor(compiler): apply component metadata asynchronously when defer blocks are present (#51182)
This commit updates compiler logic to generate the `setClassMetadataAsync` calls for components that used defer blocks. The `setClassMetadataAsync` function loads deferrable dependencies and invokes the `setClassMetadata` synchronously once everything is loaded. This change is needed to avoid eager references to deferrable symbols in component metadata in generated code.

PR Close #51182
2023-08-15 11:32:09 -07:00
Pawel Kozlowski
93675dc797 feat(core): conditional built-in control flow (#51346)
Initial PoC of the built-in control flow support. The goal is to
unblock compiler work.

PR Close #51346
2023-08-14 17:16:39 -07:00
Pawel Kozlowski
ebd217d393 Revert "refactor(core): remove class type check when clearing cache in deps tracker (#51293)" (#51358)
This reverts commit a9f609e75c.

PR Close #51358
2023-08-14 13:48:47 -07:00
Pawel Kozlowski
b1f0fc9129 Revert "refactor(core): enabled using deps tracker in JIT compilation (#51293)" (#51358)
This reverts commit bc55d82eb9.

PR Close #51358
2023-08-14 13:48:47 -07:00
Pawel Kozlowski
b0ea81d562 Revert "refactor(core): kill circular deps by moving scope runtime functions to a new scope.ts file (#51309)" (#51358)
This reverts commit 45105555da.

PR Close #51358
2023-08-14 13:48:47 -07:00
Pawel Kozlowski
b297ea7966 Revert "refactor(core): allow empty raw import info for standalone components in the runtime deps tracker (#51309)" (#51358)
This reverts commit 8156128863.

PR Close #51358
2023-08-14 13:48:47 -07:00
Pawel Kozlowski
32d30f26a7 Revert "refactor(core): more accurate types for standalone component imports in deps tracker (#51309)" (#51358)
This reverts commit e7ea016e00.

PR Close #51358
2023-08-14 13:48:47 -07:00
Pawel Kozlowski
ee73d180fd Revert "refactor(core): implement runtime logic to compute component dependencies in local compilation mode (#51309)" (#51358)
This reverts commit f7cfc3b8fa.

PR Close #51358
2023-08-14 13:48:47 -07:00
Payam Valadkhan
f7cfc3b8fa refactor(core): implement runtime logic to compute component dependencies in local compilation mode (#51309)
The runtime `ɵɵsetNgModuleScope` is modified to accept raw scope info as passed to it in local compilation mode. The runtime further registers the ng-module in the deps tracker. Then the runtime `ɵɵgetComponentDepsFactory` is implemented to use the deps tracker to get the component dependencies which leads to a valid and working Angular code.

PR Close #51309
2023-08-14 08:58:47 -07:00
Payam Valadkhan
e7ea016e00 refactor(core): more accurate types for standalone component imports in deps tracker (#51309)
The standalone components import as passed to the deps tracker will be the raw import, i.e., it is either a Type or a module with providers or a factory of these. So we use the existing type `RawScopeInfoFromDecorator` for these imports instead of the current one to be more realistic.

PR Close #51309
2023-08-14 08:58:47 -07:00
Payam Valadkhan
8156128863 refactor(core): allow empty raw import info for standalone components in the runtime deps tracker (#51309)
The current logic requires that standalone component always provide an array of raw imports. But such array could be dropped from the downstream tools if the component has no imports. So it is more natural to allow undefined raw imports for standalone components and treat it as empty array.

PR Close #51309
2023-08-14 08:58:47 -07:00
Payam Valadkhan
45105555da refactor(core): kill circular deps by moving scope runtime functions to a new scope.ts file (#51309)
This refactoring is needed for next commit not to produce circular deps as we start using the `depsTracker` inside `ɵɵsetNgModuleScope`. The runtime `ɵɵsetComponentScope` is not needed to move but it moved to the new file just for consistency sake.

PR Close #51309
2023-08-14 08:58:46 -07:00
Payam Valadkhan
bc55d82eb9 refactor(core): enabled using deps tracker in JIT compilation (#51293)
This change simply flip the flag which enables using the deps tracker in JIT compilation (the logic is already implemented in a previous PR). Some tests which depend on the old JIT implementation (e.g., patching the scope info into the type) are modified accordingly.

PR Close #51293
2023-08-14 08:57:32 -07:00
Payam Valadkhan
a9f609e75c refactor(core): remove class type check when clearing cache in deps tracker (#51293)
Using verification helpers such as `isComponent` may trigger JIT compilation. Now in some tests such compilation is made purposely to fail, and so in such cases any reference to the `depsTracker.clearScopeCacheFor` method will cause the exception to be thrown earlier than expected which results in teh test failure. Such scenario is the case in the next commit when we enable using the deps tracker in the jit compilation. Note that such failure is only for the framework tests and is a very edge case. The tests in downstream apps will not lead to such scenario of failure at all.

PR Close #51293
2023-08-14 08:57:32 -07:00
Kristiyan Kostadinov
5212b47bbf refactor(compiler): introduce defer trigger instructions (#51315)
Adds the logic for generating the instructions for the various deferred triggers.

PR Close #51315
2023-08-11 06:55:13 -07:00
Kristiyan Kostadinov
79f9d49fad refactor(compiler): introduce defer block instructions (#51315)
Adds the logic for generating `{#defer}`, `{:placeholder}`, `{:loading}` and `{:error}` block instructions in the compiler.

PR Close #51315
2023-08-11 06:55:13 -07:00
Payam Valadkhan
f8c2a0d07f refactor(core): add an empty implementation for getComponentDepsFactory runtime (#51089)
An empty runtime is added just to make the local compiled angular files valid to run. A separate PR will implement the runtime in the right way using the deps tracker.

PR Close #51089
2023-08-08 13:58:48 -07:00
Payam Valadkhan
6a7c1ab9e9 refactor(core): migrate JIT to use deps tracker behind a flag (#51122)
The current change is done behind a flag which is set to false. So no change in code path took place here. In a followup PR the flag is changed to true which will make the actual change.

PR Close #51122
2023-08-07 09:25:27 -07:00
Andrew Kushnir
55965cbf8c fix(core): handle hydration of view containers for root components (#51247)
For cases when a root component also acts as an anchor node for a ViewContainerRef (for example, when ViewContainerRef is injected in a root component), there is a need to serialize information about the component itself, as well as an LContainer that represents this ViewContainerRef. Effectively, we need to serialize 2 pieces of info: (1) hydration info for the root component itself and (2) hydration info for the ViewContainerRef instance (an LContainer). Each piece of information is included into the hydration data (in the TransferState object) separately, thus we end up with 2 ids. Since we only have 1 root element, we encode both bits of info into a single string: ids are separated by the `|` char (e.g. `10|25`, where `10` is the ngh for a component view and 25 is the `ngh` for a root view which holds LContainer).

Previously, we were only including component-related information, thus all the views in the view container remained dehydrated and duplicated (client-rendered from scratch) on the client.

Resolves #51157.

PR Close #51247
2023-08-07 09:24:26 -07:00
Pawel Kozlowski
f12f906bd7 refactor(core): introduce LView and LContainer utility functions (#51191)
This refactoring adds utility functions to add / remove LView from LContainer.
Those utils are preparation for the control flow and defer work.
Existing code was refactored to use the new utility functions and avoid
any code duplication.

PR Close #51191
2023-08-04 16:00:44 -04:00
Gerald Monaco
e53d4ecf4c feat(core): add afterRender and afterNextRender (#50607)
Add and expose the after*Render functions as developer preview

PR Close #50607
2023-08-01 13:02:27 -07:00
Matthieu Riegler
4602545fe6 refactor(core): remove useless hack (#51224)
This hack is remnant of the Ivy migration.

PR Close #51224
2023-08-01 12:12:52 -07:00
Matthieu Riegler
a871e23857 docs: remove duplicate words. (#51215)
Using the `\b(\w+)\s+\1\b` we can find duplicate word. Let's remove them.

PR Close #51215
2023-08-01 12:08:33 -07:00
Andrew Kushnir
efb486e8bc refactor(compiler): handle defer blocks in TemplateDefinitionBuilder (#51162)
Updates the TemplateDefinitionBuilder class to generate the `defer` instruction for `{#defer}` blocks. Also generates dependency function that would be invoked at runtime (with dynamic imports inside).

PR Close #51162
2023-08-01 11:50:05 -07:00
AleksanderBodurri
98d262fd27 feat(core): create injector debugging APIs (#48639)
This commit introduces 3 new APIs.

getDependenciesFromInstantiation:
- Given an injector and a token that was instantiated by that injector, discover all of the things were injected in the instance of that token
- This API is meant to enable recursive inspection of dependencies. Dependencies returned by this API include which injector they were providedIn, which enables the continous use of getDependenciesFromInstantiation to determine the dependencies of dependencies

getInjectorProviders:
- Given an injector, discover all of the providers that were configured in that injector.
- This API returns information on the configured providers of an injector, including the import path that leads to the container that the provider originated from (NgModule or standalone directive). This enables fine grained inspection to determine where a specific provider comes from.

getInjectorParent:
- Given an injector, discover the parent of that injector.
- This function is meant to be used recursively to discover the entire resolution path from a starting injector to the NullInjector.

These APIs were designed to be used together. For example, getInjectorParent can be used to discover the structure of an injector hierarchy. Once that's done, getInjectorProviders can be used to determine the providers of each injector in that hierarchy.

Another example: getDependenciesFromInstantiation can be used to discover the dependencies of a specific injector constructed instance. From there, we can use getInjectorParent to discover the injector resolution path and map each dependency to a path from the starting injector to the injector that it was provided in.

PR Close #48639
2023-08-01 11:44:40 -07:00