When a partially compiled component or directive is "linked" in JIT mode, the body
of its declaration is evaluated by the JavaScript runtime. If a class is referenced
in a query (e.g. `ViewQuery` or `ContentQuery`) but its definition is later in the
file, then the reference must be wrapped in a `forwardRef()` call.
Previously, query predicates were not wrapped correctly in partial declarations
causing the code to crash at runtime. In AOT mode, this code is never evaluated
but instead transformed as part of the build, so this bug did not become apparent
until Angular Material started running JIT mode tests on its distributable output.
This change fixes this problem by noting when queries are wrapped in `forwardRef()`
calls and ensuring that this gets passed through to partial compilation declarations
and then suitably stripped during linking.
See https://github.com/angular/components/pull/23882 and https://github.com/angular/components/issues/23907
PR Close#44113
Currently the TS version checking function interprets a version like `1.2.3-rc.5` as `1.2.NaN` which would allow it to bypass the version checking altogether.
These changes add a little bit more logic to ensure that such versions are handled correctly. There's also an error if we don't manage to parse the version string.
Also it seemed like we never actually ran the version check unit tests, because they didn't have a test target.
PR Close#44109
This commit adds additional information to encourage developers to contact
the author of View Engine libraries and ask them to update to partial Ivy.
Fixes#42308
PR Close#43996
Consider the `NgModel` directive which has the `ngModelOptions` input:
```ts
class NgModel {
@Input() ngModelOptions: { updateOn: 'blur'|'change'|'submit' };
}
```
In a template this may be set using an object literal as follows:
```html
<input ngModel [ngModelOptions]="{updateOn: 'blur'}">
```
This assignment should be accepted, as the object's type aligns with the
`ngModelOptions` input in `NgModel`. However, if the `strictNullInputTypes`
option is disabled this assignment would inadvertently produce an error:
```
Type '{ updateOn: string; }' is not assignable to type '{ updateOn: "blur"|"change"|"submit"; }'.
Types of property 'updateOn' are incompatible.
Type 'string' is not assignable to type '"blur"|"change"|"submit"'
```
This is due to the `'blur'` value being inferred to be of type `string`
instead of retaining its literal type. The non-null assertion operator
that is automatically inserted for input binding assignments when
`strictNullInputTypes` is disabled inhibits TypeScript from inferring
the string value as its literal type.
This commit fixes the issue by omitting the insertion of the non-null
operator for object literals and array literals.
PR Close#38305
When a safe method call such as `person?.getName()` is used, the
compiler would generate invalid code if the argument list also contained
a safe method call. For example, the following code:
```
person?.getName(config?.get('title').enabled)
```
would generate
```
let tmp;
ctx.person == null ? null : ctx.person.getName((tmp = tmp) == null ?
null : tmp.enabled)
```
Notice how the call to `config.get('title')` has completely disappeared,
with `(tmp = tmp)` having taken its place.
The issue occurred due to how the argument list would be converted
from expression AST to output AST twice. First, the outer safe method
call would first convert its arguments list. This resulted in a
temporary being allocated for `config.get('title')`, which was stored in
the internal `_resultMap`. Only after the argument list has been
converted would the outer safe method call realize that it should be
guarded by a safe access of `person`, entering the `convertSafeAccess`
procedure to convert itself. This would convert the argument list once
again, but this time the `_resultMap` would already contain the
temporary `tmp` for `config?.get('title')`. Consequently, the safe
method in the argument list would be emitted as `tmp`.
This commit fixes the issue by ensuring that nodes are only converted
once.
Closes#44069
PR Close#44088
Enables code spitting for ESBuild bundling of the compiler-cli. When
we initially configured ESBuild as part of APF v13, we left this option
disabled as code splitting is marked experimental. The ESM splitting
mechanism in ESBuild seems very solid so far (judging subjectively
and by experience/reports in the ESBuild repo), so we should give
it a shot, in order to significantly reduce the size of the NPM package,
and simplify debugging (by not having duplicated code portions for all
the different entry points).
To clarify: Code splitting is helpful as we have multiple entry-points
that currently duplicate code. With code splitting these entry-points
would share common code instead.
PR Close#43932
Prior refactorings caused unexpected g3 sync issues due to a patch that
changes the error documentation URL. This commit moves the base url into
a separate file to make this more apparent.
PR Close#43527
The `ErrorCode` enum in the `error_code.ts` file is governed by public
api guards but the other top-level exports from that file are exempt
from public api documentation and are therefore marked as `@internal`.
However, TypeScript is configured with the `stripInternal` compiler
option such that declarations with `@internal` markers are not emitted
into the `.d.ts` files, but this means that the reexports in the barrel
file end up referring to missing declarations.
The `stripInternal` option is considered internal and its documentation
states to use at your own risk (as per https://github.com/microsoft/TypeScript/issues/45307).
Having the option enabled is desirable for us as it works well for
hiding class fields that are marked `@internal`, which is an effective
way to hide members from the .d.ts file. As a workaround for the issue
with top-level symbols, the declarations with `@internal` markers are
moved to dedicated files for which no public api guard is setup,
therefore allowing their `@internal` markers to be dropped.
Fixes#43097
PR Close#43527
In #43879, `UmdReflectionHost` was updated to deal with the new UMD
format used by Rollup, where the parenthesis is around the wrapper
function and not the wrapper function call.
For reference, this caused failures in the `ngcc-validation` repo
([example 1][1], [example 2][2]).
This commit updates `UmdRenderingFormatter` to also handle both UMD
formats. In order to validate the change, this commit also updates the
`UmdRenderingFormatter` tests to run against both UMD formats.
[1]: https://circleci.com/gh/angular/ngcc-validation/65916
[2]: https://circleci.com/gh/angular/ngcc-validation/65758
PR Close#43931
This commit re-enables the `perform_watch` test target and updates the
test to run with the Ivy compiler.
Additionally, this target was switched over to use Angular v12 packages
as input to the test, to allow the ViewEngine tests to continue working
with v13 packages which are Ivy-only. This commit reverts those changes
now that View Engine tests are disabled, as it's desirable to test
against local artifacts that are build within the monorepo instead of
depending on NPM packages.
PR Close#43893
The View Engine compiler now throws when constructed and will be removed shortly. Direct users should switch to `NgtscProgram` to build with [Ivy](https://angular.io/guide/ivy). The View Engine compiler is being removed, so this makes it throw an error to ensure no one accidentally depends on code being removed.
PR Close#43862
Using the tag "view-engine-only" better describes the expected usage of bazel targets with the test. They can
only be run with view engine.
PR Close#43862
Since building with ViewEngine is not longer desired on CI, removing the ivy vs non-ivy testing yarn scripts
is done, informing developers to instead use `yarn test` as all tests should be run using the Ivy complier.
PR Close#43862
Recently rollup, used by ng-packagr, changed the position of parentheses
around its generated UMD wrapper functions.
This commit ensures that ngcc can handle both.
Fixes#43870
PR Close#43879
This reverts commit bba0a87055.
The reason for rollback: this change is breaking some targets in Google's codebase when there is no attribute value is displayed (attr.aria-label) when translated.
PR Close#43882
While fully dynamic bound properties (and attributes) cannot be marked for localization, properties that only contain interpolation can.
This commit ensure that attribute bindings that only contain interpolation can also be marked for localization.
Closes#43260
PR Close#43815
When extracting i18n messages from templates, ICU messages are split out from the
message that contains them. This can make it difficult in the translation files to match up
the two messages, especially if the ICU is reused in multiple placeholders.
This commit builds on top of the previous one to expose the message ID of ICU messages
from the ICU placeholders as additional metadata in the `$localize` tagged strings.
Now the metablock following any placeholder can also contain the associated ID
delimited from the placeholder name by `@@`.
Fixes#17506
PR Close#43534
Refs #42966.
Previously, a build when emitted one warning and no errors would fail with a non-zero exit code. This is not what users would expect, but had not been an issue before since the compiler did not actually emit any warnings. With upcoming extended template diagnostics and other warnings, this is now a case that needs to be supported. Warnings are printed to `stderr` as before, but `ngc` now exits with code `0` and the build is considered successful.
Implemented this by adding a new `expectedExitCode` parameter to `driveDiagnostics()` which asserts against the real exit code. Most importantly, it does not **require** the the build to pass since any exit code can be given, so it is up to the test to assert this as well as many messages printed to make sure they are acceptable. This is useful for testing warnings and ensuring the build still passes.
PR Close#43673
This commit updates the `node` engines range for all Angular
framework packages to:
* No longer support NodeJS v12 `< 12.20`. This is done because APF v13
uses package export patterns which are only supported as of v12.20.
https://nodejs.org/api/packages.html#packages_subpath_patterns.
* Allows for the latest v16 NodeJS versions. This matches with the CLI
which added NodeJS v16 support with https://github.com/angular/angular-cli/pull/21854.
We already limit this to `>= v16.10.0` in preparation to only
supporting the LTS minors of Node v16.
BREAKING CHANGE: NodeJS versions older than `v12.20.0` are no longer
supported due to the Angular packages using the NodeJS package exports
feature with subpath patterns.
PR Close#43740
Bumps the minimum required TypeScript version to 4.4.2 and removes the integration tests for 4.1, 4.2 and 4.3.
BREAKING CHANGE:
TypeScript versions older than 4.4.2 are no longer supported.
PR Close#43642
Refs #42966.
Previously, checking a template with the syntax:
```html
<div>{{ foo() ?? 'test' }}</div>
```
Where `foo()` returns a nullable value:
```typescript
@Component(/* ... */)
class TestCmp {
foo: (): string | null => null;
}
```
Would always log a nullish coalescing not nullable warning. This is because [`getSymbolOfNode(node.left)`](fe69193509/packages/compiler-cli/src/ngtsc/typecheck/extended/checks/nullish_coalescing_not_nullable/index.ts (L30)) would return the [symbol of the function (`foo`)](fe69193509/packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts (L536-L538)) rather than the symbol of its returned value (`foo()`). Fixed this by getting the symbol for the whole expression's span, rather than just the function receiver.
Also made some minor refactorings to `template_symbol_builder` to make a similar change to safe method calls. This behavior was originally for the language service in order to handle quick info, as the user highlighting a function name would actually apply to the entire expression. This is no longer true as the language service will correctly request the type from the function rather than the `Call` expression, so these hacks are not necessary anymore. This broke two existing test cases of exactly this behavior which were easily updated. Also added a test to the language service to confirm that it is not broken by this change.
PR Close#43572
`source-map` is only used during testing and therefore there is no need to list it as a dependency.
(cherry picked from commit ae7dc75bdce713acaa1658734791317a274982da)
PR Close#43644
When compiling your application using the AOT compiler, your templates
are type-checked according to a certain strictness level. Before Angular 9
there existed only two strictness levels of template type checking as
determined by [the `fullTemplateTypeCheck` compiler option](guide/angular-compiler-options).
In version 9 the `strictTemplates` family of compiler options has been
introduced as a more fine-grained approach to configuring how strict your
templates are being type-checked.
The `fullTemplateTypeCheck` flag is being deprecated in favor of the new
`strictTemplates` option and its related compiler options. Projects that
currently have `fullTemplateTypeCheck: true` configured can migrate to
the following set of compiler options to achieve the same level of
type-checking.
```json
{
"angularCompilerOptions": {
"strictTemplates": true,
"strictInputTypes": false,
"strictNullInputTypes": false,
"strictAttributeTypes": false,
"strictOutputEventTypes": false,
"strictDomEventTypes": false,
"strictDomLocalRefTypes": false,
"strictSafeNavigationTypes": false,
"strictContextGenerics": false,
}
}
```
PR Close#43224
This commits sets the JS target for all command line tools to
NodeJS v12. ESbuild will automatically downlevel the ES2020 features
we currently use to make them compatible with NodeJS v12 <-> ES2019.
ES2020 is the prodmode output, but we still support Node v12 so
there needs to be some downleveling for now.
Note: This is a separate commit because initially the target was
set to Node v14 to match up with the prodmode Bazel output.
PR Close#43431
Similar to the other private entry-points we have added for localize,
bazel or the migrations, we should expose the tooling code through
a dedicated private export. This will make the compiler-cli exports
more consistent and it will become easier for the CLI to export
necessary code.
PR Close#43431
Currently, some tests in the `compiler-cli/integrationtest` package fail
on Windows because there are spec files which are not Bazel-generated.
When Bazel runs these tests on Windows, the spec file is resolved to
the actual source file (since there is no runfile symlinking/sandboxing).
This breaks the execution of the CJS spec file since it resides in th
`packages/compiler-cli` source folder which has a `package.json` set to
`type: module`.
We fix this by adding a `package.json` file for the integration test
folder and setting `module` to `commonjs`.
PR Close#43431
With the APF v13 package output, deep files can no longer be imported.
Since we do not intend to bundle the compiler into the compiler-cli, we
need to switch all deep imports to the primary entry-point.
PR Close#43431
Updates the dynamic-compiler test to be compatible with the APF v13.
As of v13, the packages no longer come with metadata.json files and
now need to be processed with the babel linker plugin. This commit
sets up the linker plugin, and switches away from the deprecated
systemjs approach to a simpler rollup code-splitting variant.
PR Close#43431
Ngcc relies on cluster for distributing work. The master controller
sends messages to the workers as soon as the worker becomes `online`.
The online event is sent as part of the NodeJS cluster logic itself.
This does not work well because technically `online` could emit before the
worker started listening (this seems to be case now with ESM as the
imports are loaded in a way where `online` emits too early; before the
worker actually listens for messages).
We fix this by explicitly notifying the master when the worker
is ready for retrieving IPC messages/or tasks. This is more safe
anyway as it's not clearly specified when `online` emits.
PR Close#43431
Given that we ship all of compiler-cli and localize in ESM
mode now, we need to use a ESM compatible version of Yargs.
The latest version seems ESM compatible but with some small
API changes. This commit updates Yargs and updates the command
line option code to use the new API.
PR Close#43431
Updates the lock file resolution logic in ngcc to work with ESM output.
The compiler-cli is now shipped in bundles, so the actual module resolution
needs to stay to keep the lock file path consistent regardless of where the
lock file code is bundled into. The ngcc integration test needs to be updated
though since the `ngcc` entry-point will always reside in the `bundles/` directory
now.
It has been considered using the top-level `package.json` of the compiler-cli
package, but that caused problems in tests down the line because the ngcc
tests only have the `@angular/compiler-cli/ngcc/...` targets linked into
the node modules. It's not worth changing this and reworking tests if ngcc
is going away in the future anyway (+ it has been like that before!).
PR Close#43431
Switches the compiler-cli usage of `__filename` to `import.meta.url`
when ESM bundles are generated. Unfortunately we cannot start using
only `import.meta` yet as we still build and run all code in Angular
in CommonJS module output for devmode tests.
This commit also fixes various instances where a jasmine spy was applied on
a namespace export that will break with ES module (and the interop for
CommonJS output). We fix these spies by using a default import.
PR Close#43431
Removes the remaining usages of dynamic require statements in the
package output. Since we declare all shipped packages as strict ESM,
we cannot use dynamic require statements anymore. This commit switches
these usages to actual `import` statements.
Note: Tsickle continues to remain an optional dependency since bundling
does not work with its UMD package output. Also tsickle is rarely used by
consumers, if at all, so bundling does not really provide any significant
value. To continue keeping tsickle optional (since it's still needed by the
`annotateForClosureCompiler` option which is also respected in ngtsc), we
pass-through a tsickle instance as a parameter to `main`. This allows us to
keep the compile functions synchronous without having to refactor the majority
of the watch compilation code, and majority of tests for ngc, ngtsc.
Consumers (like the `ngc` bin entry-point) can then load tsickle based on their
module format. e.g. tsickle can be imported through `require` to keep everything
sync, but in ESM, the dynamic import can be used beforehand to pass `tsickle` to
the `main` function. We can revisit this in the future but for now this does the
trick without exceeding the scope of this commit..
PR Close#43431
As outlined in the previous commit which enabled the `esModuleInterop`
TypeScript compiler option, we need to update all namespace imports
for `typescript` to default imports. This is needed to allow for
TypeScript to be imported at runtime from an ES module.
Similar changes are needed for modules like `semver` where the types incorrectly
suggest named exports that will not exist at runtime when imported from ESM.
This commit refactors all imports to match with the lint rule we have
configured in the previous commit. See the previous commit for more
details on why certain imports have been changed.
A special case are the imports to `@babel/core` and `@babel/types`. For
these a special interop is needed as both default imports, or named
imports break the other module format. e.g default imports would work
well for ESM, but it breaks for CJS. For CJS, the named imports would
only work, but in ESM, only the default export exist. We work around
this for now until the devmode is using ESM as well (which would be
consistent with prodmode and gives us more valuable test results). More
details on the interop can be found in the `babel_core.ts` files (two
interops are needed for both localize/or the compiler-cli).
PR Close#43431
This wires up the `@angular/localize/tools` entry-point. For context:
This entry-point is being created to avoid deep imports into
`@angular/localize/src/tools/<..>` like the CLI relies on. Deep imports
do not play well with strict ESM, and now that all APF packages are
strict ESM, the tool code needs to be either strict ESM as well.
We use ESBuild to create individual bundles for the CLI entry-points,
and the actual tool entry-point. We use a bundler because this enables
the localize code be ESM compatible. Without a bundler, all relative imports
within the `tools` entry-point would need to explicitly have the `.js`
extension. This would be cumbersome and hard to maintain/enforce or
validate.
One might wonder why this is not a standard APF entry-point then. The
answer is that the APF entry-points do not support exposing the CLI
binaries (like `yarn localize-translate`). This could be done through
tertiary entry-points, but using ESBuild directly gives us more control
for now. We might want to revisit this in the future again.
PR Close#43431
We switched the build output for the compiler-cli to use esbuild-generated
bundles.
This means that actual devmode ES5 sources, or prodmode ES2020 non-bundled
sources are not actually needed. Only the types are needed, and this commit
makes sure only the type definitions are shipped. This reduces the code size
of the compiler-cli and also helps with avoiding incorrect module resolution.
PR Close#43431
The view engine language-service tests currently rely on the `npm_package` output
that is built locally. They rely on the package output mostly for
compiling test scenarios (with dependencies on e.g. forms), and for
the testing the metadata extraction (testing proper suggestions for VE).
The reliance on these packages becomes problematic with the new Angular
Package Format v13 where no metadata files are shipped. To continue
being able to test View Engine language-service compatibility, we will
use the v12.x framework packages for some of the test scenarios.
PR Close#43431
The View Engine ngc tests currently rely on the `npm_package` output
that is built locally. This becomes problematic with the new Angular
Package Format v13 where no metadata files are shipped. To continue
being able to test View Engine compilation, we will use the v12.x
framework packages for running the View Engine test.
Note: This means that we no longer test metadata extraction directly
for our framework packages, but given that any change to View Engine
will still land in patch, where the VE packaging still occurs, we should
be covered here.
PR Close#43431
ngcc currently dynamially loads the `Transformer` code. It does this
to avoid unnecessary parsing and loading of transformer-related code
if there is nothing to process (so-called noop case). Unfortunately
this dynamic require is not recognized by ESBuild. The import needs
to be discovered as otheriwse the transformer code would not be included
in the bundled package output of the CLI.
The ngcc code needs to use an async runtime import as it would work
in ES modules. This introduces async code into to the compililation
pipeline, breaking the `ngccMain` synchronous invocation feature.
To avoid this, we just move the dynamic require/async import to
the file top-level so that we do not break synchronous processing
which the CLI relies on. This has the downside of slowing-down
the noop case a little but I believe that should be mitigated
through bundling of ngcc anyway. In the future with full-ESM
we won't be able to get around this anyway (unless we remove the
sync variant of ngcc processing).
PR Close#43431
Exposes code needed by the Angular CLI. Previously the CLI used
deep imports for most of these things, but now with bundling
the CLI, we no longer support deep imports.
We will expose the necessary dependencies for the linker as part
of the primary entry-point (I think that is more maintable than
re-exporting them as part of the linker). We also expose the ngcc
entry-point for the CLI with a new constant that will point to the
ngcc command line entry-point (which the CLI relies on).
PR Close#43431
The Angular Core and localize package currently use deep imports for
code that is shipped. This is problematic as we want to ship the
compiler-cli as full-ESM. To achieve this we need to use a bundler and
this breaks deep imports.
We use a bundler for the compiler CLI because for full ESM
compatibility, we would need to explicitly add the `.js` extension
to all relative imports. This is very cumbersome and prone to mistakes
so to mitigate this problem in a safe way, we bundle the compiler-cli.
Note: Deep imports continue to exist for the language service as it
bundles the compiler-cli.
PR Close#43431
As part of APF v13, we ship Angular framework packages using partial
compilation. This is done in preparation of VE removal, and to
eventually get rid of `ngcc` processing.
The new library format allows libraries to switch away from the View
Engine package format without shipping Angular definitions with
instructions to NPM. This would make libraries tightly coupled to
specific versions of `@angular/core`.
Since Angular core is always compatible with itself, we always should
compile Angular core using full compilation mode. It is unreasonable
to ship Angular core with partial compilation output, especially since
we would need to export the linker `declare` functions in
`r3_symbols.ts` otherwise.
PR Close#43431