With ngcc's ability to fixup pre-Ivy ModuleWithProviders such that they
include a reference to the NgModule type, the type may become a qualified
name:
```
import {ModuleWithProviders} from '@angular/core';
import * as ngcc0 from './module';
export declare provide(): ModuleWithProviders<ngcc0.Module>;
```
ngtsc now takes this situation into account when reflecting a
ModuleWithProvider's type argument.
PR Close#27562
Closure Compiler doesn't allow non-goo.getMsg const names to start with `MSG_`, so we should use different prefix for const that references a result of the `i18nPostprocess` fn invocation. With this update we also append file-based prefix to i18n constants (via $$ postfix) to ensure the names are unique across codebase of a project (otherwise it might lead to errors while compiling a project with Closure Compiler).
PR Close#27468
Previously in Ivy, host bindings did not work if they shared a public name
with an Input because they used the `elementProperty` instruction as is.
This instruction was originally built for inside component templates, so it
would either set a directive input OR a native property. This is the
correct behavior for inside a template, but for host bindings, we always
want the native properties to be set regardless of the presence of an Input.
This change adds an extra argument to `elementProperty` so we can tell it to
ignore directive inputs and only set native properties (if it is in the
context of a host binding).
PR Close#27589
Previously, ngtsc did not respect the angularCompilerOptions settings
for generating flat module indices. This commit adds a
FlatIndexGenerator which is used to implement those options.
FW-738 #resolve
PR Close#27497
Analogously to directives, the `ngInjectableDef` field in .d.ts files is
annotated with the type of service that it represents. If the service
contains required generic type arguments, these must be included in
the .d.ts file.
PR Close#27037
A previous fix to ngtsc opened the door for duplicate directives in
the 'directives' array of a component. This would happen if the directive
was declared in a module which was imported more than once within the
component's module.
This commit adds deduplication when the component's scope is materialized,
so declarations which arrive via more than one module import are coalesced.
PR Close#27462
The method `ts.CompilerHost.directoryExists` is optional, and was not
previously handled by our ts.CompilerHost wrapper for factory and
summary shims (GeneratedShimsHostWrapper).
TypeScript checks for the existence of this method and silently ignores
things like typeRoots if it's not found. This commit adds proper handling
of directoryExists() to the shim.
A test is also added which verifies typeRoots behavior works when shims
are enabled.
PR Close#27470
Previously ngtsc assumed resource files (templateUrl, styleUrls) would be
physically present in the file system relative to the .ts file which
referenced them. However, ngc previously resolved such references in the
context of ts.CompilerOptions.rootDirs. Material depends on this
functionality in its build.
This commit introduces resolution of resources by leveraging the TypeScript
module resolver, ts.resolveModuleName(). This resolver is used in a way
which will never succeed, but on failure will return a list of locations
checked. This list is then filtered to obtain the correct potential
locations of the resource.
PR Close#27357
This commit adds support for resolution of styleUrls to ngtsc. Previously
this field was never read, and so components with styleUrls would appear
unstyled after compilation.
PR Close#27357
Previously the concept of multiple directives with the same selector was
not supported by ngtsc. This is due to the treatment of directives for a
component as a Map from selector to the directive, which is an erroneous
representation.
Now the directives for a component are stored as an array which supports
multiple directives with the same selector.
Testing strategy: a new ngtsc_spec test asserts that multiple directives
with the same selector are matched on an element.
PR Close#27298
This commit causes a call to setClassMetadata() to be emitted for every
type being compiled by ngtsc (every Angular type). With this metadata,
the TestBed should be able to recompile these classes when overriding
decorator information.
Testing strategy: Tests in the previous commit for
generateSetClassMetadataCall() verify that the metadata as generated is
correct. This commit enables the generation for each DecoratorHandler,
and a test is added to ngtsc_spec to verify all decorated types have
metadata generated for them.
PR Close#26860
We are close enough to blacklist a few test targets, rather than whitelist targets to run...
Because bazel rules can be composed of other rules that don't inherit tags automatically,
I had to explicitly mark all of our ts_library and ng_module targes with "ivy-local" and
"ivy-jit" tags so that we can create a query that excludes all fixme- tagged targets even
if those targets are composed of other targets that don't inherit this tag.
This is the updated overview of ivy related bazel tags:
- ivy-only: target that builds or runs only under ivy
- fixme-ivy-jit: target that doesn't yet build or run under ivy with --compile=jit
- fixme-ivy-local: target that doesn't yet build or run under ivy with --compile=local
- no-ivy-jit: target that is not intended to build or run under ivy with --compile=jit
- no-ivy-local: target that is not intended to build or run under ivy with --compile=local
PR Close#26471
This commit adds generation of .ngsummary.js shims alongside .ngfactory.js
shims when generated files are enabled.
Generated .ngsummary shims contain a single, null export for every exported
class with decorators that exists in the original source files. Ivy code
does not depend on summaries, so these exist only as a placeholder to allow
them to be imported and their values passed to old APIs. This preserves
backwards compatibility.
Testing strategy: this commit adds a compiler test to verify the correct
shape and contents of the generated .ngsummary.js files.
PR Close#26495
This commit builds on the NgtscTestEnvironment helper work before and
introduces template_typecheck_spec.ts, which contains compiler tests
for template type-checking.
PR Close#26203
This commit gets ready for the introduction of ngtsc template
type-checking tests by refactoring test environment setup into a
custom helper. This helper will simplify the authoring of future
ngtsc tests.
Ngtsc tests previously returned a numeric error code (a la ngtsc's CLI
interface) if any TypeScript errors occurred. The helper has the
ability to run ngtsc and return the actual array of ts.Diagnostics, which
greatly increases the ability to write clean tests.
PR Close#26203
Previously in Ivy, metadata for directives/components/modules/etc was
carried in .d.ts files inside type information encoded on the
DirectiveDef, ComponentDef, NgModuleDef, etc types of Ivy definition
fields. This works well, but has the side effect of complicating Ivy's
runtime code as these extra generic type parameters had to be specified
as <any> throughout the codebase. *DefInternal types were introduced
previously to mitigate this issue, but that's the wrong way to solve
the problem.
This commit returns *Def types to their original form, with no metadata
attached. Instead, new *DefWithMeta types are introduced that alias the
plain definition types and add extra generic parameters. This way the
only code that needs to deal with the extra metadata parameters is the
compiler code that reads and writes them - the existence of this metadata
is transparent to the runtime, as it should be.
PR Close#26203
The bootstrap property of @NgModule was not previously compiled by
the compiler in AOT or JIT modes (in Ivy). This commit adds support
for bootstrap.
PR Close#25775
This fixes a bug in ngtsc where each @Directive was compiled using a
separate ConstantPool. This resulted in two issues:
* Directive constants were not shared across the file
* Extra statements from directive compilation were dropped instead of
added to the file
This commit fixes both issues and adds a test to verify @Directive is
working properly.
PR Close#25620
When generating the 'directives:' property of ngComponentDef, ngtsc
needs to be conscious of declaration order. If a directive being
written into the array is declarated after the component currently
being compiled, then the entire directives array needs to be wrapped
in a closure.
This commit fixes ngtsc to pay attention to such ordering issues
within directives arrays.
PR Close#25392
This commit creates an API for factory functions which allows them
to be inherited from one another. To do so, it differentiates between
the factory function as a wrapper for a constructor and the factory
function in ngInjectableDefs which is determined by a default
provider.
The new form is:
factory: (t?) => new (t || SomeType)(inject(Dep1), inject(Dep2))
The 't' parameter allows for constructor inheritance. A subclass with
no declared constructor inherits its constructor from the superclass.
With the 't' parameter, a subclass can call the superclass' factory
function and use it to create an instance of the subclass.
For @Injectables with configured providers, the factory function is
of the form:
factory: (t?) => t ? constructorInject(t) : provider();
where constructorInject(t) creates an instance of 't' using the
naturally declared constructor of the type, and where provider()
creates an instance of the base type using the special declared
provider on @Injectable.
PR Close#25392
Inside of a nested template, an attempt to generate code for a banana-
in-a-box expression would cause a crash in the _AstToIrVisitor, as it
was not handling the case where a write would be generated to a local
variable.
This change supports such a mode of operation.
PR Close#25321
Previously the compiler compliance tests ran and built test code with
real dependencies on @angular/core and @angular/common. This meant that
any changes to the compiler would result in long rebuild processes
for tests to rerun.
This change removes those dependencies and causes test code to be built
against the fake_core stub of @angular/core that the ngtsc tests use.
This change also removes the dependency on @angular/common entirely, as
locality means it's possible to reference *ngIf without needing to link
to an implementation.
PR Close#25248
Existing bootstrap code in the wild depends on the existence of
.ngfactory files, which Ivy does not need. This commit adds the
capability in ngtsc to generate .ngfactory files which bridge
existing bootstrap code with Ivy.
This is an initial step. Remaining work includes complying with
the compiler option to specify a generated file directory, as well
as presumably testing in g3.
PR Close#25176
There is a bug in the existing handling for cross-file references.
Suppose there are two files, module.ts and component.ts.
component.ts declares two components, one of which uses the other.
In the Ivy model, this means the component will get a directives:
reference to the other in its defineComponent call.
That reference is generated by looking at the declared components
of the module (in module.ts). However, the way ngtsc tracks this
reference, it ends up comparing the identifier of the component
in module.ts with the component.ts file, detecting they're not in
the same file, and generating a relative import.
This commit changes ngtsc to track all identifiers of a reference,
including the one by which it is declared. This allows toExpression()
to correctly decide that a local reference is okay in component.ts.
PR Close#25080
When ngtsc encounters a reference to a type (for example, a Component
type listed in an NgModule declarations array), it traces the import
of that type and attempts to determine the best way to refer to it.
In the event the type is defined in the same file where a reference
is being generated, the identifier of the type is used. If the type
was imported, ngtsc has a choice. It can use the identifier from the
original import, or it can write a new import to the module where the
type came from.
ngtsc has a bug currently when it elects to rely on the user's import.
When writing a .d.ts file, the user's import may have been elided as
the type was not referred to from the type side of the program. Thus,
in .d.ts files ngtsc must always assume the import may not exist, and
generate a new one.
In .js output the import is guaranteed to still exist, so it's
preferable for ngtsc to continue using the existing import if one is
available.
This commit changes how @angular/compiler writes type definitions, and
allows it to use a different expression to write a type definition than
is used to write the value. This allows ngtsc to specify that types in
type definitions should always be imported. A corresponding change to
the staticallyResolve() Reference system allows the choice of which
type of import to use when generating an Expression from a Reference.
PR Close#25080
@ContentChild[ren] and @ViewChild[ren] can contain a forwardRef() to a
type. This commit allows ngtsc to unwrap the forward reference and
deal with the node inside.
It includes two modes of support for forward reference resolution -
a foreign function resolver which understands deeply nested forward
references in expressions that are being statically evaluated, and
an unwrapForwardRef() function which deals only with top-level nodes.
Both will be useful in the future, but for now only unwrapForwardRef()
is used.
PR Close#25080