Previously we were using an anonymous type `{specifier: string; qualifier: string;}`
throughout the code base. This commit gives this type a name and ensures it
is only defined in one place.
PR Close#25445
Previously, ngtsc would fail to evaluate expressions that access properties
from e.g. the `window` object. This resulted in hard to debug error messages
as no indication on where the problem originated was present in the output.
This commit cleans up the handling of unknown property accesses, such that
evaluating such expressions no longer fail but instead result in a `DynamicValue`.
Fixes#30226
PR Close#30247
A structural directive can specify a template guard for an input, such that
the type of that input's binding can be narrowed based on the guard's return
type. Previously, such template guards could only be methods, of which an
invocation would be inserted into the type-check block (TCB). For `NgIf`,
the template guard narrowed the type of its expression to be `NonNullable`
using the following declaration:
```typescript
export declare class NgIf {
static ngTemplateGuard_ngIf<E>(dir: NgIf, expr: E): expr is NonNullable<E>
}
```
This works fine for usages such as `*ngIf="person"` but starts to introduce
false-positives when e.g. an explicit non-null check like
`*ngIf="person !== null"` is used, as the method invocation in the TCB
would not have the desired effect of narrowing `person` to become
non-nullable:
```typescript
if (NgIf.ngTemplateGuard_ngIf(directive, ctx.person !== null)) {
// Usages of `ctx.person` within this block would
// not have been narrowed to be non-nullable.
}
```
This commit introduces a new strategy for template guards to allow for the
binding expression itself to be used as template guard in the TCB. Now,
the TCB generated for `*ngIf="person !== null"` would look as follows:
```typescript
if (ctx.person !== null) {
// This time `ctx.person` will successfully have
// been narrowed to be non-nullable.
}
```
This strategy can be activated by declaring the template guard as a
property declaration with `'binding'` as literal return type.
See #30235 for an example where this led to a false positive.
PR Close#30248
Preserve compatibility with rollup_bundle rule.
Add missing npm dependencies, which are now enforced by the strict_deps plugin in tsc_wrapped
PR Close#30370
At the moment the module resolver will end up in an infinite loop in Windows because we are assuming that the root directory is always `/` however in windows this can be any drive letter example `c:/` or `d:/` etc...
With this change we also resolve the drive letter in windows, when using `AbsoluteFsPath.from` for consistence so under `/foo` will be converted to `c:/foo` this is also needed because of relative paths with different drive letters.
PR Close#30297
Currently in Ivy `NgModule` registration happens when the class is declared, however this is inconsistent with ViewEngine and requires extra generated code. These changes remove the generated code for `registerModuleFactory`, pass the id through to the `ngModuleDef` and do the module registration inside `NgModuleFactory.create`.
This PR resolves FW-1285.
PR Close#30244
```
//packages/compiler-cli/test:ngc
//packages/compiler/test:test
```
This also address `node_modules` to the ignored paths for ngc compiler as otherwise the `ready` is never fired
Partially addresses #29785
PR Close#30146
Now that the dependent files and compilation scopes are being tracked in
the incremental state, we can skip analysing and emitting source files if
none of their dependent files have changed since the last compile.
The computation of what files (and their dependencies) are unchanged is
computed during reconciliation.
This commit also removes the previous emission skipping logic, since this
approach covers those cases already.
PR Close#30238
To support skipping analysis of a file containing a component
we need to know that none of the declarations that might affect
its ngtsc compilation have not changed. The files that we need to
check are those that contain classes from the `CompilationScope`
of the component. These classes are already tracked in the
`LocalModuleScopeRegistry`.
This commit modifies the `IvyCompilation` class to record the
files that are in each declared class's `CompilationScope` via
a new method, `recordNgModuleScopeDependencies()`, that is called
after all the handlers have been "resolved".
Further, if analysis is skipped for a declared class, then we need
to recover the analysis from the previous compilation run. To
support this, the `IncrementalState` class has been updated to
expose the `MetadataReader` and `MetadataRegistry` interfaces.
This is included in the `metaRegistry` object to capture these analyses,
and also in the `localMetaReader` as a fallback to use if the
current compilation analysis was skipped.
PR Close#30238
As part of incremental compilation performance improvements, we need
to track the dependencies of files due to expressions being evaluated by
the `PartialEvaluator`.
The `PartialEvaluator` now accepts a `DependencyTracker` object, which is
used to track which files are visited when evaluating an expression.
The interpreter computes this `originatingFile` and stores it in the evaluation
`Context` so it can pass this to the `DependencyTracker.
The `IncrementalState` object implements this interface, which allows it to be
passed to the `PartialEvaluator` and so capture the file dependencies.
PR Close#30238
This is the final patch to migrate the Angular styling code to have a
smaller instruction set in preparation for the runtime refactor. All
styling-related instructions now work both in template and hostBindings
functions and do not use `element` as a prefix for their names:
BEFORE:
elementStyling()
elementStyleProp()
elementClassProp()
elementStyleMap()
elementClassMap()
elementStylingApply()
AFTER:
styling()
styleProp()
classProp()
styleMap()
classMap()
stylingApply()
PR Close#30318
This patch removes all host-specific styling instructions in favor of
using element-level instructions instead. Because of the previous
patches that made sure `select(n)` worked between styling calls, all
host level instructions are not needed anymore. This patch changes each
of those instruction calls to use any of the `elementStyling*`,
`elementStyle*` and `elementClass*` styling instructions instead.
PR Close#30336
This patch is one commit of many patches that will unify all styling instructions
across both template-level bindings and host-level bindings. This patch in particular
removes the `elementIndex` param because it is already set prior to each styling
instruction via the `select(n)` instruction.
PR Close#30313
Prior to this patch, the `select(n)` instruction would only be generated
when property bindings are encountered which meant that styling-related
bindings were skipped. This patch ensures that all styling-related bindings
(i.e. class and style bindings) are always prepended with a `select()`
instruction prior to being generated in AOT.
PR Close#30311
This patch breaks up the existing `elementStylingMap` into
`elementClassMap` and `elementStyleMap` instructions. It also breaks
apart `hostStlyingMap` into `hostClassMap` and `hostStyleMap`
instructions. This change allows for better tree-shaking and reduces
the complexity of the styling algorithm code for `[style]` and `[class]`
bindings.
PR Close#30293
If an entry-point has a missing dependency then all the entry-points
that would have pointed to that dependency are also removed from
the dependency graph.
Previously we were still processing the dependencies of an entry-point
even if it had already been removed from the graph because it depended
upon a missing dependency that had previously been removed due to another
entry-point depending upon it.
This caused the dependency processing to crash rather than gracefully
logging and handling the missing invalid entry-point.
Fixes#29624
PR Close#30270
Sometimes we need to override module resolution behaviour.
We do this by implementing the optional method `resolveModuleNames()`
on `CompilerHost`.
This commit ensures that we always try this method first before falling
back to the standard `ts.resolveModuleName`
PR Close#30017
Packages that do not follow APF may have the declaration files in the same
directory as one source format, typically ES5. This is problematic for ngcc,
as it needs to create a TypeScript program with all JavaScript sources of
an entry-point, whereas TypeScript's module resolution mechanism would have
resolved an internal module import to the external facing .d.ts declaration
file, instead of the JavaScript source file. This behavior results in the
program to be analysed being incomplete.
This commit introduces a custom compiler host that recognizes the above
scenario and rewires the resolution of a .d.ts declaration file to its
JavaScript counterpart, if applicable.
Fixes#29939
PR Close#30017
Fixes `HostBinding` and `HostListener` declarations not being inherited from base classes that don't have an Angular decorator.
This PR resolves FW-1275.
PR Close#30158
This commit introduces a new interface, which abstracts access
to the underlying `FileSystem`. There is initially one concrete
implementation, `NodeJsFileSystem`, which is simply wrapping the
`fs` library of NodeJs.
Going forward, we can provide a `MockFileSystem` for test, which
should allow us to stop using `mock-fs` for most of the unit tests.
We could also implement a `CachedFileSystem` that may improve the
performance of ngcc.
PR Close#29643
By passing a `pathMappings` configuration (a subset of the
`ts.CompilerOptions` interface), we can instuct ngcc to process
additional paths outside the `node_modules` folder.
PR Close#29643
When working out the dependencies between entry-points
ngcc must parse the import statements and then resolve the
import path to the actual file. This is complicated because module
resolution is not trivial.
Previously ngcc used the node.js `require.resolve`, with some
hacking to resolve modules. This change refactors the `DependencyHost`
to use a new custom `ModuleResolver`, which is optimized for this use
case.
Moreover, because we are in full control of the resolution,
we can support TS `paths` aliases, where not all imports come from
`node_modules`. This is the case in some CLI projects where there are
compiled libraries that are stored locally in a `dist` folder.
See //FW-1210.
PR Close#29643
Previously we completely ignored entry-points that had not been
compiled with Angular, since we do not need to compile them
with ngcc. But this makes it difficult to reason about dependencies
between entry-points that were compiled with Angular and those that
were not.
Now we do track these non-Angular compiled entry-points but they
are marked as `compiledByAngular: false`.
PR Close#29643
The test now attempts to compile an entry-point (@angular/common/http/testing)
that has a transient "private" dependency. A private dependency is one that is
only visible by looking at the compiled JS code, rather than the generated TS
typings files.
This proves that we can't rely on typings files alone for computing the
dependencies between entry-points.
PR Close#29643
The `Transformer` and `Renderer` classes do not
actually need a `sourcePath` value as by the time
they are doing their work we are only working directly
with full absolute paths.
PR Close#29643
- Extracts and documents code that will be common to interpolation instructions
- Ensures that binding indices are updated at the proper time during compilation
- Adds additional tests
Related #30011
PR Close#30129
Previously, ngtsc included query fields in the list of fields which can
affect the type of a directive via its type constructor. This feature
however has yet to be built, and View Engine in default mode does not
do this inference.
This caused an unexpected bug where private query fields (which should be
an error but are allowed by View Engine) cause the type constructor
signature to be invalid. This commit fixes that issue by disabling the
logic to include query fields.
PR Close#30094
ngtsc generates type constructors which infer the type of a directive based
on its inputs. Previously, a bug existed where this inference would fail in
the case of 'any' input values. For example, the inference of NgForOf fails
when an 'any' is provided, as it causes TypeScript to attempt to solve:
T[] = any
In this case, T gets inferred as {}, the empty object type, which is not
desirable.
The fix is to assign generic types in type constructors a default type of
'any', which TypeScript uses instead of {} when inference fails.
PR Close#30094