Commit graph

36988 commits

Author SHA1 Message Date
Kristiyan Kostadinov
2ce0e98f79 fix(compiler): handle nested brackets in host object bindings
Fixes that we were parsing bindings in the `host` object with a regex that didn't account for nested brackets which may come up with something like Tailwind.

Fixes #68039.
2026-04-06 13:21:50 -07:00
Andrew Scott
9218140348 fix(compiler-cli): resolve TCB mapping failure for safe property reads with as any
- Fixes TemplateSymbolBuilder.getTcbPositionForNode to recursively unwrap AsExpression and NonNullExpression nodes.
- Added a test case in type_checker__get_symbol_of_template_node_spec.ts to verify symbol mapping when strictSafeNavigationTypes is false.
- Note: The issue likely broke in commit 13c8df67d9.
2026-04-06 13:16:19 -07:00
Andrew Scott
0a7f4ddf93 refactor: export symbols for external use
export symbols for sharing in environments outside of angular monorepo
2026-04-06 13:16:19 -07:00
Kristiyan Kostadinov
fd95735594 refactor(compiler-cli): fix failing tests
Fixes some tests that started failing after recent changes.
2026-04-06 12:33:05 -07:00
Matthieu Riegler
f3c471e0d5 refactor(compiler): remove fullTemplateTypeCheck compiler option.
The option was deprecated back in v13. Users should use `strictTemplates: true`.
2026-04-06 11:55:09 -07:00
Doug Parker
d45b7a91f9 fix(platform-browser): remove unused styles when associated host is dropped
This fixes a memory leak in `SharedStylesHost` where calling `removeHost` would leave any `<style>` or `<link>` tags associated with that host in the DOM. This is wasteful in general, and can create even more leaks if the same host is added and removed multiple times, causing styles to be consistently reappended but never removed.

BREAKING CHANGE: This removes styles when they appear to no longer be used by an associated `host`. However other DOM on the page may still be affected by those styles if not leveraging `ViewEncapsulation.Emulated` or if those styles are used by elements outside of Angular, potentially causing other DOM to appear unstyled.
2026-04-06 11:48:14 -07:00
Savio Dsouza
6e1e9766a5 ci: use immutable sha for checkout
Change to immutable SHA for checkout reference.
2026-04-06 11:47:02 -07:00
Aleksander Bodurri
33b001d478 fix(devtools): clean up removed directive entries in IdentityTracker to prevent memory leak
The IdentityTracker singleton never deleted entries from its internal
  maps (_currentDirectiveId, _currentDirectivePosition, isComponent) for
  destroyed directives. This caused the maps to grow monotonically for
  the entire DevTools session, retaining references to destroyed component
  instances and preventing garbage collection.

  The cleanup was intentionally commented out because the profiler needs
  to resolve IDs and positions of removed components during recording.

  Introduce `setProfilingActive()` to gate cleanup: when profiling is
  inactive, removed entries are deleted immediately during `index()`.
  When profiling is active, removals are deferred into a `_pendingRemovals`
  set and flushed once profiling stops via `capture.ts` start/stop calls.
2026-04-06 11:36:07 -07:00
Angular Robot
2cb67c0a26 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-06 11:14:40 -07:00
Doug Parker
1ef503e18e test(http): disable XSRF and mock location in HttpClient tests to avoid Domino failures and state leakage
The `HttpClient` tests in `client_spec.ts` were failing intermittently in Node/Domino environment because `MockPlatformLocation` defaults to `http://_empty_/`. This valid URL satisfied the URL parser in `xsrfInterceptorFn`, causing it to proceed to cookie extraction which throws `NotYetImplemented` in Domino.

To fix this:
1. Disabled XSRF protection in `client_spec.ts` using `withNoXsrfProtection()`, as these tests are not for XSRF.
2. Provided `ɵprovideFakePlatformNavigation` to remove state leakage effects and ensure consistency.
2026-04-06 11:05:53 -07:00
funsaized
d95e856a25 fix(docs-infra): align search result icon with text on mobile
On narrow viewports, the search result icon was pushed to its own flex line when the title text was too long, causing vertical misalignment.

The fix wraps the title text and package badge in a single container that manages its own flex layout, preventing the icon from being separated from the text on narrow viewports.

