This allows us to test the template pipeline TS emit (where we already
caught a bug using this), and also allows us to test the proper
recognition of e.g. `input`, `output`, `viewChild` etc- while also
testing type-checking.
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.
Currently, a listener on an element containing a dash, will result in
runtime errors because the function name will be generated using a dash.
e.g.
```
function MyApp_Template_some-comp_bla_0() {}
```
throwing with a syntax error due to the dash. We fix this by re-using
the sanitize identifier function from the current template definition
builder.
Compiler portion for supporting content queries in signal components.
This is based on the preparation work, for detecting such queries. See
previous commits.
Add a test verifying that the onDirty callback:
- does not fire initially;
- fires once when a query is marked dirty (even if there are
multiple setDirty notifications).
Make sure that null, undefined and NaN interpolated values
are rendered consistently with the current ivy approach:
- null and undefined are rendered as empty strings;
- NaN is rendered as-is.
DOM bindings are wrapped into computed now so their values
are memoized. As the result expression in DOM bindings are
re-evaluated when a component is change-detected.
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 reverts commit 2e3fe0747990647c5cfbba5429e90ed621b18e6e.
Based on the recent design discussion we are going to express property
interpolation as a computed function and reuse the propertyCreate
infrastructure.
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.
There was an interesting issue that surfaced in the type checking
tests. Previously an input was type-checked using an expression like:
```ts
myDir.input = myrDir.input2 = userExpr
```
Note how the user expression was only specified once. With signals for
type-checking we cannot do this because both inputs cannot use the same
expression unless we extract it into a separate variable. This is what
this commit implemements.
```ts
const x1 = userExpr;
toWriteableSignal(myDir.input).set(x1);
toWriteableSignal(myDir.input2).set(x2);
```
Note: Even if no input is bound, due to e.g. the `inputs` decorator
field being used and no statically analyzable class member being
discoverable- the user expression should be *evaluated*. This was
something we broke with the initial signal input prototyping.
This commit adds a test for a case of a binding targetting
multiple inputs with the same name. Test passes for both
signal based components as well as a mix of zone and signal
based components.
Previously, input signals had a bug where when their backing computation or
value would change, it would notify consumers, but consumers would poll the
input signal to check if its value really changed. This polling operation
would transitively poll the input signal's previous dependencies, which of
course would report that they hadn't changed.
This commit adds logic in the `InputSignalImpl` to skip dependency polling
whenever the signal's backing computation or value changes, until that value
is read for the first time.