This commit fixes a bug introduced in the recent refactoring whereby
caches become stale when the program changes.
This is because StaticReflector keeps its own caches that are not
clearable. The previous refactoring tried to reuse the same instance,
leading to out-of-sync program state.
Clearing out the *entire* cache is very inefficient. Instead, we could
just invalidate the symbols in the files that have changed. This
requires changes to the API of StaticReflector, but put this on hold
until the refactoring of language service for Ivy commences.
PR closes https://github.com/angular/angular/issues/32301
PR Close#32357
Currently the undecorated classes migration decorates base classes if no
explicit constructor is defined on all classes in the inheritance chain.
We only want to decorate base classes which define a constructor that is
inherited. Additionally for best practice, all classes in between the class
that inherits the constructor and the one that defines it are also decorated.
PR Close#32319
The `undecorated-classes-with-di` migration currently creates invalid object literals from parsed
NGC metadata files if there are object literal properties with keys that contain special characters.
e.g. consider a decorated base class with a host binding using `[class.X]`. Currently the migration
parses and converts the metadata to TypeScript code but incorrectly uses `[class.X]` unquoted as
identifier.
PR Close#32319
Apparently the names of the bazel test targets in the schematics are
incorrect. This commit updates the target names to match their bazel
package name.
PR Close#32318
ec4381dd40 enabled Ivy by default. This is
problematic as migrations like `undecorated-classes-with-di` depend on the
`AngularCompilerProgram` (NGC) in order to perform the migration from
version 8 to version 9. In order to ensure that the migration always runs
with NGC (and doesn't get the `NgtscProgram`), we need to explicitly disable
ivy when creating the `@angular/compiler-cli` program for the migration.
PR Close#32318
Adds support for `getDefinitionAt` when called on a templateUrl
property assignment.
The currrent architecture for getting definitions is designed to be
called on templates, so we have to introduce a new
`getTsDefinitionAndBoundSpan` method to get Angular-specific definitions
in TypeScript files and pass a `readTemplate` closure that will read the
contents of a template using `TypeScriptServiceHost#getTemplates`. We
can probably go in and make this nicer in a future PR, though I'm not
sure what the best architecture should be yet.
Part of angular/vscode-ng-language-service#111
PR Close#32238
Previously, the `SwPush` API docs were using hard-coded code snippets.
This commit switches to using code snippets from an actual example app,
which ensures that the code shown in the docs will at least continue to
compile successfully.
PR Close#32139
Reworks the compiler to output the factories for directives, components and pipes under a new static field called `ngFactoryFn`, instead of the usual `factory` property in their respective defs. This should eventually allow us to inject any kind of decorated class (e.g. a pipe).
**Note:** these changes are the first part of the refactor and they don't include injectables. I decided to leave injectables for a follow-up PR, because there's some more cases we need to handle when it comes to their factories. Furthermore, directives, components and pipes make up most of the compiler output tests that need to be refactored and it'll make follow-up PRs easier to review if the tests are cleaned up now.
This is part of the larger refactor for FW-1468.
PR Close#31953
Binding metadata are only needed:
- for property bindings;
- when TestBed tests are being run.
This commit guards binding metadata storage with the ngDevMode flag
which saves ~6% of a proerty binding processing time in the production
mode (and reduces bundle size).
PR Close#32317
After a series of recent refactorings `enterView` and `leaveView` became
identical. This PR merges both into one concept of view selectio (similar
to a node selection). This reduces number of concepts and code size.
PR Close#32263
This commit removes all the (duplicated) logic of setting lView[BINDING_INDEX]
from `enterView`. `enterView` is on the critcal path perf-wise so we should
avoid having any logic in there and minimise memory read / write.
This simple refactoring in this PR reduces time spent in noop change detection
by ~12% (from ~800ms down to ~700ms on a local machine where measurements were
taken).
PR Close#32263
When ngcc is called for a specific entry-point, it has to determine
which dependencies to transitively process. To accomplish this, ngcc
traverses the full import graph of the entry-points it encounters, for
which it uses a dependency host to find all module imports. Since
imports look different in the various bundle formats ngcc supports, a
specific dependency host is used depending on the information provided
in an entry-points `package.json` file. If there's not enough
information in the `package.json` file for ngcc to be able to determine
which dependency host to use, ngcc would fail with an error.
If, however, the entry-point is not compiled by Angular, it is not
necessary to process any of its dependencies. None of them can have
been compiled by Angular so ngcc does not need to know about them.
Therefore, this commit changes the behavior to avoid recursing into
dependencies of entry-points that are not compiled by Angular.
In particular, this fixes an issue for packages that have dependencies
on the `date-fns` package. This package has various secondary
entry-points that have a `package.json` file only containing a `typings`
field, without providing additional fields for ngcc to know which
dependency host to use. By not needing a dependency host at all, the
error is avoided.
Fixes#32302
PR Close#32303
This PR makes finding class declarations properties in decorators are
applied to more generic to all properties that may be in a decorator,
and adds helper methods enabling getting the property assignment of a
property value and verifying that a property assignment is actually in a
decorator applied to a class.
This is done so that it will be easier to provide Angular definitions
for decorator properties moving forward. Most immediately, this will
provide decorator class verification for #32238.
PR Close#32252
The TemplateInfo type is an extension of AstResult, but it is not
necessary at all. Instead, improve the current interface for AstResult
by removing all optional fileds and include the TemplateSource in
AstResult instead.
PR Close#32250
Prior to this change, the `BINDING_INDEX` of a given lView was reset after processing a template. However change detection can be triggered as a result of View queries processing, thus leading to subsequent `refreshView` call (and executing a template), which in turn operates with the binding index that is not reset after the previous `refreshView` call. This commit updates the logic to reset binding index before we execute a template, so binding index is correct for instructions inside template function.
PR Close#32201
In ngc is was valid to set the "flatModuleOutFile" option to "null". This is sometimes
necessary if a tsconfig extends from another one but the "fatModuleOutFile" option
needs to be unset (note that "undefined" does not exist as value in JSON)
Now if ngtsc is used to compile the project, ngtsc will fail with an error because it
tries to do string manipulation on the "flatModuleOutFile". This happens because
ngtsc only skips flat module indices if the option is set to "undefined".
Since this is not compatible with what was supported in ngc and such exceptions
should be avoided, the flat module check is now aligned with ngc.
```
TypeError: Cannot read property 'replace' of null
at Object.normalizeSeparators (/home/circleci/project/node_modules/@angular/compiler-cli/src/ngtsc/util/src/path.js:35:21)
at new NgtscProgram (/home/circleci/project/node_modules/@angular/compiler-cli/src/ngtsc/program.js:126:52)
```
Additionally setting the `flatModuleOutFile` option to an empty string
currently results in unexpected behavior. No errors is thrown, but the
flat module index file will be `.ts` (no file name; just extension).
This is now also fixed by treating an empty string similarly to
`null`.
PR Close#32235
Previously, ngtsc attempted to use the .d.ts schema for HTML elements to
check bindings to DOM properties. However, the TypeScript lib.dom.d.ts
schema does not perfectly align with the Angular DomElementSchemaRegistry,
and these inconsistencies would cause issues in apps. There is also the
concern of supporting both CUSTOM_ELEMENTS_SCHEMA and NO_ERRORS_SCHEMA which
would have been very difficult to do in the existing system.
With this commit, the DomElementSchemaRegistry is employed in ngtsc to check
bindings to the DOM. Previous work on producing template diagnostics is used
to support generation of this different kind of error with the same high
quality of error message.
PR Close#32171
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
Previously, `ngcc` would avoid processing a `formatPath` that a property
in `package.json` mapped to, if either the _property_ was marked as
processed or the `formatPath` (i.e. the file(s)) was processed in the
same `ngcc` run (since the `compiledFormats` set was not persisted
across runs).
This could lead in a situation where a `formatPath` would be compiled
twice (if for example properties `a` and `b` both mapped to the same
`formatPath` and one would run `ngcc` for property `a` and then `b`).
This commit fixes it by ensuring that as soon as a `formatPath` has been
processed all corresponding properties are marked as processed (which
persists across `ngcc` runs).
PR Close#32003
Previously, when `ngcc` was called with `compileAllFormats === false`
(i.e. how `@angular/cli` calls it), it would not attempt to process
more properties, once the first was successfully processed. However, it
_would_ continue looping over them and perform some unnecessary
operations, such as:
- Determining the format each property maps to (which can be an
expensive operation for some properties mapping to either UMD or
CommonJS).
- Checking whether each property has been processed (which involves
checking whether any property has been processed with a different
version of `ngcc` each time).
- Potentially marking properties as processed (which involves a
file-write operation).
This commit avoids the unnecessary operations by entirely skipping
subsequent properties, once the first one has been successfully
processed. While this theoretically improves performance, it is not
expected to have any noticeable impact in practice, since the list of
`propertiesToConsider` is typically small and the most expensive
operation (marking a property as processed) has low likelihood of
happening (plus these operations are a tiny fraction of `ngcc`'s work).
PR Close#32003
Previously, when `ngcc` needed to mark multiple properties as processed
(e.g. a processed format property and `typings` or all supported
properties for a non-Angular entry-point), it would update each one
separately and write the file to disk multiple times.
This commit changes this, so that multiple properties can be updated at
once with one file-write operation. While this theoretically improves
performance (reducing the I/O operations), it is not expected to have
any noticeable impact in practice, since these operations are a tiny
fraction of `ngcc`'s work.
This change will be useful for a subsequent change to mark all
properties that map to the same `formatPath` as processed, once it is
processed the first time.
PR Close#32003
Using `ParentInjectorPromise.all()` (which is a static method inherited
from `SyncPromise`) causes Closure Compiler (or some related tool) to
complain:
```
TypeError: ...$packages$upgrade$src$common$src$downgrade_component_ParentInjectorPromise.all is not a function
```
Switching to `SyncPromise.all()` (the static method on the parent class)
to avoid this error.
PR Close#31986
This PR changes the language service to work in two different modes:
1. TS + Angular
Plugin augments TS language service to provide additonal Angular
information. This only works with inline template and is meant to be
used as a local plugin (configured via tsconfig.json).
2. Angular only
Plugin only provides information on Angular templates, no TS info at
all. This effectively disables native TS features and is meant for
internal use only.
Default mode is `angularOnly = false` so that we don't break any users
already using Angular LS as local plugin.
As part of the refactoring, `undefined` is removed from type aliases
because it is considered bad practice.
go/tsstyle#nullableundefined-type-aliases
```
Type aliases must not include |null or |undefined in a union type.
Nullable aliases typically indicate that null values are being passed
around through too many layers of an application, and this clouds the
source of the original issue that resulted in null. They also make it
unclear when specific values on a class or interface might be absent.
```
PR Close#31935
Fixes Ivy's directive matching not capturing attribute selectors when there is one class binding, one style binding and a regular binding that precede the attribute that would match the directive. The issue appears to come from the fact that we weren't skipping over style bindings correctly which was throwing the loop off not to go into `bindingsMode` and to skip some of the bindings when matching.
PR Close#31942
This commit changes the emit order of ngcc when a class has multiple static
fields being assigned. Previously, ngcc would emit each static field
followed immediately by any extra statements specified for that field. This
causes issues with downstream tooling such as build optimizer, which expects
all of the static fields for a class to be grouped together. ngtsc already
groups static fields and additional statements. This commit changes ngcc's
ordering to match.
PR Close#31933
Fixes Ivy's `DebugElement.triggerEventHandler` to picking up events that have been registered through a `Renderer2`, unlike ViewEngine.
This PR resolves FW-1480.
PR Close#31845
Prior to this commit, the `schemas` configuration was applied to top-level view only. That leads to problems when using unknown props with elements inside nested views (for example generated as a result of *ngIf). This commit passes `schemas` information down to nested views to make sure that all the checks are consistent.
PR Close#31913
AngularJS compilation is a synchronous operation (unless having to fetch
a template, which is not supported for downgraded components).
Previously, ngUpgrade tried to retain the synchronous nature of the
compilation for downgraded components (when possible), by using a
synchronous thenable implementation (`ParentInjectorPromise`). This was
accidentally broken in #27217 by replacing a call to
`ParentInjectorPromise#then()` (which can be synchronous) with a call to
`Promise.all()` (which is asynchronous).
This commit fixes this by introducing a `SyncPromise.all()` static
method; similar to `Promise.all()` but retaining the synchronous
capabilities of `SyncPromise` (which `ParentInjectorPromise` inherits
from).
Fixes#30330
PR Close#31840
If a project being built with ngtsc has no templates to check, then ngtsc
previously generated an empty typecheck file. This seems to trigger some
pathological behavior in TS where the entire user program is re-checked,
which is extremely expensive. This likely has to do with the fact that the
empty file is not considered an ES module, meaning the module structure of
the program has changed.
This commit causes an export to be produced in the typecheck file regardless
of its other contents, which guarantees that it will be an ES module. The
pathological behavior is avoided and template type-checking is fast once
again.
PR Close#31922
Describe the indexer module for Angular compiler developers. Include
scope of analysis provided by the module and the indexers it targets as
first-party.
PR Close#31260
In #31426 a fix was implemented to render namespaced decorator imports
correctly, however it turns out that the fix only worked when decorator
information was extracted from static properties, not when using
`__decorate` calls.
This commit fixes the issue by creating the decorator metadata with the
full decorator expression, instead of only its name.
Closes#31394
PR Close#31614
An identifier may become repeated when bundling multiple source files
into a single bundle, so bundlers have a strategy of suffixing non-unique
identifiers with a suffix like $2. Since ngcc operates on such bundles,
it needs to process potentially suffixed identifiers in their canonical
form without the suffix. The "ngx-pagination" package was previously not
compiled fully, as most decorators were not recognized.
This commit ensures that identifiers are first canonicalized by removing
the suffix, such that they are properly recognized and processed by ngcc.
Fixes#31540
PR Close#31614
Any decorator information present in TypeScript is emitted into the
generated JavaScript sources by means of `__decorate` call. This call
contains both the decorators as they existed in the original source
code, together with calls to `tslib` helpers that convey additional
information on e.g. type information and parameter decorators. These
different kinds of decorator calls were not previously distinguished on
their own, but instead all treated as `Decorator` by themselves. The
"decorators" that were actually `tslib` helper calls were conveniently
filtered out because they were not imported from `@angular/core`, a
characteristic that ngcc uses to drop certain decorators.
Note that this posed an inconsistency in ngcc when it processes
`@angular/core`'s UMD bundle, as the `tslib` helper functions have been
inlined in said bundle. Because of the inlining, the `tslib` helpers
appear to be from `@angular/core`, so ngcc would fail to drop those
apparent "decorators". This inconsistency does not currently cause any
issues, as ngtsc is specifically looking for decorators based on their
name and any remaining decorators are simply ignored.
This commit rewrites the decorator analysis of a class to occur all in a
single phase, instead of all throughout the `ReflectionHost`. This
allows to categorize the various decorate calls in a single sweep,
instead of constantly needing to filter out undesired decorate calls on
the go. As an added benefit, the computed decorator information is now
cached per class, such that subsequent reflection queries that need
decorator information can reuse the cached info.
PR Close#31614
Currently the `DebugElement.listeners` array are retained after the node is destroyed. This means that they'll continue to fire through `triggerEventHandler` and can cause memory leaks. This has already been fixed in Ivy, but these changes fix it in ViewEngine for consistency.
PR Close#31820
nodejs rules 0.34.0 now includes protractor_web_test_suite rule (via new @bazel/protractor rule) so we switch to that location for that rule in this PR so that /packages/bazel/src/protractor can be removed in a future PR
this PR also brings in node toolchain support which was released in nodejs rules 0.33.0. this is a prerequisite for RBE for mac & windows users
bazel schematics also updated with the same. @bazel/bazel 0.28.1 npm package includes transitive dep on hide-bazel-files so we're able to remove an explicit dep on that as well.
PR Close#31824
In `BrowserModule` the value of `LOCALE_ID` is defined in the `APPLICATION_MODULE_PROVIDERS` after `APP_INITIALIZER` has run.
This PR ensures that `LOCALE_ID` is also set for ivy at the same moment which allows the application to fetch the locale from a backend (for example).
Fixes#31465
FW-1436 #resolve
PR Close#31566
Fixes Ivy throwing an error when something is passed in as a `forwardRef` into `@Injectable`'s `useClass` option. The error was being thrown, because we were trying to get the provider factory off of the wrapper function, rather than the value itself.
This PR resolves FW-1335.
PR Close#30532
In #30181, several testcases were added that were failing in Windows.
The reason was that a recent rebase missed a required change to interact
with the compiler's virtualized filesystems. This commit introduces the
required usage of the VFS layer to fix the testcase.
PR Close#31860
`TemplateVisitor#visitBoundAttribute` currently has to invoke visiting
expressions manually (this is fixed in #31813). Previously, it did not
bind `targetToIdentifier` to the visitor before deferring to the
expression visitor, which breaks the `targetToIdentifier` code. This
fixes that and adds a test to ensure the closure processed correctly.
This change is urgent; without it, many indexing targets in g3 are
broken.
PR Close#31861
Template AST nodes for (bound) attributes, variables and references will
now retain a reference to the source span of their value, which allows
for more accurate type check diagnostics.
PR Close#30181
The type check blocks (TCB) that ngtsc generates for achieving type
checking of Angular templates needs to be annotated with positional
information in order to translate TypeScript's diagnostics for the TCB
code back to the location in the user's template. This commit augments
the TCB by attaching trailing comments with AST nodes, such that a node
can be traced back to its source location.
PR Close#30181
Adds support for indexing template referenecs, variables, and property
and method calls inside bound attributes and bound events. This is
mostly an extension of the existing indexing infrastructure.
PR Close#31535
Currently we always generate the `read` parameter for the view and content query instructions, however since most of the time the `read` parameter won't be set, we'll end up generating `null` which adds 5 bytes for each query when minified. These changes make it so that the `read` parameter only gets generated if it has a value.
PR Close#31667
This commit fixes a bug where we assumed all dynamically created
components would have tag-name selectors, so we passed through the
"tag name" to the renderer as the first index of the selector. For
components with attribute selectors, the tag name would be "", so
the renderer would try to create an element with tag name "" and
throw. Now we default to a "div" element the same way that View
Engine did.
Closes#31785
PR Close#31812
This switches all Angular targets to be built with the same Angular compiler architecture (c.n. Ivy) that the Angular indexer uses. This eliminates issues with cross-references to transitive dependencies not being generated because of the way such dependencies are loaded by the legacy compiler arch.
PR Close#31786
Extend indexing API interface to provide information about used
directives' selectors on template elements. This enables an indexer to
xref element attributes to the directives that match them.
The current way this matching is done is by mapping selectors to indexed
directives. However, this fails in cases where the directive is not
indexed by the indexer API, like for transitive dependencies. This
solution is much more general.
PR Close#31782
When analyzing components, directives, etc we capture its base class.
Previously this assumed that the code is in TS format, which is not
always the case (e.g. ngcc).
Now this code is replaced with a call to
`ReflectionHost.getBaseClassExpression()`, which abstracts the work
of finding the base class.
PR Close#31544
Previously the last file-system being tested was left as the current
file-system. Now it is reset to an `InvalidFileSystem` to ensure future
tests are not affected.
PR Close#31544
Moves all google3 migration tslint rules into a single directory.
This makes it easier to wire up multiple migration rules in
google3 without having to update the rule directories each time
a new migration is available.
PR Close#30956
Introduces a new migration schematic for adding the "@Injectable()"
decorator to provider classes which are currently not migrated. Previously
in ViewEngine, classes which are declared as providers sometimes don't
require the "@Injectable()" decorator
(e.g. https://stackblitz.com/edit/angular-hpo7gw)
With Ivy, provider classes need to be explicitly decorated with
the "@Injectable()" decorator if they are declared as providers
of a given module. This commit introduces a migration schematic
which automatically adds the explicit decorator to places where
the decorator is currently missing.
The migration logic is designed in a CLI devkit and TSlint agnostic
way so that we can also have this migration run as part of a public
CLI migration w/ `ng update`. This will be handled as part of a follow-up to reiterate on console output etc.
Resolves FW-1371
PR Close#30956
The way the `ComponentFactory.create` is set up at the moment is that if a `rootSelectorOrNode` is passed in, the root context will be injected instead of creating dedicated one for the component. As far as I can tell, there doesn't seem to be a reason to do this and nothing seems to break because of it. These changes switch to always create the root context.
PR Close#31661
In ViewEngine nodes that were inserted through `Renderer2` would also be picked up by `DebugNode.query` and `DebugNode.queryAll`. This worked because everything in ViewEngine went through `Renderer2` and `DebugRenderer2` in dev mode which was able to keep track of the child nodes as they're being inserted. This no longer works in Ivy, because we don't use `DebugRenderer2` and debug nodes work a little differently. These changes work around the issue by walking the DOM as the logical tree is being walked and looking for matches. Note that this is __not__ optimal, because we're walking similar trees multiple times. ViewEngine could do it more efficiently, because all the insertions go through Renderer2, however that's not the case in Ivy. This approach is being used because:
1. Matching the ViewEngine behavior would mean potentially introducing a depedency from `Renderer2` to Ivy which could bring Ivy code into ViewEngine.
2. We would have to make `Renderer3` "know" about debug nodes.
3. It allows us to capture nodes that were inserted directly via the DOM.
PR Close#31716
This commit updates the `_clone` function of the `_ApplySourceSpanTransformer` class, where the for-in loop was used, resulting in copying from prototype to own properties, thus consuming more memory. Prior to NodeJS 12 (V8 versions before 7.4) there was an optimization that was improving the situation and since that logic was removed in favor of other optimizations, the situation with memory consumption caused by the for-in loop got worse. This commit adds a check to make sure we copy only own properties over to cloned object.
Closes#31627.
PR Close#31638
When injecting a `ChangeDetectorRef` into a pipe, the expected result is that the ref will be tied to the component in which the pipe is being used. This works for most cases, however when a pipe is used inside a property binding of a component (see test case as an example), the current `TNode` is pointing to component's host so we end up injecting the inner component's view. These changes fix the issue by only looking up the component view of the `TNode` if the `TNode` is a parent.
This PR resolves FW-1419.
PR Close#31438
In the previous patch () all the existing styling code was turned
off in favor of using the new refactored ivy styling code. This
patch is a follow up patch to that and removes all old, unused
styling code from the render3 directory.
PR Close#31193
This commit fixes a bug where ICU expressions inserted into ngTemplateOutlets
that are inside ngFor blocks would throw an error. We were assuming in view
insertion code that text nodes would always exist by the time a view\`s
creation block had executed. This is not true for text nodes created dynamically
by ICUs because this happens in the update block (in `i18nApply`).
This change ensures such dynamically created nodes are skipped when encountered
too early (as they will be attached later by i18n code anyway).
PR Close#31789
We currently have a handwritten version of the Ivy directive def for NgClass so
we can switch between Ivy and View Engine behavior. This generated code needs to
be kept up-to-date with what the Ivy compiler generates.
PR 30742 recently changed `classMap` such that it now requires allocation of
host binding slots. This means that the `allocHostVars()` function must be
called in the NgClass directive def to match compiler output, but the
handwritten directive def was not updated. This caused a bug where NgClass
was inappropriately overwriting data for other directives because space was
not allocated for its values.
PR Close#31788
This commit bumps the heap size of node/ngc under bazel to 4 GB instead of
the previous 2 GB. This brings it in sync with what the TS compiler uses
in g3, and fixes a bug where ngc would crash with OOM in worker mode.
PR Close#31784
Currently, template expressions and statements have their location
recorded relative to the HTML element they are in, with no handle to
absolute location in a source file except for a line/column location.
However, the line/column location is also not entirely accurate, as it
points an entire semantic expression, and not necessarily the start of
an expression recorded by the expression parser.
To support record of the source code expressions originate from, add a
new `sourceSpan` field to `ASTWithSource` that records the absolute byte
offset of an expression within a source code.
Implement part 2 of [refactoring template parsing for
stability](https://hackmd.io/@X3ECPVy-RCuVfba-pnvIpw/BkDUxaW84/%2FMA1oxh6jRXqSmZBcLfYdyw?type=book).
PR Close#31391
This commit is the final patch of the ivy styling algorithm refactor.
This patch swaps functionality from the old styling mechanism to the
new refactored code by changing the instruction code the compiler
generates and by pointing the runtime instruction code to the new
styling algorithm.
PR Close#30742
Versions of CLI prior to angular/angular-cli@0e339ee did not expose the host.getModifiedResourceFiles() method.
This meant that null was being passed through to the IncrementalState.reconcile() method
to indicate that there were either no changes or the host didn't support that method.
This commit fixes a bug where we were checking for undefined rather than null when
deciding whether any resource files had changed, causing a null reference error to be thrown.
This bug was not caught by the unit testing because the tests set up the changed files
via a slightly different process, not having access to the CompilerHost, and these test
were making the erroneous assumption that undefined indicated that there were no
changed files.
PR Close#31322
Currently developers can use the `By` class to construct common
`DebugElement` query predicates. e.g. `By.directive(MyDirective)`.
The `directive()` and `all()` predicates are currently returning
a predicate that works for `DebugElement` nodes. This return type
is too strict since the predicate is not specific to `DebugElement`
instances and can also apply to `DebugNode` instances.
Meaning that developers are currently able to use the `directive()`
predicate when using `queryAllNodes()`. This is a common practice
but will break when the project is compiled with TypeScript's
`--strictFunctionTypes` flag as the `DebugElement` predicate type
is not assignable to predicates for `DebugNode`. In order to make
these predicates usable with `--strictFuntionTypes` enabled, we
adjust the predicate type to reflect what is actually needed for
evaluation of the predicate.
PR Close#30993
Fixes all TypeScript failures caused by enabling the `--strict`
flag for test source files. We also want to enable the strict
options for tests as the strictness enforcement improves the
overall codehealth, unveiled common issues and additionally it
allows us to enable `strict` in the `tsconfig.json` that is picked
up by IDE's.
PR Close#30993
In View Engine, developers can pass bootstrap and entry components
as nested arrays. e.g.
```ts
export const MyOtherEntryComponents = [A, B, C]
@NgModule({
entryComponents: [MyComp, MyOtherEntryComponents]
})
```
Currently using nested arrays for these properties causes
unexpected errors to be reported in Ivy since the semantic
NgModule checks aren't properly recursing into the nested
entry/bootstrap components. This issue has been unveiled by
enabling the strict function parameter checks.
PR Close#30993
Currently the `ɵɵdefineComponent` method has incorrect type
definitions the `directives` and `pipes` metadata property.
The incorrect types allow developers to pass in already instantiated
`DirectiveDef` or `ComponentDef` objects. This can cause unexpected
failures because the definition internally only expects `Type` objects
and now incorrectly tries to read the `ngDirectiveDef` or `ngComponentDef`
of existing definitions.
This issue has been unveiled by enabling the strict function parameter
types flag, where the directive definitions are determined from each array
element in the `directives` or `pipes` property (which can throw).
PR Close#30993
As part of FW-1265, the `@angular/compiler` package is made compatible
with the TypeScript `--strict` flag. This already unveiled a few bugs,
so the strictness flag seems to help with increasing the overall code health.
Read more about the strict flag [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html)
PR Close#30993
As part of FW-1265, the `@angular/core` package is made compatible
with the TypeScript `--strict` flag. This already unveiled a few bugs,
so the strictness flag seems to help with increasing the overall code health.
Read more about the strict flag [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html)
PR Close#30993
Previously, the usage of `null` and `undefined` keywords in code that is
statically interpreted by ngtsc resulted in a `DynamicValue`, as they were
not recognized as special entities. This commit adds support to interpret
these keywords.
PR Close#31150
The support for decorators that were imported via a namespace,
e.g. `import * as core from `@angular/core` was implemented
piecemeal. This meant that it was easy to miss situations where
a decorator identifier needed to be handled as a namepsaced
import rather than a direct import.
One such issue was that UMD processing of decorators was not
correct: the namespace was being omitted from references to
decorators.
Now the types have been modified to make it clear that a
`Decorator.identifier` could hold a namespaced identifier,
and the corresponding code that uses these types has been
fixed.
Fixes#31394
PR Close#31426
Fixes Ivy matching directives against attribute bindings (e.g. `[attr.some-directive]="foo"`). Works by excluding attribute bindings from the attributes array during compilation. This has the added benefit of generating less code.
**Note:** My initial approach to implementing this was to have a different marker for attribute bindings so that they can be ignored when matching directives, however as I was implementing it I realized that the attributes in that array were only used for directive matching (as far as I could tell). I decided to drop the attribute bindings completely, because it results in less generated code.
PR Close#31541
Data members in TypeScriptServiceHost of Map type should be eagerly
initialized to address issue/24571. This eliminates the need to
constantly check for truthiness and makes code much more readable.
More PRs to follow to address issue/24571.
PR Close#31577
Prior to this commit, default value for LOCALE_ID was not setup for Closure Compiler. In Closure Compiler, we can use `goog.LOCALE` as a default value, which will be replaced at build time with current locale.
PR Close#31519
Currently we reuse the same instruction both for regular property bindings and property bindings on the `host`. The only difference between the two is that when it's on the host we shouldn't support inputs. We have an optional parameter called `nativeOnly` which is used to differentiate the two, however since `nativeOnly` is preceeded by another optional parameter (`sanitizer`), we have to generate two extra parameters for each host property bindings every time (e.g. `property('someProp', 'someValue', null, true)`).
These changes add a new instruction called `hostProperty` which avoids the need for the two parameters by removing `nativeOnly` which is always set and it allows us to omit `sanitizer` when it isn't being used.
These changes also remove the `nativeOnly` parameter from the `updateSyntheticHostBinding` instruction, because it's only generated for host elements which means that we can assume that its value will always be `true`.
PR Close#31550
Add support for indexing elements in the indexing module.
Opening and self-closing HTML tags have their selector indexed, as well
as the attributes on the element and the directives applied to an
element.
PR Close#31240
If zonejs is sent undefined callbacks it proceeds to attempt to call them, then fails, catches it own fail, rewrites the stack to hide the mistake, and reports a TypeError with a callstack unrelated to inputs.
Throw early if the callback is undefined (as can happen if JS or any-ified TS calls zone invokeTask).
Check for undefined onCommplete callback to zonejs jasmine wrapper.
PR Close#31497
Switch back to passing a custom bazel host instead of rewriting one that
is passed to `compile` now that the Angular indexer is stable.
Revert "feat(bazel): allow passing and rewriting an old bazel host"
This reverts commit 0a4c1c8f803a65f5c156af90e67f7d7d68ebc7f8.
PR Close#31496
There are two places in the ngcc processing where it needs to load the
content of a file given by a general path:
* when determining the format of an entry-point.
To do this ngcc uses the value of the relevant property in package.json.
But in the case of `main` it must parse the contents of the entry-point
file to decide whether the format is UMD or CommonJS.
* when parsing the source files for dependencies to determine the order in
which compilation must occur. The relative imports in each file are parsed
and followed recursively, looking for external imports.
Previously, we naively assumed that the path would match the file name exactly.
But actually we must consider the standard module resolution conventions.
E.g. the extension (.js) may be missing, or the path may refer to a directory
containing an index.js file.
This commit fixes both places.
This commit now requires the `DependencyHost` instances to check
the existence of more files than before (at worst all the different possible
post-fixes). This should not create a significant performance reduction for
ngcc. Since the results of the checks will be cached, and similar work is
done inside the TS compiler, so what we lose in doing it here, is saved later
in the processing. The main performance loss would be where there are lots
of files that need to be parsed for dependencies that do not end up being
processed by TS. But compared to the main ngcc processing this dependency
parsing is a small proportion of the work done and so should not impact
much on the overall performance of ngcc.
// FW-1444
PR Close#31509
Prior to this fix, the logic to set the right placeholder format for ICUs was a bit incorrect: if there was a nested ICU in one of the root ICU cases, that led to a problem where placeholders in subsequent branches used the wrong ({$placeholder}) format instead of {PLACEHOLDER} one. This commit updates the logic to make sure we properly transform all placeholders even if nested ICUs are present.
PR Close#31516
Prior to this commit, it was impossible to override providers defined via ModuleWithProviders using TestBed.overrideProvider API. The problem was caused by the fact that we were not taking into account these providers while calculating accumulated set of provider overrides. This commit updates the logic to extract providers from ModuleWithProviders and calculate the final set of overrides taking them into account.
PR Close#31415
Since, 7186f9c01 `compiler-cli` is no longer depending on `shelljs` for
production code. (We still use it in tests and infrastructure/tooling.)
Incidentally, this should also help with #29460.
PR Close#31468
Removes direct calls from one instruction into another, moves the shared logic into a separate function and removes the state getters from the shared function.
This PR resolves FW-1340.
PR Close#31456
Previously, resource paths beginning with '/' (aka "rooted" paths, which
are not actually absolute filesystem paths, but are relative to the
TypeScript project root directory) were not handled correctly. The leading
'/' was stripped and the path was resolved as if it was relative, but with
no containing file for context. This led to resources in different rootDirs
not being found.
Instead, such rooted paths are now resolved without TypeScript's help, by
checking each root directory. A test is added to this effect.
PR Close#31511
When determining if a `main` path points to a UMD or CommonJS
format, the contents of the file need to be loaded and parsed.
Previously, it was assumed that the path referred to the exact filename,
but did not account for normal module resolution semantics, where the
path may be missing an extension or refer to a directory containing an
`index.js` file.
// FW-1444
PR Close#31509
Since `goog.getMsg` does not process ICUs (post-processing is required via goog.i18n.MessageFormat, https://google.github.io/closure-library/api/goog.i18n.MessageFormat.html) and placeholder format used for ICUs and regular messages inside `goog.getMsg` are different, the current implementation (that assumed the same placeholder format) needs to be updated. This commit updates placeholder format used inside ICUs from `{$placeholder}` to `{PLACEHOLDER}` to better align with Closure. ICU placeholders (that were left as is prior to this commit) are now replaced with actual values in post-processing step (inside `i18nPostprocess`).
PR Close#31459
Prior to this commit, the `` unicode symbol that represents `&ngsp` in translations was not handled correctly, i.e. was not replaced with a whitespace, thus appearing on a screen. This commit adds post-processing and replaces the mentioned symbol with a whitespace.
PR Close#31479
This commit adds a test that verifies no translations are generated for bound attributes and also checks (as a part of the `verify` function) that VE and Ivy handle this case the same way.
PR Close#31481
`i18nStart` was calling `allocExpando` even if there was 0 new variable created.
This created a new expando instruction with the value 0 which was later interpreted as the start of a new expando block instead of just skipping 0 instructions.
FW-1417 #resolve
PR Close#31451
Fixes Ivy's return value for `DebugNode.context` not being consistent for the case where there is both a structural directive and a component on a node. In `ViewEngine` the instance of the component would be returned, whereas in Ivy the context of the directive is returned.
Also adds a couple of extra test cases for how `DebugNode.context` deals with directives.
This PR resolves FW-1343.
PR Close#31442
Adds a new `elementContainer` instruction that can be used to avoid two instruction (`elementContainerStart` and `elementContainerEnd`) for `ng-container` that has text-only content. This is particularly useful when we have `ng-container` inside i18n sections.
This PR resolves FW-1105.
PR Close#31444
Paths can be mapped directly to files, which was not being taken
into account when computing `basePaths` for the `EntryPointFinder`s.
Now if a `pathMapping` pattern does not exist or is a file, then we try
the containing folder instead.
Fixes#31424
PR Close#30525
Previously, ngcc had to walk the entire `node_modules` tree looking for
entry-points, even if it only needed to process a single target entry-point
and its dependencies.
This added up to a few seconds to each execution of ngcc, which is noticeable
when being run via the CLI integration.
Now, if an entry-point target is provided, only that target and its entry-points
are considered rather than the whole folder tree.
PR Close#30525
When profiling ngcc it is notable that a large amount of time
is spent dealing with an exception that is thrown (and handled
internally by fs) when checking the existence of a file.
We check file existence a lot in both finding entry-points
and when TS is compiling code. This commit adds a simple
cached `FileSystem`, which wraps a real `FileSystem` delegate.
This will reduce the number of calls through to `fs.exists()` and
`fs.readFile()` on the delegate.
Initial benchmarks indicate that the cache is miss to hit ratio
for `exists()` is about 2:1, which means that we save about 1/3
of the calls to `fs.existsSync()`.
Note that this implements a "non-expiring" cache, so it is not suitable
for a long lived `FileSystem`, where files may be modified externally.
The cache will be updated if a file is changed or moved via
calls to `FileSystem` methods but it will not be aware of changes
to the files system from outside the `FileSystem` service.
For ngcc we must create a new `FileSystem` service
for each run of `mainNgcc` and ensure that all file operations
(including TS compilation) use the `FileSystem` service.
This ensures that it is very unlikely that a file will change
externally during `mainNgcc` processing.
PR Close#30525
This message gets called if a format has already been
compiled and we only want the first. So the message itself
is wrong but it is also not very useful anyway.
PR Close#30525
The ngcc tool adds namespaced imports to files when compiling. The ngtsc
tooling was not processing types correctly when they were imported via
such namespaces. For example:
```
export declare class SomeModule {
static withOptions(...): ModuleWithProviders<ɵngcc1.BaseModule>;
```
In this case the `BaseModule` was being incorrectly attributed to coming
from the current module rather than the imported module, represented by
`ɵngcc1`.
Fixes#31342
PR Close#31367
If a package delcares a class internally on an NgModule, ngcc
needs to be able to add a public export to this class's type.
Previously, if the typing file for the declared is not imported
from the typings entry-point file, then ngcc cannot find it.
Now we try to guess the .d.ts files from the equivalent .js
files.
PR Close#31411
This partially reverts some changes from 71b9371180 (diff-dd469785fca8680a5b33b1e81c5cfd91R1420)
These broke the g3sync of zone.js because we use the output of the TypeScript compiler directly, rather than rely on the rollup commonjs plugin to define the global symbol
PR Close#31453
Non-wild-card path-mappings were not being matched correctly.
Further path-mapped secondary entry-points that
were imported from the associated primary entry-point were not
being martched correctly.
Fixes#31274
PR Close#31450
This is needed in g3 where the translation system is sensitive to the full path of the output.
For Bazel users, we don't want this because it would force them to
disable a Bazel option that prevents using the deprecated ctx.new_file
API
PR Close#31410
Adds a schematic and tslint rule that automatically migrate the consumer from `Renderer` to `Renderer2`. Supports:
* Renaming imports.
* Renaming property and method argument types.
* Casting to `Renderer`.
* Mapping all of the methods from the `Renderer` to `Renderer2`.
Note that some of the `Renderer` methods don't map cleanly between renderers. In these cases the migration adds a helper function at the bottom of the file which ensures that we generate valid code with the same return value as before. E.g. here's what the migration for `createText` looks like.
Before:
```
class SomeComponent {
createAndAddText() {
const node = this._renderer.createText(this._element.nativeElement, 'hello');
node.textContent += ' world';
}
}
```
After:
```
class SomeComponent {
createAndAddText() {
const node = __rendererCreateTextHelper(this._renderer, this._element.nativeElement, 'hello');
node.textContent += ' world';
}
}
function __rendererCreateTextHelper(renderer: any, parent: any, value: any) {
const node = renderer.createText(value);
if (parent) {
renderer.appendChild(parent, node);
}
return node;
}
```
This PR resolves FW-1344.
PR Close#30936
Updates the decision made in #31341; this is for the Angular indexer
inside Google. The indexer currently passes (and ngc-wrapped#compile
accepts) a bazel host to use, but because many methods are overwritten
specially for Angular compilation a better approach is to pass an old
bazel compiler host and siphon methods needed off of it before creating
a new host. This enables that.
PR Close#31381
Adds the new `classMapInterpolate1` through `classMapInterpolate8` instructions which handle interpolations inside the `class` attribute and moves the interpolation logic internally. This allows us to remove the `interpolationX` instructions in a follow-up PR.
These changes also add an error if an interpolation is encountered inside a `style` tag (e.g. `style="width: {{value}}"`). Up until now this would actually generate valid instructions, because `styleMap` goes through the same code path as `classMap` which does support interpolation. At runtime, however, `styleMap` would set invalid styles that look like `<div style="0:w;1:i;2:d;3:t;4:h;5::;7:1;">`. In `ViewEngine` interpolations inside `style` weren't supported either, however there we'd output invalid styles like `<div style="unsafe">`, even if the content was trusted.
PR Close#31211
There's no build time dependency from @angular/core to @angular/compiler,
so core can't directly refer to compiler types. To overcome this limitation,
there's a facade layer defined in the compiler and duplicated in core,
such that during runtime all types will correctly align.
There's a testcase in the compiler that verifies that all such facade types
are compatible across core and compiler, such that the core types can't get
misaligned with the actual definitions in the compiler. This suite of
tests were missing the `R3BaseMetadataFacade` facade type, so it was possible
for this type to get out of sync.
PR Close#31210
When a class uses Angular decorators such as `@Input`, `@Output` and
friends without an Angular class decorator, they are compiled into a
static `ngBaseDef` field on the class, with the TypeScript declaration
of the class being altered to declare the `ngBaseDef` field to be of type
`ɵɵBaseDef`. This type however requires a generic type parameter that
corresponds with the type of the class, however the compiler did not
provide this type parameter. As a result, compiling a program where such
invalid `ngBaseDef` declarations are present will result in compilation
errors.
This commit fixes the problem by providing the generic type parameter.
Fixes#31160
PR Close#31210
after update to rules_nodejs 0.32.1, @types are no longer automatically discovered by ngc-wrapped (which uses parts of ts_library) so this test needed updating so that the types files it generates is added as an explicit dep
PR Close#31325
...tsetse now falsely asserting on some lines in a few tests such as packages/core/schematics/test/injectable_pipe_migration_spec.ts.
```
await runMigration();
expect(tree.readContent('/index.ts'))
```
it asserts that "await is required on promise" on the 2nd line when there is no promise there
PR Close#31325
Brings in ts_library fixes required to get angular/angular building after 0.32.0:
typescript: exclude typescript lib declarations in node_module_library transitive_declarations
typescript: remove override of @bazel/tsetse (+1 squashed commit)
@npm//node_modules/foobar:foobar.js labels changed to @npm//:node_modules/foobar/foobar.js with fix for bazelbuild/rules_nodejs#802
also updates to rules_rass commit compatible with rules_nodejs 0.32.0
PR Close#31325
ctx.actions.declare_file now used in @angular/bazel ng_module rule as ctx.new_file is now deprecated. Fixes error:
```
File "ng_module.bzl", line 272, in _expected_outs
ctx.new_file(ctx.genfiles_dir, (ctx.label.name ..."))
Use ctx.actions.declare_file instead of ctx.new_file.
Use --incompatible_new_actions_api=false to temporarily disable this check.
```
This can be worked around with incompatible_new_actions_api flag but may as well fix it proper so downstream doesn't require this flag due to this code.
Also, depset() is no longer iterable by default without a flag. This required fixing in a few spots in @angular/bazel.
fix: foo
PR Close#31325
Some formats of CommonJS put the decorator helper calls
outside the class IIFE as statements on the top level of the
source file.
This commit adds support to the `CommonJSReflectionHost`
for this format.
PR Close#31335
Prior to this commit, host element of a view created via TestBed.createComponent was not attached to the component's host, making it problematic to use TestBed.createComponent API in component factories, which might be used for testing purposes only. This behavior is observed in google3 app tests and was supported by VE, so this commit aligns Ivy and VE.
PR Close#31318
Enable users to pass a custom Bazel CompilerHost to use for an Angular
compilation. This supports users who must override the TypeScript
compiler host.
PR Close#31341
Adds chaining to the `property`, `attribute` and `updateSyntheticHostBinding` instructions when they're used in a host binding.
This PR resolves FW-1404.
PR Close#31296
Without this change when using UrlTree redirects in `urlUpdateStrategy="eager"`, the URL would get updated to the target location, then redirected. This resulted in having an additional entry in the `history` and thus the `back` button would be broken (going back would land on the URL causing a new redirect).
Additionally, there was a bug where the redirect, even without `urlUpdateStrategy="eager"`, could create a history with too many entries. This was due to kicking off a new navigation within the navigation cancelling logic. With this PR the new navigation is pushed to the next tick with a `setTimeout`, allowing the page being redirected from to be cancelled before starting a new navigation.
Related to #27148
PR Close#31168
When `walkTNodeTree` was refactored, the case of ICU expressions was forgotten (because it was handled in the `else` previously).
This PR fixes that to handle it like `ElementContainer`.
FW-1411 #resolve
PR Close#31313
The TS compiler is likely to test paths with extensions and try to
load them as files. Therefore `fileExists()` and methods that rely
on it need to be able to distinguish between real files and directories
that have paths that look like files.
This came up as a bug in ngcc when trying to process `ngx-virtual-scroller`,
which relies upon a library called `@tweenjs/tween.js`.
PR Close#31289
Previously, (presummably due to a typo) the `okToCacheOpaque` argument
of `DataGroup#cacheResponse()` was essentially never taken into account
(since opaque responses have a non-200 status code and thus `res.ok` is
always false).
This commit fixes the typo, which allows opaque responses to be cached
when `okToCacheOpaque` is true (i.e. in data groups using the
`freshness` strategy).
Fixes#30968
PR Close#30977
This commit doesn't change the behavior wrt caching, but it makes it
more explicit that only non-timed-out responses are cached. In case of a
timeout, `res` would be set to a programmatically created 504
`Response`, so `cacheResponse()` (which checks for `res.ok`) would not
have cached it anyway, but this makes change makes it more explicit (and
more similar to the equivalent part in [handleFetchWithFreshness()][1]).
[1]: https://github.com/angular/angular/blob/2b4d5c754/packages/service-worker/worker/src/data.ts#L379-L388
PR Close#30977
Previously, opaque responses where handled a little differently than
other responses from the mock server. More specifically, they were not
tracked (so no assertions could be made for them) and their
[`Body` mixin][1] methods (such as `arrayBuffer()`, `json()`, `text()`)
would throw an error due to `body` being `null`.
This commit ensures opaque responses are also captured on the mock
server and also changes `Body` mixin methods to better simulate the
[spec'd behavior][2].
(These improvements will be necessary to test caching of opaque
responses in a subsequent commit.)
[1]: https://developer.mozilla.org/en-US/docs/Web/API/Body
[2]: https://fetch.spec.whatwg.org/#concept-body-consume-body
PR Close#30977
Currently in Ivy whenever we encounter a new namespace, we set it in the global state so that all subsequent nodes are created under the same namespace. Next time a template is run the namespace will be reset back to HTML.
This breaks down if the last node that was rendered was under the SVG or MathML namespace and we create a component through `ViewContainerRef.create`, because the next template function hasn't run yet and it hasn't had the chance to update the namespace. The result is that the root node of the new component will retain the wrong namespace and may not end up rendering at all (e.g. if we're trying to show a `div` inside the SVG namespace). This issue has the potential to affect a lot of apps, because all components inserted through the router also go through `ViewContainerRef.create`.
PR Close#31232
These files have not been formatted properly, due to issues in the
`gulp format*` tasks. See previous commits (or #31295) for more details.
PR Close#31295
If an entry-point has missing dependencies then it cannot be
processed and is marked as invalid. Similarly, if an entry-point
has dependencies that have been marked as invalid then that
entry-point too is invalid. In all these cases, ngcc should quietly
ignore these entry-points and continue processing what it can.
Previously, if an entry-point had more than one entry-point that
was transitively invalid then ngcc was crashing rather than
ignoring the entry-point.
PR Close#31276
The Angular runtime frequently calls into user code (for example, when
writing to a property binding). Since user code can throw errors, calls to
it are frequently wrapped in a try-finally block. In Ivy, the following
pattern is common:
```typescript
enterView();
try {
callUserCode();
} finally {
leaveView();
}
```
This has a significant problem, however: `leaveView` has a side effect: it
calls any pending lifecycle hooks that might've been scheduled during the
current round of change detection. Generally it's a bad idea to run
lifecycle hooks after the application has crashed. The application is in an
inconsistent state - directives may not be instantiated fully, queries may
not be resolved, bindings may not have been applied, etc. Invariants that
the app code relies upon may not hold. Further crashes or broken behavior
are likely.
Frequently, lifecycle hooks are used to make assertions about these
invariants. When these assertions fail, they will throw and "swallow" the
original error, making debugging of the problem much more difficult.
This commit modifies `leaveView` to understand whether the application is
currently crashing, via a parameter `safeToRunHooks`. This parameter is set
by modifying the above pattern:
```typescript
enterView();
let safeToRunHooks = false;
try {
callUserCode();
safeToRunHooks = true;
} finally {
leaveView(..., safeToRunHooks);
}
```
If `callUserCode` crashes, then `safeToRunHooks` will never be set to `true`
and `leaveView` won't call any further user code. The original error will
then propagate back up the stack and be reported correctly. A test is added
to verify this behavior.
PR Close#31244
Our module resolution prefers `.js` files over `.d.ts` files because
occasionally libraries publish their typings in the same directory
structure as the compiled JS files, i.e. adjacent to each other.
The standard TS module resolution would pick up the typings
file and add that to the `ts.Program` and so they would be
ignored by our analyzers. But we need those JS files, if they
are part of the current package.
But this meant that we also bring in JS files from external
imports from outside the package, which is not desired.
This was happening for the `@fire/storage` enty-point
that was importing the `firebase/storage` path.
In this commit we solve this problem, for the case of imports
coming from a completely different package, by saying that any
file that is outside the package root directory must be an external
import and so we do not analyze those files.
This does not solve the potential problem of imports between
secondary entry-points within a package but so far that does
not appear to be a problem.
PR Close#30591
Rather than passing a number of individual arguments, we can
just pass an `EntryPointBundle`, which already contains them.
This is also a precursor to using more of the properties in the bundle.
PR Close#30591
This will allow users of the `EntryPointBundle` to use some of the `EntryPoint`
properties without us having to pass them around one by one.
PR Close#30591
Previously we expected the constructor parameter `decorators`
property to be an array wrapped in a function. Now we also support
an array not wrapped in a function.
PR Close#30591
Some packages do not actually provide a `typings` field in their
package.json. But TypeScript naturally infers the typings file from
the location of the JavaScript source file.
This commit modifies ngcc to do a similar inference when finding
entry-points to process.
Fixes#28603 (FW-1299)
PR Close#30591
There are scenarios where it is not possible for ngcc to guess the format
or configuration of an entry-point just from the files on disk.
Such scenarios include:
1) Unwanted entry-points: A spurious package.json makes ngcc think
there is an entry-point when there should not be one.
2) Deep-import entry-points: some packages allow deep-imports but do not
provide package.json files to indicate to ngcc that the imported path is
actually an entry-point to be processed.
3) Invalid/missing package.json properties: For example, an entry-point
that does not provide a valid property to a required format.
The configuration is provided by one or more `ngcc.config.js` files:
* If placed at the root of the project, this file can provide configuration
for named packages (and their entry-points) that have been npm installed
into the project.
* If published as part of a package, the file can provide configuration
for entry-points of the package.
The configured of a package at the project level will override any
configuration provided by the package itself.
PR Close#30591
Previously each test relied on large shared mock file-systems, which
makes it difficult to reason about what is actually being tested.
This commit breaks up these big mock file-systems into smaller more
focused chunks.
PR Close#30591
To improve cross platform support, all file access (and path manipulation)
is now done through a well known interface (`FileSystem`).
For testing a number of `MockFileSystem` implementations are provided.
These provide an in-memory file-system which emulates operating systems
like OS/X, Unix and Windows.
The current file system is always available via the static method,
`FileSystem.getFileSystem()`. This is also used by a number of static
methods on `AbsoluteFsPath` and `PathSegment`, to avoid having to pass
`FileSystem` objects around all the time. The result of this is that one
must be careful to ensure that the file-system has been initialized before
using any of these static methods. To prevent this happening accidentally
the current file system always starts out as an instance of `InvalidFileSystem`,
which will throw an error if any of its methods are called.
You can set the current file-system by calling `FileSystem.setFileSystem()`.
During testing you can call the helper function `initMockFileSystem(os)`
which takes a string name of the OS to emulate, and will also monkey-patch
aspects of the TypeScript library to ensure that TS is also using the
current file-system.
Finally there is the `NgtscCompilerHost` to be used for any TypeScript
compilation, which uses a given file-system.
All tests that interact with the file-system should be tested against each
of the mock file-systems. A series of helpers have been provided to support
such tests:
* `runInEachFileSystem()` - wrap your tests in this helper to run all the
wrapped tests in each of the mock file-systems.
* `addTestFilesToFileSystem()` - use this to add files and their contents
to the mock file system for testing.
* `loadTestFilesFromDisk()` - use this to load a mirror image of files on
disk into the in-memory mock file-system.
* `loadFakeCore()` - use this to load a fake version of `@angular/core`
into the mock file-system.
All ngcc and ngtsc source and tests now use this virtual file-system setup.
PR Close#30921
No longer uses docker in order to pull down the toolchain configs
for remote build execution. We don't need to make docker a prerequisite
for working on the Angular repository since we can leverage the checked-in
toolchain configurations from the `@bazel-toolchains` repository.
PR Close#31251
Prior to this commit, the logic to extract query information from class fields used an instance of regular Error class to throw an error. As a result, some useful information (like reference to a specific field) was missing. Replacing Error class with FatalDiagnosticError one makes the error more verbose that should simplify debugging.
PR Close#31123
after update to rules_nodejs 0.32.1, @types are no longer automatically discovered by ngc-wrapped (which uses parts of ts_library) so this test needed updating so that the types files it generates is added as an explicit dep
PR Close#31019
...tsetse now falsely asserting on some lines in a few tests such as packages/core/schematics/test/injectable_pipe_migration_spec.ts.
```
await runMigration();
expect(tree.readContent('/index.ts'))
```
it asserts that "await is required on promise" on the 2nd line when there is no promise there
PR Close#31019
Brings in ts_library fixes required to get angular/angular building after 0.32.0:
typescript: exclude typescript lib declarations in node_module_library transitive_declarations
typescript: remove override of @bazel/tsetse (+1 squashed commit)
@npm//node_modules/foobar:foobar.js labels changed to @npm//:node_modules/foobar/foobar.js with fix for bazelbuild/rules_nodejs#802
also updates to rules_rass commit compatible with rules_nodejs 0.32.0
PR Close#31019
ctx.actions.declare_file now used in @angular/bazel ng_module rule as ctx.new_file is now deprecated. Fixes error:
```
File "ng_module.bzl", line 272, in _expected_outs
ctx.new_file(ctx.genfiles_dir, (ctx.label.name ..."))
Use ctx.actions.declare_file instead of ctx.new_file.
Use --incompatible_new_actions_api=false to temporarily disable this check.
```
This can be worked around with incompatible_new_actions_api flag but may as well fix it proper so downstream doesn't require this flag due to this code.
Also, depset() is no longer iterable by default without a flag. This required fixing in a few spots in @angular/bazel.
fix: foo
PR Close#31019
Add an IndexingContext class to store indexing information and a
transformer module to generate indexing analysis. Integrate the indexing
module with the rest of NgtscProgram and add integration tests.
Closes#30959
PR Close#31151
Previously, the usage of equality operators ==, ===, != and !== was not
supported in ngtsc's static interpreter. This commit adds support for
such operators and includes tests.
Fixes#31076
PR Close#31145
Since Angular v8, and commit b3dda0e, `parseUrl()` can be called without
`relativeTo`, thus `new URL()` can be called with `relativeTo = undefined`.
Safari does not like it and the service worker registration fails:
```js
new URL('https://angular.io/') // OK
new URL('https://angular.io/', undefined) // TypeError
```
Closes#31061
PR Close#31140
Under Bazel, we don't yet support Stylus and Less, and thus we should not offer the users to generate applications which are known not to work.
Closes#31209
PR Close#31234
In ViewEngine injecting a Renderer2 returns a renderer that is specific to the particular component, however in Ivy we inject the renderer for the parent view instead. This causes it to set incorrect `ngcontent` attributes when creating elements through the renderer.
The issue comes from the fact that the `Renderer2` is created according to the current `LView`, but because DI happens before we've entered the `LView` of the component that's injecting the renderer, we end up with one that's one level up. We work around the issue by finding the `LView` that corresponds to the `previousOrParentTNode` inside of the parent view and associating the `Renderer2` with it.
This PR resolves FW-1382.
PR Close#31063
Change the Element constructor in r3_ast to create a new ParseSourceSpan when regenerating it rather than extending an object, which does not contain the overloaded toString().
PR Close#31190
Previously, multiple ViewContainerRef instances (obtained by injecting
ViewContainerRef multiple times) each had private state that could be out of
sync with actual LContainer, if views were inserted/removed/queried across
the different instances. In particular each instance had its own array which
tracked ViewRefs inserted via that instance.
This commit moves the ViewRefs array onto the LContainer itself, so that it
can be shared across multiple ViewContainerRef instances. A test is added
that verifies ViewContainerRefs now provide a consistent view of the
container.
FW-1377 #resolve
PR Close#30985
Optimizations to skip compiling source files that had not changed
did not account for the case where only a resource file changes,
such as an external template or style file.
Now we track such dependencies and trigger a recompilation
if any of the previously tracked resources have changed.
This will require a change on the CLI side to provide the list of
resource files that changed to trigger the current compilation by
implementing `CompilerHost.getModifiedResourceFiles()`.
Closes#30947
PR Close#30954
The function `bind` has been internalized wherever it was needed, this PR makes sure that it is no longer publicly exported.
FW-1385 #resolve
PR Close#31131
Adds two new helper functions that can be used when unit testing Angular services
that depend upon upgraded AngularJS services, or vice versa.
The functions return a module (AngularJS or NgModule) that is configured to wire up
the Angular and AngularJS injectors without the need to actually bootstrap a full
hybrid application.
This makes it simpler and faster to unit test services.
PR Close#16848
This commit fixes a couple of issues with TS 3.5 compatibility in order to
unblock migration of g3. Mostly 'any's are added, and there are no behavior
changes.
PR Close#31174
Move the definition leadingTriviaChars included in parsing a template
to the parameters of parseTemplate. This allows overriding of the
default leadingTriviaChars, which is needed by some pipelines like the
indexing pipeline because leadingTriviaChars may throw off the recorded
span of selectors.
PR Close#31136
Currently the `RecursiveAstVisitor` that is part of the template expression
parser does not _always_ properly pass through the context that can be
specified when visting a given expression. Only a handful of AST types
pass through the context while others are accidentally left out. This causes
unexpected and inconsistent behavior and basically makes the `context`
parameter not usable if the type of template expression is not known.
e.g. the template variable assignment migration currently depends on
the `RecursiveAstVisitor` but sometimes breaks if developers use
things like conditionals in their template variable assignments.
Fixes#31043
PR Close#31085
A temporary check is in place to determine whether a key in an object
literal needs to be quoted during emit. Previously, only the presence of
a dash caused a key to become quoted, this however is not sufficient for
@angular/flex-layout to compile properly as it has dots in its inputs.
This commit extends the check to also use quotes when a dot is present.
Fixes#30114
PR Close#31146
Currently the `placeholders` parameter inside `i18nLocalize` is defaulted to `{}`, which means that we'll always hit the `Object.keys` call below. Since it's very likely that we won't have placeholders in the majority of strings, these changes add an extra guard so that we don't hit it on every invocation.
PR Close#31106
Currently each property binding generates an instruction like this:
```
property('prop1', ctx.value1);
property('prop2', ctx.value2);
```
The problem is that we're repeating the call to `property` for each of the properties. Since the `property` instruction returns itself, we can chain all of the calls which is more compact and it looks like this:
```
property('prop1', ctx.value1)('prop2', ctx.value2);
```
These changes implement the chaining behavior for regular property bindings and for synthetic ones, however interpolated ones are still handled like before, because they use a separate instruction.
This PR resolves FW-1389.
PR Close#31078
```
NgLSHost: AngularLanguageServiceHost
NgLS: AngularLanguageService
```
NgLSHost should not depend on NgLS, because it introduces circular
dependency.
Instead, the `getTemplateAst` and `getTemplatAstAtPosition` methods should
be moved to NgLSHost and exposed as public methods.
This removes the circular dependency, and also removes the need for the
awkward 'setSite' method in NgLSHost.
PR Close#31122
* Updates buildifier to a version that also comes with windows binaries.
* Fixes a few new formatting/lint warnings
* Removes the `args-order` warning because it is no longer a warning.. and is now part of the formatter.
PR Close#31112
Add support for indexing of property reads, method calls in a template.
Visit AST of template syntax expressions to extract identifiers.
Child of #30959
PR Close#30963
i18nExp now uses `bind` internally rather than having the compiler generate it in order to bring it in line with other functions like `textBinding` & `property`.
FW-1384 #resolve
PR Close#31089
When using `createEmbeddedView` after the creation of an ICU expression, the nodes for the current selected case were not reprojected (only the anchor comment node was moved to the new location).
Now we reproject correctly all the child nodes of an ICU expression when an anchor comment node is projected.
FW-1372 #resolve
PR Close#30979
The generated Bazel workspace by the `@angular/bazel` builder should
use the latest stable NodeJS version. This is necessary because some
packages like `selenium-webdriver` which are part of the default bazel
setup in order to support `ng e2e` depend on a minimum NodeJS version
of `10.15.0`.. This means that running e2e tests in a plain new bazel CLI
project (`ng new {projectName} --collection=@angular/bazel`) errors.
```
command.
(error selenium-webdriver@4.0.0-alpha.3: The engine "node" is incompatible with
this module. Expected version ">= 10.15.0". Got "10.13.0"
error Found incompatible module
)
```
PR Close#31088
Packages that have been compiled using an older version of TypeScript
can have their decorators at the top-level of the ES5 bundles, instead
of inside the IIFE that is emitted for the class. Before this change,
ngcc only took static property assignments inside the IIFE into account,
therefore missing the decorators that were assigned at the top-level.
This commit extends the ES5 host to look for static properties in two
places. Testcases for all bundle formats that contain ES5 have been added
to ensure that this works in the various flavours.
A patch is included to support UMD bundles. The UMD factory affects how
TypeScripts binds the static properties to symbols, see the docblock of
the patch function for more details.
PR Close#30795
- Splits core functionality off into a shared internal function
- ɵɵtextBinding will no longer require an index
- Alters the compiler to stop generating an index argument for the instruction
- Updates tests
- Updates some usage of ɵɵtextBinding in i18n to use the helper function instead
PR Close#30792
The DI's `locateDirectiveOrProvider` function operates on `TView` / `TNode`
data structures only so doesn't need to access `LView`. This refactoring
changes the argument list so the mentioned function takes less info to do
its work.
This refactoring is also mandatory for the upcoming query matching move
to TView.
PR Close#31006
Currently in Ivy we throw when attempting to destroy a `ComponentRef` that has been destroyed, however in ViewEngine we didn't which can cause some tests to break. These changes remove the error to match ViewEngine.
These changes resolve FW-1379.
PR Close#31022
The `EntryPointFinder` computes the base paths to consider
when searching for entry-points. When there are `pathMappings`
provided it works out the best top level base-paths that cover all
the potential mappings.
If this computed basePath happens to coincide with an entry-point
path itself then we were missing it.
Now we check for an entry-point even at the base-path itself.
Related to https://github.com/angular/angular-cli/pull/14755
PR Close#31027
Commit 58be2ff884 has been created
before c0386757b1 landed, and therefore
the newly created compliance test was using an outdated expectation.
This commit updates the compliance test to no longer contain
the outdated expectation.
PR Close#30983
To provide some context: The implicit receiver is part of the
parsed Angular template AST. Any property reads in bindings,
interpolations etc. read from a given object (usually the component
instance). In that case there is an _implicit_ receiver which can also
be specified explicitly by just using `this`.
e.g.
```html
<ng-template>{{this.myProperty}}</ng-template>
```
This works as expected in Ivy and View Engine, but breaks in case the
implicit receiver is not used for property reads. For example:
```html
<my-dir [myFn]="greetFn.bind(this)"></my-dir>
```
In that case the `this` will not be properly translated into the generated
template function code because the Ivy compiler currently always treats
the `ctx` variable as the implicit receiver. This is **not correct** and breaks
compatibility with View Engine. Rather we need to ensure that we retrieve
the root context for the standalone implicit receiver similar to how it works
for property reads (as seen in the example above with `this.myProperty`)
Note that this requires some small changes to the `expression_converter`
because we only want to generate the `eenextContent()` instruction if the
implicit receiver is _actually_ used/needed. View Engine determines if that is the case by recursively walking through the converted output AST and
checking for usages of the `o.variable('_co')` variable ([see here][ve_check]). This would work too for Ivy, but involves most likely more code duplication
since templates are isolated in different functions and it another pass
through the output AST for every template expression.
[ve_check]: 0d6c9d36a1/packages/compiler/src/view_compiler/view_compiler.ts (L206-L208)
Resolves FW-1366.
PR Close#30897
In a derived service class with no decorator (and therefore no factory) of
its own, the factory function of the base class will be used instead.
Previously this logic had a bug where the factory function would be called
with no arguments, which would incorrectly create an instance of the base
class.
This commit adds logic to call the base class' factory and pass the type of
the derived class, which will correctly construct an instance of the
derived class using the base class' factory. A test is also added to verify
correctness of this behavior.
PR Close#30855
Factory functions written by the compiler optionally allow an explicit type
to be passed. If called with this type, an instance of the given type will
be created instead of the type for which the factory was generated. This is
used to power inheritance of Angular types, as if the constructor of a class
is inherited from its superclass, then the factory function of the
superclass must be used (it has all the DI info) to construct an instance of
the derived class.
This commit adjusts typings in a few places to allow factory functions to be
called with this extra type parameter.
PR Close#30855
In older browsers such as IE10, inheritance of static properties on class
types is implemented by copying the properties. This makes hasOwnProperty
unreliable for checking if a static property is defined directly on a class
or is inherited. This causes problems when trying to read the
ngInjectableDef properties of inherited services, as in IE10 even inherited
definitions will appear to be local.
Instead, the 'token' property on ngInjectableDef can be leveraged to detect
when a definition is read which doesn't belong to the type itself.
PR Close#30855
The compiler generates a 'token' field when it emits an ngInjectableDef,
but this field was not required by defineInjectable or the InjectableDef
interface, nor was it added by InjectionToken.
This commit makes 'token' required and adds it where missing.
PR Close#30855
Before this change, user's tsconfig.json is cloned and some options
controlled by Bazel are removed otherwise Bazel would complain about:
```
WARNING: your tsconfig.json file specifies options which are overridden by Bazel:
- compilerOptions.target and compilerOptions.module are controlled by downstream dependencies, such as ts_devserver
- compilerOptions.typeRoots is always set to the @types subdirectory of the node_modules attribute
- compilerOptions.rootDir and compilerOptions.baseUrl are always the workspace root directory
```
Since the warning has been removed in rules_typescript/8d8d398, there's no
need to clone and backup tsconfig.json
PR Close#30877
17d87d4e10 has been created before the changes
to the `@ViewChild` and `@ContentChild` decorators. Meaning that it still uses the queries
without the `static` flag. This results in failures in `master` because #30625 has been merged.
PR Close#30967
9d9c9e43e5 has been created a few days ago
and wasn't rebased on top of recent changes that introduces a commonjs host.
This means that tests for the commonjs host haven't been updated to work with
the changes from from #30492 and now fail in `master`.
PR Close#30967
Currently undecorated classes are intentionally not processed
with ngcc. This is causing unexpected behavior because decorator
handlers such as `base_def.ts` are specifically interested in class
definitions without top-level decorators, so that the base definition
can be generated if there are Angular-specific class members.
In order to ensure that undecorated base-classes work as expected
with Ivy, we need to run the decorator handlers for all top-level
class declarations (not only for those with decorators). This is similar
to when `ngtsc` runs decorator handlers when analyzing source-files.
Resolves FW-1355. Fixes https://github.com/angular/components/issues/16178
PR Close#30821
When determining the module type of a bundle pointed to by the "main"
property, ngcc needs to read the bundle to figure out if it is CommonJS
or UMD format. However, when the "main" property does not exist ngcc
would crash while determining the path to the main bundle file.
This commit fixes the crash by checking if the "main" property is present
at all, before attempting to derive a full path to the bundle file.
Fixes#30916
Fixes FW-1369
PR Close#30950
`TView.firstChild` was defined as the first node with index 0, but when we use runtime i18n then the instruction `i18nStart` can be the one with index 0 and the first node will be index 1 or more.
With this fix we set `TView.firstChild` when we see the first node with index 0 or later if `TView.firstChild` is still null.
FW-1367 #resolve
PR Close#30920
* entry_point attribute of nodejs_binary & rollup_bundle is now a label
* symlinking of node_modules for yarn_install temporarily disabled (except for integration/bazel) until the fix for https://github.com/bazelbuild/bazel/issues/8487 makes it into a future bazel release
PR Close#30627
nodejs rules 0.30.1 has new feature to symlink node_modules with yarn_install and bazel 0.26.0 includes new managed_directories feature which enables this
PR Close#30627
This work is being done ahead of changes to how view insertion is done in Ivy in accordance with [this design document](https://hackmd.io/Ae3W_2pOQlKouu9YNy1t6A?view).
The idea is to make sure we have acceptance tests ahead of that change.
PR Close#30625
The usage of array spread syntax in source code may be downleveled to a
call to TypeScript's `__spread` helper function from `tslib`, depending
on the options `downlevelIteration` and `emitHelpers`. This proves
problematic for ngcc when it is processing ES5 formats, as the static
evaluator won't be able to interpret those calls.
A custom foreign function resolver is not sufficient in this case, as
`tslib` may be emitted into the library code itself. In that case, a
helper function can be resolved to an actual function with body, such
that it won't be considered as foreign function. Instead, a reflection
host can now indicate that the definition of a function corresponds with
a certain TypeScript helper, such that it becomes statically evaluable
in ngtsc.
Resolves#30299
PR Close#30492
- Refactors compiler to stop generating `ɵɵselect(0)` instructions
- Alters template execution to always call the equivalent of `ɵɵselect(0)` before running a template in update mode
- Updates tests to not check for or call `ɵɵselect(0)`.
The goal here is to reduce the size of generated templates
PR Close#30830
Service worker API `navigator.serviceWorker.register` can fail in multiple ways.
For example, in Chrome, with an unstable network connection you can have the
following error: `An unknown error occurred when fetching the script.`
In the current state, it creates an `Uncaught (in promise) TypeError:` style of
error, which cannot be caught by the user on his own.
I think it's better to log the error over raising an error that cannot be
caught.
PR Close#30876
The `renderStringify` function shows up pretty high in the CPU profiling.
Turns out that this function contained unnecessary `typeof` check for
function types - the check only makes sense / is used in error messages.
The PR also alligns how ivy and view engine stringify functions used in
interpolations.
PR Close#30838
In Ivy the `DebugNode.attributes` is populated directly from the DOM, but the problem is that the browser will lowercase all attribute names. These changes preserve the case by first going through the `TNode.attrs`, populating the map with the case-sensitive names and saving a reference to the lower case name. Afterwards when we're going through the attributes from the DOM, we can check whether we've mapped the attribute by its case-sensitive name already.
This PR resolves FW-1358.
PR Close#30864
A directive input that doesn't use a binding is triggered during the creation phase. But this was only executed at the first template pass, and not on subsequent ones.
Now only the creation of the update instruction is executed on the first template pass, anything else is executed every time a template is created.
FW-1361 #resolve
PR Close#30870
When translated content was projected, all of the content was reappended, even the placeholders that had been removed in the translation.
To avoid that we added a new flag on `TNode` that specifies that a node is detached, in which case it should be ignored by the projection.
FW-1319 #resolve
PR Close#30783
Fixes Ivy throwing an error if it runs into an empty property binding on an `ng-template` (e.g. `<ng-template [something]=""></ng-template>`) by not generating an update instruction for it.
Fixes#30801.
This PR resoves FW-1356.
PR Close#30829
When ngcc processes an entrypoint, it updates `package.json` with
metadata about the processed format. Previously, it overwrote the
`package.json` with the stringified JSON object without spaces. This
made the file difficult to read (for example when looking at the file
while debugging an ngcc failure).
This commit fixes it by using spaces in the new `package.json` content.
PR Close#30831
- Removes ɵɵelementProperty instruction
- Updates tests that were using it
- NOTE: There is one test under `render3/integration_spec.ts` that is commented out, and needs to be reviewed. Basically, I could not find a good why to test what it was doing, because it was doing things that I am not sure we could generate in an acceptance test.
PR Close#30645
Added a new syntax for projections (`¤` will represent `ng-content` nodes) so that we can treat them specifically.
When we enter an i18n block with the instruction `i18nStart`, a new `delayProjection` variable is set to true to prevent the instruction `projection` from projecting the nodes. Once we reach the `i18nEnd` instruction and encounter a projection in the translation we will project its nodes.
If a projection was removed from a translation, then its nodes won't be projected at all.
The variable `delayProjection` is restored to `false` at the end of `i18nEnd` so that it doesn't stop projections outside of i18n blocks.
FW-1261 #resolve
PR Close#30782
We used to ignore empty strings for optimization purposes, but it turns out that empty strings are also valid values for ICU cases and we shouldn't ignore those.
FW-1290 #resolve
PR Close#30846
When an `ng-template` element has a variable declaration without a value,
it is assigned the value of the `$implicit` property in the embedded view's
context. The template compiler inserts a property access to `$implicit` for
template variables without a value, however the type-check code generation
logic did not. This resulted in incorrect type-checking code being generated.
Fixes FW-1326
PR Close#30675
Some HTML attributes don't correspond to their DOM property name, in which
case the runtime will apply the appropriate transformation when assigning
a property using its attribute name. One example of this is the `for`
attribute, for which the DOM property is named `htmlFor`.
The type-checking machinery in ngtsc must also take this mapping into
account, as it generates type-check code in which unclaimed property bindings
are assigned to properties of (subtypes of) `HTMLElement`.
Fixes#30607
Fixes FW-1327
PR Close#30675
Before this change we would systematically call LQueries.clone() when executting
elementStart / elementContainerStart instructions. This was often unnecessary as
LQueries can be mutated under 2 conditions only:
- we are crossing an element that has directives with content queries
(new queries must be added);
- we are descending into element hierarchy (creating a child element of an existing element)
and the current LQueries object is tracking shallow queries (shallow queries are removed).
With this PR LQueires.clone() is only done when needed and this gratelly reduces number
of LQueries object created: in the "expanding rows" benchmark number of allocated
(and often GCed just after!) LQueries is reduced from ~100k -> ~35k. This represents
over 1MB of memory that is not allocated.
PR Close#30664
Projecting bare ICU expressions failed because we would assume that component's content nodes would be projected later and doing so at that point would be wasteful. But ICU nodes are handled independently and should be inserted immediately because they will be ignored by projections.
FW-1348 #resolve
PR Close#30696
Inside of `DebugNode.queryAll` we walk through all of the descendants of the node that we're querying against, however the logic that walks sideways through a node siblings also applies to the root node. This means that eventually we'll match against its nodes as well which will give us invalid results. These changes add an extra check to ensure that we aren't matching against the siblings of the root node.
This PR resolves FW-1353.
PR Close#30788
With View engine it was possible to declare multiple projection
definitions and to programmatically project nodes into the slots.
e.g.
```html
<ng-content></ng-content>
<ng-content></ng-content>
```
Using `ViewContainerRef#createComponent` allowed projecting
nodes into one of the projection defs (through index)
This no longer works with Ivy as the `projectionDef` instruction only
retrieves a list of selectors instead of also retrieving entries for
reserved projection slots which appear when using the default
selector multiple times (as seen above).
In order to fix this issue, the Ivy compiler now passes all
projection slots to the `projectionDef` instruction. Meaning that
there can be multiple projection slots with the same wildcard
selector. This allows multi-slot projection as seen in the
example above, and it also allows us to match the multi-slot node
projection order from View Engine (to avoid breaking changes).
It basically ensures that Ivy fully matches the View Engine behavior
except of a very small edge case that has already been discussed
in FW-886 (with the conclusion of working as intended).
Read more here: https://hackmd.io/s/Sy2kQlgTE
PR Close#30561
Currently with Ivy, `ModuleWithProvider` providers are processed in order
of declaration in the `NgModule` imports. This technically makes makes
sense but is a potential breaking change as `ModuleWithProvider` providers
are processed after all imported modules in View Engine.
In order to keep the behavior of View Engine, the `r3_injector` is updated
to no longer process `ModuleWithProvider` providers egarly.
Resolves FW-1349
PR Close#30688
The "async" around a couple tests was removed because of the merge conflict in one of the previous commits (80394ce08b). This change restores missing "async"s.
PR Close#30762
fix(@schematics/angular): TypeScript related migrations should cater for BOM
In the CLI `UpdateRecorder` methods such as `insertLeft`, `remove` etc.. accepts positions which are not offset by a BOM. This is because when a file has a BOM a different recorder will be used https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72 which caters for an addition offset/delta.
The main reason for this is that when a developer is writing a schematic they shouldn't need to compute the offset based if a file has a BOM or not and is handled out of the box.
Example
```ts
recorder.insertLeft(5, 'true');
```
However this is unfortunate in the case if a ts SourceFile is used and one uses `getWidth` and `getStart` method they will already be offset by 1, which at the end it results in a double offset and hence the problem.
Fixes#30713
PR Close#30719
Two issues with DebugNode/DebugElement in Ivy were causing problems in user
tests.
1. The DebugNodes returned by Ivy were not actually instances of DebugNode.
This was due to an issue with the Ivy switch logic in debug_node.ts.
The declaration of the exported DebugNode reference was set to
`DebugNode__PRE_R3__ as any`. The cast prevented the Ivy switch transform
from detecting this as a switchable declaration. The transform cannot handle
arbitrary syntax, and exports *must* be of the form "const x = y__PRE_R3__;"
or they will not work. The cast to any in this case was not needed, so this
commit removes it.
2. DebugNodes returned by Ivy multiple times for the same element were not
reference-identical. This was previously considered a minor breaking change
in Ivy, but testing has shown that users depend on referential equality of
DebugNodes. This commit caches a DebugNode on a DOM node when first creating
it, to allow returning the same instance in subsequent operations.
PR Close#30756
Due to sanitization being stored as a temp/global value between
instructions, unit tests randomly failed because one test failed
to clean up its temporary value. This patch fixes this issue.
`i18nAttributes` instructions always occur after the element instruction. This means that we need to treat `i18n-` attributes differently.
By defining a specific `AttributeMarker` we can ensure that we won't trigger directive inputs with untranslated attribute values.
FW-1332 #resolve
PR Close#30402
Changed runtime i18n to define attributes with bindings, or matching directive inputs/outputs as element properties as we are supposed to do in Angular.
This PR fixes the issue where directive inputs wouldn't be trigged.
FW-1315 #resolve
PR Close#30402
The R3TargetBinder "binds" an Angular template AST, computing semantic
information regarding the template and making it accessible.
One of the binding passes previously had a bug, where for the following
template:
<div *ngIf="foo as foo"></div>
which desugars to:
<ng-template ngIf [ngIf]="foo" let-foo="ngIf">
<div></div>
</ng-template>
would have the `[ngIf]` binding processed twice - in both the scope which
contains the `<ng-template>` and the scope inside the template. The bug
arises because during the latter, `foo` is a variable defined by `let-foo`,
and so the R3TargetBinder would incorrectly learn that `foo` inside `[ngIf]`
maps to that variable.
This commit fixes the bug by only processing inputs, outputs, and
templateAttrs from `Template`s in the outer scope.
PR Close#30669
Commit 0df719a46 introduced registration of NgModules with ids when compiled
with AOT, and f74373f2d corrected the timing to avoid issues with tree
shaking. Neither of these approaches were correct.
This commit fixes the timing to match View Engine and avoid tree shaking
issues, as well as fixes a bug with the registration of imported module ids.
A new Ivy-only test is added which verifies that modules get registered
correctly under real-world conditions.
PR Close#30706
Prior to this commit there were no explicit types setup for NgModuleFactory calls in ngfactories, so TypeScript inferred the type based on a given call. In some cases (when generic types were used for Components/Directives) that turned out to be problematic, so we add explicit typing for NgModuleFactory calls.
PR Close#30708
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
This patch is one of the final patches to refactor the styling algorithm
to be more efficient, performant and less complex.
This patch enables sanitization support for map-based and prop-based
style bindings.
PR Close#30667
Instead of linking to a markdown file explaining what the migration warnings
are about, we should link to the deprecation guide which now also contains
an entry for that schematic. This makes the deprecation explanations
consistent and more centralized.
PR Close#30702
With this change we reduce the amount of IO operations. This is especially a huge factor in windows since IO ops are slower.
With this change mainly we cache `existsSync` and `readFileSync` calls
Here's the results
Before
```
//packages/language-service/test:test
INFO: Elapsed time: 258.755s, Critical Path: 253.91s
```
After
```
//packages/language-service/test:test
INFO: Elapsed time: 66.403s, Critical Path: 63.13s
```
PR Close#30585
This fixes a collision between #30639 and #30543 where the latter added
usages of @ViewChild without the static flag present, but the former
made the flag required.
PR Close#30666
This commit makes the static flag on @ViewChild and @ContentChild required.
BREAKING CHANGE:
In Angular version 8, it's required that all @ViewChild and @ContentChild
queries have a 'static' flag specifying whether the query is 'static' or
'dynamic'. The compiler previously sorted queries automatically, but in
8.0 developers are required to explicitly specify which behavior is wanted.
This is a temporary requirement as part of a migration; see
https://angular.io/guide/static-query-migration for more details.
@ViewChildren and @ContentChildren queries are always dynamic, and so are
unaffected.
PR Close#30639
This patch in the second runtime change which refactors how styling
bindings work in Angular. This patch refactors how map-based
`[style]` and `[class]` bindings work using a new algorithm which
is faster and less complex than the former one.
This patch is a follow-up to an earlier refactor which enabled
support for prop-based `[style.name]` and `[class.name]`
bindings (see f03475cac8).
PR Close#30543
This is a new feature of the Ivy TestBed.
A common user pattern is to test one component with another. This is
commonly done by creating a `TestFixture` component which exercises the
main component under test.
This pattern is more difficult if the component under test is declared in an
NgModule but not exported. In this case, overriding the module is necessary.
In g3 (and View Engine), it's possible to use an NgSummary to override the
recompilation of a component, and depend on its AOT compiled factory. The
way this is implemented, however, specifying a summary for a module
effectively overrides much of the TestBed's other behavior. For example, the
following is legal:
```typescript
TestBed.configureTestingModule({
declarations: [FooCmp, TestFixture],
imports: [FooModule],
aotSummaries: [FooModuleNgSummary],
});
```
Here, `FooCmp` is declared in both the testing module and in the imported
`FooModule`. However, because the summary is provided, `FooCmp` is not
compiled within the context of the testing module, but _is_ made available
for `TestFixture` to use, even if it wasn't originally exported from
`FooModule`.
This pattern breaks in Ivy - because summaries are a no-op, this amounts
to a true double declaration of `FooCmp` which raises an error.
Fixing this in user code is possible, but is difficult to do in an
automated or backwards compatible way. An alternative solution is
implemented in this PR.
This PR attempts to capture the user intent of the following previously
unsupported configuration:
```typescript
TestBed.configureTestingModule({
declarations: [FooCmp, TestFixture],
imports: [FooModule],
});
```
Note that this is the same as the configuration above in Ivy, as the
`aotSummaries` value provided has no effect.
The user intent here is interpreted as follows:
1) `FooCmp` is a pre-existing component that's being used in the test
(via import of `FooModule`). It may or may not be exported by this
module.
2) `FooCmp` should be part of the testing module's scope. That is, it
should be visible to `TestFixture`. This is because it's listed in
`declarations`.
This feature effectively makes the `TestBed` testing module special. It's
able to declare components without compiling them, if they're already
compiled (or configured to be compiled) in the imports. And crucially, the
behavior matches the first example with the summary, making Ivy backwards
compatible with View Engine for tests that use summaries.
PR Close#30578
Depending on which placeholders the translation uses, there are some legitimate cases where we might not use all placeholder replacements in `i18nPostprocess`. For example if some of the placeholders of the original messages have been removed in the translation.
FW-1312 #resolve
PR Close#30632
8479cb4233 updated the static-query migration
to refer to the new guide on AIO. Unfortunately these URLs are currently not
valid as the guide is only available on `next.angular.io` right now. In order to
make the link work permanently (e.g. if we eventually remove the guide in future
major versions), we use the permalink from the `v8` subdomain.
PR Close#30649
DEPRECATION:
platform-webworker has been around since the initial release of Angular
version 2. It began as an experiment to leverage Angular's rendering
architecture and try something different: to run an entire web application
in a web worker.
We've learned a lot from this experiment, and have come to the conclusion
that pushing entire applications to run in a web worker is not a recipe for
success for most applications. This is due to a number of unresolved issues,
including:
* Poor or non-existent support for web worker APIs in web crawlers/indexers.
* Poor support in build and bundling tooling.
As a result, as of Angular version 8, we are deprecating the
`platform-webworker` APIs in Angular. This consists of both NPM packages,
`@angular/platform-webworker` and `@angular/platform-webworker-dynamic`.
Going forward, we will focus our efforts related to web workers around their
primary use case of offloading CPU-intensive but not critical work.
FW-1339 #resolve
PR Close#30642
DEPRECATION:
Angular previously has supported an integration with the Web Tracing
Framework (WTF) for performance testing of Angular applications. This
integration has not been maintained and likely does not work for the
majority of Angular applications today. As a result, we are deprecating
the integration in Angular version 8.
This deprecation covers the following public APIs:
* `WtfScopeFn`
* `wtfCreateScope`
* `wtfStartTimeRange`
* `wtfEndTimeRange`
* `wtfLeave`
FW-1338 #resolve
PR Close#30642
Currently if a project has source-files with syntax failures and the migration
has been started on a broken project, we silently migrate *as much as possible*,
but never notify the developer that the project was in a broken state and that
he can re-run the migration after the failures are fixed.
Additionally the template strategy does not need to exit gracefully if it detects
Angular semantic diagnostics on generated files (template type checking). These
diagnostics are not relevant for the query timing analysis.
PR Close#30628
We are removing the prompt for the `static-query` migration and make the
template strategy the migration strategy for the migration. The usage
strategy is good for best-practices, but for now we want to ensure that
the migration is a seamless as possible and that is only achievable my
re-using the same logic that View Engine uses for determining the
timing of a query.
PR Close#30628
Prior to this change a component was considered unresolved (i.e. having dynamic resources that should be loaded, like external template or stylesheets) even if template override was provided as an empty string (for example, via TestBed.overrideTemplateUsingTestingModule call). This commit fixes the condition that previously treated empty string as an absent template value.
PR Close#30602
With Ivy, injecting a `ViewContainerRef` for a `<ng-container>` element
results in two comments generated in the DOM. One comment as host
element for the `ElementContainer` and one for the generated `LContainer`
which is needed for the created `ViewContainerRef`.
This is problematic as developers expect the same anchor element for
the `LContainer` and the `ElementContainer` in order to be able to move
the host element of `<ng-container>` without leaving the actual
`LContainer` anchor element at the original location.
This worked differently in View Engine and various applications might
depend on the behavior where the `ViewContainerRef` shares the anchor
comment node with the host comment node of the `<ng-container>`. For
example `CdkTable` from `@angular/cdk` moves around the host element of
a `<ng-container>` and also expects embedded views to be inserted next
to the moved `<ng-container>` host element.
See: f8be5329f8/src/cdk/table/table.ts (L999-L1016)
Resolves FW-1341
PR Close#30611
The AbsoluteModuleStrategy in ngtsc assumed that the source code is
formatted as TypeScript with regards to module exports.
In ngcc this is not always the case, so this commit changes
`AbsoluteModuleStrategy` so that it relies upon a `ReflectionHost` to
compute the exports of a module.
PR Close#30200
Prior to this change we processed binding expression (including bindings with pipes) in i18n attributes before we generate update instruction. As a result, slot offsets for pipeBind instructions were calculated incorrectly. Now we perform binding expression processing when we generate "update block" instructions, so offsets are calculated correctly.
PR Close#30573
Currently the `@angular/compiler-cli` compliance tests sometimes do
not throw an exception if the expected output does not match the
generated JavaScript output. This can happen for the following cases:
1. Expected code includes character that is not part of known alphabet
(e.g. `Δ` is still used in a new compliance test after rebasing a PR)
2. Expected code asserts that a string literal matches a string with
escaped quotes. e.g. expects `const $var$ = "\"quoted\"";`)
PR Close#30597
_compile_action should take a list since we compute it within one node in the build graph
This needs to be cleaned up since Bazel is getting stricter with
disallowing iteration over depsets
PR Close#30600
Currently we try to parse CLI workspace configurations gracefully by
using the native `JSON.parse()` method. This means that the CLI workspace
configuration needs to follow the strict JSON specification because otherwise
the migrations would not be able to find TypeScript configurations in the CLI
project where JSON5 workspace configurations are supported.
In order to handle such workspace configurations, we leverage the JSON
parsing logicfrom the `@angular-devkit/core` which is also used by the CLI.
PR Close#30582
PR #29290 introduced a new `TestBed.get` signature and deprecated the existing one.
This raises a lot of TSLint deprecation warnings in projects using a strict TS config (see #29905 for context), so we are temporarily removing the `@deprecated` annotation in favor of a plain text warning until we properly fix it.
Refs #29905
Fixes FW-1336
PR Close#30514
The `flatten` function used `concat` and `slice` which created a lot of intermediary
object allocations. Because `flatten` is used from query any benchmark which
used query would exhibit high minor GC counts.
PR Close#30468
BREAKING CHANGE
In PR #19558, we fixed a bug in `TestBed.overrideProvider` where
eager providers were not being instantiated correctly. However,
it turned out that since this bug had been around for quite a bit,
many apps were relying on the broken behavior where the providers
would not be instantiated. To assist in the transition, the
`TestBed.deprecatedOverrideProvider` method was temporarily
introduced to mimic the old behavior so that apps would have a
longer time period to migrate their code.
2 years and 3 versions later, it is time to remove the temporary
method. This commit removes `TestBed.deprecatedOverrideProvider`
altogether. Any usages of `TestBed.deprecatedOverrideProvider`
should be replaced with `TestBed.overrideProvider`. This may mean
that providers that were not created before will now be instantiated,
which could mean that your tests need to provide more mocks or stubs
for the dependencies of the newly instantiated providers.
PR Close#30576
There is an encoding issue with using delta `Δ`, where the browser will attempt to detect the file encoding if the character set is not explicitly declared on a `<script/>` tag, and Chrome will find the `Δ` character and decide it is window-1252 encoding, which misinterprets the `Δ` character to be some other character that is not a valid JS identifier character
So back to the frog eyes we go.
```
__
/ɵɵ\
( -- ) - I am ineffable. I am forever.
_/ \_
/ \ / \
== == ==
```
PR Close#30546
Adds overloads to the `transform` methods of `SlicePipe`,
to have better types than `any` for `value` and `any` as a return.
With this commit, using `slice` in an `ngFor` still allow to type-check the content of the `ngFor`
with `fullTemplateTypeCheck` enabled in Ivy:
<div *ngFor="let user of users | slice:0:2">{{ user.typo }}</div>
|
`typo` does not exist on type `UserModel`
whereas it is currently not catched (as the return of `slice` is `any`) neither in VE nor in Ivy.
BREAKING CHANGE
`SlicePipe` now only accepts an array of values, a string, null or undefined.
This was already the case in practice, and it still throws at runtime if another type is given.
But it is now a compilation error to try to call it with an unsupported type.
PR Close#30156
Moves all manual render3 view_container_ref tests that use property
bindings to acceptance tests with TestBed.
Two issues surfaced and refer to a difference between Ivy and View
engine:
* Multi-slot projection is not working with Ivy: FW-1331
* ViewContainerRef throws if index is invalid while View Engine clamped index: FW-1330
PR Close#30488
Previously we defensively wrapped expressions in case they ran afoul of
precedence rules. For example, it would be easy to create the TS AST structure
Call(Ternary(a, b, c)), but might result in printed code of:
```
a ? b : c()
```
Whereas the actual structure we meant to generate is:
```
(a ? b : c)()
```
However the TypeScript renderer appears to be clever enough to provide
parenthesis as necessary.
This commit removes these defensive paraenthesis in the cases of binary
and ternary operations.
FW-1273
PR Close#30349
Previously, interpolations were generated into TCBs as a comma-separated
list of expressions, letting TypeScript infer the type of the expression
as the type of the last expression in the chain. This is undesirable, as
interpolations always result in a string type at runtime. Therefore,
type-checking of bindings such as `<img src="{{ link }}"/>` where `link`
is an object would incorrectly report a type-error.
This commit adjusts the emitted TCB code for interpolations, where a
chain of string concatenations is emitted, starting with the empty string.
This ensures that the inferred type of the interpolation is of type string.
PR Close#30177
This is the first refactor PR designed to change how styling bindings
(i.e. `[style]` and `[class]`) behave in Ivy. Instead of having a heavy
element-by-element context be generated for each element, this new
refactor aims to use a single context for each `tNode` element that is
examined and iterated over when styling values are to be applied to the
element.
This patch brings this new functionality to prop-based bindings such as
`[style.prop]` and `[class.name]`.
PR Close#30469
Previously, in order to assert that the promise was not resolved, an
error was thrown when the promise was resolved successfully. At the
same, `.catch()` was used to silence the (expected) promise rejection.
However, the chained `.catch()` handler would also catch (and swallow)
the error thrown on resolving the promise, making the test pass, even if
the promise was not rejected.
This commit fixes it by ensuring that the error thrown on resolving the
promise is not caught by the rejection handler.
PR Close#30515
Previously, [this test][1] would occasionally fail (e.g. on CI) with
"Template cache was not found in $templateCache". This was due to a
combination of:
1. [That test][2] (which removes the cache) being run right before the
failing test.
2. The async `TestBed.compileComponents()` operation run in the
`beforeEach()` block (which sets the cache) not having completed
before the `it()` block.
This commit fixes the issue by ensuring the cache is always set, before
instantiating `CachedResourceLoader`.
This commit also moves some operations that are only needed in one test
from the `beforeEach()` block to that test's `it()` block.
[1]: 79903b1842/packages/platform-browser-dynamic/test/resource_loader/resource_loader_cache_spec.ts (L50)
[2]: 79903b1842/packages/platform-browser-dynamic/test/resource_loader/resource_loader_cache_spec.ts (L37)Fixes#30499
PR Close#30515
Moves most of the tests from `render3/integration_spec` into `acceptance`. Note that there are still a handful of tests left in render3, because we don't have a way of moving all of them to go through `TestBed` since they either have r3-specific assertions or we don't have access to the same APIs as the raw instructions.
PR Close#30461
Ports render3 onDestroy tests over to be acceptance tests. Removes old render3 tests if possible.
Note the onlyInIvy test for one area where Ivy has a different behavior than ViewEngine
PR Close#30445
Previously we were relying upon the `.get()` method to return `undefined`
but it is clearer and safer to always check with `.has()` first.
PR Close#25445
Previously the same `Renderer` was used to render typings (.d.ts)
files. But the new `UmdRenderer` is not able to render typings files
correctly.
This commit splits out the typings rendering from the src rendering.
To achieve this the previous renderers have been refactored from
sub-classes of the abstract `Renderer` class to classes that implement
the `RenderingFormatter` interface, which are then passed to the
`Renderer` and `DtsRenderer` to modify its rendering behaviour.
Along the way a few utility interfaces and classes have been moved
around and renamed for clarity.
PR Close#25445
In some cases the `forwardRef` helper has been imported via a namespace,
e.g. `core.forwardRef(...)`.
This commit adds support for unwrapping such namespaced imports when
ngtsc is statically evaluating code.
PR Close#25445
Previously these fake files were full TypeScript source
files (`.ts`) but this is not necessary as we only need the
typings not the implementation.
PR Close#25445
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
- Adds inheritance tests for many combinations of directive, component and bare class inheritance
- Adds tests that are failing in ivy, but should work, marks them with `xit` and a TODO.
- Removes render3 unit tests that cover the same things.
PR Close#30442
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
Removing the sandbox improves build time by almost 40%.
For a hello world (ng new) application:
ng build with sandbox: 22.0 seconds
ng build without sandbox: 13.3 seconds
PR Close#30460
The LocationShim (replacement for `$location`) was added to centralize dealing with the browser URL. Additionally, an `onUrlChange` method was added to Angular's Location service. This PR adds a corresponding method to the LocationShim so updates from AngularJS can be tracked in Angular.
PR Close#30466
This is a tentative fix for the error `Cannot write file '/node_modules/@angular/core/core.ngfactory.d.ts' because it would overwrite input file.` that is showing in codefresh windows ci.
PR Close#30482
It's unnecessary for a jasmine_node_test rule to depend on a TypeScript library. This dependency is already satisfied via the 'data' and also having it in 'deps' causes CI flakiness on Windows
PR Close#30482
In View Engine, we would simply ignore host style bindings on template nodes. In Ivy,
we are throwing a "Cannot read length of undefined" error instead. For backwards
compatibility, we should also ignore these bindings rather than blowing up.
PR Close#30498
In View engine it is possible to instantiate a service that that has no
`@Injectable` decorator as long as it satisfies one of:
1) It has no dependencies and so a constructor with no parameters.
This is already supported in Ivy.
2) It has no constructor of its own and sub-classes a service which has
dependencies but has its own `@Injectable` decorator. This second
scenario was broken in Ivy.
In Ivy, previous to this commit, if a class to be instantiated did not have
its own `@Injectable` decorator and did not provide a constructor of
its own, then it would be created using `new` with no arguments -
i.e. falling back to the first scenario.
After this commit Ivy correctly uses the `ngInjectableDef` inherited
from the super-class to provide the `factory` for instantiating the
sub-class.
FW-1314
PR Close#30388
- Moves template ref tests from render3 unit tests to acceptance tests.
- Marks tests testing ivy specific changes as `onlyInIvy`.
- Deletes old render3 unit tests that are no longer necessary
PR Close#30443
PR #30393 corrected behavior where Object.keys sometimes returns an `undefined` value. However, the types didn't reflect this in the code. That fix actually missed one value that could return `undefined`. This PR corrects this by casting the types to what they can be in IE 11. This ensures the code behaves as it should when this edge case comes up.
PR Close#30464
In some cases where multiple navigations happen to the same URL, the router will not process a given URL. In those cases, we fall into logic that resets state for the next navigation. One piece of this resetting is to set the `browserUrlTree` to the most recent `urlAfterRedirects`i.
However, there was bug in this logic because in some cases the `urlAfterRedirects` is a stale value. This happens any time a URL won't be processed, and the previous URL will also not be processed. This creates unpredictable behavior, not the least of which ends up being a broken `back` button.
This PR kicks off new navigations with the current value the router assumes is in the browser. All the logic around how to handle future navigations is based on this value compared to the current transition, so it's important to kick off all new navigations with the current value so in the edge case described above we don't end up with an old value being set into `browserUrlTree`.
Fixes#30340
Related to #30160
PR Close#30344
Slightly improves the messages for the static-query migration in order
to make the terminal output less verbose but more helpful. Unfortunately
we are limited in what we can print due to the devkit not providing much
utilities for printing good messages from a migration schematic.
PR Close#30458
Currently if something fails in the selected strategy (e.g. AOT failures),
the migration currently accidentally falls back to the test strategy. This
is not helpful as we want to give developers the possibility to re-run
the migration after fixing potential AOT failures.
PR Close#30458
Apparently the devkit logger is not able to properly print
out error objects, so we need to convert them to a string
before in order to make the error visible to the user.
This is not testable without an e2e test that validates the CLI
terminal output.
PR Close#30458
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
Moves most of the r3 change detection tests into `acceptance`. Notes:
* A handful of tests weren't migrated, because they were testing an API that isn't exposed publicly yet.
* The `should throw if bindings in children of current view have changed` and `should NOT throw if bindings in ancestors of current view have changed` tests were removed, because there's not nice way of hitting the same code path with `TestBed` and doing the same assertion as with the raw instructions. I'm open to ideas on how we could do them.
* There were a few tests that assert that the `innerHTML` looks in a particular way. I've switched them to use `textContent`, because Ivy and ViewEngine produce slightly different DOM. The tests were only checking whether the text has changed anyway.
PR Close#30425
Moves all manual render3 property binding tests to
TestBed acceptance tests. Unfortunately three property
binding tests could not be migrated as these rely on
manual Ivy template code that is not supported within
TestBed. These can be revisited as discussed in the
framework team meeting.
PR Close#30426
Moves all manual render3 tests which are located within the
`renderer_factory_spec.ts` file to acceptance tests. A few tests
that use Ivy-specific logic which is not replicable with `TestBed`
remain in the render3 folder (e.g. using `renderTemplate`)
Additionally migrated tests that assert the lifecycles of the
renderer_factory are set to *ivy only* as the lifecycle seems
to be different in Ivy. Tracked with: FW-1320
PR Close#30435
This PR fixes an issue where IE 11 can return `undefined` in with an `Object.keys` call. Solution is to add a runtime check on the value. Based on the types being passed, this shouldn't be necessary, but is needed only for IE 11. Unit test doesn't work for this PR because it can't be replicated easily.
PR Close#30393
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
- Moves tests related to the pureFunction instructions from render3 to acceptance tests
- Leaves behind one test for in-template javascript that is not supported syntax yet
PR Close#30406
Moves over the tests from `pipe_spec` into `acceptance`. Note that the two `WrappedValue` tests haven't been moved over, because impure pipes always throw "changed after checked" errors in `TestBed`. This seems to be consistent with ViewEngine.
PR Close#30389
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
Moves most of the tests in `output_spec` into `acceptance`. Note that one test is left in `render3`, because it's testing mixing in custom logic with instructions which we can't replicate using `TestBed`.
PR Close#30372
Moves all manual `render3` content projection tests that use
the `ɵɵelementProperty` to acceptance tests. Additionally a
few other content projection tests were moved over to
acceptance. Eventually we'll be able to move all remaining
content projection tests to acceptance.
PR Close#30357
This commit moves the delegated constructor detection to a helper
function and also adds more test coverage.
The original code for this came from https://github.com/angular/angular/pull/24156
thanks to @ts2do.
Closes#24156Closes#27267
// FW-1310
PR Close#30368
After this PR is merged, maintainers no longer need to update .bazelrc
file, toolchain and platform related flags for RBE builds and tests
(unless there is a breaking change in Bazel related to those flags).
Maintainers just need to update the pin of @bazel-toolchains repo
regularly in the packages/bazel/package.bzl file according to
https://releases.bazel.build/bazel-toolchains.html to include the
latest checked-in toolchain configs. If rbe_autoconfig() cannot find
appropriate toolchain configs for the version of Bazel in the version of
@bazel_toolchains repo that is currently used by this project, it will pull
down the container and generate the configs on the fly as the beginning
of the build/test.
PR Close#29336
Currently we always just set the timing to `false` if we aren't
able to analyze a given call expression or new expression. e.g.
```ts
ngOnInit() {
thirdPartyCallSync(() => this.query.doSomething())
}
```
In that case the `thirdPartyCallSync` function comes from the `node_modules`
and is only defined through types while there is no code for the
actual function logic that can be analyzed. This makes it impossible
to tell whether the given call expression actually causes the specified
arrow function to be executed synchronously or not. In order to be able
to make this better, we now peek into the passed arrow function and
check for a synchronous query usage. If so, we set the query timing to
static and mark it as ambiguous. This ensures that the usage strategy is
less "magical" and more correct with third-party code.
Additionally since functions like `setTimeout` are not analyzable but known
to be asynchronous, there is a hard-coded list of known functions which
shouldn't be marked as ambiguous.
Resolves FW-1214. As planned within https://hackmd.io/hPiLWpPlQ4uynC1luIBdfQ
PR Close#30215
Even though we don't run the size-tracking test on CI
right now, we update the golden size map as part of
the size-tracking tool update. The size-map difference
should generally be kept up-to-date to be able to
determine which PRs contribute size to a given file.
PR Close#30257
Based on discussion that happened on the PR that introduced
the size-tracking tool, we want to have another threshold for
the raw byte difference. This allows us to better control for
which changes the size-tracking tool should report a difference.
See: https://github.com/angular/angular/pull/30070#discussion_r278332315
PR Close#30257
- splits existing property acceptance tests into property_binding and property_interpolation
- ports tests from render3 instructions tests to acceptance tests
- removes redundant or unnecessary tests that are covered by existing acceptance tests
:)
PR Close#30321
Currently the static-query migration ignores queries declared on getters
or setters as these are not part of a `PropertyDeclaration`. We need to
handle these queries in order to cover all queries within a given project.
The usage strategy is not able to detect timing for queries on accessors,
so we add a TODO and print a message. The template strategy is able
to detect the proper timing for such queries because it's not dependent
on detecting the usage of the query.
Resolves FW-1215
PR Close#30327
We have an issue where we would like to be able to test perf counter metrics in acceptance tests, but we are unable to do so, because it will break when those same tests are run with ViewEngine. This PR adds a testing utility to `onlyInIvy` that allows for testing of performance counters, and even gives readable errors for what value on `ngDevMode` is incorrect. Has typings for decent autocompletion as well.
PR Close#30339