One downside of implicit dependency tracking in `effect()`s is that it's easy
to for downstream code to end up running inside the effect context by accident.
For example, if an effect raises an event (e.g. by `next()`ing a `Subject`), the
subscribers to that `Observable` will run inside the effect's reactive context,
and any signals read within the subscriber will end up as dependencies of the
effect. This is why the `untracked` function is useful, to run certain
operations without incidental signal reads ending up tracked.
However, knowing when this is necessary is non-trivial. For example, injecting
a dependency might cause it to be instantiated, which would run the constructor
in the effect context unless the injection operation is untracked.
Therefore, Angular will automatically drop the reactive context within a number
of framework APIs. This commit addresses these use cases:
* creating and destroying views
* creating and destroying DI injectors
* injecting dependencies
* emitting outputs
Fixes#54548
There are likely other APIs which would benefit from this approach, but this
is a start.
PR Close#54614
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
Since we generate a `.mjs` file as entry-point for jasmine tests,
a couple of issues prevented the transitive dependencies from
bootstrap targets to be brought in (causing resolution errors):
1. The `_files` (previously `_esm2015`) targets are no longer needed,
and they also miss all the information on runfiles.
2. The aspect for computing linker mappings does not respect the
`bootstrap` attribute from the `spec_entrypoint` so we manually
add the extract ESM output targets (this rule works with the aspect
and forwards linker mappings).
PR Close#48521
For every `ts_library` target we expose a shorthand that grants
access to the JS files because `DefaultInfo` of a ts library
only exposes the `.d.ts` files.
We rename this away from `es2015` since in practice it's a much
higher target these days. Additionally we no longer use the devmode
output but rather use the prodmode output which has the explicit
`.mjs` output- compatible with ESM.
PR Close#48521
To make our test output i.e. devmode output more aligned
with what we produce in the NPM packages, or to be more
aligned with what Angular applications will usually consume,
the devmode output is switched from ES5 to ES2015.
Additionally various tsconfigs (outside of Bazel) have been
updated to match with the other parts of the build. The rules
are:
ES2015 for test configurations, ES2020 for actual code that will
end up being shipped (this includes the IDE-only tsconfigs).
PR Close#44505
Fixes an issue where destroy hooks are not set up for `useClass` providers
that rely on `forwardRef` for passing the actual class reference.
Currently the destroy hooks are not captured because forward refs are
not resolved for class providers. In ES2015+ this issue becomes even
more critical if arrow-functions are used for
e.g. `useClass: () => forwardRef(..)`.
This is because arrow functions do not have a prototype, unlike in ES5
where the function assigned to `useClass` would always have a prototype.
In ES2015+ a runtime exception as followed is returned (and doesn't give
any useful indication of the forwardRef issue):
```
TypeError: Cannot read properties of undefined (reading 'ngOnDestroy')
at registerDestroyHooksIfSupported (dist/packages/core/src/render3/di_setup.ts:196:35 <- dist/legacy-test-bundle.spec.js:41508:37)
at resolveProvider (dist/packages/core/src/render3/di_setup.ts:153:9 <- dist/legacy-test-bundle.spec.js:41485:11)
at resolveProvider (dist/packages/core/src/render3/di_setup.ts:70:7 <- dist/legacy-test-bundle.spec.js:41445:9)
at providersResolver (dist/packages/core/src/render3/di_setup.ts:54:5 <- dist/legacy-test-bundle.spec.js:41438:7)
at Object.definition.providersResolver (dist/packages/core/src/render3/features/providers_feature.ts:48:18 <- dist/legacy-test-bundle.spec.js:41600:16)
at resolveDirectives (dist/packages/core/src/render3/instructions/shared.ts:1179:40 <- dist/legacy-test-bundle.spec.js:35611:17)
at elementStartFirstCreatePass (dist/packages/core/src/render3/instructions/element.ts:40:7 <- dist/legacy-test-bundle.spec.js:38432:27)
at ɵɵelementStart (dist/packages/core/src/render3/instructions/element.ts:87:7 <- dist/legacy-test-bundle.spec.js:38453:43)
at ɵɵelement (dist/packages/core/src/render3/instructions/element.ts:180:3 <- dist/legacy-test-bundle.spec.js:38510:5)
at MultipleFormControls_Template (ng:///MultipleFormControls.js:9:9)
```
PR Close#44281
In order to support ESM for the `platform-server` package, we need to
remove two usages of dynamic imports and replace them with their
corresponding/equivalent import statement. This will also allow ESBuild
to recognize this import. Note that we want to keep these imports external, so
we explicitly specify the `externals` option for the `ng_package` rule.
PR Close#43431
The `render3` test targets are currently also executed for ViewEngine
builds, even though the `render3` infrastructure only concerns Ivy
infrastructure. This commit tags the test targets as ivy-only to disable
those tests for View Engine.
PR Close#40127
`zone.js` 0.8.25 introduces `zone-testing` bundle and move all `fakeAsync/async` logic
from `@angular/core/testing` to `zone.js` package. But in case some user still using the old
version of `zone.js`, an old version of `fakeAsync/async` logic were still kept inside `@angular/core/testing`
package as `fallback` logic. Since now `Angular8+` already use `zone.js 0.9+`, so
those fallback logic is removed.
PR Close#37879
This change provides better typing for the `LView.debug` property which
is intended to be used by humans while debugging the application with
`ngDevMode` turned on.
In addition this chang also adds jasmine matchers for better asserting
that `LView` is in the correct state.
PR Close#38359
The major one that affects the angular repo is the removal of the bootstrap attribute in nodejs_binary, nodejs_test and jasmine_node_test in favor of using templated_args --node_options=--require=/path/to/script. The side-effect of this is that the bootstrap script does not get the require.resolve patches with explicitly loading the targets _loader.js file.
PR Close#34736
The major one that affects the angular repo is the removal of the bootstrap attribute in nodejs_binary, nodejs_test and jasmine_node_test in favor of using templated_args --node_options=--require=/path/to/script. The side-effect of this is that the bootstrap script does not get the require.resolve patches with explicitly loading the targets _loader.js file.
PR Close#34589
This is a breaking change in nodejs rules 0.40.0 as part of the API review & cleanup for the 1.0 release. Their APIs are identical as ts_web_test was just karma_web_test without the config_file attribute.
PR Close#33802
Plural ICU expressions depend on the locale (different languages have different plural forms). Until now the locale was hard coded as `en-US`.
For compatibility reasons, if you use ivy with AOT and bootstrap your app with `bootstrapModule` then the `LOCALE_ID` token will be set automatically for ivy, which is then used to get the correct plural form.
If you use JIT, you need to define the `LOCALE_ID` provider on the module that you bootstrap.
For `TestBed` you can use either `configureTestingModule` or `overrideProvider` to define that provider.
If you don't use the compat mode and start your app with `renderComponent` you need to call `ɵsetLocaleId` manually to define the `LOCALE_ID` before bootstrap. We expect this to change once we start adding the new i18n APIs, so don't rely on this function (there's a reason why it's a private export).
PR Close#29249
We are close enough to blacklist a few test targets, rather than whitelist targets to run...
Because bazel rules can be composed of other rules that don't inherit tags automatically,
I had to explicitly mark all of our ts_library and ng_module targes with "ivy-local" and
"ivy-jit" tags so that we can create a query that excludes all fixme- tagged targets even
if those targets are composed of other targets that don't inherit this tag.
This is the updated overview of ivy related bazel tags:
- ivy-only: target that builds or runs only under ivy
- fixme-ivy-jit: target that doesn't yet build or run under ivy with --compile=jit
- fixme-ivy-local: target that doesn't yet build or run under ivy with --compile=local
- no-ivy-jit: target that is not intended to build or run under ivy with --compile=jit
- no-ivy-local: target that is not intended to build or run under ivy with --compile=local
PR Close#26471
At runtime in JIT mode, when the compiler writes a reference to a symbol that symbol
is resolved through a symbol table named angularCoreEnv in render3/jit/environment.
Previously, this symbol table was not kept up-to-date with the Ivy instruction set
and the names of symbols the compiler could reference.
This change brings the symbol table in sync, and also adds a test that verifies every
symbol the compiler can reference is available at runtime in the symbol table.
PR Close#24479
This commit adds a mechanism by which the @angular/core annotations
for @Component, @Injectable, and @NgModule become decorators which,
when executed at runtime, trigger just-in-time compilation of their
associated types. The activation of these decorators is configured
by the ivy_switch mechanism, ensuring that the Ivy JIT engine does
not get included in Angular bundles unless specifically requested.
PR Close#23833
Implement NgOnChangesFeature, ViewContainerRef, TemplateRef,
and the renderEmbeddedTemplate instruction, and wire together the
pieces required for the ngForOf directive to work.
PR Close#21430
This helps ensure we use the same tsconfig.json file for all compilations.
Next steps are to make it the same tsconfig.json file used by the editor
PR Close#20964