Fixes #68005
2026-04-06 10:57:09 -07:00
Andrew Scott
13c8df67d9 refactor(compiler-cli): decouple TemplateSymbolBuilder from ts.TypeChecker
This updates the SymbolBuilder to no longer use ts.TypeChecker internally to
build symbols for the language service. These lookups are deferred/done later
using the newly expanded template type checker API.
2026-04-06 10:55:40 -07:00
Andrew Scott
5600c4fbd9 refactor(compiler-cli): tag host directives in TCB
Add HOST_DIRECTIVE expression identifier to TCB comments to identify host directives.
2026-04-06 10:55:40 -07:00
Andrew Scott
ecae525970 Revert "refactor(core): remove ComponentFactoryResolver & ComponentFactory from the api surface"
This reverts commit 9d76ac8229.
g3 cleanup not complete
2026-04-06 09:24:11 -07:00
Doug Parker
4a174b89c8 test(platform-server): fix race condition in incremental hydration test
The test was using a brittle fixed timeout of 10ms to wait for change detection to run in Zoneless mode. This failed in CI sometimes presumably because CI can execute slower based on resource constraints. This commit replaces it with a polling approach which checks until the expected content is rendered.
2026-04-03 16:46:55 -07:00
Doug Parker
b4a3abd095 test(platform-server): replace fixed timeout with polling in event replay test
This test appears to be flakey in CI, presumably because resource constrained environments can run unexpected slower and exceed the timeout. This switches to a polling approach, waiting for the queue to drain.
2026-04-03 13:50:04 -07:00
Angular Robot
47cd6048b6 build: update bazel dependencies
See associated pull request for more information.
2026-04-03 11:28:26 -07:00
Harmeet Singh
789c2cd9fb docs(forms): clarify disabled FormArray value behavior
Document that FormArray.value includes only enabled child controls when the array is enabled, but includes all child values when the FormArray itself is disabled.

Fixes #67759
2026-04-03 11:22:33 -07:00
Angular Robot
24c5400185 build: update dependency undici to v8
See associated pull request for more information.
2026-04-03 10:54:58 -07:00
Alex Rickabaugh
394ad0c2a2 fix(forms): allow late-bound input types for signals forms
Ensure that input [type] bindings are evaluated dynamically rather than cached eagerly during initialization. This allows late-bound expressions for input types to correctly apply constraints like min/max and maxLength.

Fixes #66987
2026-04-03 10:18:09 -07:00
Kristiyan Kostadinov
9c55fcb3e6 feat(core): de-duplicate host directives
With host directives we can end up in a situation where the same directive applies multiple times to the same element, potentially with conflicting configurations. The runtime isn't set up for a directive to apply more than once so historically we were throwing an error when we detect duplicates.

This ended up limiting the usefulness of host directives to library authors, because it meant that host directives couldn't be reused as much as authors wanted. To address the issue, these changes introduce logic in the compiler and runtime that will de-duplicate host directives with the following logic:

1. If a directive matches once in the template and more than once as a host directive, the host directive matches will be discarded and only the template match will apply. The mental model is that a host directive match represents `Partial<YourDirective>` while a template match represents the full `YourDirective`.
2. If a directive matches multiple times as a host directive, we merge the input/output mappings from all the instances into a single one. If we detect a case where an input/output is exposed under multiple names during the merging process, both the compiler and the runtime will produce an error.

Fixes #57846.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
57432f1b6a refactor(compiler-cli): merge duplicate directive matches and report conflicts
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.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
22f9ee1be6 refactor(compiler): require a reference in DirectiveMeta
Requires the `DirectiveMeta` to have a `ref` so that we can find duplicates easily.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
d15ceff617 refactor(compiler-cli): move ClassPropertyMapping into compiler
Moves the `ClassPropertyMapping` into the compiler, rather than having to pass around the limited `InputOutputPropertySet` interface that is only implemented by `ClassPropertyMapping`.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
927ae3abc8 refactor(compiler): move matchSource into base metadata
Moves the `matchSource` into the base metadata so the binder can use it.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
4651b93a92 refactor(compiler-cli): pre-compute key
Updates the TCB metadata to pre-compute and store the `TcbReferenceKey`, instead of computing it on the fly.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
8fe025f514 feat(core): drop support for TypeScript 5.9
Drops support for TypeScript 5.9.

BREAKING CHANGE:
* TypeScript versions older than 6.0 are no longer supported.
2026-04-03 09:44:11 -07:00
Matthieu Riegler
9d76ac8229 refactor(core): remove ComponentFactoryResolver & ComponentFactory from the api surface
Those APIs date back to pre-ivy times and are long deprecated.

