Currently when `ɵɵtemplate` and `ɵɵelement` instructions are generated by compiler, all static attributes are
duplicated for both instructions. As a part of this duplication, i18n translation blocks for static i18n attributes
are generated twice as well, causing duplicate entries in extracted translation files (when Ivy extraction mechanisms
are used). This commit fixes this issue by introducing a cache for i18n translation blocks (for static attributes
only).
Also this commit further aligns `ɵɵtemplate` and `ɵɵelement` instruction attributes, which should help implement
more effective attributes deduplication logic.
Closes#39942.
PR Close#40077
Refactors the i18n error tests to be unit tests in ngtsc_spec.ts. There
is two reasons for doing this.
First is that the tests in compliace_old expected an expection to be be
thrown but did not fail the test if no exception was thrown. That means
that this test could miss catching a bug. It is also a big hacky to call
compile directly and expect an exception to be thrown for diagnostics.
Also, this can easily be unit tested and an end-to-end test is not
necessary since we are not making use of the goldfiles for these tests.
It is easier to maintain and less hacky to validate that we get helpful
error messages when nesting i18n sections by calling getDiagnostics
directly.
PR Close#40026
This commit replaces `bazel` with `yarn bazel` in the error message (that instructs to regenerate golden file)
thrown while executing compliance tests. We use `yarn bazel` in other places (so we use the local version of bazel,
not the global one).
PR Close#40078
Prior to this change, the `setClassMetadata` call would be invoked
inside of an IIFE that was marked as pure. This allows the call to be
tree-shaken away in production builds, as the `setClassMetadata` call
is only present to make the original class metadata available to the
testing infrastructure. The pure marker is problematic, though, as the
`setClassMetadata` call does in fact have the side-effect of assigning
the metadata into class properties. This has worked under the assumption
that only build optimization tools perform tree-shaking, however modern
bundlers are also able to elide calls that have been marked pure so this
assumption does no longer hold. Instead, an `ngDevMode` guard is used
which still allows the call to be elided but only by tooling that is
configured to consider `ngDevMode` as constant `false` value.
PR Close#39987
These tests started failing because they had type-check
errors in their templates, and a recent commit turned on
full template type-checking by default.\
This commit fixes those templates and updates the expected
files as necessary.
PR Close#40040
These tests do not pass the typecheck phase of the compiler and fail.
The option to disable typechecking was removed recently so these tests
need to be fixed to be valid applications.
PR Close#40033
A couple reasons to justify removing the flag:
* It adds code to the compiler that is only meant to support test cases
and not any production. We should avoid code in that's only
meant to support tests.
* The flag enables writing tests that do not mimic real-world behavior
because they allow invalid applications
PR Close#40013
The golden files for the partial compliance tests need to be updated
with individual Bazel run invocations, which is not very ergonomic when
a large number of golden files need to updated. This commit adds a
script to query the Bazel targets that update the goldens and then runs
those targets sequentially.
PR Close#39989
This test migrates source-mapping tests to the new compliance test framework.
The original tests are found in the file at:
`packages/compiler-cli/test/ngtsc/template_mapping_spec.ts`.
These new tests also check the mappings resulting from partial compilation
followed by linking, after flattening the pair of source-maps that each
process generates.
Note that there are some differences between the mappings for full compile
and linked compile modes, due to how TypeScript and Babel use source-span
information on AST nodes. To accommodate this, there are two expectation
files for most of these source files.
PR Close#39939
This commit allows compliance test-cases to be written that specify
source-map mappings between the source and generated code.
To check a mapping, add a `// SOURCE:` comment to the end of a line:
```
<generated code> // SOURCE: "<source-url>" <source code>
```
The generated code will still be checked, stripped of the `// SOURCE` comment,
as normal by the `expectEmit()` helper.
In addition, the source-map segments are checked to ensure that there is a
mapping from `<generated code>` to `<source code>` found in the file at
`<source-url>`.
Note:
* The source-url should be absolute, with the directory containing the
TEST_CASES.json file assumed to be `/`.
* Whitespace is important and will be included when comparing the segments.
* There is a single space character between each part of the line.
* Newlines within a mapping must be escaped since the mapping and comment
must all appear on a single line of this file.
PR Close#39939
Previously one could set a flag in a `TEST_CASES.json` file to exclude
the test-cases from being run if the input files were being compiled
partially and then linked.
There are also scenarios where one might want to exclude test-cases
from "full compile" mode test runs.
This commit changes the compliance test tooling to support a new
property `compilationModeFilter`, which is an array containing one or
more of `"full compile"` and `"linked compile"`. Only the tests
whose `compilationModeFilter` array contains the current compilation
mode will be run.
PR Close#39939
Previously files were serialized with an extra newline seperator that
was not removed when parsing. This caused the parsed file to start with
an extra newline that invalidated its source-map.
Also, the splitting was producing an empty entry at the start of the extracted
golden files which is now ignored.
PR Close#39939
The schema accidentally included the `expectedErrors` and `extraCheck`
properties below the `files` property instead of below the `expectations`
property.
PR Close#39939
The partial compiler will add a version number to the objects that are
generated so that the linker can select the appropriate partial linker
class to process the metadata.
Previously this version matching was a simple number check. Now
the partial compilation writes the current Angular compiler version
into the generated metadata, and semantic version ranges are used
to select the appropriate partial linker.
PR Close#39847
The newly built compliance test runner was not using the shared source
file cache that was added in b627f7f02e,
which offers a significant performance boost to the compliance test
targets.
PR Close#39956
If the testcase has not specified that errors were expected, then any
errors that have occurred should be reported. These errors may have
prevented an output file from being generated, which resulted in hard
to debug test failures due to missing files.
PR Close#39862
Previously this would have just printed that `false` was not equal to
`true`, which, although true, is not very helpful. This commit adds
details about which special check failed together with the generated
code, for easier debugging.
PR Close#39863
This commit provides the machinery for the new file-based compliance test
approach for i18n tests, and migrates the i18n tests to this new format.
PR Close#39661
This commit implements partial compilation of components, together with
linking the partial declaration into its full AOT output.
This commit does not yet enable accurate source maps into external
templates. This requires additional work to account for escape sequences
which is non-trivial. Inline templates that were represented using a
string or template literal are transplated into the partial declaration
output, so their source maps should be accurate. Note, however, that
the accuracy of source maps is not currently verified in tests; this is
also left as future work.
The golden files of partial compilation output have been updated to
reflect the generated code for components. Please note that the current
output should not yet be considered stable.
PR Close#39707
The JSON schema reference was off-by-one, preventing IDEs from finding
the file and offering suggestions and documentation. Additionally the
name of the golden file was slightly off.
PR Close#39707
ngtsc has a robust suite of testing utilities, designed for in-memory
testing of a TypeScript compiler. Previously these utilities lived in the
`test` directory for the compiler-cli package.
This commit moves those utilities to an `ngtsc/testing` package, enabling
them to be depended on separately and opening the door for using them from
the upcoming language server testing infrastructure.
As part of this refactoring, the `fake_core` package (a lightweight API
replacement for @angular/core) is expanded to include functionality needed
for Language Service test use cases.
PR Close#39594
This commit adds bazel rules to test whether linking the golden partial
files for test cases produces the same output as a full compile of the
test case would.
PR Close#39617
This commit contains the basic runner logic and a couple of sample test cases
for the "full compile" compliance tests, where source files are compiled
to full definitions and checked against expectations.
PR Close#39617
This commit renames the original `compliance` test directory to `compliance_old`.
Eventually this directory will be deleted once all the tests have been
migrated to the new test case based compliance tests.
PR Close#39617
In PR #38938 an additional Bazel target was introduced for the compliance
tests, as preparation to run the compliance tests in partial compilation
mode and then apply the linker transform. The linker plugin itself was
not available at the time but has since been implemented, so this commit
updates the prelink target of the compliance tests to apply the linker
transform using the Babel plugin.
Actually emitting partial compilations to be transformed will be done in
follow-up work.
PR Close#39518
When a class with a custom decorator is transpiled to ES5, it looks something like this:
```
var SomeClass = (function() {
function SomeClass() {...};
var SomeClass_1 = __decorate([Decorator()], SomeClass);
SomeClass = SomeClass_1;
return SomeClass;
})();
```
The problem is that if the class also has an Angular decorator that refers to the class itself
(e.g. `{provide: someToken, useClass: SomeClass}`), the generated `setClassMetadata` code will
be emitted after the IIFE, but will still refer to the intermediate `SomeClass_1` variable from
inside the IIFE. This happens, because we generate the `setClassMetadata` call directly from
the source AST which contains identifiers that TS will rename when it emits the ES5 code.
These changes resolve the issue by looking through the metadata AST and cloning any `Identifier`
that is referring to the class. Since TS doesn't have references to the clone, it won't rename
it when transpiling to ES5.
Fixes#39509.
PR Close#39527
Currently expressions `$event.foo()` and `this.$event.foo()`, as well as `$any(foo)` and
`this.$any(foo)`, are treated as the same expression by the compiler, because `this` is considered
the same implicit receiver as when the receiver is omitted. This introduces the following issues:
1. Any time something called `$any` is used, it'll be stripped away, leaving only the first parameter.
2. If something called `$event` is used anywhere in a template, it'll be preserved as `$event`,
rather than being rewritten to `ctx.$event`, causing the value to undefined at runtime. This
applies to listener, property and text bindings.
These changes resolve the first issue and part of the second one by preserving anything that
is accessed through `this`, even if it's one of the "special" ones like `$any` or `$event`.
Furthermore, these changes only expose the `$event` global variable inside event listeners,
whereas previously it was available everywhere.
Fixes#30278.
PR Close#39323
Currently `i18n` attributes are treated the same no matter if they have data bindings or not. This
both generates more code since they have to go through the `ɵɵi18nAttributes` instruction and
prevents the translated attributes from being injected using the `@Attribute` decorator.
These changes makes it so that static translated attributes are treated in the same way as regular
static attributes and all other `i18n` attributes go through the old code path.
Fixes#38231.
PR Close#39408
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
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
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
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
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