`findConnectedBlocks` scans siblings after an `@if` to collect connected
`@else`/`@else if` blocks. Whitespace-only text nodes encountered during
the scan were eagerly added to `processedNodes`, marking them as "do not
emit", before confirming whether a connected block actually followed.
By the time `findConnectedBlocks` runs, `WhitespaceVisitor` has already
converted `&ngsp;` (and ` `) into a plain space character, making
them indistinguishable from insignificant whitespace via `.trim().length`.
When the next sibling was a second, unrelated `@if` instead of `@else`,
the scan stopped but the text node was already silently dropped.
Fix by deferring the `processedNodes` insertion into a pending buffer and
only committing those nodes once a connected block is confirmed to follow.
Fixes#55791
(cherry picked from commit 53fc371142)
Previously, extracting foreign component imports relied on the partial
evaluator and semantic import resolution to locate declaration
references across files. This resolver-based approach is incompatible
with isolated declarations and local compilation, where cross-file type
information and full semantic resolution are unavailable.
Replace the resolver-based foreign import evaluation with a lightweight,
AST-based extraction mechanism (`extractForeignImportsFromAst`). This
allows the compiler to extract foreign component names and raw AST
expressions directly from syntax trees during the analysis phase without
requiring full type checking.
Additionally, simplify the `ForeignComponentMeta` interface by removing
the obsolete reference property and implement granular AST diagnostics
that provide actionable error messages and usage examples when invalid
expressions are passed to `foreignImports`.
Previously, foreign component `@content` blocks were rendered eagerly by
Angular and could only project a list of nodes. With this change, `@content`
can be used to declare a function (e.g. `@content(renderItem; let item)`) that
is passed as a callback prop to the foreign component, allowing the foreign
component to invoke it with context arguments at its leisure.
Implementation details:
- Introduces a new runtime instruction `ɵɵforeignContentFn` which wraps the
template function so it can be called on demand with arguments by the foreign
component.
- Extends the compiler AST to parse and validate `@content` parameters.
- Maps `@content` parameters to the corresponding positional arguments of the
calling foreign component function property.
Add `@content(propName)` blocks for passing template content to foreign
component properties by name. Previously, only a single set of direct children
could be passed to a foreign component via the default `children` property.
With this change, developers can project distinct template content to multiple
specific properties on the foreign component:
```html
<FancyButton [label]="title">
@content(icon) {
<span>Icon</span>
}
@content(description) {
<span>Description text</span>
}
<span>Other children</span>
</FancyButton>
```
Specifically:
- Add support to the HTML lexer for `@content` blocks.
- Introduce `ContentBlock` AST node to represent `@content` blocks.
- Implement validation ensuring `@content` blocks have exactly one parameter
representing a valid JS identifier.
- Throw an error during ingestion if a `@content` block is placed anywhere
other than as a direct child of a foreign component.
- Map `@content` blocks to properties of the props object passed to
`ɵɵforeignComponent`.
- Update compliance and unit tests to cover these changes.
```
Updates the template preparser to exclude namespaced SVG style tags (':svg:style') from the style elements set.
Previously, ':svg:style' elements were incorrectly classified as PreparsedElementType.STYLE, which caused them to be completely stripped from the final template DOM tree during the Render3 template transform and pushed into standard component stylesheets. By limiting the style element parsing to standard 'style' tags, namespaced SVG style tags remain safely in the template AST as normal DOM elements, preserving local SVG styling.
Closes#68977
We extract the identifier name from the `foreignImports` expression in
`ComponentDecoratorHandler` and use a `SelectorlessMatcher` to match element
tags against these names. If an element matches both a regular Angular
directive and a foreign component, a conflict error is thrown.
In addition, we implement strict template semantic validation for these matched
foreign components within `TemplateSemanticsChecker`. Elements matched as
foreign components only support static attributes and property bindings. Any
event bindings, template references, or non-property input bindings (e.g.
class, style, or attribute bindings) trigger a semantic error diagnostic.
Finally, we skip standard DOM schema checks for foreign components to prevent spurious
validation errors since foreign components are not defined in standard HTML schemas.
PR Close#68674
Currently if a `@for` loop doesn't have a `track` expression we don't produce an AST for it at all which means no type checking and language service support for it.
These changes make it so we produce the AST anyways since it gives the user more tools to resolve the issue (e.g. autocompletion when writing the `track` expression).
Implements the logic at the compiler level that will de-duplicate host directives and merge them together. It will also report if a conflict is detected during merging.
Moves the `ClassPropertyMapping` into the compiler, rather than having to pass around the limited `InputOutputPropertySet` interface that is only implemented by `ClassPropertyMapping`.
RecursiveVisitor.visitIfBlockBranch was permanently mutating the children array by pushing the expressionAlias into it. This change clones the array before pushing to avoid this side effect.
Allows specifying a timeout parameter for idle-based deferred triggers, enabling more granular control over when deferred actions are executed.
Closes angular#67187
This is to improve consistency and match developer expectations. This syntax was already deprecated a long time ago.
If you want to bind a data attribute, use the `attr.` prefix (which was already supported).
BREAKING CHANGE: data prefixed attribute no-longer bind inputs nor outputs.
fixes#26406
Back in #39323, I added a new `ThisReceiver` node to represent accesses done through `this` and I ended up making it inherit from `ImplicitReceiver`. The logic was that in most cases accessing through `this` was the same as the implicit access.
Over the years this has proven to not be a great idea, because no other AST nodes do this and one has to keep it in mind whenever dealing with `ImplicitReceiver`.
These changes remove the inheritance and update all of the usage sites accordingly.
The new animations was not correctly looking for the `.` when parsing bindings. This resulted in arbitrary event bindings creating animate.leave instruction calls.
fixes: #63466
PR Close#63470
Similar fix as #63082, but for template attributes. The root cause is the same where we should be using `fullStart` instead of `start` in order to account for whitespaces being skipped.
Fixes#63157.
PR Close#63175
When parsing expressions inside a bound attribute, we offset all of its spans by an `absoluteOffset` in order to get the right spans in the source file. The offset was incorrect when parsing an attribute with leading spaces during the construction of the Ivy AST, because of the combination of:
1. We were setting the offset by looking at `valueSpan.start`.
2. The Ivy parser sets `leadingTriviaChars: [' ', '\n']` which means that spaces and new lines will be ignored in the `sourceSpan.start`.
These changes resolve the issue by using `valueSpan.fullStart` which includes the leading spaces.
Fixes#63069.
PR Close#63082
Currently the HTML parser will stop parsing as soon as it hits an end character in the name of an attribute (e.g. `/` or `>`). This ends up being problematic with some third-party packages like Tailwind which uses a wider range of characters for its class names. While the characters are fine when inside the `class` attribute, our current parser behavior prevents users from setting those classes conditionally through `[class.]` bindings.
These changes adjust the parser to handle such cases.
Fixes#61671.
PR Close#62742
When we introduced blocks, we made a deliberate decision to treat the `@` character as a reserved character in case we need to use it for other syntax in the future. This meant that some common cases, like writing out an email address in the template, can be broken.
After some recent discussions we decided to relax the requirement and only treat `@` as a reserve character if it's followed by a character sequence that matches a known block.
PR Close#62644
Currently when there's a parser error in interpolated text, the compiler reports an error on the entire text node. This can be really noisy in long strings.
These changes switch to reporting the errors on the specific expressions that caused them.
PR Close#62258