This commit switches ngtsc's JS and DTS transform to use the new import
manager. This is a drop-in replacement as we've updated the translator
helpers in the previous commit to align with the new API suggested by
the `ImportManagerV2` (to be renamed then).
PR Close#54983
`ImportGenerator` is the abstraction used by the translator functions to
insert imports for `ExternalExpr` in an AST-agnostic way.
This was built specifically for the linker which does not use any of the
complex import managers- but rather re-uses `ngImport` or uses
`ngImport.Bla`.
This commit also switches the linker AST-agnostic generator to follow
the new signatures. This was rather trivial.
PR Close#54983
This commit introduces a new implementation of `ImportManager` that has
numerous benefits:
- It allows efficient re-use of original source file imports.
* either fully re-using original imports if matching
* updating existing import declarations to include new symbols.
- It allows efficient re-use of previous generated imports.
- The manager can be used for schematics and migrations.
The implementation is a rework of the import manager that we originally
built for schematics in Angular Material, but this commit improved it
to be more flexible, more readable, and "correct".
In follow-ups we can use this for schematics/migrations.
PR Close#54983
Previously we assumed that if a `for` loop tracking function is in the form of `someMethod($index, $item)`, it will be pure so we didn't pass the parameter to bind the context to it. This appears to be risky, because we don't know if the method is trying to access `this`.
These changes play it safe by always binding method-based tracking functions.
Fixes#53628.
PR Close#54960
We are already testing the JIT transforms via integration tests, but
this commit adds dedicated unit tests for the transform behavior for
proper test coverage (planned follow-up).
PR Close#54841
Move the initialization of class field `DelegatingPerfRecorder` into the constructor.
This fixes the error : `TypeError: Cannot read properties of undefined (reading 'eventCount')`
This is blocking the roll-out of public class.
PR Close#54834
Updates the instruction generation for two-way bindings to only emit the `twoWayBindingSet` call when writing to template variables. Since template variables are constants, it's only allowed to write to them when they're signals. Non-signal values are flagged during template type checking.
Fixes#54670.
PR Close#54714
We have a diagnostic that reports writes to template variables which worked both for regular event bindings and two-way bindings, however the latter was broken by #54154 because two-way bindings no longer had a `PropertyWrite` AST.
These changes fix the diagnostic and expand it to allow two-way bindings to template variables that are signals.
PR Close#54714
Moves the check which ensures that there are no writes to template variables into the `TemplateSemanticsChecker` to prepare for the upcoming changes.
PR Close#54714
Introduces a new `TemplateSemanticsChecker` that will be used to flag semantic errors in the user's template. Currently we do some of this in the type check block, but the problem is that it doesn't have access to the template type checker which prevents us from properly checking cases like #54670. This pass is also distinct from the extended template checks, because we don't want users to be able to turn the checks off and we want them to run even if `strictTemplates` are disabled.
PR Close#54714
Currently the `makeProgram` utility from `ngtsc/testing` does not use
the test host by default- optimizing for source file caching.
Additionally, the host can be updated to attempt caching of the `.d.ts`
files from `@angular/core`— whether that's fake core, or the real core-
is irrelevant. We are never caching if these changes between tests, so
correctness is guaranteed.
This commit reduces the type check test times form 80s to just 11
seconds, faster than what it was before with `fake_core`. The ngtsc
tests also run significantly faster. From 40s to 30s
PR Close#54650
This commit allows us to detect initializer APIs like
`outputFromObservable` that are declared in different modules- not
necessarily `@angular/core`.
PR Close#54650
This commit exposes the new `output()` API with numerous benefits:
- Symmetrical API to `input()`, `model()` etc.
- Fixed types for `EventEmitter.emit`— current `emit` method of
`EventEmitter` is broken and accepts `undefined` via `emit(value?: T)`
- Removal of RxJS specific concepts from outputs. error channels,
completion channels etc. We now have a simple consistent
interface.
- Automatic clean-up of subscribers upon directive/component destory-
when subscribed programmatically.
```ts
@Directive({..})
export class MyDir {
nameChange = output<string>(); // OutputEmitterRef<string>
onClick = output(); // OutputEmitterRef<void>
}
```
Note: RxJS custom observable cases will be handled in future commits via
explicit helpers from the interop.
PR Close#54650
This commit replaces `fake_core` with the real `@angular/core`
output. See previous commit for reasons.
Overall, this commit:
* Replaces references of `fake_core`
* Fixes tests that were testing Angular compiler detection that _would_
already be flagged by type-checking of TS directly. We keep these
tests for now, and add `@ts-ignore` to verify the Angular checks, in
case type checking is disabled in user applications- but it's worth
considering to remove these tests. Follow-up question/non-priority.
* Adds `@ts-ignore` to the tests for `defer` 1P because the property is
marked as `@internal` and now is (correctly) causing failures in the
compiler test environment.
* Fixes a couple of tests with typos, wrong properties etc that
previously weren't detected! A good sign.
PR Close#54650
As part of improving test safety of the compiler, I've noticed that
we have a special pass for detecting external `ModuleWithProviders`
where we detect the module type from an object literal.
This literal is structured like the following: `{ngModule: T}`. The
detection currently takes `T` directly, but in practice it should be
`typeof T` to satisfy the `ModuleWithProviders` type that is accepted
as part of `Component#imports`.
This commit adds support for this, so that we can fix the unit test
in preparation for using the real Angular core types in ngtsc tests.
PR Close#54650
Fixes that a query like `viewChild('locator', {read: ElementRef<HTMLElement>})` would throw because we didn't account for expressions with type parameters.
I've also included support for parenthesized expressions and `as` expressions since it's pretty easy to support them.
Fixes#54645.
PR Close#54647
Fixes that initializer functions weren't being recognized if they are aliased (e.g. `import {model as alias} from '@angular/core';`).
To do this efficiently, I had to introduce the `ImportedSymbolsTracker` which scans the top-level imports of a file and allows them to be checked quickly, without having to go through the type checker. It will be useful in the future when verifying that that initializer APIs aren't used in unexpected places.
I've also introduced tests specifically for the `tryParseInitializerApiMember` function so that we can test it in isolation instead of going through the various functions that call into it.
PR Close#54609
Fixes that initializer functions weren't being recognized if they are aliased (e.g. `import {model as alias} from '@angular/core';`).
To do this efficiently, I had to introduce the `ImportedSymbolsTracker` which scans the top-level imports of a file and allows them to be checked quickly, without having to go through the type checker. It will be useful in the future when verifying that that initializer APIs aren't used in unexpected places.
I've also introduced tests specifically for the `tryParseInitializerApiMember` function so that we can test it in isolation instead of going through the various functions that call into it.
PR Close#54480
The diagnostic for signals that haven't been invoked wasn't working internally, because the path to `@angular/core` is different. These changes resolve the issue and do some general cleanup.
PR Close#54585
Template pipeline is now the default template compiler.
A pair of source map tests is failing, related to DI in JIT mode; I will fix and re-enable these during the preview period.
PR Close#54571
This is based on an internal issue report.
An earlier change introduced a diagnostic to report cases where a symbol is in the `deferredImports` array, but is used eagerly. The check worked by looking through the deferred blocks in a scope, resolving the scope for each and checking if the element is within the scope. The problem is that resolving the scope won't work across scoped node boundaries. For example, if there's a control flow statement around the block or within the block but around the deferred dependency, it won't be able to resolve the scope since it isn't a direct child, e.g.
```
@if (true) {
@defer {
<deferred-dep/>
}
}
```
To fix this the case where the deferred block is inside a scoped node, I've changed the `R3BoundTarget.deferBlocks` to be a `Map` holding both the deferred block and its corresponding scope. Then to resolve the case where the dependency is within a scoped node inside the deferred block, I've added a depth-first traversal through the scopes within the deferred block.
PR Close#54499
We have a couple of cases now (#53753 and #54414) where we're forced to redefine enums as object literals. These literals aren't rendered in the best way in the docs so these changes introduce a new `object-literal-as-enum` tag that we can use to mark them so they're treated for documentation purposes.
PR Close#54487
This commit addresses a problem with PR #53695 that introduced support for default imports,
where the actual dynamic import used in the defer loading function continued to use the
symbol name, instead of `.default` for the dynamic import. This issue went unnoticed in the
testcase because a proper instance was being generated for the `ɵsetClassMetadataAsync` function,
but not the generated dependency loader function.
Fixes#54491
PR Close#54495
When the linker is running using an unpublished version of angular, locally built, the version will be `0.0.0`.
When encountering this situation, the range that for the linker map support is considered to be `*.*.*` allowing
for the linker to work at build time with packages built with versioned angular.
Most notably this allows for us to properly use the linker in building our documentation site with the locally
built version of angular.
PR Close#54439
The version detection condition for signal two-way bindings used an OR
instead of an AND, resulting in every `.0` patch version being considered
as supporting two-way bindings to signals.
This commit fixes the logic and adds additional parentheses to ensure the
meaning of the condition is more clear. Long term, we should switch to
semver version parsing instead.
PR Close#54443
In order to allow both signals and non-signals in two-way bindings, we have to pass the expression through `ɵunwrapWritableSignal`. The problem is that the language service uses a bundled compiler that is fairly new, but it may be compiling an older version of Angular that doesn't expose `ɵunwrapWritableSignal` (see https://github.com/angular/vscode-ng-language-service/issues/2001).
These changes add a `_angularCoreVersion` flag to the compiler which the language service can use to pass the parsed Angular version to the compiler which can then decide whether to emit the function.
PR Close#54423
Currently we have two fake copies of `@angular/core` in the compiler tests which can be out of sync and cause inconsistent tests. These changes reuse a single copy instead.
PR Close#54344
The new `model()` signal introduces a `ModelSignal` type that needs to be handled by the interpolatedSignalNotInvoked diagnostic to catch issues like:
```
<div>{{ myModel }}</div>
```
PR Close#54338
The import of `module` can conflict with the native global variable called `module` and can break some internal tests. These switch to only importing the function we need.
PR Close#54333