Template pipeline is now the default template compiler.
A pair of source map tests is failing, related to DI in JIT mode; I will fix and re-enable these during the preview period.
PR Close#54571
When the linker is running using an unpublished version of angular, locally built, the version will be `0.0.0`.
When encountering this situation, the range that for the linker map support is considered to be `*.*.*` allowing
for the linker to work at build time with packages built with versioned angular.
Most notably this allows for us to properly use the linker in building our documentation site with the locally
built version of angular.
PR Close#54439
The Template Pipeline is a brand new backend for the Angular compiler, replacing `TemplateDefinitionBuilder`. It generates the Ivy instructions corresponding to an input template (or host binding). The Template Pipeline has an all-new design based on an intermediate representation compiled over many phases, which will allow us to experiment with compiler changes more easily in the future.
With this commit, the template pipeline can now be enabled in any project via the `useTemplatePipeline` TSConfig option. However, it is still disabled by default.
PR Close#54057
This commit ensures that libraries can use signal-based queries, and the
partial compilation output will capture their metadata.
The linker is updated to support parsing this.
Two notes:
1. Older linker versions are not capable of parsing this, so the minimum
version for signal-based queries is adjusted when such are used.
2. We only emit `isSignal` metadata for queries when signal queries are
used. This enables libraries to continue supporting older linker
versions, if signal-based queries are not used.
PR Close#53978
This commit adds extra logic to produce a diagnostic in case `@Component.deferredImports` contain types from imports that also bring eager symbols. This would result in retaining a regular import and generating a dynamic import, which would not allow to defer-load dependencies.
PR Close#53899
As we introduced the new partial output for signal inputs, we also need
to update the linker code to be able to parse this. This commit adds
this functionality.
In the follow-up commit, compliance tests for linking, partial output,
and full compilations are added.
PR Close#53808
The linker AST is abstracted to be agnostic of the underlying
implementation AST. i.e. TS AST or Babel AST.
This abstraction also intends to provide some type-safety-ness to
parsing of various partial declarations. This commit improves type
safety further by fixing that `AstValue'`s were not checked for
assignability of `T`- potentially hiding issues/unaccounted values.
Additionally, we fix that `getObject()` does not properly narrow
union types to actual object literals. This happend because e.g. arrays
are of type `object`. We can improve type safety here. Using `Record`
did not help as an array would still assign to that.
PR Close#53808
This commit captures the metadata on whether an input is signal based or
not, in the `.d.ts` of directives and components. This exposes this
information to consumers of the directives. This is needed because
libraries may use signal inputs, and we need to know whether bound
inputs to this library are signal-based or not- so that we can generate
proper type-checking code (account for `InputSignal` or not).
Additionally, this commit introduces a new structure for the partial
compilation output of directive inputs. With the current emit, inputs
are captured in a data structure that is equivalent to the internal data
structure passed to `defineDirective` (the full compilation output).
This worked fine as we only captured a few strings, but in ends up
being a bad practice because partial compilation output should NOT
capture internal data structures that might be specific to a certian
Angular core version. Instead, we introduce a new "future proof"
structure that:
- can hold additional metadata in backwards-compatible ways, like
`isSignal` or `isRequired`.
- can be parsed trivially using the `AstHost` for the linker, instead of
having to unwrap/parse an array structure.
The new structure is only emitted when we discover that some inputs are
signal based (or ultimately end up configuring input flags). This is
done for backwards compatibility, so that libraries without signal
inputs remain compatible with older linker versions. In the future,
this might be the only emit.
Compliance tests for this follow in future commits, when the linker
portion is also in place. This commit specialices on the code
generation. With the linker, and compliance test infrastructure fixed
(that is broken right now), we can test the full integration.
PR Close#53521
The `@babel/core` package provides the functionality of multiple other babel packages
without the need to directly depend or import the other babel packages. Since the
`@babel/core` package is already used and imported in the locations that previously
used the other babel packages, an overall reduction in both imports and dependencies
is possible. Six babel related packages were able to be removed from the root `package.json`
and one (also present in the aforementioned six) was removed as a dependency from the
`@angular/localize` package. Unfortunately, the functionality used from the `@babel/generator`
package is not provided by `@babel/core` and is still present. Further refactoring may
allow its removal as well in the future.
The following packages were removed:
* @babel/parser
* @babel/template
* @babel/traverse
* @babel/types
* @types/babel__template
* @types/babel__traverse
PR Close#53441
The `@babel/core` package provides the functionality of multiple other babel packages
without the need to directly depend or import the other babel packages. Since the
`@babel/core` package is already used and imported in the locations that previously
used the other babel packages, an overall reduction in both imports and dependencies
is possible. Six babel related packages were able to be removed from the root `package.json`
and one (also present in the aforementioned six) was removed as a dependency from the
`@angular/localize` package. Unfortunately, the functionality used from the `@babel/generator`
package is not provided by `@babel/core` and is still present. Further refactoring may
allow its removal as well in the future.
The following packages were removed:
* @babel/parser
* @babel/template
* @babel/traverse
* @babel/types
* @types/babel__template
* @types/babel__traverse
PR Close#53374
Enables the new `@` block syntax by default by removing the `enabledBlockTypes` flags. There are still some internal flags that allow special use cases to opt out of the block syntax, like during XML parsing and when compiling older libraries (see #51979).
PR Close#51994
Adds some logic to enable parsing of block syntax in the linker. Note that the syntax is only enabled on code compiled with Angular v17 or later.
PR Close#51979
Reworks the compiler to use the API introduced in #51816 to match triggers to the element nodes they point to. This will be used to generate the new instructions for `on interaction` and `prefetch on interaction`.
PR Close#51830
Extends the compiler to add support for generating arrow functions in the output AST. This will be required for the `for` control flow block and we can potentially leverage it in other places to reduces the amount of generated code.
PR Close#51436
This commit brings the logic to calculate teh set of dependencies for each defer block. For each dependency we also identify whether it can be defer-loaded or not.
PR Close#51162
This commit updates the output AST (and related visitors) to support dynamic imports. This functionality will be used later to generate the output for defer blocks.
PR Close#51087
The new interface is discrete-unioned with the existing interface to cover the cases for local and global (i.e., full and partial) compilation modes.
This change of interface required some adjustmeents cross repo which explains the changes made to other files.
PR Close#50577
Adds the necessary compiler changes to support input transform functions. The compiler output has changed in the following ways:
### Directive handler
The directive handler now extracts a reference to the input transform function and it resolves the type of its first parameter. It also asserts that the type can be referenced in the compiled output and that it doesn't clash with any pre-existing `ngAcceptInputType_` members.
### .d.ts
In the generated declaration files the compiler now inserts an `ngAcceptInputType_` member for each input with a `transform` function. The member's type corresponds to the type of the first parameter of the function, e.g.
```typescript
// foo.directive.ts
@Directive()
export class Foo {
@Input({transform: (incomingValue: string) => parseInt(incomingValue)}) value: number;
}
// foo.directive.d.ts
export class Foo {
value: number;
static ngAcceptInputType_value: string;
}
```
### Type check block
If an input has `transform` function, the TCB will use the type of its first parameter for the setter type. This uses the same infrastructure as the `ngAcceptInputType_` members.
### Directive declaration
The generated runtime directive declaration call now includes the `transform` function in the `inputs` map, if the input is being transformed. The function will be picked up by the runtime in the next commit to do the actual transformation.
```typescript
// foo.directive.ts
@Directive()
export class Foo {
@Input({transform: (incomingValue: string) => parseInt(incomingValue)}) value: number;
}
// foo.directive.js
export class Foo {
ɵdir = ɵɵdefineDirective({
inputs: {
value: ['value', 'value', incomingValue => parseInt(incomingValue)]
}
});
}
```
PR Close#50225
This commit adds the `signals: boolean` property to the internal
directive/component metadata. This does not add it to the public API
yet, as the feature has no internal support other than compiler
detection.
PR Close#49981
The concept of "internal" and "adjacent" type expression used to be necessary to support
ngcc, as it had to process downleveled class declarations using an IIFE, where the class
name within the IIFE could be different from the outer class name. With the removal of
ngcc we no longer need to make this distinction, so this commit removes these concepts
entirely.
PR Close#49136
Adds support for marking a directive input as required. During template type checking, the compiler will verify that all required inputs have been specified and will raise a diagnostic if one or more are missing. Some specifics:
* Inputs are marked as required by passing an object literal with a `required: true` property to the `Input` decorator or into the `inputs` array.
* Required inputs imply that the directive can't work without them. This is why there's a new check that enforces that all required inputs of a host directive are exposed on the host.
* Required input diagnostics are reported through the `OutOfBandDiagnosticRecorder`, rather than generating a new structure in the TCB, because it allows us to provide a better error message.
* Currently required inputs are only supported during AOT compilation, because knowing which bindings are present during JIT can be tricky and may lead to increased bundle sizes.
Fixes#37706.
PR Close#49468
This reverts commit 13dd614cd1.
This breaks a g3 Typescript compilation tests where diagnostics are
expected for a missing input in the component.
PR Close#49467
Adds support for marking a directive input as required. During template type checking, the compiler will verify that all required inputs have been specified and will raise a diagnostic if one or more are missing. Some specifics:
* Inputs are marked as required by passing an object literal with a `required: true` property to the `Input` decorator or into the `inputs` array.
* Required inputs imply that the directive can't work without them. This is why there's a new check that enforces that all required inputs of a host directive are exposed on the host.
* Required input diagnostics are reported through the `OutOfBandDiagnosticRecorder`, rather than generating a new structure in the TCB, because it allows us to provide a better error message.
* Currently required inputs are only supported during AOT compilation, because knowing which bindings are present during JIT can be tricky and may lead to increased bundle sizes.
Fixes#37706.
PR Close#49453
This reverts commit 1a6ca68154.
This breaks tests in google3 which might be depending on private APIs. We
need to update these tests before we can land this PR.
PR Close#49449
Adds support for marking a directive input as required. During template type checking, the compiler will verify that all required inputs have been specified and will raise a diagnostic if one or more are missing. Some specifics:
* Inputs are marked as required by passing an object literal with a `required: true` property to the `Input` decorator or into the `inputs` array.
* Required inputs imply that the directive can't work without them. This is why there's a new check that enforces that all required inputs of a host directive are exposed on the host.
* Required input diagnostics are reported through the `OutOfBandDiagnosticRecorder`, rather than generating a new structure in the TCB, because it allows us to provide a better error message.
* Currently required inputs are only supported during AOT compilation, because knowing which bindings are present during JIT can be tricky and may lead to increased bundle sizes.
Fixes#37706.
PR Close#49304
Since we generate a `.mjs` file as entry-point for jasmine tests,
a couple of issues prevented the transitive dependencies from
bootstrap targets to be brought in (causing resolution errors):
1. The `_files` (previously `_esm2015`) targets are no longer needed,
and they also miss all the information on runfiles.
2. The aspect for computing linker mappings does not respect the
`bootstrap` attribute from the `spec_entrypoint` so we manually
add the extract ESM output targets (this rule works with the aspect
and forwards linker mappings).
PR Close#48521
For every `ts_library` target we expose a shorthand that grants
access to the JS files because `DefaultInfo` of a ts library
only exposes the `.d.ts` files.
We rename this away from `es2015` since in practice it's a much
higher target these days. Additionally we no longer use the devmode
output but rather use the prodmode output which has the explicit
`.mjs` output- compatible with ESM.
PR Close#48521
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.
For example, if we take the following definition:
```ts
@Directive({
hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```
Will compile to:
```js
MyDir.ɵdir = ɵɵdefineComponent({
features: [ɵɵHostDirectivesFeature([HostA, {
directive: HostB,
inputs: {
input: "alias"
}
}])]
});
```
The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.
Relates to #8785.
PR Close#46868
When generating .d.ts metadata for NgModules, by default we emit type
references to their declarations, imports, and exports. However, this
information is not necessarily useful to consumers. References to private
directives (those that aren't exported by the NgModule) for example aren't
at all useful as they can only affect other components declared in the
NgModule. References to imports are of limited usefulness - they might be
helpful for an IDE to understand the DI structure of an application, but
aren't at all used by a downstream compiler.
Generating this metadata is not without cost. When an incremental build
system uses changes in inputs to determine when a rebuild is necessary, any
changes in .d.ts files might cause downstream targets to rebuild. If those
.d.ts changes are in the "private" side of the NgModule (imports or non-
exported directives/pipes), then these rebuilds are wholly unnecessary.
This commit introduces the `onlyPublishPublicTypingsForNgModules` flag for
the compiler. When this flag is set, the compiler will filter the emitted
references in NgModule .d.ts output and only reference those directives/
pipes that are exported from the NgModule (its public API surface). Omitting
the flag preserves the existing behavior of emitting all references, both
public and private.
This is especially useful for build systems such as Bazel.
PR Close#45894
The formatting of the `babel_ast_host.ts` file is invalid due to a
recently-merged PR. The PR had a passing `lint` state but this seemed
to just appear like this because the Git comparison range on upstream
branches can become invalid (due to a known bug in CircleCI -- reported)
PR Close#46082
This commit accounts for the Babel types changes. Some properties
can now also be `undefined` so existing checks/assertions had to
be adjusted to also capture `undefined` (along with `null`).
Additionally, in preparation for a new ECMA proposal, Babel types
seem to have been updated to include private names in object property
keys. This is not necessarily the case for object expressions, but
could be for object patterns (in the future -- when implemented).
More details: https://github.com/babel/babel/pull/14304 and
https://github.com/tc39/proposal-destructuring-private.
PR Close#45967
This commit expands on the unified dependency tracking in the previous
commit and adds tracking of NgModule dependencies. These are not used for
standard components, but are emitted for standalone components to allow the
runtime to roll up providers from those NgModules into standalone injectors.
PR Close#45672
Previously, the compiler would represent template dependencies of a
component in its component definition through separate fields (`directives`,
`pipes`).
This commit refactors the compiler/runtime interface to use a single field
(`dependencies`). The runtime component definition object still has separate
`directiveDefs` and `pipeDefs`, which are calculated from the `dependencies`
when the definition is evaluated.
This change is also reflected in partially compiled declarations. To ensure
compatibility with partially compiled code already on NPM, the linker
will still honor the old form of declaration (with separate fields).
PR Close#45672
When `@angular/compiler` processes metadata and compiles a definition field,
it might also choose to return statements that are associated with that
definition, and should be included after the type being compiled. Currently,
the linker ignores these statements, as there are none generated that are
relevant in the linking operation.
A challenge to supporting such associated statements is that the linker
operates on "declare" expressions, and replaces those expressions with other
expressions. It does not have the capability to append statements after the
whole type. The linker actually faces this challenge with statements from
the `ConstantPool` as well, and solves this problem by generating an IIFE
expression that executes the statements and then returns the definition
expression.
Previously, an `EmitScope` processed the definition and converted it to an
expression, as well as collected constant statements from a `ConstantPool`.
A special `IifeEmitScope` implementation was used when emitting into a
context where top-level constant statements couldn't be added at all, and
uses the IIFE strategy in this case.
This commit adds blanket support for associated statements to the linker
using this IIFE strategy. The main `EmitScope` now uses the IIFE strategy to
emit associated statements, and `IifeEmitScope` has been renamed to
`LocalEmitScope`. Now, the `LocalEmitScope` represents constant statements
as associated statements to the main `EmitScope` implementation, so they
get included in the IIFE as well.
Tests are adjusted/added to cover this new behavior. This is a refactoring
commit because no live generated code is affected - there are no cases where
associated statements are present in linked definitions today.
PR Close#45024
The `compileNgModule` operation previously supported a flag `emitInline`,
which controlled whether template scoping information for the NgModule was
emitted directly into the compiled NgModule definition, or whether an
associated statement was generated which patched the information onto the
NgModule definition. Both options are useful in different contexts.
This commit changes this flag to an enum (and renames it), which allows for
a third option - do not emit any template scoping information. This option
is added to better represent the actual behavior of the Angular Linker,
which sometimes configures `compileNgModule` to use the side-effectful
statement generation but which does not actually emit such associated
statements. In other words, the linker effectively does not generate
scoping information for NgModules at all (in some configurations) and this
option more directly expresses that behavior.
This is a refactoring as no generated code is changed as a result of
introducing this flag, due to the linker's behavior of not emitting
associated statements.
PR Close#45024
The `@angular/localize` package depends on a version of Babel that is two years
old, so this commit updates to the latest version.
Some changes were made to the linker and compliance tests to account for slight
changes in source maps, along with a few code updates because of changes to
the typings of Babel.
PR Close#44931
This commit implements the first phase of standalone components in the Angular
compiler. This mainly includes the scoping rules for standalone components
(`@Component({imports})`).
Significant functionality from the design is _not_ implemented by this PR,
including:
* imports of standalone components into NgModules.
* the provider aspect of standalone components
Future commits will address these issues, as we proceed with the design of
this feature.
PR Close#44812
To make our test output i.e. devmode output more aligned
with what we produce in the NPM packages, or to be more
aligned with what Angular applications will usually consume,
the devmode output is switched from ES5 to ES2015.
Additionally various tsconfigs (outside of Bazel) have been
updated to match with the other parts of the build. The rules
are:
ES2015 for test configurations, ES2020 for actual code that will
end up being shipped (this includes the IDE-only tsconfigs).
PR Close#44505
This commit removes the View Engine runtime. Itself, this change is
relatively straightforward, but it represents the final step in a multi-year
journey. It's only possible due to the hard work of many current and former
team members and collaborators, who are too numerous to list here.
Co-authored-by: Alan Agius <alan.agius4@gmail.com>
Co-authored-by: Andrew Kushnir <akushnir@google.com>
Co-authored-by: Andrew Scott <atscott01@gmail.com>
Co-authored-by: Andrew Seguin <andrewjs@google.com>
Co-authored-by: Cédric Exbrayat <cedric@ninja-squad.com>
Co-authored-by: Charles Lyding <19598772+clydin@users.noreply.github.com>
Co-authored-by: Dave Shevitz <dshevitz@google.com>
Co-authored-by: Doug Parker <dgp1130@users.noreply.github.com>
Co-authored-by: Dylan Hunn <dylhunn@gmail.com>
Co-authored-by: Emma Twersky <emmatwersky@google.com>
Co-authored-by: George Kalpakas <kalpakas.g@gmail.com>
Co-authored-by: Igor Minar <iminar@google.com>
Co-authored-by: Jeremy Elbourn <jelbourn@google.com>
Co-authored-by: Jessica Janiuk <jessicajaniuk@google.com>
Co-authored-by: JiaLiPassion <JiaLi.Passion@gmail.com>
Co-authored-by: Joey Perrott <josephperrott@gmail.com>
Co-authored-by: Joost Koehoorn <joost.koehoorn@gmail.com>
Co-authored-by: Kristiyan Kostadinov <crisbeto@abv.bg>
Co-authored-by: Madleina Scheidegger <mscheid@google.com>
Co-authored-by: Mark Thompson <2554588+MarkTechson@users.noreply.github.com>
Co-authored-by: Minko Gechev <mgechev@gmail.com>
Co-authored-by: Paul Gschwendtner <paulgschwendtner@gmail.com>
Co-authored-by: Pawel Kozlowski <pkozlowski.opensource@gmail.com>
Co-authored-by: Pete Bacon Darwin <pete@bacondarwin.com>
Co-authored-by: Wagner Maciel <wagnermaciel@google.com>
Co-authored-by: Zach Arend <zachzach@google.com>
PR Close#43884
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