Currently when we transpile the HMR update module, we use the project's compiler options verbatim. This appears to break down with some module types, whereas we have to use a native export.
These changes override the compiler options to ensure that the user's options don't end up breaking HMR.
Fixes#60795.
PR Close#60797
By default, the compiler-cli uses the relative import strategy when
there is no `rootDir` or `rootDirs`. This is expected as everything is
assumed to be somehow reachable through relative imports.
With `rootDirs` that allow for a "virtual file system"-like environment,
the compiler is not necessarily able to always construct proper relative
imports. The compiler includes the `LogicalProjectStrategy` for this
reason. This strategy is able to respect `rootDirs` to construct
relative paths when possible.
This logic currently accidentally triggers when there is a `rootDir`
set. This option is not to be confused with the virtual directory
option called `rootDirs`. The compiler currently confuses this and
accidentally enters this mode when there is just a `rootDir`— breaking
in monorepos that imports can point outside the `rootDir` to e.g. other
compilation unit's `.d.ts` (which is valid; just not `.ts` sources can
live outside the root dir).
This is necessary for our Bazel toolchain migration.
PR Close#60555
When we switch to relative imports, shared `.d.ts` chunks can be
generated.
We need to also pull these into our mock virtual FS testing
environments. Notably this does not cause a test slow-down because we
are talking about very few extra `.d.ts` chunk files. In our experiments
before, with no dts bundling, we saw test time increase from e.g.
20seconds to 100seconds. The 20s are still the same locally!
In addition, since code for definitions can now reside in shared `.d.ts`
chunks, the language service tests need to be adjusted in cases where
they assert for code definition locations in `@angular/core`. A new
helper prepares for more code to be moved into arbitrary `.d.ts` files;
we should simply assert the definition comes out of
`node_modules/@angular/core`.
PR Close#60487
Currently when an incorrect value is in the `imports` array, we highlight the entire array which can be very noisy for large arrays. This comes up semi-regularly (at least for me) when an import is missing.
These changes add some logic that reports a more accurate diagnostic location for the most common case where the `imports` array is static. Non-static arrays will fall back to the current behavior.
PR Close#60455
Instead of relying on Microsoft's API extractor for `d.ts` bundling,
we are switching to Rollup-based `.d.ts` bundling.
This allows us to support code spliting, even for `.d.ts` files,
allowing for relative imports to be used between entry-points, without
ending up duplicating `.d.ts` definitions in two files. This would otherwise cause
problems with assignability of types.
It also nicely integrates into our existing rollup configuration, and
overall simplifies the `ng_package` rule even further!
Notably `tsup` also uses this rollup plugin, and it seems to work well.
Keep in mind that Microsoft's API extractor is pretty hard to integrate,
caused many problems in the past, and isn't capable of code splitting.
This aligns our d.ts bundling with the .mjs bundling (great alignment).
PR Close#60321
PR Close#60332
We had several places where we were trying to get the source file of a class for which we're generating HMR-related code. These calls will fail if the class was transformed so we have to get its source file through the original node.
Fixes#60287.
PR Close#60298
Previously we never could use relative imports to import e.g. `Component`
in e.g. the `core/tests/bundling` folder. This was necessary because otherwise the
Angular compiler wouldn't process those files as it wouldn't recognize
the Angular decorator as the one from `@angular/core`.
Notably this still isn't a large issue because relative imports still
work for most core tests, that are JIT compiled!
For bundling tests though, or some smaller targets, our new upcoming
guidelines for using relative imports inside the full package; fall
apart. This commit unblocks this effort and allows us to use relative
imports in all tests of `packages/core`. This is achieved by leveraging
the existing `isCore` functionality of the compiler, and fixing a few
instances that were missing before.
PR Close#60268
Currently only components can have resources, because they're the only symbol kinds being type checked. Since we want to add directives to it, these changes rework the resource handling to accommodate them.
PR Close#60191
Currently the `TemplateSourceManager` is set up to specifically cater to component templates. These changes make it more generic so we can reuse it for directives.
PR Close#60191
Currently a lot of the internal type checking data structures are set up specifically for components, because we only support type checking of templates. Since this will change in future commits, these changes prepare for it by renaming various methods and separating out component-specific data.
PR Close#60191
This commit fixes a bug where nodes are reused across incremental
compilations. The source file's next template ID is lost because a new
source file is created but nodes may still be retained.
PR Close#60152
The CLI uses the `ts.transform` API to apply the Angular compiler's transformers
on the source files when `isolatedModules` is true (and various other constraints)
instead of going through a full `ts.Program.emit` operation. This results in the
transformers to operate in an environment where no emit resolver is available, which
was not previously accounted for. This commit reflects the possibility for the emit
resolver to be missing and handles this scenario accordingly.
Fixes#59837
PR Close#59869
When the compiler analyzes the defer blocks in a component, it generates two sets of dependencies: ones specific for each block and others from all the deferred blocks within the component. The logic that combines all the defer block dependencies wasn't de-duplicating them which resulted in us producing `setClassMetadataAsync` calls where the callback can have multiple parameters with the same name. This was a problem both in full and partial compilation, but the latter was more visible, because Babel throws an error in such cases.
These changes add some logic to de-duplicate the dependencies so that we produce valid code.
Fixes#59922.
PR Close#59926
When we generate an HMR replacement function, we determine which locals from the file are used and we pass them by reference. This works fine in most cases, but breaks down for const enums which don't have a runtime representation.
These changes work around the issue by passing in all the values as an object literal.
Fixes#59800.
PR Close#59815
Fixes that the partial evaluator was interpreting initializer-less enum members as undefined. In this case the value is the same as the index.
PR Close#59815
Makes the following cleanups in the output AST:
* The `TemplateLiteral` and `TemplateLiteralElement` nodes have been renamed to `TemplateLiteralExpr` and `TemplateLiteralElementExpr` respectively for consistency and to avoid overlaps with the expression AST nodes.
* The `TemplateLiteralExpr` and `TemplateLiteralElementExpr` have been refactored to be `Expression`s for correctness. This involves updating some existing code.
* The `TaggedTemplateExpr` has been renamed to `TaggedTemplateLiteralExpr` for consistency.
PR Close#59230
Updates the HMR dependencies extraction logic to handle conditional expressions.
For example, `providers: [condition ? providersA : providersB]`.
PR Close#59637
Fixes that we were filtering out the component itself from the set of dependencies when HMR is enabled, breaking self-referencing components.
Fixes#59632.
PR Close#59644
When HMR is enabled, we need to capture the dependencies used in a template and forward them to the HMR replacement function. One half of this process is static, meaning that we can't change it after the initial compilation. Tree shaking becomes a problem in such a case, because the user can change the template in a way that changes the set of dependencies which will start matching with the static part of the HMR code.
These changes disable the tree shaking when HMR is enabled to ensure that the dependencies stay stable.
Fixes#59581.
PR Close#59595
Adds a new diagnostic that ensures that a standalone component using custom structural directives in a template has the necessary imports for those directives.
Fixes#37322
PR Close#59443
Fixes that the HMR dependency extraction logic wasn't handling some node types. Most of these are a bit edge-case-ey in component definitions, but variable initializers and arrow functions can realistically happen in factories.
PR Close#59445
in order for the docs to process function entry, this commit refactor function extraction by keeping the implementation as a the default entry and adds all the overloads into a separate array of entries.
fixes#56144
PR Close#56489
Fixes that the compiler wasn't capturing defer block dependencies correctly when `supportTestBed` is disabled. We had tests for this, but we didn't notice the issue because the dependencies ended up being captured because of the `setClassMetadata` calls. Once they're disabled, the dependencies stopped being recorded.
Fixes#59310.
PR Close#59313
During the HMR dependency analysis we need to check if an identifier is top-level or not. We do this by looking at each identifier and its parent, however we didn't account for some cases. These changes expand our logic to cover more of the common node types.
Related to https://github.com/angular/angular/issues/59310#issuecomment-2563963501.
PR Close#59323
Some time ago we narrowed down the expressions we support in two-way bindings, because in most cases any apart from property reads doesn't make sense. This ended up preventing users from using `$any` in the binding since it's considered a function call.
These changes update the validation logic to allow `$any`.
Fixes#51165.
PR Close#59362
We recently introduced a custom error to allow us to catch certain types
of errors. Unfortunately it doesn't work as expected in G3 because the
Node execution seems to run with ES5.
PR Close#59219
Fixes a null pointer error in the unused standalone imports diagnostic. It was caused by an inconsistency in TypeScript's built-in types.
Fixes#58872.
PR Close#59064
In the past two-way bindings used to be interpreted as `foo = $event` at the parser level. In #54065 it was changed to preserve the actual expression, because it was problematic for supporting two-way binding to signals. This unintentionally ended up causing the TCB to two-way bindings to look something like `someOutput.subscribe($event => expr);` which does nothing. It largely hasn't been a problem, because the input side of two-way bindings was still being checked, except for the case where the input side of the two-way binding has a wider type than the output side.
These changes re-add type checking for the output side by generating the following TCB instead:
```
someOutput.subscribe($event => {
var _t1 = unwrapSignalValue(this.someField);
_t1 = $event;
});
```
PR Close#59002
The `isSplitTwoWayBinding` function was a bit misleading, because it has side effects. Renames the function make it a bit more explicit.
PR Close#59002