This commit adds a no-op test for exposing the bug in the way language
service handles CRLF line endings in templates.
There is no easy fix for now, but the test should be enabled once a fix
is in place.
PR Close#32245
This commit drops our custom, change-detection specific, equality comparison util
in favour of the standard Object.is which has desired semantics.
There are multiple advantages of this approach:
- less code to maintain on our end;
- avoid NaN checks if both values are equal;
- re-write NaN checks so we don't trigger V8 deoptimizations.
PR Close#32212
Angular hooks come after 2 flavours:
- init hooks (OnInit, AfterContentInit, AfterViewInit);
- check hooks (OnChanges, DoChanges, AfterContentChecked, AfterViewChecked).
We need to do more processing for init hooks to ensure that those hooks
are run once and only once for a given directive (even in case of errors).
As soon as all init hooks execute to completion we are only left with the
checks to execute.
It turns out that keeping track of the remaining init hooks to execute is
rather expensive (multiple LView flags reads, writes and checks). But we can
observe that non of this tracking is needed as soon as all init hooks are
completed.
This PR takes advantage of the above observations and splits hooks processing
functions into:
- init-specific (slower but less common);
- check-specific (faster and more common).
NOTE: there is code duplication in this PR and it is left like this intentinally:
hand-inlining this perf-critical code makes the view refresh process substentially
faster.
PR Close#32131
Currently, it's not possible to tree-shake away the
coordination layer between HammerJS and Angular's
EventManager. This means that you get the HammerJS
support code in your production bundle whether or
not you actually use the library.
This commit removes the Hammer providers from the
default platform_browser providers list and instead
provides them as part of a `HammerModule`. Apps on
Ivy just need to import the `HammerModule` at root
to turn on Hammer support. Otherwise all Hammer code
will tree-shake away. View Engine apps will require
no change.
BREAKING CHANGE
Previously, in Ivy applications, Hammer providers
were included by default. With this commit, apps
that want Hammer support must import `HammerModule`
in their root module.
PR Close#32203
Historically, the Angular Compiler has produced both native TypeScript
diagnostics (called ts.Diagnostics) and its own internal Diagnostic format
(called an api.Diagnostic). This was done because TypeScript ts.Diagnostics
cannot be produced for files not in the ts.Program, and template type-
checking diagnostics are naturally produced for external .html template
files.
This design isn't optimal for several reasons:
1) Downstream tooling (such as the CLI) must support multiple formats of
diagnostics, adding to the maintenance burden.
2) ts.Diagnostics have gotten a lot better in recent releases, with support
for suggested changes, highlighting of the code in question, etc. None of
these changes have been of any benefit for api.Diagnostics, which have
continued to be reported in a very primitive fashion.
3) A future plugin model will not support anything but ts.Diagnostics, so
generating api.Diagnostics is a blocker for ngtsc-as-a-plugin.
4) The split complicates both the typings and the testing of ngtsc.
To fix this issue, this commit changes template type-checking to produce
ts.Diagnostics instead. Instead of reporting a special kind of diagnostic
for external template files, errors in a template are always reported in
a ts.Diagnostic that highlights the portion of the template which contains
the error. When this template text is distinct from the source .ts file
(for example, when the template is parsed from an external resource file),
additional contextual information links the error back to the originating
component.
A template error can thus be reported in 3 separate ways, depending on how
the template was configured:
1) For inline template strings which can be directly mapped to offsets in
the TS code, ts.Diagnostics point to real ranges in the source.
This is the case if an inline template is used with a string literal or a
"no-substitution" string. For example:
```typescript
@Component({..., template: `
<p>Bar: {{baz}}</p>
`})
export class TestCmp {
bar: string;
}
```
The above template contains an error (no 'baz' property of `TestCmp`). The
error produced by TS will look like:
```
<p>Bar: {{baz}}</p>
~~~
test.ts:2:11 - error TS2339: Property 'baz' does not exist on type 'TestCmp'. Did you mean 'bar'?
```
2) For template strings which cannot be directly mapped to offsets in the
TS code, a logical offset into the template string will be included in
the error message. For example:
```typescript
const SOME_TEMPLATE = '<p>Bar: {{baz}}</p>';
@Component({..., template: SOME_TEMPLATE})
export class TestCmp {
bar: string;
}
```
Because the template is a reference to another variable and is not an
inline string constant, the compiler will not be able to use "absolute"
positions when parsing the template. As a result, errors will report logical
offsets into the template string:
```
<p>Bar: {{baz}}</p>
~~~
test.ts (TestCmp template):2:15 - error TS2339: Property 'baz' does not exist on type 'TestCmp'.
test.ts:3:28
@Component({..., template: TEMPLATE})
~~~~~~~~
Error occurs in the template of component TestCmp.
```
This error message uses logical offsets into the template string, and also
gives a reference to the `TEMPLATE` expression from which the template was
parsed. This helps in locating the component which contains the error.
3) For external templates (templateUrl), the error message is delivered
within the HTML template file (testcmp.html) instead, and additional
information contextualizes the error on the templateUrl expression from
which the template file was determined:
```
<p>Bar: {{baz}}</p>
~~~
testcmp.html:2:15 - error TS2339: Property 'baz' does not exist on type 'TestCmp'.
test.ts:10:31
@Component({..., templateUrl: './testcmp.html'})
~~~~~~~~~~~~~~~~
Error occurs in the template of component TestCmp.
```
PR Close#31952
When a template contains a binding without a value, the template parser
creates an `EmptyExpr` node. This would previously be translated into
an `undefined` value, which would cause a crash downstream as `undefined`
is not included in the allowed type, so it was not handled properly.
This commit prevents the crash by returning an actual expression for empty
bindings.
Fixes#30076Fixes#30929
PR Close#31594
This commit switches the default value of the enableIvy flag to true.
Applications that run ngc will now by default receive an Ivy build!
This does not affect the way Bazel builds in the Angular repo work, since
those are still switched based on the value of the --define=compile flag.
Additionally, projects using @angular/bazel still use View Engine builds
by default.
Since most of the Angular repo tests are still written against View Engine
(particularly because we still publish VE packages to NPM), this switch
also requires lots of `enableIvy: false` flags in tsconfigs throughout the
repo.
Congrats to the team for reaching this milestone!
PR Close#32219
This option makes ngc behave as tsc, and was originally implemented before
ngtsc existed. It was designed so we could build JIT-only versions of
Angular packages to begin testing Ivy early, and is not used at all in our
current setup.
PR Close#32219
Previously, `ngcc` assumed that if a format property was defined in
`package.json` it would point to a valid format-path (i.e. a file that
is an entry-point for a specific format). This is generally the case,
except if a format property is set to a non-string value (such as
`package.json`) - either directly in the `package.json` (which is unusual)
or in ngcc.config.js (which is a valid usecase, when one wants a
format property to be ignored by `ngcc`).
For example, the following config file would cause `ngcc` to throw:
```
module.exports = {
packages: {
'test-package': {
entryPoints: {
'.': {
override: {
fesm2015: undefined,
},
},
},
},
},
};
```
This commit fixes it by ensuring that only format properties whose value
is a string are considered by `ngcc`.
For reference, this regression was introduced in #32052.
Fixes#32188
PR Close#32205
Initially the plan was to have a migration that adds `@Injectable()` to
all pipes in a CLI project so that the pipes can be injected in Ivy
similarly to how it worked in view engine.
Due to the planned refactorings which ensure that `@Directive`, `@Component`
and `@Pipe` also have a factory definition, this migration is no longer
needed for Ivy. Additionally since it is already disabled (due to
572b54967c) and we have a more generic
migration (known as `missing-injectable)` that could do the same as
`injectable-pipe`, we remove the migration from the code-base.
PR Close#32184
The API of `@microsoft/api-extractor` changed in a minor version which is causes an error when using dts flattening downstream.
API wil be updated on master https://github.com/angular/angular/pull/32185
PR Close#32187
Fixes an error that is thrown by `ngTemplateOutlet` under Ivy when switching from a template to null and back to a template. The error is thrown because the reference to the previous ViewRef is never cleared and the directive tries to detach a view that has already been detached.
Fixes#32060.
PR Close#32160
During the dependency analysis phase of ngcc, imports are resolved to
files on disk according to certain module resolution rules. Since module
specifiers are typically missing extensions, or can refer to index.js
barrel files within a directory, the module resolver attempts several
postfixes when searching for a module import on disk. Module specifiers
that already include an extension, however, would fail to be resolved as
ngcc's module resolver failed to check the location on disk without
adding any postfixes.
Closes#32097
PR Close#32181
During the recursive processing of dependencies, ngcc resolves the
requested file to an actual location on disk, by testing various
extensions. For recursive calls however, the path is known to have been
resolved in the module resolver. Therefore, it is safe to move the path
resolution to the initial caller into the recursive process.
Note that this is not expected to improve the performance of ngcc, as
the call to `resolveFileWithPostfixes` is known to succeed immediately,
as the provided path is known to exist without needing to add any
postfixes. Furthermore, the FileSystem caches whether files exist, so
the additional check that we used to do was cheap.
PR Close#32181
This commit fixes many diagnostic tests have have incorrect/uncaught assertions.
Also added more assertions to make sure TS diagnostics are clear.
A few test util methods are removed to reduce clutter and improve readability.
PR Close#32161
Remove unnecessary private method `getDeclarationFromNode` and moved
some logic to utils instead so that it can be tested in isolation of the
Language Service infrastructure.
The use of typechecker to check the directive is also not necessary,
since resolve.getNonNormalizedDirectiveMetadata() will check if the
directive is actually an Angular entity.
PR Close#32156
TypeScript downlevels `for-of` loops for ES5 targets. As a result, generated output contains extra code, including a try-catch block, which has code size and performance implications. This is especially important for runtime code where we want to keep it as small as possible. This commit changes `for-of` loops in runtime code to regular `for` loops.
PR Close#32157
Bundle size changed in both zone.js(legacy) and zone-evergreen.js
- zone.js(legacy) package increased a little because the following feature and fixes.
1. #31699, handle MSPointer events PR
2. https://github.com/angular/zone.js/pull/1219 to add __zone_symbol__ customization support
- zone-evergreen.js package decreased because
1. the MSPointer PR only for legacy
2. the Object.defineProperty patch is moved to legacy #31660
PR Close#31975
ngcc needs to solve a unique problem when compiling typings for an
entrypoint: it must resolve a declaration within a .js file to its
representation in a .d.ts file. Since such .d.ts files can be used in deep
imports without ever being referenced from the "root" .d.ts, it's not enough
to simply match exported types to the root .d.ts. ngcc must build an index
of all .d.ts files.
Previously, this operation had a bug: it scanned all .d.ts files in the
.d.ts program, not only those within the package. Thus, if a class in the
program happened to share a name with a class exported from a dependency's
.d.ts, ngcc might accidentally modify the wrong .d.ts file, causing a
variety of issues downstream.
To fix this issue, ngcc's .d.ts scanner now limits the .d.ts files it
indexes to only those declared in the current package.
PR Close#32129
One of the compiler's tasks is to enumerate the exports of a given ES
module. This can happen for example to resolve `foo.bar` where `foo` is a
namespace import:
```typescript
import * as foo from './foo';
@NgModule({
directives: [foo.DIRECTIVES],
})
```
In this case, the compiler must enumerate the exports of `foo.ts` in order
to evaluate the expression `foo.DIRECTIVES`.
When this operation occurs under ngcc, it must deal with the different
module formats and types of exports that occur. In commonjs code, a problem
arises when certain exports are downleveled.
```typescript
export const DIRECTIVES = [
FooDir,
BarDir,
];
```
can be downleveled to:
```javascript
exports.DIRECTIVES = [
FooDir,
BarDir,
```
Previously, ngtsc and ngcc expected that any export would have an associated
`ts.Declaration` node. `export class`, `export function`, etc. all retain
`ts.Declaration`s even when downleveled. But the `export const` construct
above does not. Therefore, ngcc would not detect `DIRECTIVES` as an export
of `foo.ts`, and the evaluation of `foo.DIRECTIVES` would therefore fail.
To solve this problem, the core concept of an exported `Declaration`
according to the `ReflectionHost` API is split into a `ConcreteDeclaration`
which has a `ts.Declaration`, and an `InlineDeclaration` which instead has
a `ts.Expression`. Differentiating between these allows ngcc to return an
`InlineDeclaration` for `DIRECTIVES` and correctly keep track of this
export.
PR Close#32129
Instead of destroying and recreating MetadataResolver every time the
program changes, create one instance and reuse it throughout the
lifetime of the language service.
Since Angular StaticSymbols are invalidated when program gets
out-of-date, this should be safe.
This should make the language service more more performant.
PR Close#32145
In VE the `Sanitizer` is always available in `BrowserModule` because the VE retrieves it using injection.
In Ivy the injection is optional and we have instructions instead of component definition arrays. The implication of this is that in Ivy the instructions can pull in the sanitizer only when they are working with a property which is known to be unsafe. Because the Injection is optional this works even if no Sanitizer is present. So in Ivy we first use the sanitizer which is pulled in by the instruction, unless one is available through the `Injector` then we use that one instead.
This PR does few things:
1) It makes `Sanitizer` optional in Ivy.
2) It makes `DomSanitizer` tree shakable.
3) It aligns the semantics of Ivy `Sanitizer` with that of the Ivy sanitization rules.
4) It refactors `DomSanitizer` to use same functions as Ivy sanitization for consistency.
PR Close#31934
This commit creates two concrete classes Inline and External
TemplateSource to differentiate between templates in TS file and
HTML file.
Knowing the template type makes the code much more explicit which
filetype we are dealing with.
With these two classes, there is no need for `getTemplateAt()` method in
TypeScriptHost. Removing this method is safe since it is not used in the
extension. This reduces the API surface of TypescriptHost.
PR Close#32127
Part 3/3 of language-service refactoring:
Change all language service APIs to return TS value since Angular LS
will be a proper tsserver plugin. This reduces the need to transform
results among Angular <--> TS <--> LSP.
PR Close#32116
In Angular today, the following pattern works:
```typescript
export class BaseDir {
constructor(@Inject(ViewContainerRef) protected vcr: ViewContainerRef) {}
}
@Directive({
selector: '[child]',
})
export class ChildDir extends BaseDir {
// constructor inherited from BaseDir
}
```
A decorated child class can inherit a constructor from an undecorated base
class, so long as the base class has metadata of its own (for JIT mode).
This pattern works regardless of metadata in AOT.
In Angular Ivy, this pattern does not work: without the @Directive
annotation identifying the base class as a directive, information about its
constructor parameters will not be captured by the Ivy compiler. This is a
result of Ivy's locality principle, which is the basis behind a number of
compilation optimizations.
As a solution, @Directive() without a selector will be interpreted as a
"directive base class" annotation. Such a directive cannot be declared in an
NgModule, but can be inherited from. To implement this, a few changes are
made to the ngc compiler:
* the error for a selector-less directive is now generated when an NgModule
declaring it is processed, not when the directive itself is processed.
* selector-less directives are not tracked along with other directives in
the compiler, preventing other errors (like their absence in an NgModule)
from being generated from them.
PR Close#31379
Cleanup the logic in TypeScriptHost as to when langauge service state
should be synchronized with the editor state.
The model employed follows that of tsserver, in which case it is the
caller's responsiblity to synchronize host data before any LS methods
are called.
PR Close#32017
For some reason (on OS/X) this transitive dependency is not being passed
through to the final TS builds that rely on this rule, so the build fails
with a missing file error:
```
The specified path does not exist:
'/.../sandbox/darwin-sandbox/451/execroot/angular/packages/tsconfig-build.json'.
```
PR Close#31943
Introduces a new migration schematic that follows the given
migration plan: https://hackmd.io/@alx/S1XKqMZeS.
First case: The schematic detects decorated directives which
inherit a constructor. The migration ensures that all base
classes until the class with the explicit constructor are
properly decorated with "@Directive()" or "@Component". In
case one of these classes is not decorated, the schematic
adds the abstract "@Directive()" decorator automatically.
Second case: The schematic detects undecorated declarations
and copies the inherited "@Directive()", "@Component" or
"@Pipe" decorator to the undecorated derived class. This
involves non-trivial import rewriting, identifier aliasing
and AOT metadata serializing
(as decorators are not always part of source files)
PR Close#31650
The $locationShim has onChange listeners to allow for synchronization logic between
AngularJS and Angular. When the AngularJS routing events are emitted first, this can
cause Angular code to be out of sync. Notifying the listeners earlier solves the
problem.
PR Close#32037
PR #29473 changed the docs to use a string as the input value of `formControlName`, as it used to only accept a string.
This has been changed, and `formControlName` now accepts a string or a number, so the example in the docs can use a binding as they used to.
PR Close#30606
This commit relaxes the type of the `formControlName` input to accept both a `string` and a `number`.
Currently, when using a `FormArray`, most templates look like:
```
<div formArrayName="tags">
<div *ngFor="let tag of tagsArray.controls; index as i">
<input [formControlName]="i">
</div>
</div>
```
Here `formControlName` receives a number whereas its input type is a string.
This is fine for VE and `fullTemplateTypeCheck`, but not for Ivy which does a more thorough type checking on inputs with `fullTemplateTypeCheck` enabled and throws `Type 'number' is not assignable to type 'string'`. It is fixable by using `formControlName="{{i}}"` but you have to know the difference between `a="{{b}}"` and `[a]="b"` and change it all over the application codebase. This commit allows the existing code to still type-check.
PR Close#30606
Follow-up to #30993 where we build all Angular packages with
the TypeScript `--strict` flag. The flag improves overall code
health and also helps us catch issues easier.
PR Close#31967
Part 2/3 of language service refactoring:
Now that the language service is a proper tsserver plugin, all LS
interfaces should return TS values. This PR refactors the
ng.getDiagnostics() API to return ts.Diagnostic[] instead of
ng.Diagnostic[].
PR Close#32115
The language service relies on a "context" file that is used as the
canonical "containing file" when performing module resolution.
This file is unnecessary since the language service host's current
directory always default to the location of tsconfig.json for the
project, which would give the correct result.
This refactoring allows us to simplify the "typescript host" and also
removes the need for custom logic to find tsconfig.json.
PR Close#32015
There has been a regression where enabling rollup treeshaking causes errors during runtime because it will drop const access which will always evaluate to true or false. However, such `const` in `@angular/core` cannot be dropped because their value is changed when NGCC is run on `@angular/core`
VE
```
const SWITCH_IVY_ENABLED__POST_R3__ = true;
const SWITCH_IVY_ENABLED__PRE_R3__ = false;
const ivyEnabled = SWITCH_IVY_ENABLED__PRE_R3__;
```
Ivy (After NGCC)
```
const SWITCH_IVY_ENABLED__POST_R3__ = true;
const SWITCH_IVY_ENABLED__PRE_R3__ = false;
const ivyEnabled = SWITCH_IVY_ENABLED__POST_R3__;
```
FESM2015
```
load(path) {
/** @type {?} */
const legacyOfflineMode = this._compiler instanceof Compiler;
return legacyOfflineMode ? this.loadFactory(path) : this.loadAndCompile(path);
}
```
ESM2015
```
load(path) {
/** @type {?} */
const legacyOfflineMode = !ivyEnabled && this._compiler instanceof Compiler;
return legacyOfflineMode ? this.loadFactory(path) : this.loadAndCompile(path);
}
```
From the above we can see that `ivyEnabled ` is being treeshaken away when generating the FESM bundle which is causing runtime errors such as `Cannot find module './lazy/lazy.module.ngfactory'` since in Ivy we will always load the factories.
PR Close#32069
Similar to interpolation, we do not want to completely remove whitespace
nodes that are siblings of an expansion.
For example, the following template
```html
<div>
<strong>items left<strong> {count, plural, =1 {item} other {items}}
</div>
```
was being collapsed to
```html
<div><strong>items left<strong>{count, plural, =1 {item} other {items}}</div>
```
which results in the text looking like
```
items left4
```
instead it should be collapsed to
```html
<div><strong>items left<strong> {count, plural, =1 {item} other {items}}</div>
```
which results in the text looking like
```
items left 4
```
---
**Analysis of the code and manual testing has shown that this does not cause
the generated ids to change, so there is no breaking change here.**
PR Close#31962
Previously if only a component template changed then we would know to
rebuild its component source file. But the compilation was incorrect if the
component was part of an NgModule, since we were not capturing the
compilation scope information that had a been acquired from the NgModule
and was not being regenerated since we were not needing to recompile
the NgModule.
Now we register compilation scope information for each component, via the
`ComponentScopeRegistry` interface, so that it is available for incremental
compilation.
The `ComponentDecoratorHandler` now reads the compilation scope from a
`ComponentScopeReader` interface which is implemented as a compound
reader composed of the original `LocalModuleScopeRegistry` and the
`IncrementalState`.
Fixes#31654
PR Close#31932
Moves the `renderer_to_renderer2` migration google3 tslint rule
into the new `google3` directory. This is done for consistency
as we recently moved all google3 migration rules into a new
`google3` folder (see: f69e4e6f77).
PR Close#31817
Creates a separate bazel target for the google3 migration
tests. The benefit is that it's faster to run tests for
public migrations in development. Google3 lint rules are
usually another story/implementation and the tests are quite
slow due to how TSLint applies replacements.
Additionally if something changes in the google3 tslint rules,
the tests which aren't affected re-run unnecessarily.
PR Close#31817
In Angular today, the following pattern works:
```typescript
export class BaseDir {
constructor(@Inject(ViewContainerRef) protected vcr: ViewContainerRef) {}
}
@Directive({
selector: '[child]',
})
export class ChildDir extends BaseDir {
// constructor inherited from BaseDir
}
```
A decorated child class can inherit a constructor from an undecorated base
class, so long as the base class has metadata of its own (for JIT mode).
This pattern works regardless of metadata in AOT.
In Angular Ivy, this pattern does not work: without the @Directive
annotation identifying the base class as a directive, information about its
constructor parameters will not be captured by the Ivy compiler. This is a
result of Ivy's locality principle, which is the basis behind a number of
compilation optimizations.
As a solution, @Directive() without a selector will be interpreted as a
"directive base class" annotation. Such a directive cannot be declared in an
NgModule, but can be inherited from. To implement this, a few changes are
made to the ngc compiler:
* the error for a selector-less directive is now generated when an NgModule
declaring it is processed, not when the directive itself is processed.
* selector-less directives are not tracked along with other directives in
the compiler, preventing other errors (like their absence in an NgModule)
from being generated from them.
PR Close#31379
PR #29473 changed the docs to use a string as the input value of `formControlName`, as it used to only accept a string.
This has been changed, and `formControlName` now accepts a string or a number, so the example in the docs can use a binding as they used to.
PR Close#30606
This commit relaxes the type of the `formControlName` input to accept both a `string` and a `number`.
Currently, when using a `FormArray`, most templates look like:
```
<div formArrayName="tags">
<div *ngFor="let tag of tagsArray.controls; index as i">
<input [formControlName]="i">
</div>
</div>
```
Here `formControlName` receives a number whereas its input type is a string.
This is fine for VE and `fullTemplateTypeCheck`, but not for Ivy which does a more thorough type checking on inputs with `fullTemplateTypeCheck` enabled and throws `Type 'number' is not assignable to type 'string'`. It is fixable by using `formControlName="{{i}}"` but you have to know the difference between `a="{{b}}"` and `[a]="b"` and change it all over the application codebase. This commit allows the existing code to still type-check.
PR Close#30606
Now that the Angular LS is a proper tsserver plugin, it does not make
sense for it to maintain its own language service API.
This is part one of the effort to remove our custom LanguageService
interface.
This interface is cumbersome because we have to do two transformations:
ng def -> ts def -> lsp definition
The TS LS interface is more comprehensive, so this allows the Angular LS
to return more information.
PR Close#31972
Publishing of NGCC packages should not be allowed. It is easy for a user to publish an NGCC'd version of a library they have workspace libraries which are being used in a workspace application.
If a users builds a library and afterwards the application, the library will be transformed with NGCC and since NGCC taints the distributed files that should be published.
With this change we use the npm/yarn `prepublishOnly` hook to display and error and abort the process with a non zero error code when a user tries to publish an NGCC version of the package.
More info: https://docs.npmjs.com/misc/scripts
PR Close#32031
Previously, when run with `createNewEntryPointFormats: true`, `ngcc`
would only update `package.json` with the new entry-point for the first
format property that mapped to a format-path. Subsequent properties
mapping to the same format-path would be detected as processed and not
have their new entry-point format recorded in `package.json`.
This commit fixes this by ensuring `package.json` is updated for all
matching format properties, when writing an `EntryPointBundle`.
PR Close#32052
Remove the `formatProperty` property from the `EntryPointBundle`
interface, because the property is not directly related to that type.
It was only used in one place, when calling `fileWriter.writeBundle()`,
but we can pass `formatProperty` directrly to `writeBundle()`.
PR Close#32052
This refactoring more clearly separates the different phases of the work
performed by `ngcc`, setting the ground for being able to run each phase
independently in the future and improve performance via parallelization.
Inspired by/Based on @alxhub's prototype: alxhub/angular@cb631bdb1
PR Close#32052
This change basically moves some checks to happen up front and ensures
we don't try to process any more properties than we absolutely need.
(The properties would not be processed before either, but we would
consider them, before finding out that they have already been processed
or that they do not exist in the entry-point's `package.json`.)
This change should make no difference in the work done by `ngcc`, but it
transforms the code in a way that makes the actual work known earlier,
thus making it easier to parallelize the processing of each property in
the future.
PR Close#32052
In commit 7b55ba58b (part of PR #29092), the implementation of
`makeEntryPointBundle()` was changed such that it now always return
`EntryPointBundle` (and not `null`).
However, the return type was not updated and as result we continued to
unnecessarily handle `null` as a potential return value in some places.
This commit fixes the return type to reflect the implementation and
removes the redundant code that was dealing with `null`.
PR Close#32052
ngcc analyzes the dependency structure of the entrypoints it needs to
process, as the compilation of entrypoints is ordering sensitive: any
dependent upon entrypoint must be compiled before its dependees. As part
of the analysis of the dependency graph, it is detected when a
dependency of entrypoint is not installed, in which case that entrypoint
will be marked as ignored.
For libraries that work with Angular Universal to run in NodeJS, imports
into builtin NodeJS modules can be present. ngcc's dependency analyzer
can only resolve imports within the TypeScript compilation, which
builtin modules are not part of. Therefore, such imports would
erroneously cause the entrypoint to become ignored.
This commit fixes the problem by taking the NodeJS builtins into account
when dealing with missing imports.
Fixes#31522
PR Close#31872
ngcc analyzes the dependency structure of the entrypoints it needs to
process, as the compilation of entrypoints is ordering sensitive: any
dependent upon entrypoint must be compiled before its dependees. As part
of the analysis of the dependency graph, it is detected when a
dependency of entrypoint is not installed, in which case that entrypoint
will be marked as ignored.
When a target entrypoint to compile is provided, it could occur that
given target is considered ignored because one of its dependencies might
be missing. This situation was not dealt with currently, instead
resulting in a crash of ngcc.
This commit prevents the crash by taking the above scenario into account.
PR Close#31872