This commit bundles 3 important changes, with the goal of enabling tree-shaking
of services which are never injected. Ordinarily, this tree-shaking is prevented
by the existence of a hard dependency on the service by the module in which it
is declared.
Firstly, @Injectable() is modified to accept a 'scope' parameter, which points
to an @NgModule(). This reverses the dependency edge, permitting the module to
not depend on the service which it "provides".
Secondly, the runtime is modified to understand the new relationship created
above. When a module receives a request to inject a token, and cannot find that
token in its list of providers, it will then look at the token for a special
ngInjectableDef field which indicates which module the token is scoped to. If
that module happens to be in the injector, it will behave as if the token
itself was in the injector to begin with.
Thirdly, the compiler is modified to read the @Injectable() metadata and to
generate the special ngInjectableDef field as part of TS compilation, using the
PartialModules system.
Additionally, this commit adds several unit and integration tests of various
flavors to test this change.
PR Close#22005
All of the providers in a module get compiled into a module definition in the
factory file. Some of these providers are for the actual module types, as those
are available for injection in Angular. For tree-shakeable tokens, the runtime
needs to be able to distinguish which modules are present in an injector.
This change adds a NodeFlag which tags those module providers for later
identification.
PR Close#22005
* refactor(core): provide error message in stack for reflective DI
Fixes#16355
* fix(compiler): make AOT work with `noUnusedParameters`
Fixes#15532
* refactor: use view engine also for `NgModuleFactory`s
This is a prerequisite for being able to mock providers
in AOTed code later on.
BREAKING CHANGE:
Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly.
Now, only classes that are annotated with @Component, @Directive, @Pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.
This also makes all `useValue` providers eager, which
should have no observable impact other than code size.
EXPECTED IMPACT:
Making providers eager was an incorrect behavior and never documented.
Also, providers that are used by a directive / pipe / ngModule stay eager.
So the impact should be rather small.
Fixes#14552
The main use case for the generated source maps is to give
errors a meaningful context in terms of the original source
that the user wrote.
Related changes that are included in this commit:
* renamed virtual folders used for jit:
* ng://<module type>/module.ngfactory.js
* ng://<module type>/<comp type>.ngfactory.js
* ng://<module type>/<comp type>.html (for inline templates)
* error logging:
* all errors that happen in templates are logged
from the place of the nearest element.
* instead of logging error messages and stacks separately,
we log the actual error. This is needed so that browsers apply
source maps to the stack correctly.
* error type and error is logged as one log entry.
Note that long-stack-trace zone has a bug that
disables source maps for stack traces,
see https://github.com/angular/zone.js/issues/661.
BREAKING CHANGE:
- DebugNode.source no more returns the source location of a node.
Closes 14013