This commit modifies the setup of the injector profiler to occur solely when the application is running in a browser context. This adjustment is made because the injector profile serves no purpose when the application is running on the server.
PR Close#55530
The timing of render hook execution is almost entirely identical to
`ngZone.onMicrotaskEmpty`. Developers working towards zoneless
compatibility will need to migrate `onMicrotaskEmpty` calls to use
`afterNextRender`/`afterRender` instead. This, however, would lead to
confusing issues if there are promises in the callbacks because
`onMicrotaskEmpty` emits inside the Angular zone while render hooks
execute outside today. This is problematic because it's not documented
and does not produce any notification or error message when async work
is done inside the hooks that requires change detection. Instead, change detection
simply does not run, and this behavior has proven to be surprising to
developers who are used to ZoneJS change detection behavior.
fixes#55299
PR Close#55399
The `DeferBlockFixture.render` function should not await the
`whenStable` promise of the fixture. This does not allow developers to
test any intermediate states that might occur between rendering the
initial content and the full app stability.
fixes#55235
PR Close#55271
The previous example had an incomplete code snippet that would not work if copied and pasted as is. There were two missing closing parentheses, one for the `inject` function, and the other for the `waitForAsync` function.
PR Close#55407
Adds a check that disables the timer scheduling for `placeholder` and `loading` blocks on the server since the underlying timer will delay the server response.
Fixes#55475.
PR Close#55480
`RouterOutlet` uses a unique injector logic that returns a value that correspond to the `ActivatedRoute` token dynamically. This logic breaks when a component/directive/pipe that injects the `ActivatedRoute` is located within a `@defer` block, because defer creates an `EnvironmentInjector` instance, which doesn't have that dynamic logic.
We've added some special handling of the `OutletInjector` in one of the previous commits, but it was incomplete and it was not covering cases when different routes use the same component. This commit updates defer logic to re-establish this dynamic behavior for `ActivatedRoute` by creating an instance of the `OutletInjector` when a parent injector was also an instance of `OutletInjector`.
This fix is a short-term solution and longer term we should find a way to achieve the dynamic behavior that Router relies on, but without adding a special case logic into defer.
Resolves#54864.
PR Close#55374
Expect that the number of template executions is `===` to a number, rather than expect that it
does not contain a number. As they were, these expectations would pass regardless of the expected
value.
PR Close#55294
The fix from PR #55079 introduced a configuration of the injector chain, which wasn't properly handled by the injector debug utils, thus resulting in JS exceptions in DevTools. This commit updates injector debug utils logic that calculates injector resolution path to also handle `ChainedInjector`s.
Resolves#55137.
PR Close#55144
The control flow migration was using a couple of Greek letters as placeholders. This ended up conflicting with templates authored in Greek.
These changes use a more obscure placeholder to make conflicts less likely. It also moves the placeholder generation to a centralized function so it's easier to make changes if we decide to update the pattern again.
Fixes#55085.
PR Close#55113
Fixes that the control flow migration was throwing an error if the `imports` of a component are initialized to an identifier.
Fixes#55080.
PR Close#55081
This commit adds support for ignoring specific doc entries when
extracting doc entries. This allows us to drop e.g. `InputFunction` from
the API docs, given that the `input` API entry holds all the relevant
information.
`InputFunction` only exists for type purposes in the `.d.ts`.
PR Close#55053
Similar to `input`, `model`, `output`, the query initializer APIs are
also explicitly denoted as such. This allows angular.dev to display them
more readable and compactly.
PR Close#55053
This improves the API documentatino for `output` in angular.dev,
similar to how we improved the API for `input`.
Angular.dev can now show these documentation entries more
readable if annotated explicitly as initializer API.
Note: output API is short enough that we want to include
the types in the code snippet previews.
PR Close#55053
This commit improves the API documentation for `input` after
we added support for initializer APIs in angular.dev docs generation.
Changes:
- Rename `ReadT` to `T`. This conceptually makes it easy to talk about
inputs of type `T` if there is no transform involved. The common case.
- Rename `WriteT` to `TransformT`. This makes it clear that this is the
type that the "transform" needs to handle.
- Improves the "overall" description of the input function so that it
can be shown as a general overview for the API site.
- Improves usage notes to be a little more helpful, yielding more useful
content in the API docs usage notes section.
- Add short JSDoc description for each individual overload.
PR Close#55053
This commit updates the `@defer` logic to establish proper injector resolution order. More specifically:
- Makes node injectors to be inspected first, similar to how it happens when `@defer` block is not used.
- Adds extra handling for the Router's `OutletInjector`, until we replace it with an `EnvironmentInjector`.
Resolves#54864.
Resolves#55028.
Resolves#55036.
PR Close#55079
This update enhances the encoding handling of request bodies to generate the necessary cache key for transfer cache functionality.
Closes#54956
PR Close#54980
Previously we assumed that if a `for` loop tracking function is in the form of `someMethod($index, $item)`, it will be pure so we didn't pass the parameter to bind the context to it. This appears to be risky, because we don't know if the method is trying to access `this`.
These changes play it safe by always binding method-based tracking functions.
Fixes#53628.
PR Close#54960
In some cases the hydration mismatch is nested within a component.
As the devTool only reports issues on the component level, we need to mark the component node rather than the actual mismatched node.
PR Close#54671
This commit updates the name of an internal function argument that represents an embedded view injector. Also it introduces a new config option that allows passing an environment injector to be used in the underlying LView. There are no changes to the behavior, just some initial cleanup for upcoming changes.
PR Close#54903
The logic in `isCssClassMatching` is only interested in two areas in the attributes:
implicit attributes and the `AttributeMarker.Classes` area, with the first area only
of interest for projection matching, not directive matching. This commit splits these
two searches to make this more apparent.
PR Close#54800
This commit resolves a regression that was introduced when the compiler switched from
`TemplateDefinitionBuilder` (TDB) to the template pipeline (TP) compiler. The TP compiler
has changed the output of
```html
if (false) { <div class="test"></div> }
```
from
```ts
defineComponent({
consts: [['class', 'test'], [AttributeMarker.Classes, 'test']],
template: function(rf) {
if (rf & 1) {
ɵɵtemplate(0, App_Conditional_0_Template, 2, 0, "div", 0)
}
}
});
```
to
```ts
defineComponent({
consts: [[AttributeMarker.Classes, 'test']],
template: function(rf) {
if (rf & 1) {
ɵɵtemplate(0, App_Conditional_0_Template, 2, 0, "div", 0)
}
}
});
```
The last argument to the `ɵɵtemplate` instruction (0 in both compilation outputs) corresponds with
the index in `consts` of the element's attribute's, and we observe how TP has allocated only a single
attribute array for the `div`, where there used to be two `consts` entries with TDB. Consequently,
the `ɵɵtemplate` instruction is now effectively referencing a different attributes array, where the
distinction between the `"class"` attribute vs. the `AttributeMarker.Classes` distinction affects
the behavior: TP's emit causes the runtime to incorrectly match a directive with `selector: '.foo'` to
be instantiated on the `ɵɵtemplate` instruction as if it corresponds with a structural directive!
Instead of changing TP to align with TDB's emit, this commit updates the runtime instead. This uncovered
an inconsistency in selector matching for class names, where there used to be two paths dealing with
class matching:
1. The first check was commented to be a special-case for class matching, implemented in `isCssClassMatching`.
2. The second path was part of the main selector matching algorithm, where `findAttrIndexInNode` was being used
to find the start position in `tNode.attrs` to match the selector's value against.
The second path only considers `AttributeMarker.Classes` values if matching for content projection, OR of the
`TNode` is not an inline template. The special-case in path 1 however does not make that distinction, so it
would consider the `AttributeMarker.Classes` binding as a selector match, incorrectly causing a directive to
match on the `ɵɵtemplate` itself.
The second path was also buggy for class bindings, as the return value of `classIndexOf` was incorrectly
negated: it considered a matching class attribute as non-matching and vice-versa. This bug was not observable
because of another issue, where the class-handling in part 2 was never relevant because of the special-case
in part 1.
This commit separates path 1 entirely from path 2 and removes the buggy class-matching logic in part 2, as
that is entirely handled by path 1 anyway. `isCssClassMatching` is updated to exclude class bindings from
being matched for inline templates.
Fixes#54798
PR Close#54800
Add an internal API to enable and use i18n hydration for testing and development. This helps ensure that we don't accidentally break the current behavior until we are completely ready to roll out i18n support.
PR Close#54784
Currently if an `(output)` listener fails, it will be handled gracefully
by Angular and reported to the `ErrorHandler`.
For programmatic subscriptions with `OutputEmitterRef`, this is not the case.
Instead, as soon as any subscription is failing, all other subsequent
subscription callbacks are not firing anymore.
This commit intends to make this more consistent by gracefully
reporting errors from `OutputEmitterRef#emit` to `ErrorHandler`,
allowing for listener execution to continue.
PR Close#54821
Ensures that all of the functions intended to be run in initializers are in an injection context. This is a stop-gap until we have a compiler diagnostic for it.
PR Close#54761
This commits assert that the repeater instruction gets a reference
to a tracking function. This change will allow us to better track
occurences of https://github.com/angular/angular/issues/53628 -
in certain situations a reference to a tracking function might be
undefiened.
We are not fixing the underlying issue here, just getting better
visibility.
PR Close#54814
Speeds up the retrieval of `DestroyRef` in `EventEmitter` because
`try/catch` is expensive if there is no injection context.
We saw a script time regression in Cloud.
The goldens had to be updated because `getInjectImplementation` is now
referenced. `inject` also references the underlying field, but directly.
This is super minimal overhead of a function exposing the internal
field.
PR Close#54748
This commit updates HTML sanitization logic to avoid infinite loops in case clobbered elements contain fields like `nextSibling` or `parentNode`. Those fields are used for DOM traversal and this update makes sure that those calls return valid results.
Also this commit fixes an issue when clobbering `nodeName` causes JS exceptions.
PR Close#54425
An i18n message effectively acts as a dynamic template: two elements with contiguous instruction indices won't necessarily be contiguous in the DOM.
For that reason, we need to maintain a mapping from instruction index to a physical DOM node in order to hydrate views with i18n, pointing to where hydration for that view should begin.
PR Close#54750
Updates the instruction generation for two-way bindings to only emit the `twoWayBindingSet` call when writing to template variables. Since template variables are constants, it's only allowed to write to them when they're signals. Non-signal values are flagged during template type checking.
Fixes#54670.
PR Close#54714
The `runCallbackOnce` closure is declared not to have any parameters itself, so it is
compatible as `queueMicrotask` callback without the extra closure. This reduces the call
stack by a frame and avoids the extra closure allocation.
PR Close#54801
This commit ensures that render hooks are rerun when a node is attached
or detached. We do not necessarily need to run change detection but DOM
did change so render hooks should execute.
PR Close#54083
This commit updates the `afterRender` and `afterNextRender` hooks to
notify the scheduler (which subsequently schedules change detection)
when created. This makes the hooks similar to `requestAnimationFrame`,
which requests that the browser schedule a rendering operation. This
reqeust is not conditional. Even if there was nothing to repaint, the
`requestAnimationFrame` callback will execute.
In Angular, this is useful because callers of `afterNextRender` don't
necessarily have any way of knowing whether a change detection is even
scheduled. For example, the anchor scrolling with the Angular Router
needs to wait for rendering to complete before attempting to scroll
because rendering can affect the size of the page. However, if the user
is already on the page that the navigation is targeting, such as
navigating to an anchor on the page, there is nothing new for the Router
to render so a render might not even be scheduled.
Related to https://github.com/angular/angular/issues/53985, which
could use `afterNextRender` instead of `setTimeout` to ensure the
scrolling happens in the same frame as the page rendering, but would not
necessarily work without this change (as described above). Note that the
scrolling _cannot_ use a microtask to ensure scrolling happens in the
same frame because `NgZone` will ensure microtasks flush before
change detection, so it would cause the scroll to happen before rendering.
PR Close#54083
In order to serialize and hydrate i18n blocks, we need to be able to walk an AST for the translated message. This AST is generated during normal parsing of the message.
PR Close#54724