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
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
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
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
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
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
non-destructive hydration expects the DOM tree to have the same structure in both places.
With this commit, the app will throw an error if comments are stripped out by the http server (eg by some CDNs).
fixes#51160
PR Close#51170
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
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 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
walkProviderTree and processInjectorTypesWithProviders both perform some generic traversal logic of the import graph of an input NgModule or Standalone component. Currently, these functions pass around a `providersOut` array that is used to collect providers at each step of the traversal.
This PR converts those functions to accept visitor callbacks instead of the `providersOut` array. This is done to make the traversal logic of these functions reusable, while leaving it up to the visitor to determine the logic that fires for each visited node.
This refactor would allow us to reuse `walkProviderTree` for injector debugging APIs that could support some cool features in DevTools, like tracing the injector resolution path of an injected property on a component instance all the way up to the specific imported module/standalone component.
PR Close#48639
Currently, understanding dependency injection in Angular requires a lot of context and has been sited in our surveys as one of the largest points of confusion that our users have with the framework. This commit is the beginning of our approach to make debugging dependency injection in Angular easier.
This commit introduces injector profiler callbacks in parts of the framework to emit injector events. It also introduces a default handler for these events. This default handler parses the stream of events to construct some data structures that will support new injector debug APIs.
We have implemented a similar pattern in the past to minimize overhead. There is also the possiblity of making the internal `setInjectorProfiler` function a public debug API in the future, so that users can implement their own handlers to debug DI events. Lastly DI in Angular maps nicely to a stream of events.
For production applications there is no runtime overhead. For applications in dev mode there is some additional overhead from the default profiler handling injector events and holding debug data in memory.
For production applications, dead code elimination should strip all of the code used by this PR.
PR Close#48639
This commit updates the Injector.create function to accept the `Provider` type in addition to the `StaticProvider` type. This should make it easier to work with the Injector.create function and have less type casts if you have a list of `Provider`s available.
PR Close#49587
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
Prior to this change, we've used `componentDef.id` as a key in a Map that acts as a cache to avoid re-creating injector instances for standalone components. In v16, the logic that generates the id has changed from an auto-incremental to a generation based on metadata. If multiple components have similar metadata, their ids might overlap.
This commit updates the logic to stop using `componentDef.id` as a key and instead, use the `componentDef` itself. This would ensure that we always have a correct instance of an injector associated with a standalone component instance.
Resolves#50724.
PR Close#50954
This commit updates the implementation of the `getNativeRequestAnimationFrame`
and checks whether the current code runs in the browser before retrieving
`requestAnimationFrame`. `requestAnimationFrame` is not available when the code
is running in the Node.js environment. We have to fallback to `setTimeout` for
delaying the change detection.
PR Close#50820
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 previous API design for the runtime deps tracker was done with only local compilation in mind. Now if we want to use it for JIT as well then some new requirements come along which are addressed by this commit as follows:
- JIT scopes need distinct sets for directive and pipes. Thus the ScopeData interface is modified to include these info.
- JIT needs access to scopes for various operations. So methods `getNgModuleScope` and `getStandaloneComponentScope` are added to the tracker's public api.
- Test bed needs to clear the scope cache for its override mechanism. So method `clearScopeCacheFor` is added to the tracker's public api for this reason.
PR Close#50606
The types and interfaces re;ated to the runtime deps tracker are added. Also an empty implementation is added to be completed in follow up PRs (after the interfaces are confirmed in this PR).
The added files are not used anywhere, so the change should not affect anything in anyway.
PR Close#50606
This commit updates an internal hydration logic to make sure that the content of components with i18n blocks is cleaned up before we start rendering it.
Resolves#50627.
PR Close#50644
Components are implied to be self-referencing, but if they explicitly set themselves in the `imports` array, they would throw an error because we weren't filtering them out.
Fixes#50525.
PR Close#50559
Previously, with `mergeMap` we did not cancel previous subscriptions to zoneIsStable which caused the application to be stablized before hand.
Closes: #50562
PR Close#50573
According to the HTML specification most attributes are defined as strings, however some can be interpreted as different types like booleans or numbers. [In the HTML standard](https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes), boolean attributes are considered `true` if they are present on a DOM node and `false` if they are omitted. Common examples of boolean attributes are `disabled` on interactive elements like `<button>` or `checked` on `<input type="checkbox">`. Another example of an attribute that is defined as a string, but interpreted as a different type is the `value` attribute of `<input type="number">` which logs a warning and ignores the value if it can't be parsed as a number.
Historically, authoring Angular inputs that match the native behavior in a type-safe way has been difficult for developers, because Angular interprets all static attributes as strings. While some recent TypeScript versions made this easier by allowing setters and getters to have different types, supporting this pattern still requires a lot of boilerplate and additional properties to be declared. For example, currently developers have to write something like this to have a `disabled` input that behaves like the native one:
```typescript
import {Directive, Input} from '@angular/core';
@Directive({selector: 'mat-checkbox'})
export class MatCheckbox {
@Input()
get disabled() {
return this._disabled;
}
set disabled(value: any) {
this._disabled = typeof value === 'boolean' ? value : (value != null && value !== 'false');
}
private _disabled = false;
}
```
This feature aims to address the issue by introducing a `transform` property on inputs. If an input has a `transform` function, any values set through the template will be passed through the function before being assigned to the directive instance. The example from above can be rewritten to the following:
```typescript
import {Directive, Input, booleanAttribute} from '@angular/core';
@Directive({selector: 'mat-checkbox'})
export class MatCheckbox {
@Input({transform: booleanAttribute}) disabled: boolean = false;
}
```
These changes also add the `booleanAttribute` and `numberAttribute` utilities to `@angular/core` since they're common enough to be useful for most projects.
Fixes#8968.
Fixes#14761.
PR Close#50420
This commit updates the `ApplicationRef.isStable` API to account for
pending rendering task. This is needed as once a pending rendering task
is done, new macrotask and microtask could be created which previously caused these not
to be intercepted and thus ignored when doing SSR.
PR Close#50425
When an embedded view injector is present anywhere above a node in the tree, the `Self` flag was effectively ignored. With this change, embedded view injectors are not checked at all when the `Self` flag is present, because resolution should stop at the current node before reaching any embedded view injector(s).
Fixes#49959
PR Close#50270