The compiler generates a 'token' field when it emits an ngInjectableDef,
but this field was not required by defineInjectable or the InjectableDef
interface, nor was it added by InjectionToken.
This commit makes 'token' required and adds it where missing.
PR Close#30855
There is an encoding issue with using delta `Δ`, where the browser will attempt to detect the file encoding if the character set is not explicitly declared on a `<script/>` tag, and Chrome will find the `Δ` character and decide it is window-1252 encoding, which misinterprets the `Δ` character to be some other character that is not a valid JS identifier character
So back to the frog eyes we go.
```
__
/ɵɵ\
( -- ) - I am ineffable. I am forever.
_/ \_
/ \ / \
== == ==
```
PR Close#30546
Ivy uses R3Injector, but we are currently pulling in both the StaticInjector
(View Engine injector) and the R3Injector when running with Ivy. This commit
adds an ivy switch so calling Injector.create() pulls in the correct
implementation of the injector depending on whether you are using VE or Ivy.
This saves us about 3KB in the bundle.
PR Close#30219
The `Δ` caused issue with other infrastructure, and we are temporarily
changing it to `ɵɵ`.
This commit also patches ts_api_guardian_test and AIO to understand `ɵɵ`.
PR Close#29850
Prior to this change, any provider that was independently resolved using
its InjectableDef would not be considered when destroying the module it
was requested from. This commit provides a fix for this issue by storing
the resolved provider in the module's list of provider definitions.
Fixes#28927
PR Close#28943
Improve the stacktrace for `R3Injector` errors by adding the source component (or module) that tried to inject the missing provider, as well as the name of the injector which triggered the error (`R3Injector`).
e.g.:
```
R3InjectorError(SomeModule)[car -> SportsCar]:
NullInjectorError: No provider for SportsCar!
```
FW-807 #resolve
FW-875 #resolve
PR Close#28207
This change is a prerequasity for a later change which will turn the
'di' into its own bazel package. In order to do that we have to:
- have `Injector` type be importable by Ivy. This means that we need
to create `Injector` as a pure type in `interface` folder which is
already a bazel package which Ivy can depend on.
- Remove the dependency of `class Injector` on Ivy so that it can be
compiled in isolation. We do that by using `-1` as special value for
`__NG_ELEMENT_ID__` which tells the Ivy `NodeInjector` than
`Injector` is being requested.
PR Close#28066
All the tests in `packages/core/test/view/` are specific to the `ViewEngine` and shouldn't run for ivy. This PR introduces a new BUILD.bazel file to run those tests separately.
PR Close#27645
Tree shakable providers use the APP_ROOT token to determine where to attach themselves. APP_ROOT gets set on NgModule with BrowserModule irrespective of whether it is actually the root(Ex. in case of SSR app where the shell app is first bootstrapped without BrowserModule being the root module).
This change allows a NgModule with BrowserModule to explicitly mark itself as not the root by setting APP_ROOT token to false. This allows tree shakable providers to be attached to the right rott module.
PR Close#24814
With these changes, the types are a little stricter now and also not
compatible with Protractor's jasmine-like syntax. So, we have to also
use `@types/jasminewd2` for e2e tests (but not for non-e2e tests).
I also had to "augment" `@types/jasminewd2`, because the latest
typings from [DefinitelyTyped][1] do not reflect the fact that the
`jasminewd2` version (v2.1.0) currently used by Protractor supports
passing a `done` callback to a spec.
[1]: 566e039485/types/jasminewd2/index.d.ts (L9-L15)Fixes#23952Closes#24733
PR Close#19904
All errors for existing fields have been detected and suppressed with a
`!` assertion.
Issue/24571 is tracking proper clean up of those instances.
One-line change required in ivy/compilation.ts, because it appears that
the new syntax causes tsickle emitted node to no longer track their
original sourceFiles.
PR Close#24572
Previously, ngOnDestroy was only called on services which were statically
determined to have ngOnDestroy methods. In some cases, such as with services
instantiated via factory functions, it's not statically known that the service
has an ngOnDestroy method.
This commit changes the runtime to look for ngOnDestroy when instantiating
all DI tokens, and to call the method if it's present.
Fixes#22466Fixes#22240Fixes#14818
PR Close#23755
Ivy definition looks something like this:
```
class MyService {
static ngInjectableDef = defineInjectable({
…
});
}
```
Here the argument to `defineInjectable` is well known public contract which needs
to be honored in backward compatible way between versions. The type of the
return value of `defineInjectable` on the other hand is private and can change
shape drastically between versions without effecting backwards compatibility of
libraries publish to NPM. To our users it is effectively an `OpaqueToken`.
By prefixing the type with `ɵ` we are communicating the the outside world that
the value is not public API and is subject to change without backward compatibility.
PR Close#23371
- Remove default injection value from `inject` / `directiveInject` since
it is not possible to set using annotations.
- Module `Injector` is stored on `LView` instead of `LInjector` data
structure because it can change only at `LView` level. (More efficient)
- Add `ngInjectableDef` to `IterableDiffers` so that existing tests can
pass as well as enable `IterableDiffers` to be injectable without
`Injector`
PR Close#23345
Currently the context for inject() is only set when the token is seen
for the first time. This has two issues:
* It should always be set when injecting from that injector, because
a constructor may wish to call inject() directly.
* If an NgModuleFactory is .create()'d twice, and an ngInjectableDef
token is requested from each of them, the second time will fail.
This is because the first injection adds the provider definition
and calls the factory, and the provider definitions are shared.
The second injector will see the provider definition and call the
factory to create an instance, but without setting the correct
context for inject().
Fixes angular/material2#10586.
PR Close#23148
This adds compilation of @NgModule providers and imports into
ngInjectorDef statements in generated code. All @NgModule annotations
will be compiled and the @NgModule decorators removed from the
resultant js output.
All @Injectables will also be compiled in Ivy mode, and the decorator
removed.
PR Close#22458
Rename @Injectable({scope -> providedIn}).
Instead of {providedIn: APP_ROOT_SCOPE}, accept {providedIn: 'root'}.
Also, {providedIn: null} implies the injectable should not be added
to any scope.
PR Close#22655
@Injectable() supports a scope parameter which specifies the target module.
However, it's still difficult to specify that a particular service belongs
in the root injector. A developer attempting to ensure that must either
also provide a module intended for placement in the root injector or target
a module known to already be in the root injector (e.g. BrowserModule).
Both of these strategies are cumbersome and brittle.
Instead, this commit adds a token APP_ROOT_SCOPE which provides a
straightforward way of targeting the root injector directly, without
requiring special knowledge of modules within it.
PR Close#22185
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
Adding the binding name to the error message recieved by the user gives
extra context on what exactly changed. The tests are also updated to
reflect the new error message.
PR Close#20352
`main()` function used to be needed to support dart, since dart
Does not allow top level statements. Since we no longer use dart
The need for `main()` has been removed.
In preparation for `Basel` and standardized way of running tests
we are removing `main()`
PR Close#21053
Each node now has two index: nodeIndex and checkIndex.
nodeIndex is the index in both the view definition and the view data.
checkIndex is the index in in the update function (update directives and update
renderer).
While nodeIndex and checkIndex have the same value for now, having both of them
will allow changing the structure of view definition after compilation (ie for
runtime translations).
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes#18496
Angular can make many assumptions about its event handlers. As a result
the bookkeeping for native addEventListener is significantly cheaper
than Zone's addEventLister which can't make such assumptions.
This change bypasses the Zone's addEventListener if present and always
uses the native addEventHandler. As a result registering event listeners
is about 3 times faster.
PR Close#18107