Currently the TS generated output (not JIT), breaks at runtime because
we emit all variables using the `Final` modifier. i.e. constants.
This breaks shallow references when we run our acceptance signal
tests using AOT.
Compiler portion for supporting content queries in signal components.
This is based on the preparation work, for detecting such queries. See
previous commits.
With the recent changes for local refs, we now also generate all
variables in the create block.
This works overall, but we end up with incorrect variable optimization
because calls of `nextContext` in listener functions end up tricking
the optimization logic into thinking that the outer `nextContext` calls
in the create block are _relevant_ for the listener function body.
e.g.
```
if (create) {
const _bla = nextContext();
i0.listener(() => {
restoreView();
const _ctx1 = nextContext();
/* do somth with _ctx1 */
});
}
```
`_bla` can safely be removed here, even though a `ContextRead/Write` has
occurred inside the listener operation. We process listeners separately.
We recently changed the pure function code to look for
all operations in a view. This ended up causing pure functions
to be generated for expressions in listeners. This might be fine
but diverges from the existing TDB and breaks compliance tests.
Culprit commit: https://github.com/angular/angular/commit/a61e41c88049eb12a0b23b1e7fa49a16b0eb91d7
New implementation of type-checking for signal inputs. Much simpler, and
without causing signficant type check block changes that would require
more changes to the language service completion logic / or rewrites of
more than 50+ handwritten code output tests for type check blocks.
See previous commits for other explored solutions.
NOTE: This is very experimental and manual type check block code is not
updated. All of this complexity arises from the fact of attempting to
support bindings where they go to the same directive with multiple
inputs of the same name.
Potentially we can deprecate this behavior for input signal based
components and avoid this complexity. Alternative solution is to simply
repeat expression diagnostics if a binding goes to two same fields.
This commit adds support for local refs in signal property bindings, by
generating variables in the creation block. To implement this support:
* a new instruction shallowReference() is introduced, which is not tied to
the current view context.
* variables are now generated for creation mode as well as update mode
* a new template pipeline pass (`phaseCreationVarColocation`) handles
ordering of reference variable declaration and assignment in the creation
block (guaranteeing references are only read after declarations).
Previously the compiler output AST did not support using
`o.BinaryExpression` for assignments (as TypeScript does). Instead
`o.WriteVarExpr` is defined, which only allows writing to string named
variables.
Previously the template pipeline would prefer to use a local variable
definition in favor of ctx. This commit improves the logic to prefer `ctx`
for the root view even if a variable for the context is available.
In prod builds, selectors are optimized and spaces a removed. #48558 introduced a regression on selectors without spaces. This commit fixes tihs.
Fixes#49100
PR Close#49118
Currently the compiler allocates a variable slot to the `@for` loop expression which ends up unused since we don't store the result on the `LView`.
PR Close#52158
A new flag added to the component's debug info to determine whether to throw runtime error (in dev mode) if component is being rendered without its NgModule. This flag is only set for non-standalone components.
PR Close#52061
Updates the Ivy AST to allow for `@switch` blocks to capture nested blocks that are not `@case` and `@default`. These blocks will be used for autocompletion in the language service.
These changes also update the logic for `@switch` and `@if` blocks so that they produce an AST node even if there are errors. The errors will still be surfaced to users, but producing AST nodes allows us to recover parts of the expression later if necessary.
PR Close#52136
Fixes that the new block syntax was generating instructions in the wrong order which meant that pipes were being declared too early. This meant that if the block is first in the template, any pipes used in it won't be able to inject things like `ChangeDetectorRef`.
These changes update the compiler and add a bunch of tests to ensure that pipes work as expected.
Fixes#52102.
PR Close#52112
This commit updates `@defer` logic related to handling `after` and `minimum` parameters tree-shakable.
If `after` or `minimum` was used on a `@loading` or `@placeholder` blocks, compiler generates an extra argument for the `ɵɵdefer` instruction. This extra argument is a reference to a function that brings timer-related code.
PR Close#52042
A new utility function `compileClassDebugInfo` is introduced which creates compile result necessary to generate statement for attaching some useful debug info into angular classes. An example of teh new statement would be:
```
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(Main, { className: "Main", filePath: "$PROJECT_ROOT/src/main.ts", lineNumber: 8 }); })();
```
Currently, the debug info contains:
- the class name
- the file path in which it is defined
- the line number in which it is defined
The debug info will be used in runtime to generate more helpful error messages.
PR Close#51919
Cleans up the i18n placeholder resolution phase by extracting the
details of how the map is serialized into its own class, instead of
mixing it with the phase's traversal logic.
PR Close#51988
Template instructions exist in the parent view, but for the purposes of
the i18n placeholders, they should use the subTemplateIndex of the i18n
op wrapping their view.
PR Close#51988
The custom logic in the generate advance phase for i18n expressions did
not work in all cases. Instead we add a new phase to update the
expression's target op, and then allow the standard advance generation
code to determine the number of advance instructions needed.
Co-authored-by: Dylan Hunn <dylhunn@users.noreply.github.com>
PR Close#51988
Fills in values for sub-template placeholders in i18n messages. This
includes both the tag placeholders for ng-template tags, as well as
merging in any placeholders from the child i18n block.
PR Close#51988
Adds an additional sub-template index parameter to child i18n blocks
that are propagated from the root block. This additional paramete
indicates the index of the template in the i18n message.
Co-authored-by: Dylan Hunn <dylhunn@users.noreply.github.com>
PR Close#51988
Fixes that the compiler wasn't picking up pipes used inside defer block triggers as dependencies. We had implemented the `visitDeferredTrigger` visitor method, but it wasn't being called, because we weren't going through the `visitAll` method of the deferred block. We don't use `visitAll`, because child nodes have to be processed differently than the connected blocks and triggers.
Fixes#52068.
PR Close#52071
Two key refactors to enable deeper language service support for blocks:
(1) We now generate accurate source spans for the various block types. Additionally, all the top-level source spans for a block are now *inclusive* of all the connected or descending blocks. This helps the language service visit connected blocks.
(2) The language service's template visitor was previously skipping over the AST nodes corresponding to several block types. We are now careful to visit all such nodes.
PR Close#52038
Adds an `UnknownBlock` node to the Ivy AST to represent blocks that haven't been recognized by the compiler. This will make it easier to integrate blocks into the language service.
PR Close#52047
Adds some logic to treat incomplete blocks as empty blocks so that we can recover from them. Also logs an error about the incomplete block.
PR Close#52047
Updates the lexer to parse blocks as incomplete, instead of throwing errors. This will allow us to better handle them further down in the pipeline.
PR Close#52047
Consider an `ng-template` which is generated as a result of a structural directive:
```
<div *ngFor="let inner of items"
(click)="onClick(inner)"
[title]="getTitle()"
>
```
This should logically expand into something like the following:
```
<ng-template [ngForOf]="..." >
<div (click)="..." [title]="..."></div>
</ng-template>
```
Note that the `(click)` handler and the `[title]` property are only present on the inner div, *not* on the enclosing generated `ng-template`.
Previously, Template Pipeline would place these bindings on *both* the tempate and the inner element.
However, we can't just remove them completely, because these bindings should still be matchable on the generated `ng-template` (which is very surprising, but nonetheless true).
We resolve this issue with two improvements:
(1) The ingestion step is now much smarter about determining not only if a binding is on a template element, but whether it actually targets that template element.
(2) We use `ExtractedAttributeOp` directly, rather than going through `BindingOp`, to cause the `ng-template` to still receive these bindings in its `consts` array for matching purposes.
PR Close#51950
For components, the parser already extracts the `important` property (and it is later disregarded). However, because host bindings use a totally separate parsing code path, this was never happing for host bindings.
Here, we add some code to the host style parsing phase to drop the `!important` suffix.
We could solve this category of problems for good by parsing host bindings with the same code as template bindings.
PR Close#51950
Previously, we always generated temporary variable declarations at the beginning of each view's update block. This is wrong, for two reasons:
1. Temporaries can be used in the create block
2. When listeners use temporaries, we should declare them inside the listener.
Now, we always place temporaries at the beginning of the enclosing OpList, and recursively try to generate them when we find a listener.
PR Close#51950
Reworks a few more places to output arrow functions instead of function declarations in order to reduce the amount of code we generate. Some of these places include:
* Factories in injectable definitions.
* Forward references.
* `dependencies` function in the component definition.
* `consts` function in the component definition.
PR Close#52010
The template pipeline now supports basic forms of `defer` blocks. This includes the `loading`, `placeholder`, and `error` blocks, as well as the loading and placeholder configuration options.
Lazy dependencies and prefetch are not yet implemented.
PR Close#51942
Previously, we had many individual constants collected at different places in the template pipeline, using `job.addConst(...)`. Now, this trait can be used to cause any op or expression to receive const collection.
PR Close#51942
Ops with `ConsumesSlotOpTrait` have a self-xref, and are assigned a corresponding `slot`.
Ops with `UsesSlotIndexTrait` have a `target`-xref, and are assigned the `slot` of that `target`.
In both cases, the field name `slot` is used, but it means different things. Therefore, any op which both consumes and uses a slot will have a collision of two different meanings on its `slot` field.
This commit renames `slot` to `slotTarget` in the `UsesSlotIndexTrait`, to eliminate this collision.
PR Close#51942
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
Increases the `minVersion` of component declarations that use bloks to v17 in order to indicate to users that they need to update if the library they're using is on the new syntax, while preserving backwards compatibility for libraries that do not use the syntax.
PR Close#51979
We were previously emitting pure functions as `function foo(args) {return bar;}`, but `TemplateDefinitionBuilder` uses arrow functions instead (`const foo = (args) => bar`). By matching this behavior, we can enable many additional tests.
PR Close#51961