The new function does not try to restrict the kind of AST node that it
finds, leaving that to the caller. This will make it more resuable in the
UMD reflection host.
PR Close#38959
Sometimes UMD exports appear in the following form:
```
exports.MyClass = alias1 = alias2 = <<declaration>>
```
Previously the declaration of the export would have been captured
as `alias1 = alias2 = <<declaration>>`, which the `PartialInterpreter`
would have failed on, since it cannot handle assignments.
Now we skip over these aliases capturing only the `<<declaration>>`
expression.
Fixes#38947
PR Close#38959
UMD files export values by assigning them to an `exports` variable.
When evaluating expressions ngcc was failing to cope with expressions
like `exports.MyComponent`.
This commit fixes the `UmdReflectionHost.getDeclarationOfIdentifier()`
method to map the `exports` variable to the current source file.
PR Close#38959
The `SIMPLE_CLASS_FILE` contained a `ChildClass` that had an
internal aliases implementation and extended a `SuperClass` base
class. The call to `__extends` was using the wrong argument for
the child class.
PR Close#38959
This clarifies that this is specifically about statements of the form
`exports.<name> = <declaration>`, rather than a general export
statement such as `export class <ClassName> { ... }`.
PR Close#38959
There is no need to check that the `ref.node` is of any particular type
because immediately after this check the entry is tested to see if it passes
`isClassDeclarationReference()`.
The only difference is that the error that is reported is slightly different
in the case that it is a `ref` but not one of the TS node types.
Previously:
```
`Value at position ${idx} in the NgModule.${arrayName} of ${
className} is not a reference`
```
now
```
`Value at position ${idx} in the NgModule.${arrayName} of ${
className} is not a class`
```
Arguably the previous message was wrong, since this entry IS a reference
but is not a class.
PR Close#38959
Since IE 9 and IE 10 were deprecated and support is removed in v11, this commit updates ZoneJs
configs to avoid running tests in these browsers.
PR Close#39189
Although in SSR we patch the global prototypes with DOM globals
like Element and Node, this patch does not occur before the
matches function is called in Angular Elements. This is similar
to the behavior in @angular/upgrade.
Fixes#24551
PR Close#37799
At a high level, the current shadow DOM shim logic works by escaping the content of a CSS rule
(e.g. `div {color: red;}` becomes `div {%BLOCK%}`), using a regex to parse out things like the
selector and the rule body, and then re-adding the content after the selector has been modified.
The problem is that the regex has to be very broad in order capture all of the different use cases,
which can cause it to match strings suffixed with a semi-colon in some places where it shouldn't,
like this URL from Google Fonts `https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap`.
Most of the time this is fine, because the logic that escapes the rule content to `%BLOCK%` will
have converted it to something that won't be matched by the regex. However, it breaks down for rules
like `@import` which don't have a body, but can still have quoted content with characters that can
match the regex.
These changes resolve the issue by making a second pass over the escaped string and replacing all
of the remaining quoted content with `%QUOTED%` before parsing it with the regex. Once everything
has been processed, we make a final pass where we restore the quoted content.
In a previous iteration of this PR, I went with a shorter approach which narrowed down the
regex so that it doesn't capture rules without a body. It fixed the issue, but it also ended
up breaking some of the more contrived unit test cases. I decided not to pursue it further, because
we would've ended up with a very long and brittle regex that likely would've broken in even weirder
ways.
Fixes#38587.
PR Close#38716
Removes `ViewEncapsulation.Native` which has been deprecated for several major versions.
BREAKING CHANGES:
* `ViewEncapsulation.Native` has been removed. Use `ViewEncapsulation.ShadowDom` instead. Existing
usages will be updated automatically by `ng update`.
PR Close#38882
Expressions within ICU expressions in templates were not previously
type-checked, as they were skipped while traversing the elements
within a template. This commit enables type checking of these
expressions by actually visiting the expressions.
BREAKING CHANGE:
Expressions within ICUs are now type-checked again, fixing a regression
in Ivy. This may cause compilation failures if errors are found in
expressions that appear within an ICU. Please correct these expressions
to resolve the type-check errors.
Fixes#39064
PR Close#39072
Prior to this change, expressions within ICUs would have a source span
corresponding with the whole ICU. This commit narrows down the source
spans of these expressions to the exact location in the source file, as
a prerequisite for reporting type check errors within these expressions.
PR Close#39072
Updates to rules_nodejs 2.2.0. This is the first major release in 7 months and includes a number of features as well
as breaking changes.
Release notes: https://github.com/bazelbuild/rules_nodejs/releases/tag/2.0.0
Features of note for angular/angular:
* stdout/stderr/exit code capture; this could be potentially be useful
* TypeScript (ts_project); a simpler tsc rule that ts_library that can be used in the repo where ts_library is too
heavy weight
Breaking changes of note for angular/angular:
* loading custom rules from npm packages: `ts_library` is no longer loaded from `@npm_bazel_typescript//:index.bzl`
(which no longer exists) but is now loaded from `@npm//@bazel/typescript:index.bzl`
* with the loading changes above, `load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")` is
no longer needed in the WORKSPACE which also means that yarn_install does not need to run unless building/testing
a target that depends on @npm. In angular/angular this is a minor improvement as almost everything depends on @npm.
* @angular/bazel package is also updated in this PR to support the new load location; Angular + Bazel users that
require it for ng_package (ng_module is no longer needed in OSS with Angular 10) will need to load from
`@npm//@angular/bazel:index.bzl`. I investigated if it was possible to maintain backward compatability for the old
load location `@npm_angular_bazel` but it is not since the package itself needs to be updated to load from
`@npm//@bazel/typescript:index.bzl` instead of `@npm_bazel_typescript//:index.bzl` as it depends on ts_library
internals for ng_module.
* runfiles.resolve will now throw instead of returning undefined to match behavior of node require
Other changes in angular/angular:
* integration/bazel has been updated to use both ng_module and ts_libary with use_angular_plugin=true.
The latter is the recommended way for rules_nodejs users to compile Angular 10 with Ivy. Bazel + Angular ViewEngine is
supported with @angular/bazel <= 9.0.5 and Angular <= 8. There is still Angular ViewEngine example on rules_nodejs
https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular_view_engine on these older versions but users
that want to update to Angular 10 and are on Bazel must switch to Ivy and at that point ts_library with
use_angular_plugin=true is more performant that ng_module. Angular example in rules_nodejs is configured this way
as well: https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular. As an aside, we also have an
example of building Angular 10 with architect() rule directly instead of using ts_library with angular plugin:
https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular_bazel_architect.
NB: ng_module is still required for angular/angular repository as it still builds ViewEngine & @angular/bazel
also provides the ng_package rule. ng_module can be removed in the future if ViewEngine is no longer needed in
angular repo.
* JSModuleInfo provider added to ng_module. this is for forward compat for future rules_nodejs versions.
PR Close#39182
This is a roll forward of #39082, using `ts.createIdentifier(`'legacy'`)` as a cross-version compatible way of making
a single quoted string literal.
Migrated code now uses single quotes, which is in line with the default linting options, so there is no lint error after
migration.
PR Close#39102
This PR enables `getSemanticDiagnostics()` to be called on external templates.
Several changes are needed to land this feature:
1. The adapter needs to implement two additional methods:
a. `readResource()`
Load the template from snapshot instead of reading from disk
b. `getModifiedResourceFiles()`
Inform the compiler that external templates have changed so that the
loader could invalidate its internal cache.
2. Create `ScriptInfo` for external templates in MockHost.
Prior to this, MockHost only track changes in TypeScript files. Now it
needs to create `ScriptInfo` for external templates as well.
For (1), in order to make sure we don't reload the template if it hasn't
changed, we need to keep track of its version. Since the complexity has
increased, the adapter is refactored into its own class.
PR Close#39065
Temporarily disable the //packages/compiler-cli/integrationtest:integrationtest
target while continuing to investigate its unknown failures
PR Close#39168
The right needs to be wrapped in parens or we cannot accurately match its
span to just the RHS. For example, the span in `e = $event /*0,10*/` is ambiguous.
It could refer to either the whole binary expression or just the RHS.
We should instead generate `e = ($event /*0,10*/)` so we know the span 0,10 matches RHS.
This is specifically needed for the TemplateTypeChecker/Language Service
when mapping template positions to items in the TCB.
PR Close#39143
As of #32671, the type of `AbstractControl.parent` can be null which can cause
compilation errors in existing apps. These changes add a migration that will append
non-null assertions to existing unsafe accesses.
````
// Before
console.log(control.parent.value);
// After
console.log(control.parent!.value);
```
The migration also tries its best to avoid cases where the non-null assertions aren't
necessary (e.g. if the `parent` was null checked already).
PR Close#39009
This commit introduces a new API for the `TemplateTypeChecker` which allows
for autocompletion in a global expression context (for example, in a new
interpolation expression such as `{{|}}`). This API returns instances of the
type `GlobalCompletion`, which can represent either a completion result from
the template's component context or a declaration such as a local reference
or template variable. The Language Service will use this API to implement
autocompletion within templates.
PR Close#39048
The template binding API in @angular/compiler exposes information about a
template that is synthesized from the template structure and its scope
(associated directives and pipes).
This commit introduces a new API, `getEntitiesInTemplateScope`, which
accepts a `Template` object (or `null` to indicate the root template) and
returns all `Reference` and `Variable` nodes that are visible at that level
of the template, including those declared in parent templates.
This API is needed by the template type-checker to support autocompletion
APIs for the Language Service.
PR Close#39048
Previously the value passed to `AstFactory.attachComments()` could be
`undefined` which is counterintuitive, since why attach something that
doesn't exist? Now it expects there to be a defined array. Further it no
longer returns a statement. Both these aspects of the interface were designed
to make the usage simpler but has the result of complicating the implemenation.
The `ExpressionTranslatorVisitor` now has a helper function (`attachComments()`)
to handle `leadingComments` being undefined and also returning the statement.
This keeps the usage in the translator simple, while ensuring that the `AstFactory`
API is not influenced by how it is used.
PR Close#39076
Fixed a boolean logic error that prevented hybrid visitor from returning
undefined when a variable does not have value and cursor is not in the
key span.
PR Close#39061
Prior to this change, the `validators` and `asyncValidators` fields of a few Forms directives
were typed as `any[]`. This commit updates the types and makes them consistent for all directives
in the Forms package.
BREAKING CHANGE:
Directives in the `@angular/forms` package used to have `any[]` as a type of `validators` and
`asyncValidators` arguments in constructors. Now these arguments are properly typed, so if your
code relies on directive constructor types it may require some updates to improve type safety.
PR Close#38944
In the `packages/examples/common/ngif/module.ts` file, the field `show` is given an explicit
boolean type. Since typescript infers boolean type, it is redundant and this commit removes it.
PR Close#39081
Previously, RouterTestingModule only assigned two of the options within ExtraOptions to the Router.
Now, it assigns the same options as RouterModule does (with the exception of enableTracing) via a
new shared function assignExtraOptionsToRouter.
Fixes#23347
PR Close#39096
Rather than having the Ivy implementation add the VE code to the deps
list, create a new common package that both Ivy and VE depend on. This
will make it more straightforward in the future to remove the VE code
completely.
PR Close#39098
This is needed so that the Language Service can provide the module name
in the quick info for a directive/component.
To accomplish this, the compiler's `LocalModuleScope` is provided to the
`TemplateTypeCheckerImpl`. This will also allow the `TemplateTypeChecker` to
provide more completions in the future, giving it a way to determine all the
directives/pipes/etc. available to a template.
PR Close#39099
The expression parser already has support for recovering on malformed
property reads, but did not have tests describing the recovered ast in
such cases. This commit adds tests to demonstrate such cases; in
particular, the recovered ast is a full PropertyRead but with an empty
property name. This is likely the most preferred option, as it does not
constrain consumers of the AST to what the property name should look
like. Furthermore, we cannot mark the property name as empty in any
other way (e.g. an EmptyExpr) because the property name, as of present,
is a string field rather than an AST itself.
Note that tokens past a malformed property read are not preserved in the
AST (for example in `foo.1234`, `1234` is not preserved in the AST).
This is because the extra tokens do not belong to the singular
expression created by the property read, and there is not a meaningful
way to interpret a secondary expression in a single parsed expression.
Part of #38596
PR Close#38998
Close#38851, support `jest` fakeTimers APIs' integration with `fakeAsync()`.
After enable this feature, calling `jest.useFakeTimers()` will make all test
run into `fakeAsync()` automatically.
```
beforeEach(() => {
jest.useFakeTimers('modern');
});
afterEach(() => {
jest.useRealTimers();
});
test('should run into fakeAsync() automatically', () => {
const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
expect(fakeAsyncZoneSpec).toBeTruthy();
});
```
Also there are mappings between `jest` and `zone` APIs.
- `jest.runAllTicks()` will call `flushMicrotasks()`.
- `jest.runAllTimers()` will call `flush()`.
- `jest.advanceTimersByTime()` will call `tick()`
- `jest.runOnlyPendingTimers()` will call `flushOnlyPendingTimers()`
- `jest.advanceTimersToNextTimer()` will call `tickToNext()`
- `jest.clearAllTimers()` will call `removeAllTimers()`
- `jest.getTimerCount()` will call `getTimerCount()`
PR Close#39016
It's perfectly valid for an abstract control not to have a defined parent; yet previously the
types were asserting that AbstractControl#parent is not a null value. This changes correctly
reflects the run-time behavior through the types.
BREAKING CHANGE: Type of AbstractFormControl.parent now includes null
`null` is now included in the types of .parent. If you don't already have a check for this case,
the TypeScript compiler might compain. A v11 migration exists which adds the not-null assertion
operator where necessary.
In an unlikely case your code was testing the parnet against undefined with sitrct equality,
you'll need to change this to `=== null` instead, since the parent is not explicily initialized
with `null` instead of being left `undefined`.
Fixes#16999
PR Close#32671
This patch refactors the interpolation parser to do so iteratively
rather than using a regex. Doing so prepares us for supporting granular
recovery on poorly-formed interpolations, for example when an
interpolation does not terminate (`{{ 1 + 2`) or is not terminated
properly (`{{ 1 + 2 {{ 2 + 3 }}`).
Part of #38596
PR Close#38977
The compiler maintains an internal dependency graph of all resource
dependencies for application source files. This information can be useful
for tools that integrate the compiler and need to support file watching.
This change adds a `getResourceDependencies` method to the
`NgCompiler` class that allows compiler integrations to access resource
dependencies of files within the compilation.
PR Close#38048
This patch adds support for recovering well-formed (and near-complete)
ASTs for semantically malformed keyed reads and keyed writes. See the
added tests for details on the types of semantics we can now recover;
in particular, notice that some assumptions are made about the form of
a keyed read/write intended by a user. For example, in the malformed
expression `a[1 + = 2`, we assume that the user meant to write a binary
expression for the key of `a`, and assign that key the value `2`. In
particular, we now parse this as `a[1 + <empty expression>] = 2`. There
are some different interpretations that can be made here, but I think
this is reasonable.
The actual changes in the parser code are fairly minimal (a nice
surprise!); the biggest addition is a `writeContext` that marks whether
the `=` operator can serve as a recovery point after error detection.
Part of #38596
PR Close#39004
Updates to rules_nodejs 2.2.0. This is the first major release in 7 months and includes a number of features as well
as breaking changes.
Release notes: https://github.com/bazelbuild/rules_nodejs/releases/tag/2.0.0
Features of note for angular/angular:
* stdout/stderr/exit code capture; this could be potentially be useful
* TypeScript (ts_project); a simpler tsc rule that ts_library that can be used in the repo where ts_library is too
heavy weight
Breaking changes of note for angular/angular:
* loading custom rules from npm packages: `ts_library` is no longer loaded from `@npm_bazel_typescript//:index.bzl`
(which no longer exists) but is now loaded from `@npm//@bazel/typescript:index.bzl`
* with the loading changes above, `load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")` is
no longer needed in the WORKSPACE which also means that yarn_install does not need to run unless building/testing
a target that depends on @npm. In angular/angular this is a minor improvement as almost everything depends on @npm.
* @angular/bazel package is also updated in this PR to support the new load location; Angular + Bazel users that
require it for ng_package (ng_module is no longer needed in OSS with Angular 10) will need to load from
`@npm//@angular/bazel:index.bzl`. I investigated if it was possible to maintain backward compatability for the old
load location `@npm_angular_bazel` but it is not since the package itself needs to be updated to load from
`@npm//@bazel/typescript:index.bzl` instead of `@npm_bazel_typescript//:index.bzl` as it depends on ts_library
internals for ng_module.
* runfiles.resolve will now throw instead of returning undefined to match behavior of node require
Other changes in angular/angular:
* integration/bazel has been updated to use both ng_module and ts_libary with use_angular_plugin=true.
The latter is the recommended way for rules_nodejs users to compile Angular 10 with Ivy. Bazel + Angular ViewEngine is
supported with @angular/bazel <= 9.0.5 and Angular <= 8. There is still Angular ViewEngine example on rules_nodejs
https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular_view_engine on these older versions but users
that want to update to Angular 10 and are on Bazel must switch to Ivy and at that point ts_library with
use_angular_plugin=true is more performant that ng_module. Angular example in rules_nodejs is configured this way
as well: https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular. As an aside, we also have an
example of building Angular 10 with architect() rule directly instead of using ts_library with angular plugin:
https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular_bazel_architect.
NB: ng_module is still required for angular/angular repository as it still builds ViewEngine & @angular/bazel
also provides the ng_package rule. ng_module can be removed in the future if ViewEngine is no longer needed in
angular repo.
* JSModuleInfo provider added to ng_module. this is for forward compat for future rules_nodejs versions.
@josephperrott, this touches `packages/bazel/src/external.bzl` which will make the sync to g3 non-trivial.
PR Close#37727
This updates the migration to align with the style guide and work with default lint rules. It avoids a lint error on
newly migrated projects and fixes a test in the CLI repo.
PR Close#39070
This commit adds the `AstHost` interface, along with implementations for
both Babel and TS.
It also implements the Babel vesion of the `AstFactory` interface, along
with a linker specific implementation of the `ImportGenerator` interface.
These classes will be used by the new "ng-linker" to transform prelinked
library code using a Babel plugin.
PR Close#38866
The `AstFactory.createFunctionDeclaration()` was allowing `null` to be
passed as the function `name` value. This is not actually possible, since
function declarations must always have a name.
PR Close#38866
The tests were assuming that newlines were `\n` characters but this is not
the case on Windows. This was fixed in #38925, but a better solution is to
configure the TS printer to always use `\n` characters for newlines.
PR Close#38866
In certain circumstances (errors during component constructor) the router outlet may not be activated before
redirecting to a new route. If the new route requires running guards and resolvers the current logic will throw
when accessing outlet.component due to an isActivated check within the property getter. This update brings the
logic inline with deactivateRouterAndItsChildren, namely checking outlet.isActivated before trying to access
outlet.component.
Fixes#39030
PR Close#39049
These free standing functions rely upon the "current" `FileSystem`,
but it is safer to explicitly pass the `FileSystem` into functions or
classes that need it.
Fixes#38711
PR Close#39006
These free standing functions rely upon the "current" `FileSystem`,
but it is safer to explicitly pass the `FileSystem` into functions or
classes that need it.
PR Close#39006
To verify the correctness of the linker output, we leverage the existing
compliance tests. The plan is to test the linker by running all compliance
tests using a full round trip of pre-linking and subsequently post-linking,
where the generated code should be identical to a full AOT compile.
This commit adds an additional Bazel target that runs the compliance
tests in partial mode. Follow-up work is required to implement the logic
for running the linker round trip.
PR Close#38938
This is a precursor to introducing the Angular linker. As an initial
step, a compiler option to configure the compilation mode is introduced.
This option is initially internal until the linker is considered ready.
PR Close#38938
It used to be the case that all microsyntax bindings share the same source
span, so the second bound attribute would overwrite the first.
This has been fixed in #39036, this case is added to prevent regression.
PR Close#39062
Create stubs for getTypeDefinitionAtPosition for both VE and Ivy Language Service implementations.
This will prevent failed requests when it is implemented on the vscode plugin side
PR Close#39050
* Add `templateNode` to `ElementSymbol` and `TemplateSymbol` so callers
can use the information about the attributes on the
`TmplAstElement`/`TmplAstTemplate` for directive matching
* Remove helper function `getSymbolOfVariableDeclaration` and favor
more specific handling for scenarios. The generic function did not
easily handle different scenarios for all types of variable declarations
in the TCB
PR Close#39047
Currently it is impossible to determine the source of a binding that
generates `BoundAttribute` because all bound attributes generated from a
microsyntax expression share the same source span.
For example, in
```html
<div *ngFor="let item of items; trackBy: trackByFn"></div>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
source span for all `BoundAttribute`s generated from microsyntax
```
the `BoundAttribute` for both `ngForOf` and `ngForTrackBy`
share the same source span.
A lot of hacks were necessary in View Engine language service to work
around this limitation. It was done by inspecting the whole source span
then figuring out the relative position of the cursor.
With this change, we introduce a flag to set the binding span as the
source span of the `ParsedProperty` in Ivy AST.
This flag is needed so that we don't have to change VE ASTs.
Note that in the binding parser, we already set `bindingSpan` as the
source span for a `ParsedVariable`, and `keySpan` as the source span for
a literal attribute. This change makes the Ivy AST more consistent by
propagating the binding span to `ParsedProperty` as well.
PR Close#39036
In preparation for the Ivy Language service, add the same properties to AppComponent that appear in
TemplateReference so the inline template can be tested thoroughly.
PR Close#39033
This commit adds an API to `NgCompiler`, a method called
`getComponentsWithTemplateFile`. Given a filesystem path to an external
template file, it retrieves a `Set` (actually a `ReadonlySet`) of component
declarations which are using this template. In most cases, this will only be
a single component.
This information is easily determined by the compiler during analysis, but
is hard for a lot of Angular tooling (e.g. the language service) to infer
independently. Therefore, it makes sense to expose this as a compiler API.
PR Close#39002
Instead of doing all sorts of checks in the `visit()` method, move checks
that are specific to `BoundEvent` to the `visitBoundEvent()` method.
PR Close#38985
Remove @angular/platform-webworker and @angular/platform-webworker-dynamic
as they were deprecated in v8
BREAKING CHANGE: @angular/platform-webworker and @angular/platform-webworker-dynamic
have been removed as they were deprecated in v8
PR Close#38846
With the introduction of incremental type checking in #36211, an
intermediate `ts.Program` for type checking is only created if there are
any templates to check. This rendered some tests ineffective at avoiding
regressions, as the intermediate `ts.Program` was required for the tests
to fail if the scenario under test would not be accounted for. This
commit adds a single component to these tests, to ensure the
intermediate `ts.Program` is in fact created.
PR Close#39011
Prior to this fix, incremental rebuilds could fail to type check due to
missing ambient types from auto-discovered declaration files in @types
directories, or type roots in general. This was caused by the
intermediary `ts.Program` that is created for template type checking,
for which a `ts.CompilerHost` was used which did not implement the
optional `directoryExists` methods. As a result, auto-discovery of types
would not be working correctly, and this would retain into the
`ts.Program` that would be created for an incremental rebuild.
This commit fixes the issue by forcing the custom `ts.CompilerHost` used
for type checking to properly delegate into the original
`ts.CompilerHost`, even for optional methods. This is accomplished using
a base class `DelegatingCompilerHost` which is typed in such a way that
newly introduced `ts.CompilerHost` methods must be accounted for.
Fixes#38979
PR Close#39011
We weren't resolving a path correctly which resulted in an error on Windows.
For reference, here's the error. Note the extra slash before `C:`:
```
Error: ENOENT: no such file or directory, scandir '/C:/bazel_output_root/yxvwd24o/external/npm/node_modules/typescript'
at Object.readdirSync (fs.js:854:3)
```
PR Close#39005
BlacklistedStackFrames to InternalZoneJsStackFrames along with other related
symbols renamed with the same changes (with appropriate casing style).
PR Close#38978
This commit updates the symbols in the TemplateTypeCheck API and methods
for retrieving them:
* Include `isComponent` and `selector` for directives so callers can determine which
attributes on an element map to the matched directives.
* Add a new `TextAttributeSymbol` and return this when requesting a symbol for a `TextAttribute`.
* When requesting a symbol for `PropertyWrite` and `MethodCall`, use the
`nameSpan` to retrieve symbols.
* Add fix to retrieve generic directives attached to elements/templates.
PR Close#38844
`NodeInjector` is store in expando as a list of values in an array. The
offset constant into the array have been brought together into a single
`NodeInjectorOffset` enum with better documentation explaining their usage.
PR Close#38707
This change makes `getPreviousOrParentTNode` return `TNode|null` (rather
than just `TNode`) which is more reflective of the reality. The
`getPreviousOrParentTNode` can be `null` upon entering the `LView`.
PR Close#38707
`TNodeType.View` was created to support inline views. That feature did
not materialize and we have since removed the instructions for it, leave
an unneeded `TNodeType.View` which was still used in a very
inconsistent way. This change no longer created `TNodeType.View` (and
there will be a follow up chang to completely remove it.)
Also simplified the mental model so that `LView[HOST]`/`LView[T_HOST]`
always point to the insertion location of the `LView`.
PR Close#38707
Host `TNode` was passed into `getOrCreateTNode` just so that we can
compute weather or not we are a root node. This was needed because
`previousOrParentTNode` could have `TNode` from `TView` other then
current `TView`. This is confusing mental model. Previous change
ensured that `previousOrParentTNode` must always be part of `TView`,
which enabled this change to remove the unneeded argument.
PR Close#38707
`previousOrParentTNode` stores current `TNode`. Due to inconsistent
implementation the value stored would sometimes belong to the current
`TView` and sometimes to the parent. We have extra logic which accounts
for it. A better solution is to just ensure that `previousOrParentTNode`
always belongs to current `TNode`. This simplifies the mental model
and cleans up some code.
PR Close#38707
Even in the overloads, state that it can accept `null` and
`undefined`, in order to ensure easy composition with `async`.
Additionally, change the implementation to return `null` on an
`undefined` input, for consistency with other pipes.
BREAKING CHANGE:
The `slice` pipe now returns `null` for the `undefined` input value,
which is consistent with the behavior of most pipes. If you rely on
`undefined` being the result in that case, you now need to check for it
explicitly.
PR Close#37447
As shown in the tests, `KeyValuePipe.transform` can accept
`undefined`, in which case it always returns `null`.
Additionally, the typing for `string` keys can be made generic, so the
comparison function is only required to accept the relevant cases.
Finally, the typing for `number` records now shows that the comparison
function and the result entries will actually receive the string version
of the numeric keys, just as shown in the tests.
BREAKING CHANGE:
The typing of the `keyvalue` pipe has been fixed to report that for
input objects that have `number` keys, the result will contain the
string representation of the keys. This was already the case and the
code has simply been updated to reflect this. Please update the
consumers of the pipe output if they were relying on the incorrect
types. Note that this does not affect use cases where the input values
are `Map`s, so if you need to preserve `number`s, this is an effective
way.
PR Close#37447
I18nPluralPipe can actually accept `null` and `undefined` (which are
convenient for composing it with the async pipe), but it is currently
typed to only accept `number`.
PR Close#37447
Make typing of number pipes stricter to catch some misuses (such as
passing an Observable or an array) at compile time.
BREAKING CHANGE:
The signatures of the number pipes now explicitly state which types are
accepted. This should only cause issues in corner cases, as any other
values would result in runtime exceptions.
PR Close#37447
Make typing of DatePipe stricter to catch some misuses (such as passing
an Observable or an array) at compile time.
BREAKING CHANGE:
The signature of the `date` pipe now explicitly states which types are
accepted. This should only cause issues in corner cases, as any other
values would result in runtime exceptions.
PR Close#37447
`AsyncPipe.transform` will never return `undefined`, even when passed
`undefined` in input, in contrast with what was declared in the
overloads.
Additionally the "actual" method signature can be updated to match the
most generic case, since the implementation does not rely on wrappers
anymore.
BREAKING CHANGE:
The async pipe no longer claims to return `undefined` for an input that
was typed as `undefined`. Note that the code actually returned `null` on
`undefined` inputs. In the unlikely case you were relying on this,
please fix the typing of the consumers of the pipe output.
PR Close#37447
The old implementation of case conversion types can handle several
values which are not strings, but the signature did not reflect this.
The new one reports errors when falsy non-string inputs are given to
the pipe (such as `false` or `0`) and has a new signature which
instead reflects the behaviour on `null` and `undefined`.
Fixes#36259
BREAKING CHANGE:
The case conversion pipes no longer let falsy values through. They now
map both `null` and `undefined` to `null` and raise an exception on
invalid input (`0`, `false`, `NaN`) just like most "common pipes". If
your code required falsy values to pass through, you need to handle them
explicitly.
PR Close#37447
For the following example, the cursor is between `keySpan` and `valueSpan`
of the `BoundAttribute`.
```html
<test-cmp [foo]¦="bar"></test-cmp>
```
Our hybrid visitor will return `Element`in this case, which is the parent
node of the `BoundAttribute`.
This is because we only look at the `keySpan` and `valueSpan`, and not
the source span. The last element in the AST path is `Element`, so it gets
returned.
In this PR, I propose fixing this by adding a sentinel value `undefined`
to the AST path to signal that we've found a source span but the cursor is
neither in the key span nor the value span.
PR Close#38995
Now that we have `keySpan` for `BoundAttribute` (implemented in
https://github.com/angular/angular/pull/38898) we could do the same
for `Variable`.
This would allow us to distinguish the LHS and RHS from the whole source
span.
PR Close#38965
Prior to this change, each invocation of `loadStandardTestFiles` would
load the necessary files from disk. This function is typically called
at the top-level of a test module in order to share the result across
tests. The `//packages/compiler-cli/test/ngtsc` target has 8 modules
where this call occurs, each loading their own copy of
`node_modules/typescript` which is ~60MB in size, so the memory overhead
used to be significant. This commit loads the individual packages into
a standalone `Folder` and mounts this folder into the filesystem of
standard test files, such that all file contents are no longer
duplicated in memory.
PR Close#38909
Some compiler tests take a long time to run, even using multiple
executors. A profiling session revealed that most time is spent in
parsing source files, especially the default libraries are expensive to
parse.
The default library files are constant across all tests, so this commit
introduces a shared cache of parsed source files of the default
libraries. This achieves a significant improvement for several targets
on my machine:
//packages/compiler-cli/test/compliance: from 23s to 5s.
//packages/compiler-cli/test/ngtsc: from 115s to 11s.
Note that the number of shards for the compliance tests has been halved,
as the extra shards no longer provide any speedup.
PR Close#38909
`router.navigateByUrl` and `router.createUrlTree` only use a subset of the `NavigationExtras`. This commit
changes the parameter type to use new interfaces that only specify the properties used by
those function implementations. `NavigationExtras` extends both of those interfaces.
Fixes#18798
BREAKING CHANGE: While the new parameter types allow a variable of type
`NavigationExtras` to be passed in, they will not allow object literals,
as they may only specify known properties. They will also not accept
types that do not have properties in common with the ones in the `Pick`.
To fix this error, only specify properties from the `NavigationExtras` which are
actually used in the respective function calls or use a type assertion
on the object or variable: `as NavigationExtras`.
PR Close#38227
We are changing the default value from 'legacy' to 'corrected' so that new
applications are automatically opted-in to the corrected behavior from #22394.
BREAKING CHANGE: This commit changes the default value of
`relativeLinkResolution` from `'legacy'` to `'default'`. If your
application previously used the default by not specifying a value in the
`ExtraOptions` and uses relative links when navigating from children of
empty path routes, you will need to update your `RouterModule` to
specifically specify `'legacy'` for `relativeLinkResolution`.
See https://angular.io/api/router/ExtraOptions#relativeLinkResolution
for more details.
PR Close#25609
The keySpan in bound attributes provides more fine-grained location information and can be used
to disambiguate multiple bound attributes in a single microsyntax binding. Previously,
this case could not distinguish between the two different attributes because
the sourceSpans were identical and valueSpans would not match if the cursor
was located in a key.
PR Close#38955
Close#38334.
zone.js provides a flag DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION to let zone.js
throw the original error instead of wrap it when uncaught promise rejection found.
But the rejection value could be anything includes primitive value such as number.
In that case, we should not attach any additional properties to the value.
PR Close#38476
In Ivy, template type-checking has 3 modes: basic, full, and strict. The
primary difference between basic and full modes is that basic mode only
checks the top-level template, whereas full mode descends into nested
templates (embedded views like ngIfs and ngFors). Ivy applies this approach
to all of its template type-checking, including the DOM schema checks which
validate whether an element is a valid component/directive or not.
View Engine has both the basic and the full mode, with the same distinction.
However in View Engine, DOM schema checks happen for the full template even
in the basic mode.
Ivy's behavior here is technically a "fix" as it does not make sense for
some checks to apply to the full template and others only to the top-level
view. However, since g3 relies exclusively on the basic mode of checking and
developers there are used to DOM checks applying throughout their template,
this commit re-enables the nested schema checks even in basic mode only in
g3. This is done by enabling the checks only when Closure Compiler
annotations are requested.
Outside of g3, it's recommended that applications use at least the full mode
of checking (controlled by the `fullTemplateTypeCheck` flag), and ideally
the strict mode (`strictTemplates`).
PR Close#38943
The default value for `relativeLinkResolution` is changing from 'legacy' to 'corrected'.
This migration updates `RouterModule` configurations that use the default value to
now specifically use 'legacy' to prevent breakages when updating.
PR Close#38698
Though we currently have the knowledge of where the `key` for an
attribute binding appears during parsing, we do not propagate this
information to the output AST. This means that once we produce the
template AST, we have no way of mapping a template position to the key
span alone. The best we can currently do is map back to the
`sourceSpan`. This presents problems downstream, specifically for the
language service, where we cannot provide correct information about a
position in a template because the AST is not granular enough.
PR Close#38898
There is an inconsistency in overrideProvider behaviour. Testing documentation says
(https://angular.io/guide/testing-components-basics#createcomponent) that all override...
methods throw error if TestBed is already instantiated. However overrideProvider doesn't throw any error, but (same as
other override... methods) doesn't replace providers if TestBed is instantiated. Add TestBed instantiation check to
overrideProvider method to make it consistent.
BREAKING CHANGE:
If you call `TestBed.overrideProvider` after TestBed initialization, provider overrides are not applied. This
behavior is consistent with other override methods (such as `TestBed.overrideDirective`, etc) but they
throw an error to indicate that, when the check was missing in the `TestBed.overrideProvider` function.
Now calling `TestBed.overrideProvider` after TestBed initialization also triggers an
error, thus there is a chance that some tests (where `TestBed.overrideProvider` is
called after TestBed initialization) will start to fail and require updates to move `TestBed.overrideProvider` calls
before TestBed initialization is completed.
Issue mentioned here: https://github.com/angular/angular/issues/13460#issuecomment-636005966
Documentation: https://angular.io/guide/testing-components-basics#createcomponent
PR Close#38717
This commit introduces a new option for the service worker, called
`navigationRequestStrategy`, which adds the possibility to force the service worker
to always create a network request for navigation requests.
This enables the server redirects while retaining the offline behavior.
Fixes#38194
PR Close#38565
This commit refactors the `ExpressionTranslatorVisitor` so that it
is not tied directly to the TypeScript AST. Instead it uses generic
`TExpression` and `TStatement` types that are then converted
to concrete types by the `TypeScriptAstFactory`.
This paves the way for a `BabelAstFactory` that can be used to
generate Babel AST nodes instead of TypeScript, which will be
part of the new linker tool.
PR Close#38775
Previously each identifier was being imported individually, which made for a
very long import statement, but also obscurred, in the code, which identifiers
came from the compiler.
PR Close#38775
This file contains a number of classes making it long and hard to work with.
This commit splits the `ImportManager`, `Context` and `TypeTranslatorVisitor`
classes, along with associated functions and types into their own files.
PR Close#38775
When the target of the compiler is ES2015 or newer then we should
be generating `let` and `const` variable declarations rather than `var`.
PR Close#38775
Using an interface makes the code cleaner and more readable.
This change also adds the `range` property to the type to be used
for source-mapping.
PR Close#38775
The cast to `ts.Identifier` was a hack that "just happened to work".
The new approach is more robust and doesn't have to undermine
the type checker.
PR Close#38775
Let's say we have a code like
```html
<div<span>123</span>
```
Currently this gets parsed into a tree with the element tag `div<span`.
This has at least two downsides:
- An incorrect diagnostic that `</span>` doesn't close an element is
emitted.
- A consumer of the parse tree using it for editor services is unable to
provide correct completions for the opening `<span>` tag.
This patch attempts to fix both issues by instead parsing the code into
the same tree that would be parsed for `<div></div><span>123</span>`.
In particular, we do this by optimistically scanning an open tag as
usual, but if we do not notice a terminating '>', we mark the tag as
"incomplete". A parser then emits an error for the incomplete tag and
adds a synthetic (recovered) element node to the tree with the
incomplete open tag's name.
What's the downside of this? For one, a breaking change.
<ol>
<li>
The first breaking change is that `<` symbols that are ambiguously text
or opening tags will be parsed as opening tags instead of text in
element bodies. Take the code
```html
<p>a<b</p>
```
Clearly we cannot have the best of both worlds, and this patch chooses
to swap the parsing strategy to support the new feature. Of course, `<`
can still be inserted as text via the `<` entity.
</li>
</ol>
Part of #38596
PR Close#38681
This commit re-enables some tests that were temporarily disabled on Windows,
as they failed on native Windows CI. The Windows filesystem emulation has
been corrected in an earlier commit, such that the original failure would
now also occur during emulation on Linux CI.
PR Close#37782
In native windows, the drive letter is a capital letter, while our Windows
filesystem emulation would use lowercase drive letters. This difference may
introduce tests to behave differently in native Windows versus emulated
Windows, potentially causing unexpected CI failures on Windows CI after a PR
has been merged.
Resolves FW-2267
PR Close#37782
NG_VALUE_ACCESSOR is a multi injection token, users can and
should expect more than one ControlValueAccessor to be
available (and this is how it is used in @angular/forms).
This is now reflected in the definition of the injection token
by typing it as an array of ControlValueAccessor. The motivating
reason is that using the programmatic Injector api will now
type Injector#get correspondingly.
fixes#29351
BREAKING CHANGES
NG_VALUE_ACCESSOR is now typed as a readonly array rather than
a mutable scalar. It is used as a multi injection token and as
such it should always be expected that more than one accessor
may be returned.
PR Close#29723
The logic for computing identifiers, specifically for bound attributes
can be simplified by using the value span of the binding rather than the
source span.
PR Close#38899
The current tests print out the span numbers, which are really difficult to verify
since it requires manually going to the template string and looking at what
characters appear within those indexes. The better humanization would be
to use the toString method of the spans, which prints the span text itself
PR Close#38902
Currently, when we call jsonp method without importing HttpClientJsonpModule, an error message appears saying
'Attempted to construct Jsonp request without JsonpClientModule installed.' instance of 'Attempted to
construct Jsonp request without HttpClientJsonpModule installed.'
PR Close#38756
This commit updates several import statements in the core package to decrease the number of
cycles detected by the dependency checker tool.
PR Close#38805
Close#38795
in the XMLHttpRequest patch, when get `readystatechange` event, zone.js try to
invoke `load` event listener first, then call `invokeTask` to finish the
`XMLHttpRequest::send` macroTask, but if the request failed because the
server can not be reached, the `load` event listener will not be invoked,
so the `invokeTask` of the `XMLHttpRequest::send` will not be triggered either,
so we will have a non finished macroTask there which will make the Zone
not stable, also memory leak.
So in this PR, if the `XMLHttpRequest.status = 0` when we get the `readystatechange`
event, that means something wents wrong before we reached the server, we need to
invoke the task to finish the macroTask.
PR Close#38836
In #38666 we changed how ngcc deals with type expressions, where it
would now always emit the original type expression into the generated
code as a "local" type value reference instead of synthesizing new
imports using an "imported" type value reference. This was done as a fix
to properly deal with renamed symbols, however it turns out that the
compiler has special handling for certain imported symbols, e.g.
`ChangeDetectorRef` from `@angular/core`. The "local" type value
reference prevented this special logic from being hit, resulting in
incorrect compilation of pipe factories.
This commit fixes the issue by manually inspecting the import of the
type expression, in order to return an "imported" type value reference.
By manually inspecting the import we continue to handle renamed symbols.
Fixes#38883
PR Close#38892
Common AST formats such as TS and Babel do not use a separate
node for comments, but instead attach comments to other AST nodes.
Previously this was worked around in TS by creating a `NotEmittedStatement`
AST node to attach the comment to. But Babel does not have this facility,
so it will not be a viable approach for the linker.
This commit refactors the output AST, to remove the `CommentStmt` and
`JSDocCommentStmt` nodes. Instead statements have a collection of
`leadingComments` that are rendered/attached to the final AST nodes
when being translated or printed.
PR Close#38811
Close#38561, #38669
zone.js 0.11.1 introduces a breaking change to adpat Angular package format,
and it breaks the module loading order, before 0.11, in IE11, the `zone.js` es5
format bundle will be imported, but after 0.11, the `fesm2015` format bundle will
be imported, which causes error.
And since the only purpose of the `dist` folder of zone.js bundles is to keep backward
compatibility, in the original commit, I use package redirect to implement that, but
it is not fully backward compatible, we should keep the same dist structure as `0.10.3`.
PR Close#38797
When the response type is JSON, the `put()` overload signature did not have `reportProgress`
and `params` options. This makes it difficult to type-check this overload.
This commit adds them to the overload signature.
Fixes#23600
PR Close#37873
This change prevents comments from a resolved node from appearing at
each location the resolved expression is used and also prevents callers
of `Scope#resolve` from accidentally modifying / adding comments to the
declaration site.
PR Close#38857
Before Zone.js `v0.11.1`, Zone.js provides two format of bundles under `dist` folder,
`ES5` bundle `zone.js` and `ES2015` bundle `zone-evergreen.js`, these bundles are used
for `differential loading` of Angular. By default, the following code
```
import 'zone.js';
```
loads the `ES5` bundle `zone.js`.
From `v0.11.1`, Zone.js follows the [Angular Package Format]
(https://docs.google.com/document/d/1CZC2rcpxffTDfRDs6p1cfbmKNLA6x5O-NtkJglDaBVs),
so the folder structure of the Zone.js bundles is updated to match `Angular Package Format`.
So the same code
```
import 'zone.js';
```
loads the `ES2015` bundle.
This is a breaking change, so if the apps import zone.js in this way,
the apps will not work in legacy browsers such as `IE11`.
Zone.js still provides the same bundles under `dist` folder to keep backward
compatibility after `v0.11.1`. So the following code in `polyfills.ts` generated
by `Angular CLI` still works.
```
import 'zone.js/dist/zone';
```
For details, please refer the [changelog](./CHANGELOG.md) and
the [PR](https://github.com/angular/angular/pull/36540).
PR Close#38821
In #38227 the signatures of `navigateByUrl` and `createUrlTree` were updated to exclude unsupported
properties from their `extras` parameter. This migration looks for the relevant method calls that
pass in an `extras` parameter and drops the unsupported properties.
**Before:**
```
this._router.navigateByUrl('/', {skipLocationChange: false, fragment: 'foo'});
```
**After:**
```
this._router.navigateByUrl('/', {
/* Removed unsupported properties by Angular migration: fragment. */
skipLocationChange: false
});
```
These changes also move the method call detection logic out of the `Renderer2` migration and into
a common place so that it can be reused in other migrations.
PR Close#38825
The `createOrReuseChildren` function calls shouldReuseRoute with the
previous child values use as the future and the future child value used
as the current argument. This is incosistent with the argument order in
`createNode`. This inconsistent order can make it difficult/impossible
to correctly implement the `shouldReuseRoute` function. Usually this
order doesn't matter because simple equality checks are made on the
args and it doesn't matter which is which.
More detail can be found in the bug report: #16192.
Fix#16192
BREAKING CHANGE: This change corrects the argument order when calling
RouteReuseStrategy#shouldReuseRoute. Previously, when evaluating child
routes, they would be called with the future and current arguments would
be swapped. If your RouteReuseStrategy relies specifically on only the future
or current snapshot state, you may need to update the shouldReuseRoute
implementation's use of "future" and "current" ActivateRouteSnapshots.
PR Close#26949
In the integration test suite of ngcc, we load a set of files from
`node_modules` into memory. This includes the `typescript` package and
`@angular` scoped packages, which account for a large number of large
files that needs to be loaded from disk. This commit moves this work
to the top-level, such that it doesn't have to be repeated in all tests.
PR Close#38840
Recent optimizations to ngcc have significantly reduced the total time
it takes to process `node_modules`, to such extend that sharding across
multiple processes has become less effective. Previously, running
ngcc asynchronously would allow for up to 8 workers to be allocated,
however these workers have to repeat work that could otherwise be shared.
Because ngcc is now able to reuse more shared computations, the overhead
of multiple workers is increased and therefore becomes less effective.
As an additional benefit, having fewer workers requires less memory and
less startup time.
To give an idea, using the following test setup:
```bash
npx @angular/cli new perf-test
cd perf-test
yarn ng add @angular/material
./node_modules/.bin/ngcc --properties es2015 module main \
--first-only --create-ivy-entry-points
```
We observe the following figures on CI:
| | 10.1.1 | PR #38840 |
| ----------------- | --------- | --------- |
| Sync | 85s | 25s |
| Async (8 workers) | 22s | 16s |
| Async (4 workers) | - | 11s |
In addition to changing the default number of workers, ngcc will now
use the environment variable `NGCC_MAX_WORKERS` that may be configured
to either reduce or increase the number of workers.
PR Close#38840
ngcc creates typically two `ts.Program` instances for each entry-point,
one for processing sources and another one for processing the typings.
The creation of these programs is somewhat expensive, as it concerns
module resolution and parsing of source files.
This commit implements several layers of caching to optimize the
creation of programs:
1. A shared module resolution cache across all entry-points within a
single invocation of ngcc. Both the sources and typings program
benefit from this cache.
2. Sharing the parsed `ts.SourceFile` for a single entry-point between
the sources and typings program.
3. Sharing parsed `ts.SourceFile`s of TypeScript's default libraries
across all entry-points within a single invocation. Some of these
default library typings are large and therefore expensive to parse,
so sharing the parsed source files across all entry-points offers
a significant performance improvement.
Using a bare CLI app created using `ng new` + `ng add @angular/material`,
the above changes offer a 3-4x improvement in ngcc's processing time
when running synchronously and ~2x improvement for asynchronous runs.
PR Close#38840
When type-checking a component, the declaring NgModule scope is used
to create a directive matcher that contains flattened directive metadata,
i.e. the metadata of a directive and its base classes. This computation
is done for all components, whereas the type-check scope is constant per
NgModule. Additionally, the flattening of metadata is constant per
directive instance so doesn't necessarily have to be recomputed for
each component.
This commit introduces a `TypeCheckScopes` class that is responsible
for flattening directives and computing the scope per NgModule. It
caches the computed results as appropriate to avoid repeated computation.
PR Close#38539
For the compilation of a component, the compiler has to prepare some
information about the directives and pipes that are used in the template.
This information includes an expression for directives/pipes, for usage
within the compilation output. For large NgModule compilation scopes
this has shown to introduce a performance hotspot, as the generation of
expressions is quite expensive. This commit reduces the performance
overhead by only generating expressions for the directives/pipes that
are actually used within the template, significantly cutting down on
the compiler's resolve phase.
PR Close#38539
This commit creates a sample router test application to introduce the
symbol tests. It serves as a guard to ensure that any future work on the
router package does not unintentionally increase the payload size.
PR Close#38714
Recent work on compiler internals in #38539 led to an unexpected failure,
where a pipe used exclusively inside of an ICU would no longer be
emitted into the compilation output. This caused runtime errors due to
missing pipes.
The issue occurred because the change in #38539 would determine the set
of used pipes up-front, independent from the template compilation using
the `R3TargetBinder`. However, `R3TargetBinder` did not consider
expressions within ICUs, so any pipe usages within those expressions
would not be detected. This fix unblocks #38539 and also concerns
upcoming linker work, given that prelink compilations would not go
through full template compilation but only `R3TargetBinder`.
PR Close#38810
Close#38584
In zone.js 0.11.1, the `types` field is missing in the `package.json`,
the reason is in zone.js 0.11.0, the `files` field is used to specify the
types, but it cause the npm package not contain any bundles issue, so zone.js
0.11.1 remove the `files` field, which cause the `type` definition gone.
This PR concat the `zone.js.d.ts`, `zone.configurations.api.ts`, `zone.api.extensions.ts`
types into a single `zone.d.ts` file.
PR Close#38585
To discourage developers from mutating the arrays returned
from the following methods, their return types have been marked
as readonly.
* `getLocaleDayPeriods()`
* `getLocaleDayNames()`
* `getLocaleMonthNames()`
* `getLocaleEraNames()`
Fixes#27003
BREAKING CHANGE:
The locale data API has been marked as returning readonly arrays, rather
than mutable arrays, since these arrays are shared across calls to the
API. If you were mutating them (e.g. calling `sort()`, `push()`, `splice()`, etc)
then your code will not longer compile. If you need to mutate the array, you
should now take a copy (e.g. by calling `slice()`) and mutate the copy.
PR Close#30397
In a microsyntax expressions, some attributes are not bound after
desugaring. For example,
```html
<div *ngFor="let item of items">
</div>
```
gets desugared to
```html
<ng-template ngFor let-items [ngForOf]="items">
</ngtemplate>
```
In this case, `ngFor` should be a literal attribute with no RHS value.
Therefore, its source span should be just the `keySpan` and not the
source span of the original template node.
This allows language service to precisely pinpoint different spans in a
microsyntax to provide accurate information.
PR Close#38766
Adds `TemplateTypeChecker` operation to retrieve the `Symbol` of a
`TmplAstVariable` or `TmplAstReference` in a template.
Sometimes we need to traverse an intermediate variable declaration to arrive at
the correct `ts.Symbol`. For example, loop variables are declared using an intermediate:
```
<div *ngFor="let user of users">
{{user.name}}
</div>
```
Getting the symbol of user here (from the expression) is tricky, because the TCB looks like:
```
var _t0 = ...; // type of NgForOf
var _t1: any; // context of embedded view for NgForOf structural directive
if (NgForOf.ngTemplateContextGuard(_t0, _t1)) {
// _t1 is now NgForOfContext<...>
var _t2 = _t1.$implicit; // let user = '$implicit'
_t2.name; // user.name expression
}
```
Just getting the `ts.Expression` for the `AST` node `PropRead(ImplicitReceiver, 'user')`
via the sourcemaps will yield the `_t2` expression. This function recognizes that `_t2`
is a variable declared locally in the TCB, and actually fetch the `ts.Symbol` of its initializer.
These special handlings show the versatility of the `Symbol`
interface defined in the API. With this, when we encounter a template variable,
we can provide the declaration node, as well as specific information
about the variable instance, such as the `ts.Type` and `ts.Symbol`.
PR Close#38618
Adds support to the `TemplateTypeChecker` to get a `Symbol` of an AST
expression in a component template.
Not all expressions will have `ts.Symbol`s (e.g. there is no `ts.Symbol`
associated with the expression `a + b`, but there are for both the a and b
nodes individually).
PR Close#38618
Adds support to the `TemplateTypeChecker` for retrieving a `Symbol` for
`TmplAstTemplate` and `TmplAstElement` nodes in a component template.
PR Close#38618
Specifically, this commit adds support for retrieving a `Symbol` from a
`TmplAstBoundEvent` or `TmplAstBoundAttribute`. Other template nodes
will be supported in following commits.
PR Close#38618
The statements generated in the TCB are optimized for performance and producing diagnostics.
These optimizations can result in generating a TCB that does not have all the information
needed by the `TemplateTypeChecker` for retrieving `Symbol`s. For example, as an optimization,
the TCB will not generate variable declaration statements for directives that have no
references, inputs, or outputs. However, the `TemplateTypeChecker` always needs these
statements to be present in order to provide `ts.Symbol`s and `ts.Type`s for the directives.
This commit adds logic to the TCB generation to ensure the required
information is available in a form that the `TemplateTypeChecker` can
consume. It also adds an option to the `NgCompiler` that makes this
generation configurable.
PR Close#38618
This commit defines the interfaces which outline the information the
`TemplateTypeChecker` can return when requesting a Symbol for an item in the
`TemplateAst`.
Rather than providing the `ts.Symbol`, `ts.Type`, etc.
information in several separate functions, the `TemplateTypeChecker` can
instead provide all the useful information it knows about a particular
node in the `TemplateAst` and allow the callers to determine what to do
with it.
PR Close#38618
Currently, the `DatePipe` (via `formatDate()`) rounds fractions of a millisecond to the
nearest millisecond. This can cause dates that are less than a millisecond before midnight
to be incremented to the following day.
The [ECMAScript specification](https://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.11)
defines that `DateTime` milliseconds should always be rounded down, so that `999.9ms`
becomes `999ms`.
This change brings `formatDate()` and so `DatePipe` inline with the ECMAScript
specification.
Fixes#37989
BREAKING CHANGE:
When passing a date-time formatted string to the `DatePipe` in a format that contains
fractions of a millisecond, the milliseconds will now always be rounded down rather than
to the nearest millisecond.
Most applications will not be affected by this change. If this is not the desired behaviour
then consider pre-processing the string to round the millisecond part before passing
it to the `DatePipe`.
PR Close#38009
Some lower level APIs are used by CLI, and requiring
the `formatOpions` argument at that level is a
breaking change. This commit makes it optional
at every level to avoid the breaking change.
PR Close#38787
The `RefreshTransplantedView` flag is used to indicate that the view or one of its children
is transplanted and dirty, so it should still be refreshed as part of change detection.
This flag is set on the transplanted view itself as well setting a
counter on as its parents.
When a transplanted view is detached and still has this flag, it means
it got detached before it was refreshed. This can happen for "backwards
references" or transplanted views that are inserted at a location that
was already checked. In this case, we should decrement the parent
counters _and_ clear the flag on the detached view so it's not seen as
"transplanted" anymore (it is detached and has no parent counters to
adjust).
fixes#38619
PR Close#38768
This commit adds `ngDevMode` guard to throw some errors only in dev mode
The ngDevMode flag helps to tree-shake these error messages from production
builds (in dev mode everything will work as it works right now) to decrease
production bundle size.
PR Close#38674
This change contains the test from #38780 and also removes `defer` from
the `apply_redirects` logic because the change that introduced
`concatMap` instead of `map`...`concatAll` makes `defer` unnecessary.
PR Close#38781
This commit improves the error thrown by the downgrade module with a more
descriptive message on why the downgrade is failing.
Closes#37579
PR Close#38671
In the test project there are no longer reference markers and location
markers, so there's no need to "pre-process" the source files to remove
them. This will make the Ivy tests cleaner and faster.
PR Close#38777
When type-checking a component, the declaring NgModule scope is used
to create a directive matcher that contains flattened directive metadata,
i.e. the metadata of a directive and its base classes. This computation
is done for all components, whereas the type-check scope is constant per
NgModule. Additionally, the flattening of metadata is constant per
directive instance so doesn't necessarily have to be recomputed for
each component.
This commit introduces a `TypeCheckScopes` class that is responsible
for flattening directives and computing the scope per NgModule. It
caches the computed results as appropriate to avoid repeated computation.
PR Close#38539
For the compilation of a component, the compiler has to prepare some
information about the directives and pipes that are used in the template.
This information includes an expression for directives/pipes, for usage
within the compilation output. For large NgModule compilation scopes
this has shown to introduce a performance hotspot, as the generation of
expressions is quite expensive. This commit reduces the performance
overhead by only generating expressions for the directives/pipes that
are actually used within the template, significantly cutting down on
the compiler's resolve phase.
PR Close#38539
Whitespace can be relevant in extracted XLIFF translation files.
Some i18n tools - e.g. CAT tool (OmegaT) - will reformat
the file to collapse whitespace if there is no indication to tell it
not to.
This commit adds the ability to specify "format options" that are passed
to the translation file serializer. The XLIFF 1.2 and 2.0 seralizers have
been updated to accept `{"xml:space":"preserve"}` format option which will
by added to the `<file>` element in the serialized translation file during
extraction.
Fixes#38679
PR Close#38737
In most browsers, clicking links with the Alt key has a special behavior, for example, Chrome
downloads the target resource. As with other modifier keys, the router should stop the original
navigation to avoid preventing the browser’s default behavior.
When users click a link while holding the Alt key together, the browsers behave as follows.
Windows 10:
| Browser | Behavior |
|:-----------|:--------------------------------------------|
| Chrome 84 | Download the target resource |
| Firefox 79 | Prevent navigation and therefore do nothing |
| Edge 84 | Download the target resource |
| IE 11 | No impact |
macOS Catalina:
| Browser | Behavior |
|:-----------|:--------------------------------------------|
| Chrome 84 | Download the target resource |
| Firefox 79 | Prevent navigation and therefore do nothing |
| Safari 13 | Download the target resource |
PR Close#38375
The type-to-value conversion could previously crash if a symbol was
resolved that does not have any declarations, e.g. because it's imported
from a missing module. This would typically result in a semantic
TypeScript diagnostic and halt further compilation, therefore not
reaching the type-to-value conversion logic. In Bazel however, it turns
out that Angular semantic diagnostics are requested even if there are
semantic TypeScript errors in the program, so it would then reach the
type-to-value conversation and crash.
This commit fixes the unsafe access and adds a test that ignores the
TypeScript semantic error, effectively replicating the situation as
experienced under Bazel.
Fixes#38670
PR Close#38684
Previously, localized strings had very limited or incorrect source-mapping
information available.
Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.
This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.
See #38588 (comment)
PR Close#38645
The `MessagePiece` and derived classes, `LiteralPiece` and `PlaceholderPiece`
need to be referenced in the `LocalizedString` output AST class, so that we
can render the source-spans of each piece.
PR Close#38645
The `TagPlaceholder` can contain children, in which case there are two source
spans of interest: the opening tag and the closing tag. This commit now allows
the closing tag source-span to be tracked, so that it can be used later in
source-mapping.
PR Close#38645
The expression parser will split the expression up at the interpolation markers
into expressions and static strings. This commit also captures the positions of
these strings in the expression to be used in source-mapping later.
PR Close#38645
Since the `defineProperty` not swallow error any longer, now the tests compile
source code in `commonjs` mode, and the code generated includes the code like this
```
Object.defineProperty(exports, "__esModule", {value: true});
```
And the `exports` is undefined in some browsers, but the error is swallowed before
this PR, and all tests run successfully, but it is not correct behavior. After this PR,
the code above failed. So we need to compile the source code in `umd` mode.
PR Close#37582
Close#37432
zone.js monkey patches the `Object.defineProperty` API long time ago
angular/zone.js@383b479
to resolve issues in very old version of Chrome web which override the
property of `CustomElements`, and this is not an issue any longer, so
we want to remove this monkey patch, since it may swallow the errors when the user
want to define property on unconfigurable or frozen object properties.
But currently there are several apps and tests depends on this patch, since
it also change the `configurable` property to `true` by default, so
in this PR we update the logic to not to swallow error any longer unless the property
is the callbacks of `document.registerElements`.
BREAKING CHANGE:
ZoneJS no longer swallows errors produced by `Object.defineProperty` calls.
Prior to this change, ZoneJS monkey patched `Object.defineProperty` and if there is an error
(such as the property is not configurable or not writable) the patched logic swallowed it
and only console.log was produced. This behavior used to hide real errors,
so the logic is now updated to trigger original errors (if any). One exception
where the patch remains in place is `document.registerElement`
(to allow smooth transition for code/polyfills that rely on old behavior in legacy browsers).
If your code relies on the old behavior (where errors were not thrown before),
you may need to update the logic to handle the errors that are no longer masked by ZoneJS patch.
PR Close#37582
Previously this interface was mostly stored in compiler-cli, but it
contains some properties that would be useful for compiling the
"declare component" prelink code.
This commit moves some of the interface over to the compiler
package so that it can be referenced there without creating a
circular dependency between the compiler and compiler-cli.
PR Close#38594
The `R3TargetBinder` accepts an interface for directive metadata which
declares types for `input` and `output` objects. These types convey the
mapping between the property names for an input or output and the
corresponding property name on the component class. Due to
`R3TargetBinder`'s requirements, this mapping was specified with property
names as keys and field names as values.
However, because of duck typing, this interface was accidentally satisifed
by the opposite mapping, of field names to property names, that was produced
in other parts of the compiler. This form more naturally represents the data
model for inputs.
Rather than accept the field -> property mapping and invert it, this commit
introduces a new abstraction for such mappings which is bidirectional,
eliminating the ambiguous plain object type. This mapping uses new,
unambiguous terminology ("class property name" and "binding property name")
and can be used to satisfy both the needs of the binder as well as those of
the template type-checker (field -> property).
A new test ensures that the input/output metadata produced by the compiler
during analysis is directly compatible with the binder via this unambiguous
new interface.
PR Close#38685
This commit adds `ngDevMode` guard to throw some errors only in dev mode
(similar to how things work in other parts of Ivy runtime code). The
`ngDevMode` flag helps to tree-shake these error messages from production
builds (in dev mode everything will work as it works right now) to decrease
production bundle size.
PR Close#38612
If a type has been renamed when it was exported, we need to
reference the external public alias name rather than the internal
original name for the type. Otherwise we will try to import the
type by its internal name, which is not publicly accessible.
Fixes#38238
PR Close#38666
A recent change to `@angular/localize` brought in the `AbsoluteFsPath` type
from the `@angular/compiler-cli`. But this brought along with it a reference
to NodeJS typings - specifically the `FileSystem` interface refers to the
`Buffer` type from NodeJS.
This affects compilation of `@angular/localize` code that will be run in
the browser - for example projects that reference `loadTranslations()`.
The compilation breaks if the NodeJS typings are not included in the build.
Clearly it is not desirable to have these typings included when the project
is not targeting NodeJS.
This commit replaces references to the NodeJS `Buffer` type with `Uint8Array`,
which is available across all platforms and is actually the super-class of
`Buffer`.
Fixes#38692
PR Close#38700
Previously, the location of a translation message, in XLIFF 2, was only
rendered if there were also notes for meaning or description. Now the
location will be rendered even if the other metadata is not provided.
Fixes#38705
PR Close#38713
In general, the router only matches and loads a single Route config tree. However,
named outlets with empty paths are a special case where the router can
and should actually match two different `Route`s and ensure that the
modules are loaded for each match.
This change updates the "ApplyRedirects" stage to ensure that named
outlets with empty paths finish loading their configs before proceeding
to the next stage in the routing pipe. This is necessary because if the
named outlet has `loadChildren` but the associated lazy config is not loaded
before following stages attempt to match and activate relevant `Route`s,
an error will occur.
fixes#12842
PR Close#38379
Previously, the compiler was not able to display template parsing errors as
true `ts.Diagnostic`s that point inside the template. Instead, it would
throw an actual `Error`, and "crash" with a stack trace containing the
template errors.
Not only is this a poor user experience, but it causes the Language Service
to also crash as the user is editing a template (in actuality the LS has to
work around this bug).
With this commit, such parsing errors are converted to true template
diagnostics with appropriate span information to be displayed contextually
along with all other diagnostics. This majorly improves the user experience
and unblocks the Language Service from having to deal with the compiler
"crashing" to report errors.
PR Close#38576
The template type-checking engine includes utilities for creating
`ts.Diagnostic`s for component templates. Previously only the template type-
checker itself created such diagnostics. However, the template parser also
produces errors which should be represented as template diagnostics.
This commit prepares for that conversion by extracting the machinery for
producing template diagnostics into its own sub-package, so that other parts
of the compiler can depend on it without depending on the entire template
type-checker.
PR Close#38576
`tView` that is stored on a component def contains information about directives and pipes
that are available in the scope of this component. Patching component scope causes `tView` to be
updated. Prior to this commit, the `tView` information was not restored/reset in case component
class is not declared in the `declarations` field while calling `TestBed.configureTestingModule`,
thus causing `tView` to be reused between tests (thus preserving scopes information between tests).
This commit updates TestBed logic to preserve `tView` value before applying scope changes and
reset it back to the previous state between tests.
Closes#38600.
PR Close#38659
Previously this package was installed in the default `dependencies` section
of `package.json`, but this meant that its own dependencies are treated as
dependencies of the main project: Babel, for example.
Generally, $localize` is not used at runtime - it is compiled out by the
translation tooling, so there is no need for it to be a full dependency.
In fact, even if it is used at runtime, the package itself is only used
at dev-time since the runtime bits will be bundled into a distributable.
So putting this package in `devDependencies` would only prevent libraries
from bringing the package into application projects that used them. This
is probably good in itself, since it should be up to the downstream project
to decide if it wants to include `@angular/localize` at runtime.
This commit changes the default location of the package to be the
`devDependencies` section, but gives an option `useAtRuntime` to choose
otherwise.
Fixes#38329
PR Close#38680
Remove CollectionChangeRecord as it was deprecated for removal in v4, use
IterableChangeRecord instead.
BREAKING CHANGE: CollectionChangeRecord has been removed, use IterableChangeRecord
instead
PR Close#38668
Previously, the `sourceSpan` and `startSourceSpan` were the same
object, which meant that you had the following situation:
```
element = <div>some content</div>
sourceSpan = <div>
startSourceSpan = <div>
endSourceSpan = </div>
```
This made `sourceSpan` redundant and meant that if you
wanted a span for the whole element including its content
and closing tag, it had to be computed.
Now `sourceSpan` is separated from `startSourceSpan`
resulting in:
```
element = <div>some content</div>
sourceSpan = <div>some content</div>
startSourceSpan = <div>
endSourceSpan = </div>
```
PR Close#38581
Previously, the `startSourceSpan` property could be null
but in reality it is always well defined - except for a legacy
case in the old i18n extraction/merging code, where the
typings for source-spans are already being undermined.
Making this property non-null, simplifies code elsewhere
in the project.
PR Close#38581
Previously the lexer was responsible for deciding whether an "inline"
template should also have its line-endings normalized.
Now this decision is made higher up in the call stack to allow more
flexibility in the parser/lexer.
PR Close#38581
Previously the position of the error in a translation file when parsing
it was not displayed. Just the error message.
Now the position (line and column) and some context is displayed
along with the error messages.
Fixes#38377
PR Close#38673
This commit ensures that the `updateValueAndValidity` method takes the
`asyncValidator` into consideration to emit on the `statusChanges` observables.
This is necessary so that any subsequent changes are emitted properly to any
subscribers.
Closes#20424Closes#14542
BREAKING CHANGE:
Previously if FormControl, FormGroup and FormArray class instances had async validators
defined at initialization time, the status change event was not emitted once async validator
completed. After this change the status event is emitted into the `statusChanges` observable.
If your code relies on the old behavior, you can filter/ignore this additional status change
event.
PR Close#38354
The HTML parser gets an element's namespace either from the tag name
(e.g. `<svg:rect>`) or from its parent element `<svg><rect></svg>`) which
breaks down when an element is inside of an SVG `foreignElement`,
because foreign elements allow nodes from a different namespace to be
inserted into an SVG.
These changes add another flag to the tag definitions which tells child
nodes whether to try to inherit their namespaces from their parents.
It also adds a definition for `foreignObject` with the new flag,
allowing elements placed inside it to infer their namespaces instead.
Fixes#37218.
PR Close#38477
In several occasions it has been observed when the browser has evicted
eagerly cached assets from the cache and which can also not be found on the
server anymore. This can lead to broken state where only parts of the application
will load and others will fail.
This commit fixes this issue by checking for the missing asset in the cache
and on the server. If this condition is true, the broken client will be
notified about the current state through the `UnrecoverableStateError`.
Closes#36539
PR Close#36847
Previously, the condition to make the cache busted was executing although
the network request was successful. However, this is not valid. The cache
should only be marked as busted when the request failed. This commit fixes
the invalid condition.
PR Close#36847
Prior to this commit, a lot of internal-only class properties and methods (such as `ngOnChanges`)
of the Forms package directives were exposed on angular.io website. These fields are not expected
to be called externally (they are used/invoked by framework only), since they are part of internal
implementations of the following interfaces:
* Angular lifecycle hook interfaces
* ControlValueAccessor interface
* Validator interface
Having these internal-only fields in docs creates unnecessary noise on directive detail pages.
This commit adds the `@nodoc` annotation to these properties and methods to keep fields in the
golden files, but hide them in docs.
PR Close#38583
When extracting i18n messages from source code, the XLIFF
serializers were missing some required attributes on the `<file>`
element.
This commit re-introduces the `original` property to each of XLIFF 1.2
and 2.0 serializers. Also it adds in the required `id` property for the
XLIFF 2.0 seralizer.
Fixes#38570
PR Close#38575
Formats like XLIFF allow the text of the original source to
be included as metadata. This commit fixes the message
extractor to also render this text when available.
PR Close#38536
Some translation file formats would like to be able to render the
text of placeholders taken from the original source files. This commit
adds this information to the extracted messages so that it can be
used in translation file serializers.
PR Close#38536
Previously, exceptions that were not `BabelParseError`s were just ignored.
Such exceptions are most likely programming errors in the package.
They are now re-thrown to ensure that the error is not hidden.
PR Close#38536
This commit is a tidy up of the translate plugin unit tests, but also ensures
that the tests are run in the context of a mock FileSystem. This ensures
that the tests are resilient to future refactors of the plugins that will
require a FileSystem to be initialized.
PR Close#38536
When extracting messages, source-mapping information is used to find
the original location of the message being extracted. This commit will
now include the text from the original source in the message location
so that it can be serialized into the translation file.
PR Close#38536
In preparation for supporting `equiv-text` placeholder information in
extracted translation files, this commit adds these optional properties
to the `ParsedMessage` interface and updates `parseMessage()` to
be able to store them.
PR Close#38536
Close#38361
zone.js monkey patch toString, and check the instance is `Promise` or not by using `instanceof Promise`,
sometimes when Promise is not available, the `instanceof` operation fails
and throw `TypeError: Right-hand side of 'instanceof' is not an object`
this PR check `typeof Promise` equals to function or not to prevent the error.
PR Close#38350
With Typescript 4, `ts.updateIdentifier` is no longer available.
Calling `ts.updateIdentifier` used to return the same node when
`typeArguments` was `undefined` because `node.typeArguments`
was also `undefined`.
Relevant TS code:
```js
function updateIdentifier(node, typeArguments) {
return node.typeArguments !== typeArguments
? updateNode(createIdentifier(ts.idText(node), typeArguments), node)
: node;
}
```
PR Close#38076
This commit adds a guard before throwing any forms errors. This will tree-shake
error messages which cannot be minified. It should also help to reduce the
bundle size of the `forms` package in production by ~20%.
Closes#37697
PR Close#37821
In many testing scenarios, there is a common pattern:
1. Overwrite template (inline or external)
2. Find cursor position
3. Call one of language service APIs
4. Inspect spans in result
In order to faciliate this pattern, this commit refactors
`MockHost.overwrite()` and `MockHost.overwriteInlineTemplate()` to
allow a faux cursor symbol `¦` to be injected into the template, and
the methods will automatically remove it before updating the script snapshot.
Both methods will return the cursor position and the new text without
the cursor symbol.
This makes testing very convenient. Here's a typical example:
```ts
const {position, text} = mockHost.overwrite('template.html', `{{ ti¦tle }}`);
const quickInfo = ngLS.getQuickInfoAtPosition('template.html', position);
const {start, length} = quickInfo!.textSpan;
expect(text.substring(start, start + length)).toBe('title');
```
PR Close#38552
This commit introduces two visitors, one for Template AST and the other
for Expression AST to allow us to easily find the node that most closely
corresponds to a given cursor position.
This is crucial because many language service APIs take in a `position`
parameter, and the information returned depends on how well we can find
a good candidate node.
In View Engine implementation of language service, the search for the node
and the processing of information to return the result are strongly coupled.
This makes the code hard to understand and hard to debug because the stack
trace is often littered with layers of visitor calls.
With this new feature, we could test the "searching" part separately and
colocate all the logic (aka hacks) that's required to retrieve an accurate
span for a given node.
Right now, only the most "narrow" node is returned by the main exported
function `findNodeAtPosition`. If needed, we could expose the entire AST
path, or expose other methods to provide more context for a node.
Note that due to limitations in the template AST interface, there are
a few known cases where microsyntax spans are not recorded properly.
This will be dealt with in a follow-up PR.
PR Close#38540
Prior to this change, the unary + and - operators would be parsed as `x - 0`
and `0 - x` respectively. The runtime semantics of these expressions are
equivalent, however they may introduce inaccurate template type checking
errors as the literal type is lost, for example:
```ts
@Component({
template: `<button [disabled]="isAdjacent(-1)"></button>`
})
export class Example {
isAdjacent(direction: -1 | 1): boolean { return false; }
}
```
would incorrectly report a type-check error:
> error TS2345: Argument of type 'number' is not assignable to parameter
of type '-1 | 1'.
Additionally, the translated expression for the unary + operator would be
considered as arithmetic expression with an incompatible left-hand side:
> error TS2362: The left-hand side of an arithmetic operation must be of
type 'any', 'number', 'bigint' or an enum type.
To resolve this issues, the implicit transformation should be avoided.
This commit adds a new unary AST node to represent these expressions,
allowing for more accurate type-checking.
Fixes#20845Fixes#36178
PR Close#37918
We had a couple of places where we were assuming that if a particular
symbol has a value, then it will exist at runtime. This is true in most cases,
but it breaks down for `const` enums.
Fixes#38513.
PR Close#38542
Previously, if `useLegacyIds` was enabled, the message extractor
was always rendering the legacy message ids in translation
files even if an explicit "custom message id" had been provided
in the original message.
PR Close#38498
Fix a bug in the HTML sanitizer where an unclosed iframe tag would
result in an escaped closing body tag as the output:
_sanitizeHtml(document, '<iframe>') => '</body>'
This closing body tag comes from the DOMParserHelper where the HTML to be
sanitized is wrapped with surrounding body tags. When an opening iframe
tag is parsed by DOMParser, which DOMParserHelper uses, everything up
until its matching closing tag is consumed as a text node. In the above
example this includes the appended closing body tag.
By removing the explicit closing body tag from the DOMParserHelper and
relying on the body tag being closed implicitly at the end, the above
example is sanitized as expected:
_sanitizeHtml(document, '<iframe>') => ''
PR Close#38454
Previously nested container placeholders (i.e. HTML elements) were
not being fully parsed from translation files. This resulted in bad
translation of messages that contain these placeholders.
Note that this causes the canonical message ID to change for
such messages. Currently all messages generated from
templates use "legacy" message ids that are not affected by
this change, so this fix should not be seen as a breaking change.
Fixes#38422
PR Close#38452
When creating a `ParsedTranslation` from a set of message parts and
placeholder names a textual representation of the message is computed.
Previously the last placeholder and text segment were missing from this
computed message string.
PR Close#38452
This commit adds a `getTemplateOfComponent` method to the
`TemplateTypeChecker` API, which retrieves the actual nodes parsed and used
by the compiler for template type-checking. This is advantageous for the
language service, which may need to query other APIs in
`TemplateTypeChecker` that require the same nodes used to bind the template
while generating the TCB.
Fixes#38352
PR Close#38355
In general, the router only matches and loads a single Route config tree. However,
named outlets with empty paths are a special case where the router can
and should actually match two different `Route`s and ensure that the
modules are loaded for each match.
This change updates the "ApplyRedirects" stage to ensure that named
outlets with empty paths finish loading their configs before proceeding
to the next stage in the routing pipe. This is necessary because if the
named outlet has `loadChildren` but the associated lazy config is not loaded
before following stages attempt to match and activate relevant `Route`s,
an error will occur.
fixes#12842
PR Close#38379
Close#38526, #38516, #38513
After update to `APF`, the `directories` and `files` options are not compatible,
so we need to remove those fileds to make sure everything work as expected.
PR Close#38528
This commit introduces a new subscription in the `routerLinkActive` directive which triggers an update
when any of its associated routerLinks have changes. `RouterLinkActive` not only needs to know when
links are added or removed, but it also needs to know about if a link it already knows about
changes in some way.
Quick note that `from...mergeAll` is used instead of just a simple
`merge` (or `scheduled...mergeAll`) to avoid introducing new rxjs
operators in order to keep bundle size down.
Fixes#18469
PR Close#38511
This commit introduces a new subscription in the `routerLinkActive` directive which triggers an update
when any of its associated routerLinks have changes. `RouterLinkActive` not only needs to know when
links are added or removed, but it also needs to know about if a link it already knows about
changes in some way.
Quick note that `from...mergeAll` is used instead of just a simple
`merge` (or `scheduled...mergeAll`) to avoid introducing new rxjs
operators in order to keep bundle size down.
Fixes#18469
PR Close#38349
Now that Ivy compiler has a proper `TemplateTypeChecker` interface
(see https://github.com/angular/angular/pull/38105) we no longer need to
keep the temporary compiler implementation.
The temporary compiler was created to enable testing infrastructure to
be developed for the Ivy language service.
This commit removes the whole `ivy/compiler` directory and moves two
functions `createTypeCheckingProgramStrategy` and
`getOrCreateTypeCheckScriptInfo` to the `LanguageService` class.
Also re-enable the Ivy LS test since it's no longer blocking development.
PR Close#38310
Similarly to the change we landed in the `@angular/core` reflection
capabilities, we need to make sure that ngcc can detect pass-through
delegate constructors for classes using downleveled ES2015 output.
More details can be found in the preceding commit, and in the issue
outlining the problem: #38453.
Fixes#38453.
PR Close#38463
In the Angular Package Format, we always shipped UMD bundles and previously even ES5 module output.
With V10, we removed the ES5 module output but kept the UMD ES5 output.
For this, we were able to remove our second TypeScript transpilation. Instead we started only
building ES2015 output and then downleveled it to ES5 UMD for the NPM packages. This worked
as expected but unveiled an issue in the `@angular/core` reflection capabilities.
In JIT mode, Angular determines constructor parameters (for DI) using the `ReflectionCapabilities`. The
reflection capabilities basically read runtime metadata of classes to determine the DI parameters. Such
metadata can be either stored in static class properties like `ctorParameters` or within TypeScript's `design:params`.
If Angular comes across a class that does not have any parameter metadata, it tries to detect if the
given class is actually delegating to an inherited class. It does this naively in JIT by checking if the
stringified class (function in ES5) matches a certain pattern. e.g.
```js
function MatTable() {
var _this = _super.apply(this, arguments) || this;
```
These patterns are reluctant to changes of the class output. If a class is not recognized properly, the
DI parameters will be assumed empty and the class is **incorrectly** constructed without arguments.
This actually happened as part of v10 now. Since we downlevel ES2015 to ES5 (instead of previously
compiling sources directly to ES5), the class output changed slightly so that Angular no longer detects
it. e.g.
```js
var _this = _super.apply(this, __spread(arguments)) || this;
```
This happens because the ES2015 output will receive an auto-generated constructor if the class
defines class properties. This constructor is then already containing an explicit `super` call.
```js
export class MatTable extends CdkTable {
constructor() {
super(...arguments);
this.disabled = true;
}
}
```
If we then downlevel this file to ES5 with `--downlevelIteration`, TypeScript adjusts the `super` call so that
the spread operator is no longer used (not supported in ES5). The resulting super call is different to the
super call that would have been emitted if we would directly transpile to ES5. Ultimately, Angular no
longer detects such classes as having an delegate constructor -> and DI breaks.
We fix this by expanding the rather naive RegExp patterns used for the reflection capabilities
so that downleveled pass-through/delegate constructors are properly detected. There is a risk
of a false-positive as we cannot detect whether `__spread` is actually the TypeScript spread
helper, but given the reflection patterns already make lots of assumptions (e.g. that `super` is
actually the superclass, we should be fine making this assumption too. The false-positive would
not result in a broken app, but rather in unnecessary providers being injected (as a noop).
Fixes#38453
PR Close#38463
Previously placeholders were only rendered for dynamic interpolation
expressons in `$localize` tagged strings. But there are also potentially
dynamic values in ICU expressions too, so we need to render these as
placeholders when extracting i18n messages into translation files.
PR Close#38484
This commit updates the code to move generated i18n statements into the `consts` field of
ComponentDef to avoid invoking `$localize` function before component initialization (to better
support runtime translations) and also avoid problems with lazy-loading when i18n defs may not
be present in a chunk where it's referenced.
Prior to this change the i18n statements were generated at the top leve:
```
var I18N_0;
if (typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode) {
var MSG_X = goog.getMsg(“…”);
I18N_0 = MSG_X;
} else {
I18N_0 = $localize('...');
}
defineComponent({
// ...
template: function App_Template(rf, ctx) {
i0.ɵɵi18n(2, I18N_0);
}
});
```
This commit updates the logic to generate the following code instead:
```
defineComponent({
// ...
consts: function() {
var I18N_0;
if (typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode) {
var MSG_X = goog.getMsg(“…”);
I18N_0 = MSG_X;
} else {
I18N_0 = $localize('...');
}
return [
I18N_0
];
},
template: function App_Template(rf, ctx) {
i0.ɵɵi18n(2, 0);
}
});
```
Also note that i18n template instructions now refer to the `consts` array using an index
(similar to other template instructions).
PR Close#38404
This commit fixes a regression from "fix(common): ensure
scrollRestoration is writable (#30630)" that caused scrolling to not
happen at all in browsers that do not support scroll restoration. The
issue was that `supportScrollRestoration` was updated to return `false`
if a browser did not have a writable `scrollRestoration`. However, the
previous behavior was that the function would return `true` if
`window.scrollTo` was defined. Every scrolling function in the
`ViewportScroller` used `supportScrollRestoration` and, with the update
in bb88c9fa3d, no scrolling would be
performed if a browser did not have writable `scrollRestoration` but
_did_ have `window.scrollTo`.
Note, that this failure was detected in the saucelabs tests. IE does not
support scroll restoration so IE tests were failing.
PR Close#38468
When removal of one view causes removal of another one from the same
ViewContainerRef it triggers an error with views length calculation. This commit
fixes this bug by removing a view from the list of available views before invoking
actual view removal (which might be recursive and relies on the length of the list
of available views).
Fixes#38201.
PR Close#38317
For a template that contains for example `<span *ngIf="first"></span>`
there's no need to render the `NgIf` guard expression, as the child
scope does not have any type-checking statements, so any narrowing
effect of the guard is not applicable.
This seems like a minor improvement, however it reduces the number of
flow-node antecedents that TypeScript needs to keep into account for
such cases, resulting in an overall reduction of type-checking time.
PR Close#38418
The template type-checker would always generate a directive declaration
even if its type was never used. For example, directives without any
input nor output bindings nor exportAs references don't need the
directive to be declared, as its type would never be used.
This commit makes the `TcbOp`s that are responsible for declaring a
directive as optional, such that they are only executed when requested
from another operation.
PR Close#38418
The template type-checker would generate a statement with a call
expression for all DOM elements in a template of the form:
```
const _t1 = document.createElement("div");
```
Profiling has shown that this is a particularly expensive call to
perform type inference on, as TypeScript needs to perform signature
selection of `Document.createElement` and resolve the exact type from
the `HTMLElementTagNameMap`. However, it can be observed that the
statement by itself does not contribute anything to the type-checking
result if `_t1` is not actually used anywhere, which is only rarely the
case---it requires that the element is referenced by its name from
somewhere else in the template. Consequently, the type-checker can skip
generating this statement altogether for most DOM elements.
The effect of this optimization is significant in several phases:
1. Less type-check code to generate
2. Less type-check code to emit and parse again
3. No expensive type inference to perform for the call expression
The effect on phase 3 is the most significant here, as type-checking is
not currently incremental in the sense that only phases 1 and 2 can
be reused from a prior compilation. The actual type-checking of all
templates in phase 3 needs to be repeated on each incremental
compilation, so any performance gains we achieve here are very
beneficial.
PR Close#38418
The `@HostListener` functions and lifecycle hooks aren't intended to be public API but
do need to appear in the `.d.ts` files or type checking will break. Adding the
nodoc annotation will correctly hide this function on the docs site.
Again, note that `@internal` cannot be used because the result would be
that the functions then do not appear in the `.d.ts` files. This would
break lifecycle hooks because the class would be seen as not
implementing the interface correctly. This would also break
`HostListener` because the compiled templates would attempt to call the
`onClick` functions, but those would also not appear in the `d.ts` and
would produce errors like "Property 'onClick' does not exist on type 'RouterLinkWithHref'".
PR Close#38448
Fixes an error if a CSS custom property, used inside a host binding, has a
number in its name. The error is thrown because the styling parser only
expects characters from A to Z,dashes, underscores and a handful of other
characters.
Fixes#37292.
PR Close#38432
The compiler does not currently report errors when there's an `@Input()`
for a `private`, `protected`, or `readonly` directive/component class member.
This change adds an option to enable reporting errors when a template
attempts to bind to one of these restricted input fields.
PR Close#38249
Prior to this change, the template type checker would always use a
type-constructor to instantiate a directive. This type-constructor call
serves two purposes:
1. Infer any generic types for the directive instance from the inputs
that are passed in.
2. Type check the inputs that are passed into the directive's inputs.
The first purpose is only relevant when the directive actually has any
generic types and using a type-constructor for these cases inhibits
a type-check performance penalty, as a type-constructor's signature is
quite complex and needs to be generated for each directive.
This commit refactors the generated type-check blocks to only generate
a type-constructor call for directives that have generic types. Type
checking of inputs is achieved by generating individual statements for
all inputs, using assignments into the directive's fields.
Even if a type-constructor is used for type-inference of generic types
will the input checking also be achieved using the individual assignment
statements. This is done to support the rework of the language service,
which will start to extract symbol information from the type-check
blocks.
As a future optimization, it may be possible to reduce the number of
inputs passed into a type-constructor to only those inputs that
contribute the the type-inference of the generics. As this is not a
necessity at the moment this is left as follow-up work.
Closes#38185
PR Close#38249
"Quote expressions" are expressions that start with an identifier followed by a
comma, allowing arbitrary syntax to follow. These kinds of expressions would
throw a an error in the template type checker, which would make them hard to
track down. As quote expressions are not generally used at all, the error would
typically occur for URLs that would inadvertently occur in a binding:
```html
<a [href]="https://example.com"></a>
```
This commit lets such bindings be inferred as the `any` type.
Fixes#36568
Resolves FW-2051
PR Close#37917
In TypeScript 3.8 support was added for type-only imports, which only brings in
the symbol as a type, not their value. The Angular compiler did not yet take
the type-only keyword into account when representing symbols in type positions
as value expressions. The class metadata that the compiler emits would include
the value expression for its parameter types, generating actual imports as
necessary. For type-only imports this should not be done, as it introduces an
actual import of the module that was originally just a type-only import.
This commit lets the compiler deal with type-only imports specially, preventing
a value expression from being created.
Fixes#37900
PR Close#37912
When using the safe navigation operator in a binding expression, a temporary
variable may be used for storing the result of a side-effectful call.
For example, the following template uses a pipe and a safe property access:
```html
<app-person-view [enabled]="enabled" [firstName]="(person$ | async)?.name"></app-person-view>
```
The result of the pipe evaluation is stored in a temporary to be able to check
whether it is present. The temporary variable needs to be declared in a separate
statement and this would also cause the full expression itself to be pulled out
into a separate statement. This would compile into the following
pseudo-code instructions:
```js
var temp = null;
var firstName = (temp = pipe('async', ctx.person$)) == null ? null : temp.name;
property('enabled', ctx.enabled)('firstName', firstName);
```
Notice that the pipe evaluation happens before evaluating the `enabled` binding,
such that the runtime's internal binding index would correspond with `enabled`,
not `firstName`. This introduces a problem when the pipe uses `WrappedValue` to
force a change to be detected, as the runtime would then mark the binding slot
corresponding with `enabled` as dirty, instead of `firstName`. This results
in the `enabled` binding to be updated, triggering setters and affecting how
`OnChanges` is called.
In the pseudo-code above, the intermediate `firstName` variable is not strictly
necessary---it only improved readability a bit---and emitting it inline with
the binding itself avoids the out-of-order execution of the pipe:
```js
var temp = null;
property('enabled', ctx.enabled)
('firstName', (temp = pipe('async', ctx.person$)) == null ? null : temp.name);
```
This commit introduces a new `BindingForm` that results in the above code to be
generated and adds compiler and acceptance tests to verify the proper behavior.
Fixes#37194
PR Close#37911
In JIT compiled apps, component definitions are compiled upon first
access. For a component class `A` that extends component class `B`, the
`B` component is also compiled when the `InheritDefinitionFeature` runs
during the compilation of `A` before it has finalized. A problem arises
when the compilation of `B` would flush the NgModule scoping queue,
where the NgModule declaring `A` is still pending. The scope information
would be applied to the definition of `A`, but its compilation is still
in progress so requesting the component definition would compile `A`
again from scratch. This "inner compilation" is correctly assigned the
NgModule scope, but once the "outer compilation" of `A` finishes it
would overwrite the inner compilation's definition, losing the NgModule
scope information.
In summary, flushing the NgModule scope queue could trigger a reentrant
compilation, where JIT compilation is non-reentrant. To avoid the
reentrant compilation, a compilation depth counter is introduced to
avoid flushing the NgModule scope during nested compilations.
Fixes#37105
PR Close#37795
When navigations coming from Angular router we may have a payload stored in state property. When this
exists, set extras's state to the payload.
PR Close#28176
Queries weren't matching directives that provide themselves via string
injection tokens, because the assumption was that any string passed to
a query decorator refers to a template reference.
These changes make it so we match both template references and
providers while giving precedence to the template references.
Fixes#38313.
Fixes#38315.
PR Close#38321
When we were outputting class members for `setClassMetadata` calls,
we were using the string representation of the member name. This can
lead to us generating invalid code when the name contains dashes and
is quoted (e.g. `@Output() 'has-dashes' = new EventEmitter()`), because
the quotes will be stripped for the string representation.
These changes fix the issue by using the original name AST node that was
used for the declaration and which knows whether it's supposed to be
quoted or not.
Fixes#38311.
PR Close#38387
This commit contains no changes to code. It only breaks `i18n.ts` file
into `i18n.ts` + `i18n_apply.ts` + `i18n_parse.ts` +
`i18n_postprocess.ts` for easier maintenance.
PR Close#38368
Defer loading the wildcard module so that it is not loaded until
subscribed to. This fixes an issue where it was being eagerly loaded.
As an example, wildcard module loading should only occur after all other potential
matches have been exhausted. A test case for this was also added to
demonstrate the fix.
Fixes#25494
PR Close#38348
When a ServerStylesHost instance is destroyed, all of the shared styles added to the DOM
head element by that instance should be removed. Without this removal, over time a large
number of style rules will build up and cause extra memory pressure. This brings the
ServerStylesHost in line with the DomStylesHost used by the platform browser, which
performs this same cleanup.
PR Close#38367
The currently selected ICU was incorrectly being stored it `TNode`
rather than in `LView`.
Remove: `TIcuContainerNode.activeCaseIndex`
Add: `LView[TIcu.currentCaseIndex]`
PR Close#38345
This commit performs minor refactoring in Forms package to get rid of duplicate functions.
It looks like the functions were duplicated due to a slightly different type signatures, but
their logic is completely identical. The logic in retained functions remains the same and now
these function also accept a generic type to achieve the same level of type safety.
PR Close#38371
This commit uses getElementById and getElementsByName when an anchor scroll happens,
to avoid escaping the anchor and wrapping the code in a try/catch block.
Related to #28960
PR Close#30143
This change provides better typing for the `LView.debug` property which
is intended to be used by humans while debugging the application with
`ngDevMode` turned on.
In addition this chang also adds jasmine matchers for better asserting
that `LView` is in the correct state.
PR Close#38359
The Chrome debugger is not able to render the syntax properly when the
code contains backticks. This is a known issue in Chrome and they have an
open [issue](https://bugs.chromium.org/p/chromium/issues/detail?id=659515) for that.
This commit adds the work-around to use double backslash with one
backtick ``\\` `` at the end of the line.
This can be reproduced by running the following command:
`yarn bazel test //packages/forms/test --config=debug`
When opening the chrome debugger tools, you should see the correct
code highlighting syntax.
PR Close#38332
For attribute bindings that target a directive's input, the template
type checker is able to verify that the type of the input expression is
compatible with the directive's declaration for said input. This
checking adheres to the `strictNullChecks` flag as configured in the
TypeScript compilation, such that errors are reported for expressions
that include `undefined` or `null` in their type if the input's
declaration does not include those types.
There was a bug with this level of type-checking for directives that
also declare coercion members, where binding an expression that includes
the `undefined` type to a directive's input that does not include the
`undefined` type would not be reported as error.
This commit fixes the bug by changing the type-constructor in type-check
code to use an intersection type of regular inputs and coerced inputs,
instead of a union type. The union type would inadvertently allow
`undefined` types to be assigned into the regular inputs, as that would
still satisfy the characteristics of a union type.
As a result of this change, you may start to see build failures if
`strictTemplates` is enabled and `strictInputTypes` is not disabled.
These errors are legitimate and some action is required to achieve a
successful build:
1. Update the templates for which an error is reported and introduce the
non-null assertion operator at the end of the expression. This
removes the `undefined` type from the expression's type, making it
appear as a valid assignment.
2. Disable `strictNullInputTypes` in the compiler options. This will
implicitly add the non-null assertion operators similar to option 1,
but all templates in the compilation are affected.
3. Update the directive's input declaration to include the `undefined`
type, if the directive is not implemented in an external library.
PR Close#38273
I18n code breaks up internationalization into opCodes which are then stored
in arrays. To make it easier to debug the codebase this PR adds `debug`
property to the arrays which presents the data in human readable format.
PR Close#38154
Roll forward of #38147.
This allows Closure compiler to tree shake unused constructor calls to `NgModuleFactory`, which is otherwise considered
side-effectful. The Angular compiler generates factory objects which are exported but typically not used, as they are
only needed for compatibility with View Engine. This results in top-level constructor calls, such as:
```typescript
export const FooNgFactory = new NgModuleFactory(Foo);
```
`NgModuleFactory` has a side-effecting constructor, so this statement cannot be tree shaken, even if `FooNgFactory` is
never imported. The `NgModuleFactory` continues to reference its associated `NgModule` and prevents the module and all
its unused dependencies from being tree shaken, making Closure builds significantly larger than necessary.
The fix here is to wrap `NgModuleFactory` constructor with `noSideEffects(() => /* ... */)`, which tricks the Closure
compiler into assuming that the invoked function has no side effects. This allows it to tree-shake unused
`NgModuleFactory()` constructors when they aren't imported. Since the factory can be removed, the module can also be
removed (if nothing else references it), thus tree shaking unused dependencies as expected.
The one notable edge case is for lazy loaded modules. Internally, lazy loading is done as a side effect when the lazy
script is evaluated. For Angular, this side effect is registering the `NgModule`. In Ivy this is done by the
`NgModuleFactory` constructor, so lazy loaded modules **cannot** have their top-level `NgModuleFactory` constructor
call tree shaken. We handle this case by looking for the `id` field on `@NgModule` annotations. All lazy loaded modules
include an `id`. When this `id` is found, the `NgModuleFactory` is generated **without** with `noSideEffects()` call,
so Closure will not tree shake it and the module will lazy-load correctly.
PR Close#38320
This introduces a new `ModuleInfo` interface to represent some of the statically analyzed data from an `NgModule`. This
gets passed into transforms to give them more context around a given `NgModule` in the compilation.
PR Close#38320
This commit refactors the argument of the `parseEventName` function
to use an object with named properties instead of using an object indexer.
PR Close#38089
Some specialised browsers that do not support scroll restoration
(e.g. some web crawlers) do not allow `scrollRestoration` to be
writable.
We already sniff the browser to see if it has the `window.scrollTo`
method, so now we also check whether `window.history.scrollRestoration`
is writable too.
Fixes#30629
PR Close#30630
Previously, the `ngOnDestroy` method called `unsubscribe` regardless of if `subscription` had
been initialized. This can lead to an error attempting to call `unsubscribe` of undefined.
This change prevents this error, and instead only attempts `unsubscribe` when the subscription
has been defined.
PR Close#38344
The `TscPlugin` interface using a type of `ts.CompilerHost&Partial<UnifiedModulesHost>` for the `host` parameter
of the `wrapHost` method. However, prior to this change, the interface implementing `NgTscPlugin` class used a
type of `ts.CompilerHost&UnifiedModulesHost` for the parameter. This change corrects the inconsistency and
allows `UnifiedModulesHost` members to be optional when using the `NgtscPlugin`.
PR Close#38004
@angular/core/testing provide `async` test utility, but the name `async` is
confusing with the javascript keyword `async`. And in some test case, if you
want to use both the `async` from `@angular/core/testing` and `async/await`,
you may have to write the code like this.
```typescript
it('test async operations', async(async() => {
const result = await asyncMethod();
expect(result).toEqual('expected');
}));
```
So in this PR, the `async` is renamed to `waitForAsync` and also deprecate `async`.
PR Close#37583
This reverts commit b4449e35bf.
The example given from the previous change was for a component selector and not a provider selector.
This change fixes it.
Fixes#38323.
PR Close#38325
Within an angular template, when a character entity is unable to be parsed, previously a generic
unexpected character error was thrown. This does not properly express the issue that was discovered
as the issue is actually caused by the discovered character making the whole of the entity unparsable.
The compiler will now instead inform via the error message what string was attempted to be parsed
and what it was attempted to be parsed as.
Example, for this template:
```
<p>
ģp
</p>
```
Before this change:
`Unexpected character "p"`
After this change:
`Unable to parse entity "ģp" - hexadecimal character reference entities must end with ";"`
Fixes#26067
PR Close#38319
This commit removes compiler instantiation at startup.
This is because the constructor is invoked during the plugin loading phase,
in which the project has not been completely loaded.
Retrieving `ts.Program` at startup will trigger an `updateGraph` operation,
which could only be called after the Project has loaded completely.
Without this change, the Ivy LS cannot be loaded as a tsserver plugin.
Note that the whole `Compiler` class is temporary, so changes made there are
only for development. Once we have proper integration with ngtsc the
`Compiler` class would be removed.
PR Close#38120
Currently the `getInheritedFactory` function is implemented to allow
closure to remove the call if the base factory is unused. However, this
method does not work with terser. By adding the PURE annotation,
terser will also be able to remove the call when unused.
PR Close#38291
This commit fixes a bug in View Engine whereby the compiler errorneously
thinks that a method of a component has decorator metadata when that
method is one of those in `Object.prototype`, for example `toString`.
This bug is discovered in v10.0.4 of `@angular/language-service` after
the default bundle format was switched from ES5 to ES2015.
ES5 output:
```js
if (propMetadata[propName]) {
decorators.push.apply(decorators, __spread(propMetadata[propName]));
}
```
ES2015 output:
```js
if (propMetadata[propName]) {
decorators.push(...propMetadata[propName]);
}
```
The bug was not discovered in ES5 because the polyfill for the spread
operator happily accepts parameters that do not have the `iterable`
symbol:
```js
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
```
whereas in es2015 it’ll fail since the iterable symbol is not present in
`propMetadata['toString']` which evaluates to a function.
Fixes https://github.com/angular/vscode-ng-language-service/issues/859
PR Close#38292
This reverts commit 7f8c2225f2.
This commit caused test failures internally, which were traced back to the
optimizer removing NgModuleFactory constructor calls when those calls caused
side-effectful registration of NgModules by their ids.
PR Close#38303
This commit disables one TypeChecker test (added as a part of
https://github.com/angular/angular/pull/38105) which make assertions about the filename while
running on Windows.
Such assertions are currently suffering from a case sensitivity issue.
PR Close#38294
The documentation is not clear on how the base href and APP_BASE_HREF are used. This commit
should help clarify more complicated use-cases beyond the most common one of just a '/'
PR Close#38123
This allows Closure compiler to tree shake unused constructor calls to `NgModuleFactory`, which is otherwise considered
side-effectful. The Angular compiler generates factory objects which are exported but typically not used, as they are
only needed for compatibility with View Engine. This results in top-level constructor calls, such as:
```typescript
export const FooNgFactory = new NgModuleFactory(Foo);
```
`NgModuleFactory` has a side-effecting constructor, so this statement cannot be tree shaken, even if `FooNgFactory` is
never imported. The `NgModuleFactory` continues to reference its associated `NgModule` and prevents the module and all
its unused dependencies from being tree shaken. This effectively prevents all components from being tree shaken, making
Closure builds significantly larger than they should be.
The fix here is to wrap `NgModuleFactory` constructor with `noSideEffects(() => /* ... */)`, which tricks the Closure
compiler into assuming that the invoked function has no side effects. This allows it to tree-shake unused
`NgModuleFactory()` constructors when they aren't imported. Since the factory can be removed, the module can also be
removed (if nothing else references it), thus tree shaking unused components as expected.
PR Close#38147
Large strings constants are now wrapped in a function which is called whenever used. This works around a unique
limitation of Closure, where it will **always** inline string literals at **every** usage, regardless of how large the
string literal is or how many times it is used.The workaround is to use a function rather than a string literal.
Closure has differently inlining semantics for functions, where it will check the length of the function and the number
of times it is used before choosing to inline it. By using a function, `ngtsc` makes Closure more conservative about
inlining large strings, and avoids blowing up the bundle size.This optimization is only used if the constant is a large
string. A wrapping function is not included for other use cases, since it would just increase the bundle size and add
unnecessary runtime performance overhead.
PR Close#38253
This commit adds a method `getDiagnosticsForComponent` to the
`TemplateTypeChecker`, which does the minimum amount of work to retrieve
diagnostics for a single component.
With the normal `ReusedProgramStrategy` this offers virtually no improvement
over the standard `getDiagnosticsForFile` operation, but if the
`TypeCheckingProgramStrategy` supports separate shims for each component,
this operation can yield a faster turnaround for components that are
declared in files with many other components.
PR Close#38105
Previously, a stable template id was implemented for each component in a
file. This commit adds this id to each `TemplateDiagnostic` generated from
the template type-checker, so it can potentially be used for filtration.
PR Close#38105
This commit adds an `overrideComponentTemplate` operation to the template
type-checker. This operation changes the template used during template
type-checking operations.
Overriding a template causes any previous work for it to be discarded, and
the template type-checking engine will regenerate the TCB for that template
on the next request.
This operation can be used by a consumer such as the language service to
get rapid feedback or diagnostics as the user is editing a template file,
without the need for a full incremental build iteration.
Closes#38058
PR Close#38105
Previously, the `TemplateTypeChecker` abstraction allowed fetching
diagnostics for a single file, but under the hood would generate type
checking code for the entire program to satisfy the request.
With this commit, an `OptimizeFor` hint is passed to `getDiagnosticsForFile`
which indicates whether the user intends to request diagnostics for the
whole program or is truly interested in just the single file. If the latter,
the `TemplateTypeChecker` can perform only the work needed to produce
diagnostics for just that file, thus returning answers more efficiently.
PR Close#38105
The template type-checking engine relies on the abstraction interface
`TypeCheckingProgramStrategy` to create updated `ts.Program`s for
template type-checking. The basic API is that the type-checking engine
requests changes to certain files in the program, and the strategy provides
an updated `ts.Program`.
Typically, such changes are made to 'ngtypecheck' shim files, but certain
conditions can cause template type-checking to require "inline" operations,
which change user .ts files instead. The strategy used by 'ngc' (the
`ReusedProgramStrategy`) supports these kinds of updates, but other clients
such as the language service might not always support modifying user files.
To accommodate this, the `TypeCheckingProgramStrategy` interface was
modified to include a `supportsInlineOperations` flag. If an implementation
specifies `false` for inline support, the template type-checking system will
return diagnostics on components which would otherwise require inline
operations.
Closes#38059
PR Close#38105
This commit significantly refactors the 'typecheck' package to introduce a
new abstraction, the `TemplateTypeChecker`. To achieve this:
* a 'typecheck:api' package is introduced, containing common interfaces that
consumers of the template type-checking infrastructure can depend on
without incurring a dependency on the template type-checking machinery as
a whole.
* interfaces for `TemplateTypeChecker` and `TypeCheckContext` are introduced
which contain the abstract operations supported by the implementation
classes `TemplateTypeCheckerImpl` and `TypeCheckContextImpl` respectively.
* the `TemplateTypeChecker` interface supports diagnostics on a whole
program basis to start with, but the implementation is purposefully
designed to support incremental diagnostics at a per-file or per-component
level.
* `TemplateTypeChecker` supports direct access to the type check block of a
component.
* the testing utility is refactored to be a lot more useful, and new tests
are added for the new abstraction.
PR Close#38105