BREAKING CHANGE: `ComponentFactoryResolver` and `ComponentFactory` are no longer available. Pass the component class directly to APIs that previously required a factory, such as `ViewContainerRef.createComponent` or use the standalone `createComponentFunction`.
2026-04-02 16:00:57 -07:00
SkyZeroZx
164cf98879 docs(docs-infra): Enhances update guide layout responsiveness
The version dropdown width now uses `clamp()` for better responsiveness.
2026-04-02 15:49:27 -07:00
Kam
a6a5e8a4a5 feat(docs-infra): update Stack Overflow icon to new logo
Updated the Stack Overflow icon in the navigation social menu to use the new Stack Overflow logo.
2026-04-02 15:48:10 -07:00
Kam
ba70e8ba0c feat(docs-infra): add Stack Overflow link to navigation social menu
Added Stack Overflow icon and link to the navigation component.
2026-04-02 15:48:10 -07:00
Jessica Janiuk
30f63fc1c2 refactor(core): address review comments on NG0750 error message
This commit addresses review comments from AndrewKushnir regarding conditional formatting of error messages and updating tests.
2026-04-02 14:55:42 -07:00
Jessica Janiuk
8218d2e34a refactor(core): Add more detail to NG0750 error message
This adds a bit more context to the NG0750 error message to provide details about which module failed to load when executing the dependencyResolverFn. This can help with debugging a failed lazy load in a defer block.
2026-04-02 14:55:42 -07:00
Andrew Scott
8216d34976 feat(migrations): Add migration for CanMatchFn snapshot parameter (#67452)
the third partial match snapshot parameter is now required in the types
since the Router always providers it

PR Close #67452
2026-04-02 12:53:57 -07:00
Andrew Scott
579440170b fix(router): make currentSnapshot required in CanMatchFn (#67452)
it was only optional to avoid a breaking change in a minor

BREAKING CHANGE: The `currentSnapshot` parameter in `CanMatchFn` and the `canMatch` method of the `CanMatch` interface is now required. While this was already the behavior of the Router at runtime, existing class implementations of `CanMatch` must now include the third argument to satisfy the interface.

PR Close #67452
2026-04-02 12:53:57 -07:00
SkyZeroZx
7f9450219f feat(compiler-cli): Adds warning for prefetch without main defer trigger
Emit a warning when an `@defer` block uses `prefetch` triggers but does not define an explicit main trigger.

Closes #52746
2026-04-02 12:21:09 -07:00
SkyZeroZx
b19fda0b15 refactor(compiler-cli): Add diagnostics for idle prefetch triggers
Extends the extended diagnostic for `@defer` trigger misconfiguration to include `on idle` triggers
2026-04-02 12:21:09 -07:00
Angular Robot
11f047f195 build: update all non-major dependencies
See associated pull request for more information.
2026-04-02 11:45:22 -07:00
Georgi Serev
68a8396baa
refactor(devtools): show appropriate change detection label in the directive tree
Depending on the client app version, either show "OnPush" (pre-v22) or "Eager" (v22+); As part of the change, `APP_DATA` root signal has been introduced along with a minor bug fix related to component metadata displaying.
2026-04-02 11:37:34 -07:00
Angular Robot
36966ba6ec docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-02 11:06:49 -07:00
Angular Robot
a65440182e build: update all github actions
See associated pull request for more information.
2026-04-02 08:41:19 -07:00
SkyZeroZx
ab9910c17c docs(docs-infra): Adds anchor links to class member headers for linking
Adds anchor links to class member headers for direct linking.
Add test to ensure anchors render correctly.

Fixes #67970
2026-04-02 08:40:46 -07:00
Andrew Scott
75ac120493 fix(language-service): get quick info at local var location to align with TS semantics and support type narrowing
Previously, the Language Service fetched Quick Info and definitions for template variables (such as `@let` declarations) using mapping to their `initializerLocation` (the right-hand side expression). This aggressively bubbled the type, JSDoc, and definition identity of the initializer backwards onto the variable itself.

This approach had two flaws:
1. It broke type narrowing because the LS read the original un-narrowed type from the source expression rather than the type of the narrowed intermediate variable in the Type Check Block.
2. It deviated from native TypeScript semantics, where a local `let` binding (`let address = hero.address`) does not inherit the docstrings or `(property)` kind of its initializer, acting solely as a local inferred variable.

By using `localVarLocation` rather than `initializerLocation` for LetDeclaration Quick Info and Type Definitions, these intermediate variables now properly preserve type narrowing within templates and flawlessly match the standard behavior expected of TypeScript block variables. `VariableSymbol.initializerLocation` is retained solely to map the value spans of structural directive contexts (e.g., `exportAs` strings).

fixes #65491
2026-04-01 12:22:07 -07:00
SkyZeroZx
c15e3a005d test(core): refactors test to use timeout utility
Replaces direct `setTimeout` wrapped in a Promise with the `timeout` helper from `@angular/private/testing`
2026-04-01 20:46:00 +02:00
Pawel Kozlowski
f99172ddde release: cut the v22.0.0-next.6 release 2026-04-01 20:42:20 +02:00
Pawel Kozlowski
3771e264fc docs: release notes for the v21.2.7 release 2026-04-01 20:37:55 +02:00
Matthieu Riegler
bf8105ef76 ci: exclude test files from primitives review
Those files aren't synced into G3 and shouldn't require external reviews
2026-04-01 20:27:26 +02:00
Angular Robot
436c5df488 build: update cross-repo angular dependencies to v22.0.0-next.4
See associated pull request for more information.
2026-04-01 18:31:00 +02:00
Angular Robot
1f3ac4a71b build: update cross-repo angular dependencies to 616a50d
See associated pull request for more information.
2026-04-01 13:23:04 +02:00
Andrew Scott
daa9b2a9d6 fix(router): pass outlet context to split to fix empty path named outlets
The `split` helper function in `packages/router/src/utils/config_matching.ts` was blind to the current outlet being processed. When encountering an empty path named outlet in the config, it would assume it needed to pull it in as a synthetic empty group, even if we were already in the process of resolving that very outlet!

When navigating to `/(secondary:component-copy)` with this config:

```typescript
{
  path: '',
  component: MainLayout,
  children: [
    { path: '', outlet: 'secondary', component: SecondaryComponent, children: [{path: 'component-copy'}] }
  ]
}
```

The router uses `MainLayout` as a pass-through and calls `split` on its children with segments `['component-copy']`.
`split` uses the `containsEmptyPathMatchesWithNamedOutlets` helper to determine if there are any candidate empty path named outlets to pull in. Because of this, it sees `{ path: '', outlet: 'secondary' }` and says: "Ah, an empty path named outlet! I must pull it in!"
Rather than falling through to standard segment matching, it returns `UrlSegmentGroup(segments: [], children: {secondary: emptyGroup})`.
The router then tries to process `primary` (with `[]` segments) and fails because the config only has `secondary`. It also tries to process `secondary` with the `emptyGroup`. While `{ path: '', outlet: 'secondary' }` matches the empty group, its child `{ path: 'component-copy' }` fails to match because the `emptyGroup` has no segments! So both branches fail, resulting in a `NoMatch` error for the entire navigation!

Pulling in empty path named outlets IS desired when they act as siblings to segments we are matching. This has worked before and continues to work!

```typescript
{
  path: 'a',
  children: [
    { path: 'b', component: ComponentB },
    { path: '', component: ComponentC, outlet: 'aux' }
  ]
}
```

When navigating to `a/b`, `split` sees segments `['b']` and the `aux` empty path. It pulls in `aux` so it gets instantiated alongside `b`. This is correct!

If we have a named outlet with a non-empty path under an empty path parent:

```typescript
{
  path: '',
  component: MainLayout,
  children: [
    { path: 'component-copy', outlet: 'secondary', component: ComponentE }
  ]
}
```

When we navigate to `/(secondary:component-copy)`:
- `split` uses `containsEmptyPathMatchesWithNamedOutlets` to see if there are any empty path named outlets. Since it only sees `path: 'component-copy'`, it returns `false`.
- It falls through to standard segment matching, which finds `component-copy` in the segments array and activates it flawlessly!

This worked perfectly before the fix because it didn't use `containsEmptyPathMatchesWithNamedOutlets`.

The fix passes the **current active outlet context** into `split`. If `split` finds an empty path named outlet that matches the outlet we are already processing, it ignores it as a pull-in candidate.

When evaluating `MainLayout` children for `secondary`:
- URL Segments left to process: `['component-copy']`
- Current Outlet: `secondary`
- `childConfig`: `[{ path: '', outlet: 'secondary' }]`

Previously, `split` saw the empty path and pulled it in as a synthetic empty group, breaking matching. Now, since `getOutlet(r) === outlet` (both are `secondary`), the fix ignores it. Instead of returning empty segments, it **falls through to standard segment matching**, which successfully find the `component-copy` segment!

When evaluating `ComponentA` children for `primary`:
- URL Segments left to process: `['b']`
- Current Outlet: `primary`
- `childConfig`: `[{ path: 'b' }, { path: '', outlet: 'aux' }]`

Since `getOutlet(aux) !== primary`, the fix **does not ignore it**. `split` pulls in `aux: emptyGroup` as a sibling, instantiating `ComponentC` alongside `ComponentB`. This preserves correct behavior for auxiliary outlets!

fixes #67708
2026-04-01 11:48:42 +02:00