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
Standalone component need to include the imported NgModules as part of their dependencies in order to be able to use the injection tokens coming from these NgModules. To do so, in this change the imported NgModules are included in the standalone component compilation scope.
PR Close#51819
Currently deps tracker includes the exported scope of the exported NgModule only in the exported scope of that NgModule. This is in agreement with what AoT does today. But JIT diverges from this behavior by including these exported scopes into the compilation scope as well. Since deps tracker is going to be used for both AoT (local compilation mode) and JIT, the question might be which behavior the deps tracker should follow? Today it follows the AoT one, but it breaks some tests in Google which seem to depend on this behavior of JIT. So it is better to migrate deps tracker to what JIT does. This leads to a wider compilation scope in local compilation compared to full compilations, but it won't break any existing thing.
PR Close#51791
This change flattens the imports info on standalone component decorators in runtime dev mode by adding flattening logic to the deps tracker. Such flattening has no effect in AoT full compilation mode since these arrays are already resolved and flattened by AoT static analysis, but in local compilation mode it is needed since the raw array as appears on the component decorator will be passed to the deps tracker, and so it needs to be flattened.
This change does not affect prod runtime since deps tracker is only used in dev mode.
PR Close#51767
Certain code patterns and tools in Google (and possibly 3P world) lead to the situation that a component is bootstrapped/rendered without its ng-module being loaded in the browser. Technically speaking this should be an anti-pattern since the ng-module could contain some runtime logic (e.g., providing something, calling some services, etc) and its not being loaded leads to unexpected behaviour. However, in many cases ng-module is an empty class and its only usage is for providing scope, and since in AoT full compilation mode we already hard-code dependencies into components so we can get away with not loading the ng-module. But in AoT local compilation mode it is not possible to get away since the component's dependencies are computed in runtime and the presence of the corresponding ng-module in the browser is needed. For this reason in this change it is forbidden to attempt to render a component without first loading its ng-module in local compilation mode and an explicit error message is created to make this situation clear. This error message can help with catching such cases when running TGP in Google.
It would be an interesting question as to whether to ban this situation in full compilation mode as well, as it is error prone and these errors are sometimes very hard to debug.
PR Close#51726
Currently internally Angular has some customized tsconfig files, because we don't align with the tsconfig of the rest of g3. These changes enable `noImplicitReturns` and `noPropertyAccessFromIndexSignature` to align better with the internal config.
PR Close#51728
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
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
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
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
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
Creates unit tests for the following APIs
- setInjectorProfiler
- getInjectorProviders
- getInjectorResolutionPath
- getDependenciesFromInjectable
Modifies existing tests in
- packages/examples/core/di/ts/injector_spec.ts
- packages/core/test/render3/jit/declare_injectable_spec.ts
- packages/core/test/render3/jit/declare_factory_spec.ts
because they setup framework injector context manually.
Exports setInjectorProfilerContext in packages/core/src/core_private_export.ts in order for use
in the the modified tests above.
PR Close#48639
This includes implementation of methods getComponentDependencies and registerNgModule.
In order to correlate ng-modules with their declarations it is required to use the method registerNgModule to regiater the ng-module. However, the actual correlation will happen lazily once getComponentDependencies method is called. This lazy behaviour also allows for forward refs to be resolved.
The method getComponentDependencies will be used in local compilation mode to compute the rendering component deps in runtime.
PR Close#50980
The implementation is more or less follows the pattern in render3/jit/module.ts#transitiveScopesFor helper. A few additional helper functions also added to jit utils.
PR Close#50980
Exposes the function used to transform an input on `ComponentFactory.inputs` and `ComponentMirror.inputs`. We'll need this to support input transforms in `elements`.
PR Close#50713
The existing microbenchmarks are not widely known
and are not used to drive design / coding decissions.
At the same time those test add to the maintanance cost:
- use hand-written instructions;
- plug into runtime internals and are fragile;
- require development of mocks for the runtime internals.
Those tests are removed since they are costly to maintain
and, at the same, don't provide enough value.
PR Close#50786
Fixes an error that surfaced in #50580 where the compiler was throwing an error in JIT mode when reading the result of `compileDirectiveDeclaration`. It is caused by the fact that input transform functions were being passed around directly, instead of being wrapped in an AST node.
PR Close#50600
Both the render and update instructions live in the same file and are
only separated via a "render*" vs "refresh*" naming convention. This
commit moves these functions to completely separate files.
PR Close#50017
As described in
https://github.com/angular/angular/discussions/49681#discussioncomment-5628930,
if an `Observable` created from a signal with `toObservable` is
subscribed to in a template, it will initially have `null` as the value.
Immediately after the template is done executing, effects are flushed
and this results in the `AsyncPipe` getting a new value before the
`checkNoChanges` pass, resulting in `ExpressionChanged` error.
```
template: '{{obs$ | async}}'
...
obs$ = toObservable(signal(0));
```
Instead, this commit updates the `toObservable` to synchronously emit
the initial value to the Observable stream.
Side note here: We don't exactly encourage this pattern. Instead of
using `AsyncPipe`, the template should just read signals.
PR Close#49894
This change explicitly resets a reactive consumer before setting inputs
on directive instances. This is to assure that any potential input setters
do _not_ run in the reactive context.
PR Close#49906
This fix assures that templates functions executed in the creation mode
are run outside of the reactive context. This avoids the situation where
signal reads in a directive constructor (executed as part of the creation
mode) would mark the host component as dirty.
Fixes#49871
PR Close#49883
Angular doesn't support IE anymore. We can remove the workarounds related to IE.
Some workarounds are keep because of the support of domino but the comments related to IE are removed.
PR Close#49763
This change makes is possible to use async functions
(ones returning a promise) as effect run functions.
To make it possible, the signature of the effect function
changed: effect cleanup function is registered now
(using a dedicated callback passed to the effect creation)
instead of being returned from the effect function.
PR Close#49783
This commits updates the render to able to handle the slight differences between platform-server and platform-browser.
This is needed to eventually be able to remove `ServerRendererFactory2` and `EmulatedEncapsulationServerRenderer2` from platform-server.
PR Close#49630
Angular lifecycle hooks should never be run as part of the reactive
context: we do not expect that signal reads in lifecycle hooks
report to any consumers.
In the current Angular some of the lifecycle hooks can be flushed
early, while executting template update pass. We need to make sure
that signal reads in those lifecycle hooks do not register as part
of the effect that marks components for check.
"
PR Close#49701
`ComponentRef.setInput` internally calls `markDirtyIfOnPush` which only marks
the given view as dirty but does not mark parents dirty like `ChangeDetectorRef.markForCheck` would.
f071224720/packages/core/src/render3/instructions/shared.ts (L1018-L1024)
`markDirtyIfOnPush` has an assumption that it’s being called from the parent’s template. That is, we don’t need to mark dirty to the root, because we’ve already traversed down to it.
The function used to only be called during template execution for input
bindings but was added to `setInput` later. It's not a good fit because
it means that if you are responding to events such as an emit from an `Observable`
and call `setInput`, the view of your `ComponentRef` won't necessarily get checked
when change detection runs next. If this lives inside some `OnPush` component tree
that's not already dirty, it only gets refreshed if you also call
`ChangeDetectorRef.markForCheck` in the host component (because it will be "shielded" be a non-dirty parent).
PR Close#49711
* Prevent reads of signals during the notification process. This shouldn't
ever be triggered by user code but is more of a preventative for
internal misuse. Reading a signal during notification would/could create
glitches where the values being read are not updated to reflect the
values being updated by the notification.
* Prevent signal writes inside of computed's. These are meant to be
derived values and should not have any side-effects like writing new
values to other signals
* Prevent signal writes inside of effects by default. Writing to signal
values during the execution of an effect can lead to the
`ExpressionChangedAfterItHasBeenCheckedError` if writing to signals
that represent global state which is read in a parent component. This is
mostly just a problem for `OnPush`/`CheckAlways` components, but with
signals being new and pure signal components not even available yet,
it will be the majority for a long time.
PR Close#49631
This commit updates the `effect` primitive and significantly changes the
timing of effect execution.
Previously, effects were scheduled via the microtask queue. This commit
changes effects to run throughout the change detection process instead.
Running effects this way avoids needing additional rounds of change
detection to resolve effects, with the tradeoff that they're harder to use
for model-to-model synchronization (which can be seen as a good thing).
PR Close#49641
This commit consolidates the `RendererFactory` and `Sanitizer` properties
of `LView` onto a single object, the `LViewEnvironment`. These properties
are both set from DI when the root view is created, and not overridden when
child views are created (but inherited from the parent view).
This is a precursor commit to adding the `EffectManager` into the
`LViewEnvironment`.
PR Close#49641
This change extends the effect API surface so effects can, optionally,
return a cleanup function. Such function, if returned, is executed
prior to the subsequent effect run.
PR Close#49625
Previously, effects were queued in the global microtask queue and executed
directly. This had an undesired consequence: whichever effect scheduled
first determined the zone in which all other effects would run, *and* that
zone depended on where the signal happened to be set which triggered that
first effect. This behavior would be extremely unpredictable.
This commit adds zone awareness to the effect API. effects now capture the
current zone when they're created, and this zone is used to run the effect
callback regardless of which zone set the signal.
PR Close#49529
The `effect` implemented in the signal library is useful for testing but
does not integrate with Angular. This commit moves that code to the
actual framework package and integrates it with automatic cleanup via
`DestroyRef`. A simpler effect implementation is used in the signal tests to
test the `Watch` primitive.
Further commits will update the scheduling to tie effects together with
change detection.
PR Close#49529
`ComponentRef.setInput` currently sets the input on the component regardless
of the previous value the method was called with. This results in
different behavior from bindings in templates, which only set inputs
when the value differs in the `Object.is` check from its previous value.
BREAKING CHANGE: ComponentRef.setInput will only set the input on the
component if it is different from the previous value (based on `Object.is`
equality). If code relies on the input always being set, it should be
updated to copy objects or wrap primitives in order to ensure the input
value differs from the previous call to `setInput`.
PR Close#49607
The mentioned 2 classes have been combined since it is no longer required to have a separate `SharedStylesHost` for SSR. This changes also reduces the memory usage footprint as remove 1 Map that stores the CSS strings.
PR Close#49424
This commit updates the serialization logic to include information about templates that were used to create embedded views. The information is needed during hydration to pick a correct instance of dehydrated view (this logic will be implemented in a followup commit).
PR Close#49382
Prior to this change component styles generated on the server where removed prior to the client side component being rendered and attached it's own styles. In some cases this caused flickering. To mitigate this `initialNavigation: enabledBlocking'` was introduced which allowed the remove of server styles to be defer to a latter stage when the application has finished initialization.
This commit changes the need for this, by not removing the server generated component styles and reuse them for client side rendering.
PR Close#48253
Previously (at the early days of Ivy) a TNode used to keep an array of TViews, but the logic was changed since that time, but the `tViews` field remained on TNode interface (+ corresponding typings).
This commit renames TNode.tViews to TNode.tView and cleans up typings.
PR Close#49313